示例#1
0
文件: manage.c 项目: Acidburn0zzz/i3
/*
 * Go through all existing windows (if the window manager is restarted) and manage them
 *
 */
void manage_existing_windows(xcb_window_t root) {
    xcb_query_tree_reply_t *reply;
    int i, len;
    xcb_window_t *children;
    xcb_get_window_attributes_cookie_t *cookies;

    /* Get the tree of windows whose parent is the root window (= all) */
    if ((reply = xcb_query_tree_reply(conn, xcb_query_tree(conn, root), 0)) == NULL)
        return;

    len = xcb_query_tree_children_length(reply);
    cookies = smalloc(len * sizeof(*cookies));

    /* Request the window attributes for every window */
    children = xcb_query_tree_children(reply);
    for (i = 0; i < len; ++i)
        cookies[i] = xcb_get_window_attributes(conn, children[i]);

    /* Call manage_window with the attributes for every window */
    for (i = 0; i < len; ++i)
        manage_window(children[i], cookies[i], true);

    free(reply);
    free(cookies);
}
示例#2
0
void find_window_by_property(xcb_window_t window, xcb_atom_t property,
		xcb_window_t *res) {
	*res = XCB_WINDOW_NONE;
	
	xcb_get_property_cookie_t get_property_cookie =
			xcb_get_property(display, 0, window, property, XCB_ATOM_ANY, 0, 0);
	xcb_get_property_reply_t *get_property_reply =
			xcb_get_property_reply(display, get_property_cookie, NULL);
	if (get_property_reply != NULL) {
		if (get_property_reply->type != XCB_ATOM_NONE) {
			*res = window;
			free(get_property_reply);
			return;
		}
		free(get_property_reply);
	}
	
	xcb_query_tree_cookie_t query_tree_cookie =
			xcb_query_tree(display, window);
	xcb_query_tree_reply_t *query_tree_reply =
			xcb_query_tree_reply(display, query_tree_cookie, NULL);
	if (query_tree_reply == NULL)
		return;
	int length = xcb_query_tree_children_length(query_tree_reply);
	xcb_window_t *children = xcb_query_tree_children(query_tree_reply);
	for (int i = 0; i < length; i++) {
		find_window_by_property(children[i], property, res);
		if (*res != XCB_WINDOW_NONE)
			break;
	}
	free(query_tree_reply);
}
示例#3
0
/*
 * Find a window that has WM_STATE set in the window tree below win.
 * Unmapped/unviewable windows are not considered valid matches.
 * Children are searched in top-down stacking order.
 * The first matching window is returned, None if no match is found.
 */
static xcb_window_t
Find_Client_In_Children(xcb_connection_t * dpy, xcb_window_t win)
{
    xcb_query_tree_cookie_t qt_cookie;
    xcb_query_tree_reply_t *tree;
    xcb_window_t *children;
    unsigned int n_children;
    int i;

    qt_cookie = xcb_query_tree (dpy, win);
    tree = xcb_query_tree_reply (dpy, qt_cookie, NULL);
    if (!tree)
        return XCB_WINDOW_NONE;
    n_children = xcb_query_tree_children_length (tree);
    if (!n_children) {
        free (tree);
        return XCB_WINDOW_NONE;
    }
    children = xcb_query_tree_children (tree);

    /* Check each child for WM_STATE and other validity */
    win = XCB_WINDOW_NONE;
    for (i = (int) n_children - 1; i >= 0; i--) {
        if (!Window_Is_Viewable(dpy, children[i])) {
            /* Don't bother descending into this one */
            children[i] = XCB_WINDOW_NONE;
            continue;
        }
        if (!Window_Has_Property(dpy, children[i], atom_wm_state))
            continue;

        /* Got one */
        win = children[i];
        goto done;
    }

    /* No children matched, now descend into each child */
    for (i = (int) n_children - 1; i >= 0; i--) {
        if (children[i] == XCB_WINDOW_NONE)
            continue;
        win = Find_Client_In_Children(dpy, children[i]);
        if (win != XCB_WINDOW_NONE)
            break;
    }

  done:
    free (tree); /* includes children */

    return win;
}
示例#4
0
文件: nwm.c 项目: brandoninvergo/nwm
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]);
}
QList< xcb_window_t > LinuxWindowCapture::listWindowsRecursive( const xcb_window_t& window ) {
  QList< xcb_window_t > windows;
  xcb_connection_t* xcbConn = QX11Info::connection();
  xcb_query_tree_cookie_t queryC = xcb_query_tree( xcbConn, window );
  CScopedPointer< xcb_query_tree_reply_t > queryR( xcb_query_tree_reply( xcbConn, queryC, nullptr ) );

  if ( queryR ) {
    xcb_window_t* children = xcb_query_tree_children( queryR.data() );
    for( auto c = 0; c < xcb_query_tree_children_length( queryR.data() ); ++c ) {
      windows << children[ c ];
      windows << listWindowsRecursive( children[ c ] );
    }
  }
  return windows;
}
示例#6
0
/*
  Generate a XCWM_EVENT_WINDOW_CREATE event for all
  existing mapped top-level windows when we start
*/
static void
_xcwm_windows_adopt(xcwm_context_t *context, xcwm_event_cb_t callback_ptr)
{
    xcb_query_tree_cookie_t tree_cookie = xcb_query_tree(context->conn, context->root_window->window_id);
    xcb_query_tree_reply_t *reply = xcb_query_tree_reply(context->conn, tree_cookie, NULL);
    if (NULL == reply) {
        return;
    }

    int len = xcb_query_tree_children_length(reply);
    xcb_window_t *children = xcb_query_tree_children(reply);

    int i;
    for (i = 0; i < len; i ++) {
        xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(context->conn, children[i]);
        xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(context->conn, cookie, NULL);

        if (!attr) {
            fprintf(stderr, "Couldn't get attributes for window 0x%08x\n", children[i]);
            continue;
        }

        if (attr->map_state == XCB_MAP_STATE_VIEWABLE) {
            printf("window 0x%08x viewable\n", children[i]);

            xcwm_window_t *window = _xcwm_window_create(context, children[i], context->root_window->window_id);
            if (!window) {
                continue;
            }

            _xcwm_window_composite_pixmap_update(window);

            xcwm_event_t return_evt;
            return_evt.window = window;
            return_evt.event_type = XCWM_EVENT_WINDOW_CREATE;

            callback_ptr(&return_evt);
        }
        else {
            printf("window 0x%08x non-viewable\n", children[i]);
        }

        free(attr);
    }

    free(reply);
}
示例#7
0
QList< xcb_window_t > LinuxWindowCapture::listWindowsRecursive( xcb_connection_t* dpy, xcb_window_t& window )
{
  QList< xcb_window_t > windows;
  xcb_query_tree_reply_t* queryR;

  xcb_query_tree_cookie_t queryC = xcb_query_tree( dpy, window );

  if( ( queryR = xcb_query_tree_reply( dpy, queryC, NULL ) ) ) {
    xcb_window_t* children = xcb_query_tree_children( queryR );

    for( int c = 0; c < xcb_query_tree_children_length( queryR ); ++c  ) {
      windows << children[ c ];
      windows << listWindowsRecursive( dpy, children[ c ]);
    }
    free( queryR );
  }
  return windows;
}
示例#8
0
/** Finish  redirection by  adding  all the  existing  windows in  the
 *  hierarchy
 */
void
display_init_redirect_finalise(void)
{
  assert(_query_tree_cookie.sequence);

  /* Get all the windows below the root window */
  xcb_query_tree_reply_t *query_tree_reply =
    xcb_query_tree_reply(globalconf.connection,
			 _query_tree_cookie,
			 NULL);

  /* Add all these windows excluding the root window of course */
  const int nwindows = xcb_query_tree_children_length(query_tree_reply);
  if(nwindows)
    window_manage_existing(nwindows,
			   xcb_query_tree_children(query_tree_reply));

  free(query_tree_reply);
}
示例#9
0
文件: window.c 项目: Stebalien/bspwm
void adopt_orphans(void)
{
	xcb_query_tree_reply_t *qtr = xcb_query_tree_reply(dpy, xcb_query_tree(dpy, root), NULL);
	if (qtr == NULL) {
		return;
	}

	int len = xcb_query_tree_children_length(qtr);
	xcb_window_t *wins = xcb_query_tree_children(qtr);

	for (int i = 0; i < len; i++) {
		uint32_t idx;
		xcb_window_t win = wins[i];
		if (xcb_ewmh_get_wm_desktop_reply(ewmh, xcb_ewmh_get_wm_desktop(ewmh, win), &idx, NULL) == 1) {
			schedule_window(win);
		}
	}

	free(qtr);
}
示例#10
0
文件: xconn.c 项目: carlodoro88/lxdm
void xconn_clean(xconn_t c)
{
#if 0
	xcb_query_tree_cookie_t wintree;
	xcb_query_tree_reply_t *rep;
	xcb_window_t *children;
	xcb_window_t root;
	int i,len;
	if(!c) return;
	root=xconn_get_root(c);
	wintree = xcb_query_tree(c->c, root);
	rep = xcb_query_tree_reply(c->c, wintree, 0);
	if(!rep) return;
	len = xcb_query_tree_children_length(rep);
	children = xcb_query_tree_children(rep);
	for(i=0;i<len;i++)
		xcb_kill_client(c->c,children[i]);
	free(rep);
	xcb_flush(c->c);
#endif
}
示例#11
0
文件: hidden.c 项目: notaudrey/qtwm2
/*
 * List all hidden windows.
 *
 */
int findhidden(void) {
    xcb_query_tree_reply_t *reply;
    int i;
    int len;
    xcb_window_t *children;
    xcb_get_window_attributes_reply_t *attr;
    uint32_t state;
    xcb_get_property_cookie_t cookie;
    xcb_icccm_get_text_property_reply_t prop;
    xcb_generic_error_t *error;

    /* Get all children. */
    reply = xcb_query_tree_reply(conn,
                                 xcb_query_tree(conn, screen->root), 0);
    if (NULL == reply) {
        return -1;
    }

    len = xcb_query_tree_children_length(reply);
    children = xcb_query_tree_children(reply);

    /* List all hidden windows on this root. */
    for (i = 0; i < len; i ++) {
        attr = xcb_get_window_attributes_reply(
                   conn, xcb_get_window_attributes(conn, children[i]), NULL);

        if (!attr) {
            fprintf(stderr, "Couldn't get attributes for window %d.",
                    children[i]);
            continue;
        }

        /*
         * Don't bother windows in override redirect mode.
         *
         * This mode means they wouldn't have been reported to us
         * with a MapRequest if we had been running, so in the
         * normal case we wouldn't have seen them.
         */
        if (!attr->override_redirect) {
            state = get_wm_state(children[i]);
            if (state == XCB_ICCCM_WM_STATE_ICONIC) {
                /*
                 * Example names:
                 *
                 * _NET_WM_ICON_NAME(UTF8_STRING) = 0x75, 0x72, 0x78,
                 * 0x76, 0x74 WM_ICON_NAME(STRING) = "urxvt"
                 * _NET_WM_NAME(UTF8_STRING) = 0x75, 0x72, 0x78, 0x76,
                 * 0x74 WM_NAME(STRING) = "urxvt"
                 */
                cookie = xcb_icccm_get_wm_icon_name(conn, children[i]);
                xcb_icccm_get_wm_icon_name_reply(conn, cookie, &prop, &error);

                prop.name[prop.name_len] = '\0';
                if (printcommand) {
                    /* FIXME: Need to escape : in prop.name. */
                    printf("'%s':'xdotool windowmap 0x%x windowraise 0x%x'\n",
                           prop.name, children[i], children[i]);
                } else {
                    puts(prop.name);
                }
            }
        } /* if not override redirect */

        free(attr);
    } /* for */

    free(reply);

    return 0;
}
示例#12
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;
}
示例#13
0
文件: awesome.c 项目: klug/awesome
/** Scan X to find windows to manage.
 */
static void
scan(xcb_query_tree_cookie_t tree_c)
{
    int i, tree_c_len;
    xcb_query_tree_reply_t *tree_r;
    xcb_window_t *wins = NULL;
    xcb_get_window_attributes_reply_t *attr_r;
    xcb_get_geometry_reply_t *geom_r;
    long state;

    tree_r = xcb_query_tree_reply(globalconf.connection,
                                  tree_c,
                                  NULL);

    if(!tree_r)
        return;

    /* Get the tree of the children windows of the current root window */
    if(!(wins = xcb_query_tree_children(tree_r)))
        fatal("cannot get tree children");

    tree_c_len = xcb_query_tree_children_length(tree_r);
    xcb_get_window_attributes_cookie_t attr_wins[tree_c_len];
    xcb_get_property_cookie_t state_wins[tree_c_len];

    for(i = 0; i < tree_c_len; i++)
    {
        attr_wins[i] = xcb_get_window_attributes_unchecked(globalconf.connection,
                       wins[i]);

        state_wins[i] = xwindow_get_state_unchecked(wins[i]);
    }

    xcb_get_geometry_cookie_t *geom_wins[tree_c_len];

    for(i = 0; i < tree_c_len; i++)
    {
        attr_r = xcb_get_window_attributes_reply(globalconf.connection,
                 attr_wins[i],
                 NULL);

        state = xwindow_get_state_reply(state_wins[i]);

        if(!attr_r || attr_r->override_redirect
                || attr_r->map_state == XCB_MAP_STATE_UNMAPPED
                || state == XCB_ICCCM_WM_STATE_WITHDRAWN)
        {
            geom_wins[i] = NULL;
            p_delete(&attr_r);
            continue;
        }

        p_delete(&attr_r);

        /* Get the geometry of the current window */
        geom_wins[i] = p_alloca(xcb_get_geometry_cookie_t, 1);
        *(geom_wins[i]) = xcb_get_geometry_unchecked(globalconf.connection, wins[i]);
    }

    for(i = 0; i < tree_c_len; i++)
    {
        if(!geom_wins[i] || !(geom_r = xcb_get_geometry_reply(globalconf.connection,
                                       *(geom_wins[i]), NULL)))
            continue;

        client_manage(wins[i], geom_r, true);

        p_delete(&geom_r);
    }

    p_delete(&tree_r);
}
示例#14
0
文件: dsimple.c 项目: aosm/X11apps
static xcb_window_t
recursive_Window_With_Name  (
    xcb_connection_t *dpy,
    xcb_window_t window,
    struct wininfo_cookies *cookies,
    const char *name)
{
    xcb_window_t *children;
    unsigned int nchildren;
    int i;
    xcb_window_t w = 0;
    xcb_generic_error_t *err;
    xcb_query_tree_reply_t *tree;
    struct wininfo_cookies *child_cookies;
    xcb_get_property_reply_t *prop;

    if (cookies->get_net_wm_name.sequence) {
	prop = xcb_get_property_reply (dpy, cookies->get_net_wm_name, &err);

	if (prop) {
	    if (prop->type == atom_utf8_string) {
		const char *prop_name = xcb_get_property_value (prop);
		int prop_name_len = xcb_get_property_value_length (prop);

		/* can't use strcmp, since prop.name is not null terminated */
		if (strncmp (prop_name, name, prop_name_len) == 0) {
		    w = window;
		}
	    }
	    free (prop);
	} else if (err) {
	    if (err->response_type == 0)
		Print_X_Error (dpy, err);
	    return 0;
	}
    }

    if (w) {
	xcb_discard_reply (dpy, cookies->get_wm_name.sequence);
    } else {
#ifdef USE_XCB_ICCCM
	xcb_get_text_property_reply_t nameprop;

	if (xcb_get_wm_name_reply (dpy, cookies->get_wm_name,
				   &nameprop, &err)) {
	    /* can't use strcmp, since nameprop.name is not null terminated */
	    if (strncmp (nameprop.name, name, nameprop.name_len) == 0) {
		w = window;
	    }

	    xcb_get_text_property_reply_wipe (&nameprop);
	}
#else
	prop = xcb_get_property_reply (dpy, cookies->get_wm_name, &err);

	if (prop) {
	    if (prop->type == XCB_ATOM_STRING) {
		const char *prop_name = xcb_get_property_value (prop);
		int prop_name_len = xcb_get_property_value_length (prop);

		/* can't use strcmp, since prop.name is not null terminated */
		if (strncmp (prop_name, name, prop_name_len) == 0) {
		    w = window;
		}
	    }
	    free (prop);
	}
#endif
	else if (err) {
	    if (err->response_type == 0)
		Print_X_Error (dpy, err);
	    return 0;
	}
    }

    if (w)
    {
	xcb_discard_reply (dpy, cookies->query_tree.sequence);
	return w;
    }

    tree = xcb_query_tree_reply (dpy, cookies->query_tree, &err);
    if (!tree) {
	if (err->response_type == 0)
	    Print_X_Error (dpy, err);
	return 0;
    }

    nchildren = xcb_query_tree_children_length (tree);
    children = xcb_query_tree_children (tree);
    child_cookies = calloc(nchildren, sizeof(struct wininfo_cookies));

    if (child_cookies == NULL)
	Fatal_Error("Failed to allocate memory in recursive_Window_With_Name");

    for (i = 0; i < nchildren; i++) {
	if (atom_net_wm_name && atom_utf8_string)
	    child_cookies[i].get_net_wm_name =
		xcb_get_net_wm_name (dpy, children[i]);
	child_cookies[i].get_wm_name = xcb_get_wm_name (dpy, children[i]);
	child_cookies[i].query_tree = xcb_query_tree (dpy, children[i]);
    }
    xcb_flush (dpy);

    for (i = 0; i < nchildren; i++) {
	w = recursive_Window_With_Name (dpy, children[i],
					&child_cookies[i], name);
	if (w)
	    break;
    }

    if (w)
    {
	/* clean up remaining replies */
	for (/* keep previous i */; i < nchildren; i++) {
	    if (child_cookies[i].get_net_wm_name.sequence)
		xcb_discard_reply (dpy,
				   child_cookies[i].get_net_wm_name.sequence);
	    xcb_discard_reply (dpy, child_cookies[i].get_wm_name.sequence);
	    xcb_discard_reply (dpy, child_cookies[i].query_tree.sequence);
	}
    }

    free (child_cookies);
    free (tree); /* includes storage for children[] */
    return (w);
}
示例#15
0
/** Scan X to find windows to manage.
 */
static void
scan(xcb_query_tree_cookie_t tree_c[])
{
    int i, x_screen, tree_c_len;
    const int screen_max = xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
    xcb_query_tree_reply_t *tree_r;
    xcb_window_t *wins = NULL;
    xcb_get_window_attributes_reply_t *attr_r;
    xcb_get_geometry_reply_t *geom_r;
    long state;

    for(x_screen = 0; x_screen < screen_max; x_screen++)
    {
        tree_r = xcb_query_tree_reply(globalconf.connection,
                                      tree_c[x_screen],
                                      NULL);

        if(!tree_r)
            continue;

        /* Get the tree of the children windows of the current root window */
        if(!(wins = xcb_query_tree_children(tree_r)))
            fatal("cannot get tree children");

        tree_c_len = xcb_query_tree_children_length(tree_r);
        xcb_get_window_attributes_cookie_t attr_wins[tree_c_len];
        xcb_get_property_cookie_t state_wins[tree_c_len];

        for(i = 0; i < tree_c_len; i++)
        {
            attr_wins[i] = xcb_get_window_attributes_unchecked(globalconf.connection,
                                                               wins[i]);

            state_wins[i] = window_state_get_unchecked(wins[i]);
        }

        xcb_get_geometry_cookie_t *geom_wins[tree_c_len];

        for(i = 0; i < tree_c_len; i++)
        {
            attr_r = xcb_get_window_attributes_reply(globalconf.connection,
                                                     attr_wins[i],
                                                     NULL);

            state = window_state_get_reply(state_wins[i]);

            if(!attr_r || attr_r->override_redirect
               || attr_r->map_state == XCB_MAP_STATE_UNMAPPED
               || state == XCB_ICCCM_WM_STATE_WITHDRAWN)
            {
                geom_wins[i] = NULL;
                p_delete(&attr_r);
                continue;
            }

            p_delete(&attr_r);

            /* Get the geometry of the current window */
            geom_wins[i] = p_alloca(xcb_get_geometry_cookie_t, 1);
            *(geom_wins[i]) = xcb_get_geometry_unchecked(globalconf.connection, wins[i]);
        }

        for(i = 0; i < tree_c_len; i++)
        {
            if(!geom_wins[i] || !(geom_r = xcb_get_geometry_reply(globalconf.connection,
                                                                  *(geom_wins[i]), NULL)))
                continue;

            /* The window can be mapped, so force it to be undrawn for startup */
            xcb_unmap_window(globalconf.connection, wins[i]);

            client_manage(wins[i], geom_r,
                          phys_screen_getbycoord(geom_r->x, geom_r->y, geom_r->root),
                          x_screen, true);

            p_delete(&geom_r);
        }

        p_delete(&tree_r);
    }
}
示例#16
0
xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md, bool ignoreNonXdndAwareWindows)
{
    if (w == shapedPixmapWindow()->handle()->winId())
        return 0;

    if (md) {
        xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(xcb_connection(), w);
        xcb_get_window_attributes_reply_t *reply = xcb_get_window_attributes_reply(xcb_connection(), cookie, 0);
        if (!reply)
            return 0;

        if (reply->map_state != XCB_MAP_STATE_VIEWABLE)
            return 0;

        free(reply);

        xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(xcb_connection(), w);
        xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(xcb_connection(), gcookie, 0);
        if (!greply)
            return 0;

        QRect windowRect(greply->x, greply->y, greply->width, greply->height);
        free(greply);
        if (windowRect.contains(pos)) {
            bool windowContainsMouse = !ignoreNonXdndAwareWindows;
            {
                xcb_get_property_cookie_t cookie =
                        Q_XCB_CALL(xcb_get_property(xcb_connection(), false, w, connection()->atom(QXcbAtom::XdndAware),
                                                    XCB_GET_PROPERTY_TYPE_ANY, 0, 0));
                xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);

                bool isAware = reply && reply->type != XCB_NONE;
                free(reply);
                if (isAware) {
                    const QPoint relPos = pos - windowRect.topLeft();
                    // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we
                    // need to check both here so that in the case one is set and the other is not we still get the correct result.
                    if (connection()->hasInputShape())
                        windowContainsMouse = windowInteractsWithPosition(xcb_connection(), relPos, w, XCB_SHAPE_SK_INPUT);
                    if (windowContainsMouse && connection()->hasXShape())
                        windowContainsMouse = windowInteractsWithPosition(xcb_connection(), relPos, w, XCB_SHAPE_SK_BOUNDING);
                    if (!connection()->hasInputShape() && !connection()->hasXShape())
                        windowContainsMouse = true;
                    if (windowContainsMouse)
                        return w;
                }
            }

            xcb_query_tree_cookie_t cookie = xcb_query_tree (xcb_connection(), w);
            xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, 0);

            if (!reply)
                return 0;
            int nc = xcb_query_tree_children_length(reply);
            xcb_window_t *c = xcb_query_tree_children(reply);

            xcb_window_t r = 0;
            for (uint i = nc; !r && i--;)
                r = findRealWindow(pos - windowRect.topLeft(), c[i], md-1, ignoreNonXdndAwareWindows);

            free(reply);
            if (r)
                return r;

            // We didn't find a client window!  Just use the
            // innermost window.

            // No children!
            if (!windowContainsMouse)
                return 0;
            else
                return w;
        }
    }
    return 0;
}
示例#17
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;
}