Esempio n. 1
0
    //_____________________________________________
    void SizeGrip::embed( void )
    {

        #if OXYGEN_HAVE_X11

        if( !QX11Info::isPlatformX11() ) return;
        auto c = m_decoration.data()->client().data();

        xcb_window_t windowId = c->windowId();
        if( windowId )
        {

            /*
            find client's parent
            we want the size grip to be at the same level as the client in the stack
            */
            xcb_window_t current = windowId;
            auto connection = QX11Info::connection();
            xcb_query_tree_cookie_t cookie = xcb_query_tree_unchecked( connection, current );
            ScopedPointer<xcb_query_tree_reply_t> tree(xcb_query_tree_reply( connection, cookie, nullptr ) );
            if( !tree.isNull() && tree->parent ) current = tree->parent;

            // reparent
            xcb_reparent_window( connection, winId(), current, 0, 0 );
            setWindowTitle( "Oxygen::SizeGrip" );

        } else {

            hide();

        }

        #endif
    }
Esempio n. 2
0
void scan_windows(void)
{
    const int screens_len = xcb_setup_roots_length(xcb_get_setup(wm_conf.connection));
    int screen_idx;
    xcb_window_t root_wins[screens_len];
    xcb_query_tree_cookie_t root_tree_cookies[screens_len];

    /* request window trees for the root window of each screen */
    for (screen_idx = 0; screen_idx < screens_len; ++screen_idx) {
        xcb_screen_t *screen = xcb_aux_get_screen(wm_conf.connection, screen_idx);
        root_wins[screen_idx] = screen->root;
        root_tree_cookies[screen_idx] = xcb_query_tree_unchecked(wm_conf.connection,
                                                                 root_wins[screen_idx]);
    }

    xcb_query_tree_reply_t *root_tree_replies[screens_len];
    xcb_window_t *wins;
    int wins_len;

    /* collect replies */
    for (screen_idx = 0; screen_idx < screens_len; ++screen_idx) {
        root_tree_replies[screen_idx] = xcb_query_tree_reply(wm_conf.connection,
                                                             root_tree_cookies[screen_idx],
                                                             NULL);
        wins = xcb_query_tree_children(root_tree_replies[screen_idx]);
        if (!wins)
            fprintf(stderr, "failed to get child tree for window %u\n", root_wins[screen_idx]);
        wins_len = xcb_query_tree_children_length(root_tree_replies[screen_idx]);
        fprintf(stderr, "root window %u has %d children\n", root_wins[screen_idx], wins_len);

        fprintf(stderr, "examining children\n");
        xcb_window_t child_win;
        int i;
        for (i = 0; i < wins_len; ++i) {
            child_win = wins[i];
            fprintf(stderr, "  child window %u\n", child_win);
            client_t *client = find_client(child_win);
            if (!client) {
                client = client_init(client_alloc());
                client->window = child_win;
                sglib_client_t_add(&client_list, client);
            }
            read_client_geometry(client);
        }
    }

    for (screen_idx = 0; screen_idx < screens_len; ++screen_idx)
        free(root_tree_replies[screen_idx]);
}
Esempio n. 3
0
/** Redirect all  the windows to  the off-screen buffer  starting from
 *  the  root window  and change  root window  attributes to  make the
 *  server reporting meaningful events
 */
void
display_init_redirect(void)
{
  /* Manage all children windows from the root window */
  _query_tree_cookie = xcb_query_tree_unchecked(globalconf.connection,
						globalconf.screen->root);

  xcb_composite_redirect_subwindows(globalconf.connection,
				    globalconf.screen->root,
				    XCB_COMPOSITE_REDIRECT_MANUAL);

  /* Declare interest in meaningful events */
  const uint32_t select_input_val =
    XCB_EVENT_MASK_KEY_PRESS |
    XCB_EVENT_MASK_KEY_RELEASE |
    XCB_EVENT_MASK_BUTTON_RELEASE |
    XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
    XCB_EVENT_MASK_STRUCTURE_NOTIFY |
    XCB_EVENT_MASK_PROPERTY_CHANGE;

  xcb_change_window_attributes(globalconf.connection, globalconf.screen->root,
			       XCB_CW_EVENT_MASK, &select_input_val);
}
Esempio n. 4
0
/* FIXME: round trips */
static Shadow *
_ecore_x_window_tree_walk(Ecore_X_Window window)
{
   Shadow *s, **sl;
   xcb_get_window_attributes_reply_t *reply_attr;
   xcb_get_geometry_reply_t *reply_geom;
   xcb_query_tree_reply_t *reply_tree;
   xcb_get_window_attributes_cookie_t cookie_attr;
   xcb_get_geometry_cookie_t cookie_geom;
   xcb_query_tree_cookie_t cookie_tree;
   int i, j;

   CHECK_XCB_CONN;

   cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window);
   reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL);
   if (!reply_attr) return NULL;
   if (reply_attr->map_state != XCB_MAP_STATE_VIEWABLE)
     {
        free(reply_attr);
        return NULL;
     }

   free(reply_attr);

   cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window);
   reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL);
   if (!reply_geom) return NULL;

   if (!(s = calloc(1, sizeof(Shadow))))
     {
        free(reply_geom);
        return NULL;
     }

   s->win = window;
   s->x = reply_geom->x;
   s->y = reply_geom->y;
   s->w = reply_geom->width;
   s->h = reply_geom->height;

   free(reply_geom);

   cookie_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, window);
   reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL);
   if (reply_tree)
     {
        xcb_window_t *list;
        int num;

        num = xcb_query_tree_children_length(reply_tree);
        list = xcb_query_tree_children(reply_tree);

        s->children = calloc(1, sizeof(Shadow *) * num);
        if (s->children)
          {
             s->children_num = num;
             for (i = 0; i < num; i++)
               {
                  s->children[i] = _ecore_x_window_tree_walk(list[i]);
                  if (s->children[i])
                    s->children[i]->parent = s;
               }
             /* compress list down */
             j = 0;
             for (i = 0; i < num; i++)
               {
                  if (s->children[i])
                    {
                       s->children[j] = s->children[i];
                       j++;
                    }
               }
             if (j == 0)
               {
                  free(s->children);
                  s->children = NULL;
                  s->children_num = 0;
               }
             else
               {
                  s->children_num = j;
                  sl = realloc(s->children, sizeof(Shadow *) * j);
                  if (sl) s->children = sl;
               }
          }

        free(reply_tree);
     }

   return s;
}
Esempio n. 5
0
/** Hello, this is main.
 * \param argc Who knows.
 * \param argv Who knows.
 * \return EXIT_SUCCESS I hope.
 */
int
main(int argc, char **argv)
{
    char *confpath = NULL;
    int xfd, i, screen_nbr, opt, colors_nbr;
    xcolor_init_request_t colors_reqs[2];
    ssize_t cmdlen = 1;
    xdgHandle xdg;
    xcb_generic_event_t *event;
    static struct option long_options[] =
    {
        { "help",    0, NULL, 'h' },
        { "version", 0, NULL, 'v' },
        { "config",  1, NULL, 'c' },
        { "check",   0, NULL, 'k' },
        { NULL,      0, NULL, 0 }
    };

    /* event loop watchers */
    ev_io xio    = { .fd = -1 };
    ev_check xcheck;
    ev_prepare a_refresh;
    ev_signal sigint;
    ev_signal sigterm;
    ev_signal sighup;

    /* clear the globalconf structure */
    p_clear(&globalconf, 1);
    globalconf.keygrabber = LUA_REFNIL;
    globalconf.mousegrabber = LUA_REFNIL;
    buffer_init(&globalconf.startup_errors);

    /* save argv */
    for(i = 0; i < argc; i++)
        cmdlen += a_strlen(argv[i]) + 1;

    globalconf.argv = p_new(char, cmdlen);
    a_strcpy(globalconf.argv, cmdlen, argv[0]);

    for(i = 1; i < argc; i++)
    {
        a_strcat(globalconf.argv, cmdlen, " ");
        a_strcat(globalconf.argv, cmdlen, argv[i]);
    }

    /* Text won't be printed correctly otherwise */
    setlocale(LC_CTYPE, "");

    /* Get XDG basedir data */
    xdgInitHandle(&xdg);

    /* init lua */
    luaA_init(&xdg);

    /* check args */
    while((opt = getopt_long(argc, argv, "vhkc:",
                             long_options, NULL)) != -1)
        switch(opt)
        {
          case 'v':
            eprint_version();
            break;
          case 'h':
            exit_help(EXIT_SUCCESS);
            break;
          case 'k':
            if(!luaA_parserc(&xdg, confpath, false))
            {
                fprintf(stderr, "✘ Configuration file syntax error.\n");
                return EXIT_FAILURE;
            }
            else
            {
                fprintf(stderr, "✔ Configuration file syntax OK.\n");
                return EXIT_SUCCESS;
            }
          case 'c':
            if(a_strlen(optarg))
                confpath = a_strdup(optarg);
            else
                fatal("-c option requires a file name");
            break;
        }

    globalconf.loop = ev_default_loop(0);
    ev_timer_init(&globalconf.timer, &luaA_on_timer, 0., 0.);

    /* register function for signals */
    ev_signal_init(&sigint, exit_on_signal, SIGINT);
    ev_signal_init(&sigterm, exit_on_signal, SIGTERM);
    ev_signal_init(&sighup, restart_on_signal, SIGHUP);
    ev_signal_start(globalconf.loop, &sigint);
    ev_signal_start(globalconf.loop, &sigterm);
    ev_signal_start(globalconf.loop, &sighup);
    ev_unref(globalconf.loop);
    ev_unref(globalconf.loop);
    ev_unref(globalconf.loop);

    struct sigaction sa = { .sa_handler = signal_fatal, .sa_flags = 0 };
    sigemptyset(&sa.sa_mask);
    sigaction(SIGSEGV, &sa, 0);

    /* XLib sucks */
    XkbIgnoreExtension(True);

    /* X stuff */
    globalconf.display = XOpenDisplay(NULL);
    if (globalconf.display == NULL)
        fatal("cannot open display");

    globalconf.default_screen = XDefaultScreen(globalconf.display);

    globalconf.connection = XGetXCBConnection(globalconf.display);

    /* Double checking then everything is OK. */
    if(xcb_connection_has_error(globalconf.connection))
        fatal("cannot open display");

    /* Prefetch all the extensions we might need */
    xcb_prefetch_extension_data(globalconf.connection, &xcb_big_requests_id);
    xcb_prefetch_extension_data(globalconf.connection, &xcb_test_id);
    xcb_prefetch_extension_data(globalconf.connection, &xcb_randr_id);
    xcb_prefetch_extension_data(globalconf.connection, &xcb_shape_id);

    /* initialize dbus */
    a_dbus_init();

    /* Get the file descriptor corresponding to the X connection */
    xfd = xcb_get_file_descriptor(globalconf.connection);
    ev_io_init(&xio, &a_xcb_io_cb, xfd, EV_READ);
    ev_io_start(globalconf.loop, &xio);
    ev_check_init(&xcheck, &a_xcb_check_cb);
    ev_check_start(globalconf.loop, &xcheck);
    ev_unref(globalconf.loop);
    ev_prepare_init(&a_refresh, &a_refresh_cb);
    ev_prepare_start(globalconf.loop, &a_refresh);
    ev_unref(globalconf.loop);

    /* Grab server */
    xcb_grab_server(globalconf.connection);

    /* Make sure there are no pending events. Since we didn't really do anything
     * at all yet, we will just discard all events which we received so far.
     * The above GrabServer should make sure no new events are generated. */
    xcb_aux_sync(globalconf.connection);
    while ((event = xcb_poll_for_event(globalconf.connection)) != NULL)
    {
        /* Make sure errors are printed */
        uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(event);
        if(response_type == 0)
            event_handle(event);
        p_delete(&event);
    }

    for(screen_nbr = 0;
        screen_nbr < xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
        screen_nbr++)
    {
        const uint32_t select_input_val = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;

        /* This causes an error if some other window manager is running */
        xcb_change_window_attributes(globalconf.connection,
                                     xutil_screen_get(globalconf.connection, screen_nbr)->root,
                                     XCB_CW_EVENT_MASK, &select_input_val);
    }

    /* Need to xcb_flush to validate error handler */
    xcb_aux_sync(globalconf.connection);

    /* Process all errors in the queue if any. There can be no events yet, so if
     * this function returns something, it must be an error. */
    if (xcb_poll_for_event(globalconf.connection) != NULL)
        fatal("another window manager is already running");

    /* Prefetch the maximum request length */
    xcb_prefetch_maximum_request_length(globalconf.connection);

    /* check for xtest extension */
    const xcb_query_extension_reply_t *xtest_query;
    xtest_query = xcb_get_extension_data(globalconf.connection, &xcb_test_id);
    globalconf.have_xtest = xtest_query->present;

    /* Allocate the key symbols */
    globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection);
    xcb_get_modifier_mapping_cookie_t xmapping_cookie =
        xcb_get_modifier_mapping_unchecked(globalconf.connection);

    /* init atom cache */
    atoms_init(globalconf.connection);

    /* init screens information */
    screen_scan();

    /* init default font and colors */
    colors_reqs[0] = xcolor_init_unchecked(&globalconf.colors.fg,
                                           "black", sizeof("black") - 1);

    colors_reqs[1] = xcolor_init_unchecked(&globalconf.colors.bg,
                                           "white", sizeof("white") - 1);

    globalconf.font = draw_font_new("sans 8");

    for(colors_nbr = 0; colors_nbr < 2; colors_nbr++)
        xcolor_init_reply(colors_reqs[colors_nbr]);

    xutil_lock_mask_get(globalconf.connection, xmapping_cookie,
                        globalconf.keysyms, &globalconf.numlockmask,
                        &globalconf.shiftlockmask, &globalconf.capslockmask,
                        &globalconf.modeswitchmask);

    /* Get the window tree associated to this screen */
    const int screen_max = xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
    xcb_query_tree_cookie_t tree_c[screen_max];

    /* do this only for real screen */
    for(screen_nbr = 0; screen_nbr < screen_max; screen_nbr++)
    {
        /* select for events */
        const uint32_t change_win_vals[] =
        {
            XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
                | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW
                | XCB_EVENT_MASK_STRUCTURE_NOTIFY
                | XCB_EVENT_MASK_PROPERTY_CHANGE
                | XCB_EVENT_MASK_BUTTON_PRESS
                | XCB_EVENT_MASK_BUTTON_RELEASE
                | XCB_EVENT_MASK_FOCUS_CHANGE
        };

        tree_c[screen_nbr] = xcb_query_tree_unchecked(globalconf.connection,
                                                      xutil_screen_get(globalconf.connection, screen_nbr)->root);

        xcb_change_window_attributes(globalconf.connection,
                                     xutil_screen_get(globalconf.connection, screen_nbr)->root,
                                     XCB_CW_EVENT_MASK,
                                     change_win_vals);
        ewmh_init(screen_nbr);
        systray_init(screen_nbr);
    }

    /* init spawn (sn) */
    spawn_init();

    /* we will receive events, stop grabbing server */
    xcb_ungrab_server(globalconf.connection);

    /* Parse and run configuration file */
    if (!luaA_parserc(&xdg, confpath, true))
        fatal("couldn't find any rc file");

    scan(tree_c);

    xcb_flush(globalconf.connection);

    /* main event loop */
    ev_loop(globalconf.loop, 0);

    /* cleanup event loop */
    ev_ref(globalconf.loop);
    ev_check_stop(globalconf.loop, &xcheck);
    ev_ref(globalconf.loop);
    ev_prepare_stop(globalconf.loop, &a_refresh);
    ev_ref(globalconf.loop);
    ev_io_stop(globalconf.loop, &xio);

    awesome_atexit(false);

    return EXIT_SUCCESS;
}
Esempio n. 6
0
int main(int argc,char**argv){
	xcb_connection_t*d=xcb_connect(0,0);
	int32_t*x,*y,*tx=0,mx,my,rt=xcb_setup_roots_iterator(xcb_get_setup(d)).data->root,cs[255],*cz=cs+1;
	uint8_t mz,mZ;
	xcb_change_window_attributes(d,rt,XCB_CW_EVENT_MASK,&cwa);
	xcb_grab_key(d,1,rt,0,64,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC);
	xcb_grab_key(d,1,rt,8,XCB_GRAB_ANY,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC);
	xcb_grab_button(d,1,rt,XCB_EVENT_MASK_BUTTON_PRESS,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC,XCB_NONE,XCB_NONE,XCB_GRAB_ANY,8);
	#ifdef COMPOSITE
	xcb_composite_redirect_subwindows(d,rt,XCB_COMPOSITE_REDIRECT_AUTOMATIC);
	#endif
	xcb_generic_event_t*e=0;
main:xcb_flush(d);
	waitpid(-1,0,WNOHANG);
noflush:x=y=cz-1;
again:free(e);
	switch((e=xcb_wait_for_event(d))->response_type&127){
	case XCB_BUTTON_PRESS:
		for(;x>cs;x--)
			if(*x==((xcb_button_press_event_t*)e)->child){
				if(((xcb_key_press_event_t*)e)->detail==2)goto pocus;
			case XCB_KEY_PRESS:
				mz=128|((xcb_key_press_event_t*)e)->detail;
				my=((xcb_key_press_event_t*)e)->state;
				goto*(cz==cs+1?&&kcode:&&stack);
			}
		goto noflush;
	case XCB_KEY_RELEASE:
		if(((xcb_key_press_event_t*)e)->detail!=64||!tx)default:goto again;
		xt:x=tx;
		tx=0;
		goto stack;
	case XCB_CONFIGURE_REQUEST:{
		void*p=buf;
		for(mz=0;mz<5;mz++)
			if(((xcb_configure_request_event_t*)e)->value_mask&1<<mz){*(uint32_t*)p=*(int16_t*)(((void*)e)+16+mz*2);p+=4;}
		if(((xcb_configure_request_event_t*)e)->value_mask&XCB_CONFIG_WINDOW_SIBLING){*(uint32_t*)p=((xcb_configure_request_event_t*)e)->sibling;p+=4;}
		if(mz=((xcb_configure_request_event_t*)e)->value_mask&XCB_CONFIG_WINDOW_STACK_MODE)*(uint32_t*)p=((xcb_configure_request_event_t*)e)->stack_mode;
		xcb_configure_window(d,((xcb_configure_request_event_t*)e)->window,((xcb_configure_request_event_t*)e)->value_mask,buf);
		if(mz){
			p=xcb_query_tree_reply(d,xcb_query_tree_unchecked(d,rt),0);
			int32_t*cl=p+32+((xcb_query_tree_reply_t*)p)->children_len*4;
			for(y=p+32;y<cl;y++){
				for(x=cs+1;x<cz;x++)
					if(*x==*y)goto nono;
				*y=0;
				nono:;
			}
			x=cs;
			for(y=p+32;y<cl;y++)
				if(*y)*++x=*y;
			free(p);
			goto pocus;
		}else goto main;}
	case XCB_MAP_REQUEST:{
		void*p=xcb_get_window_attributes_reply(d,xcb_get_window_attributes_unchecked(d,((xcb_map_request_event_t*)e)->window),0);
		if(((xcb_get_window_attributes_reply_t*)p)->override_redirect){
			free(p);
			goto pocus;
		}
		free(p);
		for(;x>cs;x--)
			if(*x==((xcb_map_request_event_t*)e)->window)goto noflush;
		xcb_map_window(d,*cz++=((xcb_map_request_event_t*)e)->window);
		goto hocus;}
	case XCB_MOTION_NOTIFY:
		*buf=mZ&&((xcb_motion_notify_event_t*)e)->root_x<=mx?:((xcb_motion_notify_event_t*)e)->root_x-mx;
		buf[1]=mZ&&((xcb_motion_notify_event_t*)e)->root_y<=my?:((xcb_motion_notify_event_t*)e)->root_y-my;
		xcb_configure_window(d,*x,mZ?XCB_CONFIG_WINDOW_WIDTH|XCB_CONFIG_WINDOW_HEIGHT:XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y,buf);
		goto main;
	case XCB_BUTTON_RELEASE:
		xcb_ungrab_pointer(d,XCB_CURRENT_TIME);
		goto main;
	case XCB_UNMAP_NOTIFY:unmap:goto*(x==cs?&&noflush:*x==((xcb_unmap_notify_event_t*)e)->window&&--cz>cs+1?&&stack:(x--,&&unmap));
	}
stack:mx=*x;
	for(;x!=y;x+=x<y?:-1)*x=x[x<y?:-1];
	*x=mx;
hocus:x=cz-1;
	xcb_configure_window(d,*x,XCB_CONFIG_WINDOW_STACK_MODE,di);
pocus:xcb_set_input_focus(d,XCB_INPUT_FOCUS_POINTER_ROOT,*x,XCB_CURRENT_TIME);
	if(!(mz&128))goto main;
kcode:switch(mz&=127){
	void*p;
	case 1:case 3:
		p=xcb_grab_pointer_reply(d,xcb_grab_pointer_unchecked(d,0,rt,XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_POINTER_MOTION,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC,XCB_NONE,XCB_NONE,XCB_CURRENT_TIME),0);
		if(((xcb_grab_pointer_reply_t*)p)->status!=XCB_GRAB_STATUS_SUCCESS){
			free(p);
			goto noflush;
		}
		free(p);
		p=xcb_get_geometry_reply(d,xcb_get_geometry_unchecked(d,*y),0);
		mx=((xcb_get_geometry_reply_t*)p)->x;
		my=((xcb_get_geometry_reply_t*)p)->y;
		free(p);
		if(mZ=mz==1){
			p=xcb_query_pointer_reply(d,xcb_query_pointer_unchecked(d,rt),0);
			mx=((xcb_query_pointer_reply_t*)p)->root_x-mx;
			my=((xcb_query_pointer_reply_t*)p)->root_y-my;
			free(p);
		}
		goto noflush;
	case 23:case 49:
		if(cz-cs<3)goto main;
		y=tx;
		tx=mz==23?(y!=cs+1?(y?:x)-1:x):!y||y==x?cs+1:y+1;
		if(y&&y<cz-1){
			*buf=y[mz==23?:-1];
			buf[1]=mz==23;
			xcb_configure_window(d,*y,XCB_CONFIG_WINDOW_SIBLING|XCB_CONFIG_WINDOW_STACK_MODE,buf);
		}
		xcb_configure_window(d,*tx,XCB_CONFIG_WINDOW_STACK_MODE,di);
		goto main;
	case 32:return 0;
	case 44:
		if(cz>cs+1)xcb_configure_window(d,*y,XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y|XCB_CONFIG_WINDOW_WIDTH|XCB_CONFIG_WINDOW_HEIGHT,di);
		goto main;
	case 46:
		if(cz==cs+1)goto main;
		if(tx)goto*(mz|=128,&&xt);
		{xcb_intern_atom_cookie_t c1=xcb_intern_atom_unchecked(d,0,12,"WM_PROTOCOLS"),c2=xcb_intern_atom_unchecked(d,0,16,"WM_DELETE_WINDOW");
		p=xcb_intern_atom_reply(d,c1,0);
		mx=((xcb_intern_atom_reply_t*)p)->atom;
		free(p);
		p=xcb_intern_atom_reply(d,c2,0);}
		my=((xcb_intern_atom_reply_t*)p)->atom;
		free(p);
		p=xcb_get_property_reply(d,xcb_get_property_unchecked(d,0,*y,mx,XCB_ATOM_ATOM,0,-1),0);
		xcb_send_event(d,0,*y,XCB_EVENT_MASK_NO_EVENT,(void*)(xcb_client_message_event_t[]){{.response_type=XCB_CLIENT_MESSAGE,.window=*y,.type=mx,.format=32,.data.data32={my,XCB_CURRENT_TIME}}});
Esempio n. 7
0
/** Hello, this is main.
 * \param argc Who knows.
 * \param argv Who knows.
 * \return EXIT_SUCCESS I hope.
 */
int
main(int argc, char **argv)
{
    char *confpath = NULL;
    int xfd, i, opt;
    ssize_t cmdlen = 1;
    xdgHandle xdg;
    bool no_argb = false;
    xcb_generic_event_t *event;
    xcb_query_tree_cookie_t tree_c;
    static struct option long_options[] =
    {
        { "help",    0, NULL, 'h' },
        { "version", 0, NULL, 'v' },
        { "config",  1, NULL, 'c' },
        { "check",   0, NULL, 'k' },
        { "no-argb", 0, NULL, 'a' },
        { NULL,      0, NULL, 0 }
    };

    /* event loop watchers */
    ev_io xio    = { .fd = -1 };
    ev_check xcheck;
    ev_prepare a_refresh;
    ev_signal sigint;
    ev_signal sigterm;
    ev_signal sighup;

    /* clear the globalconf structure */
    p_clear(&globalconf, 1);
    globalconf.keygrabber = LUA_REFNIL;
    globalconf.mousegrabber = LUA_REFNIL;
    buffer_init(&globalconf.startup_errors);

    /* save argv */
    for(i = 0; i < argc; i++)
        cmdlen += a_strlen(argv[i]) + 1;

    awesome_argv = p_new(char, cmdlen);
    a_strcpy(awesome_argv, cmdlen, argv[0]);

    for(i = 1; i < argc; i++)
    {
        a_strcat(awesome_argv, cmdlen, " ");
        a_strcat(awesome_argv, cmdlen, argv[i]);
    }

    /* Text won't be printed correctly otherwise */
    setlocale(LC_CTYPE, "");

    /* Get XDG basedir data */
    xdgInitHandle(&xdg);

    /* init lua */
    luaA_init(&xdg);

    /* check args */
    while((opt = getopt_long(argc, argv, "vhkc:a",
                             long_options, NULL)) != -1)
        switch(opt)
        {
        case 'v':
            eprint_version();
            break;
        case 'h':
            exit_help(EXIT_SUCCESS);
            break;
        case 'k':
            if(!luaA_parserc(&xdg, confpath, false))
            {
                fprintf(stderr, "✘ Configuration file syntax error.\n");
                return EXIT_FAILURE;
            }
            else
            {
                fprintf(stderr, "✔ Configuration file syntax OK.\n");
                return EXIT_SUCCESS;
            }
        case 'c':
            if(a_strlen(optarg))
                confpath = a_strdup(optarg);
            else
                fatal("-c option requires a file name");
            break;
        case 'a':
            no_argb = true;
            break;
        }

    globalconf.loop = ev_default_loop(EVFLAG_NOSIGFD);

    /* register function for signals */
    ev_signal_init(&sigint, exit_on_signal, SIGINT);
    ev_signal_init(&sigterm, exit_on_signal, SIGTERM);
    ev_signal_init(&sighup, restart_on_signal, SIGHUP);
    ev_signal_start(globalconf.loop, &sigint);
    ev_signal_start(globalconf.loop, &sigterm);
    ev_signal_start(globalconf.loop, &sighup);
    ev_unref(globalconf.loop);
    ev_unref(globalconf.loop);
    ev_unref(globalconf.loop);

    struct sigaction sa = { .sa_handler = signal_fatal, .sa_flags = 0 };
    sigemptyset(&sa.sa_mask);
    sigaction(SIGSEGV, &sa, 0);

    /* X stuff */
    globalconf.connection = xcb_connect(NULL, &globalconf.default_screen);
    if(xcb_connection_has_error(globalconf.connection))
        fatal("cannot open display");

    globalconf.screen = xcb_aux_get_screen(globalconf.connection, globalconf.default_screen);
    /* FIXME The following two assignments were swapped on purpose */
    if(!no_argb)
        globalconf.visual = a_default_visual(globalconf.screen);
    if(!globalconf.visual)
        globalconf.visual = a_argb_visual(globalconf.screen);
    globalconf.default_depth = a_visual_depth(globalconf.screen, globalconf.visual->visual_id);
    globalconf.default_cmap = globalconf.screen->default_colormap;
    if(globalconf.default_depth != globalconf.screen->root_depth)
    {
        // We need our own color map if we aren't using the default depth
        globalconf.default_cmap = xcb_generate_id(globalconf.connection);
        xcb_create_colormap(globalconf.connection, XCB_COLORMAP_ALLOC_NONE,
                            globalconf.default_cmap, globalconf.screen->root,
                            globalconf.visual->visual_id);
    }

    /* Prefetch all the extensions we might need */
    xcb_prefetch_extension_data(globalconf.connection, &xcb_big_requests_id);
    xcb_prefetch_extension_data(globalconf.connection, &xcb_test_id);
    xcb_prefetch_extension_data(globalconf.connection, &xcb_randr_id);
    xcb_prefetch_extension_data(globalconf.connection, &xcb_xinerama_id);

    /* initialize dbus */
    a_dbus_init();

    /* Get the file descriptor corresponding to the X connection */
    xfd = xcb_get_file_descriptor(globalconf.connection);
    ev_io_init(&xio, &a_xcb_io_cb, xfd, EV_READ);
    ev_io_start(globalconf.loop, &xio);
    ev_check_init(&xcheck, &a_xcb_check_cb);
    ev_check_start(globalconf.loop, &xcheck);
    ev_unref(globalconf.loop);
    ev_prepare_init(&a_refresh, &a_refresh_cb);
    ev_prepare_start(globalconf.loop, &a_refresh);
    ev_unref(globalconf.loop);

    /* Grab server */
    xcb_grab_server(globalconf.connection);

    /* Make sure there are no pending events. Since we didn't really do anything
     * at all yet, we will just discard all events which we received so far.
     * The above GrabServer should make sure no new events are generated. */
    xcb_aux_sync(globalconf.connection);
    while ((event = xcb_poll_for_event(globalconf.connection)) != NULL)
    {
        /* Make sure errors are printed */
        uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(event);
        if(response_type == 0)
            event_handle(event);
        p_delete(&event);
    }

    {
        const uint32_t select_input_val = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;

        /* This causes an error if some other window manager is running */
        xcb_change_window_attributes(globalconf.connection,
                                     globalconf.screen->root,
                                     XCB_CW_EVENT_MASK, &select_input_val);
    }

    /* Need to xcb_flush to validate error handler */
    xcb_aux_sync(globalconf.connection);

    /* Process all errors in the queue if any. There can be no events yet, so if
     * this function returns something, it must be an error. */
    if (xcb_poll_for_event(globalconf.connection) != NULL)
        fatal("another window manager is already running");

    /* Prefetch the maximum request length */
    xcb_prefetch_maximum_request_length(globalconf.connection);

    /* check for xtest extension */
    const xcb_query_extension_reply_t *xtest_query;
    xtest_query = xcb_get_extension_data(globalconf.connection, &xcb_test_id);
    globalconf.have_xtest = xtest_query->present;

    /* Allocate the key symbols */
    globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection);
    xcb_get_modifier_mapping_cookie_t xmapping_cookie =
        xcb_get_modifier_mapping_unchecked(globalconf.connection);

    /* init atom cache */
    atoms_init(globalconf.connection);

    /* init screens information */
    screen_scan();

    xutil_lock_mask_get(globalconf.connection, xmapping_cookie,
                        globalconf.keysyms, &globalconf.numlockmask,
                        &globalconf.shiftlockmask, &globalconf.capslockmask,
                        &globalconf.modeswitchmask);

    /* do this only for real screen */
    ewmh_init();
    systray_init();

    /* init spawn (sn) */
    spawn_init();

    /* The default GC is just a newly created associated with a window with
     * depth globalconf.default_depth */
    xcb_window_t tmp_win = xcb_generate_id(globalconf.connection);
    globalconf.gc = xcb_generate_id(globalconf.connection);
    xcb_create_window(globalconf.connection, globalconf.default_depth,
                      tmp_win, globalconf.screen->root,
                      -1, -1, 1, 1, 0,
                      XCB_COPY_FROM_PARENT, globalconf.visual->visual_id,
                      XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP,
                      (const uint32_t [])
    {
        globalconf.screen->black_pixel,
                          globalconf.screen->black_pixel,
                          globalconf.default_cmap
    });
    xcb_create_gc(globalconf.connection, globalconf.gc, tmp_win, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND,
    (const uint32_t[]) {
        globalconf.screen->black_pixel, globalconf.screen->white_pixel
    });
    xcb_destroy_window(globalconf.connection, tmp_win);

    /* Get the window tree associated to this screen */
    tree_c = xcb_query_tree_unchecked(globalconf.connection,
                                      globalconf.screen->root);

    xcb_change_window_attributes(globalconf.connection,
                                 globalconf.screen->root,
                                 XCB_CW_EVENT_MASK,
                                 ROOT_WINDOW_EVENT_MASK);

    /* we will receive events, stop grabbing server */
    xcb_ungrab_server(globalconf.connection);

    /* Parse and run configuration file */
    if (!luaA_parserc(&xdg, confpath, true))
        fatal("couldn't find any rc file");

    p_delete(&confpath);

    xdgWipeHandle(&xdg);

    /* scan existing windows */
    scan(tree_c);

    xcb_flush(globalconf.connection);

    /* main event loop */
    ev_loop(globalconf.loop, 0);

    /* cleanup event loop */
    ev_ref(globalconf.loop);
    ev_check_stop(globalconf.loop, &xcheck);
    ev_ref(globalconf.loop);
    ev_prepare_stop(globalconf.loop, &a_refresh);
    ev_ref(globalconf.loop);
    ev_io_stop(globalconf.loop, &xio);

    awesome_atexit(false);

    return EXIT_SUCCESS;
}
Esempio n. 8
0
Compositor::Compositor()
    : connection_(QX11Info::connection()),
      root_(QX11Info::appRootWindow()),
      damageExt_(xcb_get_extension_data(connection_, &xcb_damage_id)),
      initFinished_(false)
{
    qRegisterMetaType<ClientWindow *>();

    Q_ASSERT(QCoreApplication::instance());
    QCoreApplication::instance()->installNativeEventFilter(this);

    auto ewmhCookie = xcb_ewmh_init_atoms(connection_, &ewmh_);
    if (!xcb_ewmh_init_atoms_replies(&ewmh_, ewmhCookie, Q_NULLPTR)) {
        qFatal("Cannot init EWMH");
    }

    auto wmCmCookie = xcb_ewmh_get_wm_cm_owner_unchecked(&ewmh_, QX11Info::appScreen());
    xcb_window_t wmCmOwnerWin = XCB_NONE;
    if (!xcb_ewmh_get_wm_cm_owner_reply(&ewmh_, wmCmCookie, &wmCmOwnerWin, Q_NULLPTR)) {
        qFatal("Cannot check _NET_WM_CM_Sn");
    }
    if (wmCmOwnerWin) {
        qFatal("Another compositing manager is already running");
    }

    auto attributesCookie = xcb_get_window_attributes_unchecked(connection_, root_);
    auto damageQueryVersionCookie = xcb_damage_query_version_unchecked(connection_, 1, 1);
    auto overlayWindowCookie = xcb_composite_get_overlay_window_unchecked(connection_, root_);

    auto attributes =
            xcbReply(xcb_get_window_attributes_reply(connection_, attributesCookie, Q_NULLPTR));
    if (!attributes) {
        qFatal("Cannot get root window attributes");
    }
    auto newEventMask = attributes->your_event_mask
            | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
            | XCB_EVENT_MASK_STRUCTURE_NOTIFY
            | XCB_EVENT_MASK_PROPERTY_CHANGE;
    xcb_change_window_attributes(connection_, root_, XCB_CW_EVENT_MASK, &newEventMask);

    auto treeCookie = xcb_query_tree_unchecked(connection_, root_);
    auto rootGeometryCookie = xcb_get_geometry_unchecked(connection_, root_);

    auto damageVersion =
            xcbReply(xcb_damage_query_version_reply(connection_, damageQueryVersionCookie, Q_NULLPTR));
    if (!damageVersion) {
        qFatal("Cannot query version of Damage extension");
    }

    auto overlayWindow =
            xcbReply(xcb_composite_get_overlay_window_reply(connection_, overlayWindowCookie, Q_NULLPTR));
    if (!overlayWindow) {
        qFatal("Cannot get overlay window");
    }
    overlayWindow_.reset(QWindow::fromWinId(overlayWindow->overlay_win));

    auto region = xcb_generate_id(connection_);
    xcb_xfixes_create_region(connection_, region, 0, Q_NULLPTR);
    xcb_xfixes_set_window_shape_region(connection_, overlayWindow->overlay_win, XCB_SHAPE_SK_INPUT, 0, 0, region);
    xcb_xfixes_destroy_region(connection_, region);

    xcb_composite_redirect_subwindows(connection_, root_, XCB_COMPOSITE_REDIRECT_MANUAL);

    auto rootGeometry =
            xcbReply(xcb_get_geometry_reply(connection_, rootGeometryCookie, Q_NULLPTR));
    if (!rootGeometry) {
        qFatal("Cannot query root window geometry");
    }
    rootGeometry_ = QRect(rootGeometry->x, rootGeometry->y, rootGeometry->width, rootGeometry->height);

    auto tree = xcbReply(xcb_query_tree_reply(connection_, treeCookie, Q_NULLPTR));
    if (!tree) {
        qFatal("Cannot query window tree");
    }

    auto children = xcb_query_tree_children(tree.get());
    for (int i = 0; i < xcb_query_tree_children_length(tree.get()); i++) {
        addChildWindow(children[i]);
    }
    updateActiveWindow();

    initFinished_ = true;
}