/* * 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); }
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); }
/* * 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; }
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; }
/* 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); }
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; }
/** 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); }
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); }
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 }
/* * 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; }
/* 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; }
/** 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); }
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); }
/** 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); } }
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; }
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; }