diff --git a/event.c b/event.c index 527a0f1a8..453654436 100644 --- a/event.c +++ b/event.c @@ -737,8 +737,8 @@ event_handle_mappingnotify(xcb_mapping_notify_event_t *ev) foreach(_c, globalconf.clients) { client_t *c = *_c; - xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->window, XCB_BUTTON_MASK_ANY); - xwindow_grabkeys(c->window, &c->keys); + xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->frame_window, XCB_BUTTON_MASK_ANY); + xwindow_grabkeys(c->frame_window, &c->keys); } } } @@ -747,6 +747,8 @@ static void event_handle_reparentnotify(xcb_reparent_notify_event_t *ev) { client_t *c; +#warning ugly, gotta do this properly + return 0; if((c = client_getbywin(ev->window))) client_unmanage(c); diff --git a/objects/client.c b/objects/client.c index c9e29b9cb..0af0c7aa5 100644 --- a/objects/client.c +++ b/objects/client.c @@ -227,7 +227,7 @@ client_t * client_getbywin(xcb_window_t w) { foreach(c, globalconf.clients) - if((*c)->window == w) + if((*c)->window == w || (*c)->frame_window == w) return *c; return NULL; @@ -313,7 +313,7 @@ client_ban(client_t *c) { if(!c->isbanned) { - xcb_unmap_window(globalconf.connection, c->window); + xcb_unmap_window(globalconf.connection, c->frame_window); c->isbanned = true; @@ -328,20 +328,32 @@ void client_ignore_enterleave_events(void) { foreach(c, globalconf.clients) + { xcb_change_window_attributes(globalconf.connection, (*c)->window, XCB_CW_EVENT_MASK, (const uint32_t []) { CLIENT_SELECT_INPUT_EVENT_MASK & ~(XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW) }); + xcb_change_window_attributes(globalconf.connection, + (*c)->frame_window, + XCB_CW_EVENT_MASK, + (const uint32_t []) { FRAME_SELECT_INPUT_EVENT_MASK & ~(XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW) }); + } } void client_restore_enterleave_events(void) { foreach(c, globalconf.clients) + { xcb_change_window_attributes(globalconf.connection, (*c)->window, XCB_CW_EVENT_MASK, (const uint32_t []) { CLIENT_SELECT_INPUT_EVENT_MASK }); + xcb_change_window_attributes(globalconf.connection, + (*c)->frame_window, + XCB_CW_EVENT_MASK, + (const uint32_t []) { FRAME_SELECT_INPUT_EVENT_MASK }); + } } /** Record that a client got focus. @@ -439,6 +451,7 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen, (uint32_t[]) { XCB_STACK_MODE_BELOW}); client_t *c = client_new(globalconf.L); + xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen); /* This cannot change, ever. */ c->phys_screen = phys_screen; @@ -446,6 +459,23 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen, c->isbanned = true; /* Store window */ c->window = w; + c->frame_window = xcb_generate_id(globalconf.connection); + xcb_create_window(globalconf.connection, s->root_depth, c->frame_window, s->root, + wgeom->x, wgeom->y, wgeom->width, wgeom->height, + wgeom->border_width, XCB_COPY_FROM_PARENT, s->root_visual, + XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY + | XCB_CW_WIN_GRAVITY | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, + (const uint32_t []) + { + globalconf.colors.bg.pixel, + globalconf.colors.bg.pixel, + XCB_GRAVITY_NORTH_WEST, + XCB_GRAVITY_NORTH_WEST, + 1, + FRAME_SELECT_INPUT_EVENT_MASK + }); + xcb_reparent_window(globalconf.connection, w, c->frame_window, 0, 0); + xcb_map_window(globalconf.connection, w); luaA_object_emit_signal(globalconf.L, -1, "property::window", 0); /* Duplicate client and push it in client list */ @@ -693,9 +723,11 @@ client_resize(client_t *c, area_t geometry, bool hints) client_ignore_enterleave_events(); xcb_configure_window(globalconf.connection, c->window, - XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y - | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, - (uint32_t[]) { geometry.x, geometry.y, geometry.width, geometry.height }); + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, + (uint32_t[]) { geometry.width, geometry.height }); + xcb_configure_window(globalconf.connection, c->frame_window, + XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, + (uint32_t[]) { geometry.x, geometry.y, geometry.width, geometry.height }); client_restore_enterleave_events(); @@ -934,7 +966,7 @@ client_unban(client_t *c) { if(c->isbanned) { - xcb_map_window(globalconf.connection, c->window); + xcb_map_window(globalconf.connection, c->frame_window); c->isbanned = false; } @@ -989,6 +1021,8 @@ client_unmanage(client_t *c) * after a restart anymore. */ xcb_change_save_set(globalconf.connection, XCB_SET_MODE_DELETE, c->window); + xcb_destroy_window(globalconf.connection, c->frame_window); + /* set client as invalid */ c->invalid = true; @@ -1651,8 +1685,8 @@ luaA_client_keys(lua_State *L) { luaA_key_array_set(L, 1, 2, keys); luaA_object_emit_signal(L, 1, "property::keys", 0); - xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->window, XCB_BUTTON_MASK_ANY); - xwindow_grabkeys(c->window, keys); + xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->frame_window, XCB_BUTTON_MASK_ANY); + xwindow_grabkeys(c->frame_window, keys); } return luaA_key_array_get(L, 1, keys); diff --git a/objects/client.h b/objects/client.h index 9baa2f86d..0f70f4cbc 100644 --- a/objects/client.h +++ b/objects/client.h @@ -31,10 +31,13 @@ #define CLIENT_SELECT_INPUT_EVENT_MASK (XCB_EVENT_MASK_STRUCTURE_NOTIFY \ | XCB_EVENT_MASK_PROPERTY_CHANGE \ - | XCB_EVENT_MASK_ENTER_WINDOW \ - | XCB_EVENT_MASK_LEAVE_WINDOW \ | XCB_EVENT_MASK_FOCUS_CHANGE) +#define FRAME_SELECT_INPUT_EVENT_MASK (XCB_EVENT_MASK_STRUCTURE_NOTIFY \ + | XCB_EVENT_MASK_ENTER_WINDOW \ + | XCB_EVENT_MASK_LEAVE_WINDOW \ + | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT) + /** Windows type */ typedef enum { diff --git a/objects/window.c b/objects/window.c index 78256165b..e24c1856d 100644 --- a/objects/window.c +++ b/objects/window.c @@ -28,6 +28,14 @@ LUA_CLASS_FUNCS(window, window_class) +static xcb_window_t +window_get(window_t *window) +{ + if (window->frame_window != XCB_NONE) + return window->frame_window; + return window->window; +} + static void window_wipe(window_t *window) { @@ -47,7 +55,7 @@ luaA_window_buttons(lua_State *L) { luaA_button_array_set(L, 1, 2, &window->buttons); luaA_object_emit_signal(L, 1, "property::buttons", 0); - xwindow_buttons_grab(window->window, &window->buttons); + xwindow_buttons_grab(window_get(window), &window->buttons); } return luaA_button_array_get(L, 1, &window->buttons); @@ -87,7 +95,7 @@ window_set_opacity(lua_State *L, int idx, double opacity) if(window->opacity != opacity) { window->opacity = opacity; - xwindow_set_opacity(window->window, opacity); + xwindow_set_opacity(window_get(window), opacity); luaA_object_emit_signal(L, idx, "property::opacity", 0); } } @@ -141,7 +149,7 @@ luaA_window_set_border_color(lua_State *L, window_t *window) if(color_name && xcolor_init_reply(xcolor_init_unchecked(&window->border_color, color_name, len))) { - xwindow_set_border_color(window->window, &window->border_color); + xwindow_set_border_color(window_get(window), &window->border_color); luaA_object_emit_signal(L, -3, "property::border_color", 0); } @@ -162,7 +170,7 @@ window_set_border_width(lua_State *L, int idx, int width) return; if(window->window) - xcb_configure_window(globalconf.connection, window->window, + xcb_configure_window(globalconf.connection, window_get(window), XCB_CONFIG_WINDOW_BORDER_WIDTH, (uint32_t[]) { width }); diff --git a/objects/window.h b/objects/window.h index 12a36d2e9..a409dd989 100644 --- a/objects/window.h +++ b/objects/window.h @@ -30,6 +30,8 @@ LUA_OBJECT_HEADER \ /** The X window number */ \ xcb_window_t window; \ + /** The frame window, might be XCB_NONE */ \ + xcb_window_t frame_window; \ /** Opacity */ \ double opacity; \ /** Strut */ \ diff --git a/stack.c b/stack.c index ed33b5ac0..0f3e218a1 100644 --- a/stack.c +++ b/stack.c @@ -96,9 +96,9 @@ stack_window_above(xcb_window_t w, xcb_window_t previous) static xcb_window_t stack_client_above(client_t *c, xcb_window_t previous) { - stack_window_above(c->window, previous); + stack_window_above(c->frame_window, previous); - previous = c->window; + previous = c->frame_window; /* stack transient window on top of their parents */ foreach(node, globalconf.stack)