/* * This sets up the DAMAGE extentsion to receive damage events on all * child windows * */ static void set_up_damage_notifications(xcb_connection_t *conn, xcb_screen_t *scr) { xcb_damage_query_version_unchecked(conn, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION); dam_ext_data = xcb_get_extension_data(conn, &xcb_damage_id); xcb_query_tree_reply_t *reply = xcb_query_tree_reply(conn, xcb_query_tree(conn, scr->root), NULL); xcb_window_t *children = xcb_query_tree_children(reply); xcb_get_window_attributes_cookie_t *attribs = (xcb_get_window_attributes_cookie_t *)malloc( sizeof(xcb_get_window_attributes_cookie_t) * reply->children_len); if (!attribs) { errx(EXIT_FAILURE, "Failed to allocate memory"); } for (int i = 0; i < reply->children_len; ++i) { attribs[i] = xcb_get_window_attributes_unchecked(conn, children[i]); } for (int i = 0; i < reply->children_len; ++i) { /* Get attributes to check if input-only window */ xcb_get_window_attributes_reply_t *attrib = xcb_get_window_attributes_reply(conn, attribs[i], NULL); create_damage(conn, children[i], attrib); } free(attribs); free(reply); }
void X11XRenderBackend::init(bool createOverlay) { if (m_front != XCB_RENDER_PICTURE_NONE) xcb_render_free_picture(connection(), m_front); bool haveOverlay = createOverlay ? m_overlayWindow->create() : (m_overlayWindow->window() != XCB_WINDOW_NONE); if (haveOverlay) { m_overlayWindow->setup(XCB_WINDOW_NONE); ScopedCPointer<xcb_get_window_attributes_reply_t> attribs(xcb_get_window_attributes_reply(connection(), xcb_get_window_attributes_unchecked(connection(), m_overlayWindow->window()), NULL)); if (!attribs) { setFailed("Failed getting window attributes for overlay window"); return; } m_format = XRenderUtils::findPictFormat(attribs->visual); if (m_format == 0) { setFailed("Failed to find XRender format for overlay window"); return; } m_front = xcb_generate_id(connection()); xcb_render_create_picture(connection(), m_front, m_overlayWindow->window(), m_format, 0, NULL); } else { // create XRender picture for the root window m_format = XRenderUtils::findPictFormat(defaultScreen()->root_visual); if (m_format == 0) { setFailed("Failed to find XRender format for root window"); return; // error } m_front = xcb_generate_id(connection()); const uint32_t values[] = {XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS}; xcb_render_create_picture(connection(), m_front, rootWindow(), m_format, XCB_RENDER_CP_SUBWINDOW_MODE, values); } createBuffer(); }
int handle_map_request_event(void *data, xcb_connection_t *c, xcb_map_request_event_t *event) { xcb_get_window_attributes_cookie_t win_attrs_cookie; xcb_get_window_attributes_reply_t *win_attrs_reply; win_attrs_cookie = xcb_get_window_attributes_unchecked(c, event->window); win_attrs_reply = xcb_get_window_attributes_reply(c, win_attrs_cookie, NULL); if (!win_attrs_reply) { fprintf(stderr, "map request: failed to get window attributes\n"); return -1; } if (win_attrs_reply->override_redirect) { fprintf(stderr, "map request: window has override redirect set - ignoring map request\n"); return 0; } client_t *client = NULL; client = find_client(event->window); if (!client) client = manage_window(event->window); xcb_map_window(c, event->window); run_arrange_hook(); free(win_attrs_reply); return 0; }
/** The map request event handler. * \param ev The event. */ static void event_handle_maprequest(xcb_map_request_event_t *ev) { client_t *c; xcb_get_window_attributes_cookie_t wa_c; xcb_get_window_attributes_reply_t *wa_r; xcb_get_geometry_cookie_t geom_c; xcb_get_geometry_reply_t *geom_r; wa_c = xcb_get_window_attributes_unchecked(globalconf.connection, ev->window); if(!(wa_r = xcb_get_window_attributes_reply(globalconf.connection, wa_c, NULL))) return; if(wa_r->override_redirect) goto bailout; if(xembed_getbywin(&globalconf.embedded, ev->window)) { xcb_map_window(globalconf.connection, ev->window); xembed_window_activate(globalconf.connection, ev->window); } else if((c = client_getbywin(ev->window))) { /* Check that it may be visible, but not asked to be hidden */ if(client_on_selected_tags(c) && !c->hidden) { lua_State *L = globalconf_get_lua_State(); luaA_object_push(L, c); client_set_minimized(L, -1, false); lua_pop(L, 1); /* it will be raised, so just update ourself */ client_raise(c); } } else { geom_c = xcb_get_geometry_unchecked(globalconf.connection, ev->window); if(!(geom_r = xcb_get_geometry_reply(globalconf.connection, geom_c, NULL))) { goto bailout; } client_manage(ev->window, geom_r, wa_r); p_delete(&geom_r); } bailout: p_delete(&wa_r); }
int add_winvec(struct window **list, xcb_window_t wid[], int len) { xcb_get_window_attributes_cookie_t ack[len]; xcb_get_geometry_cookie_t gck[len]; struct window *w; int i, n = 0; for (i = 0; i < len; ++i) { ack[i] = xcb_get_window_attributes_unchecked(X, wid[i]); gck[i] = xcb_get_geometry_unchecked(X, wid[i]); } for (i = 0; i < len; ++i) { xcb_get_window_attributes_reply_t *ar; xcb_get_geometry_reply_t *gr; if ((w = add_win(list, wid[i])) != NULL) { ar = xcb_get_window_attributes_reply(X, ack[i], NULL); gr = xcb_get_geometry_reply(X, gck[i], NULL); if (ar && gr) { w->visual = ar->visual; w->_class = ar->_class; w->map_state = ar->map_state; w->x = gr->x; w->y = gr->y; w->width = gr->width; w->height = gr->height; w->border_width = gr->border_width; free(ar); free(gr); ++n; } else { if (ar) free(ar); if (gr) free(gr); remove_win(list, w); continue; } } } debugf("add_winvec: added %d of %d windows to stack\n", n, len); return n; }
static void handle_map_request(xcb_map_request_event_t *e) { xcb_get_window_attributes_reply_t *reply; struct client_t *c; struct workspace_t *ws; NIL_LOG("event: map request win=%d", e->window); reply = xcb_get_window_attributes_reply(nil_.con, xcb_get_window_attributes_unchecked(nil_.con, e->window), 0); if (!reply) { NIL_ERR("no reply %d", e->window); return; } if (reply->override_redirect) { NIL_ERR("override_redirect %d", e->window); free(reply); return; } free(reply); c = find_client(e->window, &ws); if (!c) { NIL_ERR("no client %d", e->window); return; } init_client(c); NIL_SET_FLAG(c->flags, CLIENT_DISPLAY); if (!NIL_HAS_FLAG(c->flags, CLIENT_FLOAT)) { /* only rearrange if it's not float */ arrange_ws(ws); } if (check_client_size(c)) { /* fix window size if needed */ update_client_geom(c); } config_client(c); if (ws == &nil_.ws[nil_.ws_idx]) { xcb_map_window(nil_.con, c->win); xcb_set_input_focus(nil_.con, XCB_INPUT_FOCUS_POINTER_ROOT, c->win, XCB_CURRENT_TIME); } xcb_flush(nil_.con); }
void FdoSelectionManager::addDamageWatch(xcb_window_t client) { qCDebug(SNIPROXY) << "adding damage watch for " << client; xcb_connection_t *c = QX11Info::connection(); const auto attribsCookie = xcb_get_window_attributes_unchecked(c, client); auto damageId = xcb_generate_id(c); m_damageWatches[client] = damageId; xcb_damage_create(c, damageId, client, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> attr(xcb_get_window_attributes_reply(c, attribsCookie, Q_NULLPTR)); uint32_t events = XCB_EVENT_MASK_STRUCTURE_NOTIFY; if (!attr.isNull()) { events = events | attr->your_event_mask; } // the event mask will not be removed again. We cannot track whether another component also needs STRUCTURE_NOTIFY (e.g. KWindowSystem). // if we would remove the event mask again, other areas will break. xcb_change_window_attributes(c, client, XCB_CW_EVENT_MASK, &events); }
/* 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, 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); } }
QPixmap QXcbScreen::grabWindow(WId window, int x, int y, int width, int height) const { if (width == 0 || height == 0) return QPixmap(); // TODO: handle multiple screens QXcbScreen *screen = const_cast<QXcbScreen *>(this); xcb_window_t root = screen->root(); if (window == 0) window = root; xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry_unchecked(xcb_connection(), window); xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(xcb_connection(), geometry_cookie, NULL); if (!reply) { return QPixmap(); } if (width < 0) width = reply->width - x; if (height < 0) height = reply->height - y; geometry_cookie = xcb_get_geometry_unchecked(xcb_connection(), root); xcb_get_geometry_reply_t *root_reply = xcb_get_geometry_reply(xcb_connection(), geometry_cookie, NULL); if (!root_reply) { free(reply); return QPixmap(); } if (reply->depth == root_reply->depth) { // if the depth of the specified window and the root window are the // same, grab pixels from the root window (so that we get the any // overlapping windows and window manager frames) // map x and y to the root window xcb_translate_coordinates_cookie_t translate_cookie = xcb_translate_coordinates_unchecked(xcb_connection(), window, root, x, y); xcb_translate_coordinates_reply_t *translate_reply = xcb_translate_coordinates_reply(xcb_connection(), translate_cookie, NULL); if (!translate_reply) { free(reply); free(root_reply); return QPixmap(); } x = translate_reply->dst_x; y = translate_reply->dst_y; window = root; free(translate_reply); free(reply); reply = root_reply; } else { free(root_reply); root_reply = 0; } xcb_get_window_attributes_reply_t *attributes_reply = xcb_get_window_attributes_reply(xcb_connection(), xcb_get_window_attributes_unchecked(xcb_connection(), window), NULL); if (!attributes_reply) { free(reply); return QPixmap(); } const xcb_visualtype_t *visual = screen->visualForId(attributes_reply->visual); free(attributes_reply); xcb_pixmap_t pixmap = xcb_generate_id(xcb_connection()); xcb_create_pixmap(xcb_connection(), reply->depth, pixmap, window, width, height); uint32_t gc_value_mask = XCB_GC_SUBWINDOW_MODE; uint32_t gc_value_list[] = { XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS }; xcb_gcontext_t gc = xcb_generate_id(xcb_connection()); xcb_create_gc(xcb_connection(), gc, pixmap, gc_value_mask, gc_value_list); xcb_copy_area(xcb_connection(), window, pixmap, gc, x, y, 0, 0, width, height); QPixmap result = qt_xcb_pixmapFromXPixmap(connection(), pixmap, width, height, reply->depth, visual); free(reply); xcb_free_gc(xcb_connection(), gc); xcb_free_pixmap(xcb_connection(), pixmap); return result; }
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}}});
/** 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); }
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; }