/** Handle systray message. * \param ev The event. * \return 0 on no error. */ int systray_process_client_message(xcb_client_message_event_t *ev) { int screen_nbr = 0, ret = 0; xcb_get_geometry_cookie_t geom_c; xcb_get_geometry_reply_t *geom_r; xcb_screen_iterator_t iter; switch(ev->data.data32[1]) { case SYSTEM_TRAY_REQUEST_DOCK: geom_c = xcb_get_geometry_unchecked(globalconf.connection, ev->window); if(!(geom_r = xcb_get_geometry_reply(globalconf.connection, geom_c, NULL))) return -1; for(iter = xcb_setup_roots_iterator(xcb_get_setup(globalconf.connection)), screen_nbr = 0; iter.rem && iter.data->root != geom_r->root; xcb_screen_next (&iter), ++screen_nbr); p_delete(&geom_r); ret = systray_request_handle(ev->data.data32[2], screen_nbr, NULL); break; } return ret; }
void Client::updateState(xcb_ewmh_connection_t* ewmhConn) { xcb_connection_t* conn = ewmhConn->connection; xcb_get_geometry_cookie_t geomCookie; if (!mOwned) geomCookie = xcb_get_geometry_unchecked(conn, mWindow); const xcb_get_property_cookie_t normalHintsCookie = xcb_icccm_get_wm_normal_hints(conn, mWindow); const xcb_get_property_cookie_t leaderCookie = xcb_get_property(conn, 0, mWindow, Atoms::WM_CLIENT_LEADER, XCB_ATOM_WINDOW, 0, 1); const xcb_get_property_cookie_t transientCookie = xcb_icccm_get_wm_transient_for(conn, mWindow); const xcb_get_property_cookie_t hintsCookie = xcb_icccm_get_wm_hints(conn, mWindow); const xcb_get_property_cookie_t classCookie = xcb_icccm_get_wm_class(conn, mWindow); const xcb_get_property_cookie_t nameCookie = xcb_icccm_get_wm_name(conn, mWindow); const xcb_get_property_cookie_t protocolsCookie = xcb_icccm_get_wm_protocols(conn, mWindow, Atoms::WM_PROTOCOLS); const xcb_get_property_cookie_t strutCookie = xcb_ewmh_get_wm_strut(ewmhConn, mWindow); const xcb_get_property_cookie_t partialStrutCookie = xcb_ewmh_get_wm_strut_partial(ewmhConn, mWindow); const xcb_get_property_cookie_t stateCookie = xcb_ewmh_get_wm_state(ewmhConn, mWindow); const xcb_get_property_cookie_t typeCookie = xcb_ewmh_get_wm_window_type(ewmhConn, mWindow); const xcb_get_property_cookie_t pidCookie = xcb_ewmh_get_wm_pid(ewmhConn, mWindow); if (!mOwned) updateSize(conn, geomCookie); updateNormalHints(conn, normalHintsCookie); updateLeader(conn, leaderCookie); updateTransient(conn, transientCookie); updateHints(conn, hintsCookie); updateClass(conn, classCookie); updateName(conn, nameCookie); updateProtocols(conn, protocolsCookie); updateStrut(ewmhConn, strutCookie); updatePartialStrut(ewmhConn, partialStrutCookie); updateEwmhState(ewmhConn, stateCookie); updateWindowTypes(ewmhConn, typeCookie); updatePid(ewmhConn, pidCookie); }
/** * Sends the GetGeometry request. * @param drawable Drawable whose characteristics are sought. * @ingroup Ecore_X_Drawable_Group */ EAPI void ecore_x_drawable_geometry_get_prefetch(Ecore_X_Drawable drawable) { xcb_get_geometry_cookie_t cookie; if (drawable == 0) drawable = ((xcb_screen_t *)_ecore_xcb_screen)->root; cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, drawable); _ecore_xcb_cookie_cache(cookie.sequence); }
/** 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); }
static void towel_window_init_cairo(towel_window_t *win) { xcb_visualtype_t *vt; xcb_get_geometry_cookie_t cookie = xcb_get_geometry_unchecked(win->conn, win->id); xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply(win->conn, cookie, NULL); vt = xcb_aux_find_visual_by_id(win->screen, win->screen->root_visual); win->cs = cairo_xcb_surface_create(win->conn, win->id, vt, geo->width, geo->height); win->cr = cairo_create(win->cs); free(geo); }
/* Read the X window geometry and record it in the client structure */ void read_client_geometry(client_t *client) { xcb_get_geometry_cookie_t geometry_cookie; xcb_get_geometry_reply_t *geometry_reply; geometry_cookie = xcb_get_geometry_unchecked(wm_conf.connection, client->window); geometry_reply = xcb_get_geometry_reply(wm_conf.connection, geometry_cookie, NULL); if (geometry_reply) { client->rect.x = geometry_reply->x; client->rect.y = geometry_reply->y; client->rect.width = geometry_reply->width; client->rect.height = geometry_reply->height; client->border_width = geometry_reply->border_width; free(geometry_reply); } else { fprintf(stderr, " ! failed to get geometry geometry for window %u\n", client->window); } }
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 towel_window_t* towel_create_window(xcb_connection_t *conn) { /* Get screen setup and root window */ towel_window_t *win = calloc(1, sizeof(towel_window_t)); const xcb_setup_t *setup = xcb_get_setup(conn); xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); xcb_get_geometry_cookie_t geo_cookie; xcb_get_geometry_reply_t *geo; uint32_t mask = XCB_CW_EVENT_MASK; uint32_t values[] = {XCB_EVENT_MASK_EXPOSURE|XCB_EVENT_MASK_POINTER_MOTION}; win->conn = conn; win->screen = iter.data; geo_cookie = xcb_get_geometry_unchecked(conn, win->screen->root); geo = xcb_get_geometry_reply(win->conn, geo_cookie, NULL); win->x = 0; win->y = 0; win->width = geo->width; win->height = geo->height; free(geo); win->id = xcb_generate_id(conn); xcb_create_window(conn, XCB_COPY_FROM_PARENT, win->id, win->screen->root, win->x, win->y, win->width, win->height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, win->screen->root_visual, mask, values); xcb_flush(conn); towel_window_init_cairo(win); return win; }
/** Handle systray message. * \param ev The event. * \return 0 on no error. */ int systray_process_client_message(xcb_client_message_event_t *ev) { int ret = 0; xcb_get_geometry_cookie_t geom_c; xcb_get_geometry_reply_t *geom_r; switch(ev->data.data32[1]) { case SYSTEM_TRAY_REQUEST_DOCK: geom_c = xcb_get_geometry_unchecked(globalconf.connection, ev->window); if(!(geom_r = xcb_get_geometry_reply(globalconf.connection, geom_c, NULL))) return -1; if(globalconf.screen->root == geom_r->root) ret = systray_request_handle(ev->data.data32[2], NULL); p_delete(&geom_r); break; } return ret; }
/** 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); }
/* 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); } }
/** The configure event handler. * \param ev The event. */ static void event_handle_configurerequest(xcb_configure_request_event_t *ev) { client_t *c; if((c = client_getbywin(ev->window))) { area_t geometry = c->geometry; uint16_t bw = c->border_width; uint16_t tb_left = c->titlebar[CLIENT_TITLEBAR_LEFT].size; uint16_t tb_right = c->titlebar[CLIENT_TITLEBAR_RIGHT].size; uint16_t tb_top = c->titlebar[CLIENT_TITLEBAR_TOP].size; uint16_t tb_bottom = c->titlebar[CLIENT_TITLEBAR_BOTTOM].size; uint16_t deco_left = bw + tb_left; uint16_t deco_right = bw + tb_right; uint16_t deco_top = bw + tb_top; uint16_t deco_bottom = bw + tb_bottom; int16_t diff_w = 0, diff_h = 0, diff_border = 0; lua_State *L = globalconf_get_lua_State(); if(ev->value_mask & XCB_CONFIG_WINDOW_X) { int16_t diff = 0; geometry.x = ev->x; xwindow_translate_for_gravity(c->size_hints.win_gravity, deco_left, 0, deco_right, 0, &diff, NULL); geometry.x += diff; } if(ev->value_mask & XCB_CONFIG_WINDOW_Y) { int16_t diff = 0; geometry.y = ev->y; xwindow_translate_for_gravity(c->size_hints.win_gravity, 0, deco_top, 0, deco_bottom, NULL, &diff); geometry.y += diff; } if(ev->value_mask & XCB_CONFIG_WINDOW_WIDTH) { uint16_t old_w = geometry.width; geometry.width = ev->width; /* The ConfigureRequest specifies the size of the client window, we want the frame */ geometry.width += tb_left + tb_right; diff_w = geometry.width - old_w; } if(ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { uint16_t old_h = geometry.height; geometry.height = ev->height; /* The ConfigureRequest specifies the size of the client window, we want the frame */ geometry.height += tb_top + tb_bottom; diff_h = geometry.height - old_h; } if(ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) { diff_border = ev->border_width - bw; diff_h += diff_border; diff_w += diff_border; luaA_object_push(L, c); window_set_border_width(L, -1, ev->border_width); lua_pop(L, 1); } /* If the client resizes without moving itself, apply window gravity */ if(c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY) { int16_t diff_x = 0, diff_y = 0; xwindow_translate_for_gravity(c->size_hints.win_gravity, diff_border, diff_border, diff_w, diff_h, &diff_x, &diff_y); if(!(ev->value_mask & XCB_CONFIG_WINDOW_X)) geometry.x += diff_x; if(!(ev->value_mask & XCB_CONFIG_WINDOW_Y)) geometry.y += diff_y; } c->got_configure_request = true; /* Request the changes to be applied */ luaA_object_push(L, c); lua_pushstring(L, "ewmh"); /* context */ lua_newtable(L); /* props */ /* area, it needs to be directly in the `hints` table to comply with the "protocol" */ lua_pushstring(L, "x"); lua_pushinteger(L, geometry.x); lua_rawset(L, -3); lua_pushstring(L, "y"); lua_pushinteger(L, geometry.y); lua_rawset(L, -3); lua_pushstring(L, "width"); lua_pushinteger(L, geometry.width); lua_rawset(L, -3); lua_pushstring(L, "height"); lua_pushinteger(L, geometry.height); lua_rawset(L, -3); luaA_object_emit_signal(L, -3, "request::geometry", 2); lua_pop(L, 1); } else if (xembed_getbywin(&globalconf.embedded, ev->window)) { /* Ignore this so that systray icons cannot resize themselves. * We decide their size! * However, Xembed says that we act like a WM to the embedded window and * thus we have to send a synthetic configure notify informing the * window that its configure request was denied. */ xcb_get_geometry_cookie_t geom_cookie = xcb_get_geometry_unchecked(globalconf.connection, ev->window); xcb_translate_coordinates_cookie_t coords_cookie = xcb_translate_coordinates_unchecked(globalconf.connection, ev->window, globalconf.screen->root, 0, 0); xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(globalconf.connection, geom_cookie, NULL); xcb_translate_coordinates_reply_t *coords = xcb_translate_coordinates_reply(globalconf.connection, coords_cookie, NULL); if (geom && coords) { xwindow_configure(ev->window, (area_t) { .x = coords->dst_x, .y = coords->dst_y, .width = geom->width, .height = geom->height }, 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; }
} #include "config.h" /* EVENT HANDLERS [!!] {{{ */ /* event_map_request - map request handler {{{ */ static int event_map_request(void *data __attribute__ ((unused)), xcb_connection_t *connection, xcb_map_request_event_t *ev) { xcb_get_geometry_cookie_t geom_cookie; xcb_get_geometry_reply_t *geom_reply; geom_cookie = xcb_get_geometry_unchecked(connection, ev->window); geom_reply = xcb_get_geometry_reply(connection, geom_cookie, NULL); client_manage(ev->window, geom_reply); bar_draw(rootconf.bar); return 0; } /* }}} */ /* event_enter_notify - enter notify event handler {{{ */ static int event_enter_notify(void *data __attribute__ ((unused)), xcb_connection_t *connection, xcb_enter_notify_event_t *ev) {
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}}});