/** 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);
/** 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; 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) { lua_State *L = globalconf_get_lua_State(); 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; } if(!client_resize(c, geometry, false)) /* ICCCM 4.1.5 / 4.2.3, if nothing was changed, send an event saying so */ client_send_configure(c); } else if (xembed_getbywin(&globalconf.embedded, ev->window)) { /* Ignore this so that systray icons cannot resize themselves. * We decide their size! */ } else event_handle_configurerequest_configure_window(ev); }