From 6c27f4295b3cd24e08c1e6c2814e922f0c388a73 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 22 Jul 2018 22:05:11 +0200 Subject: [PATCH] client_manage(): Check that reparenting works (#2298) When a new client appears, we reparent its window into a window of our choice so that we can add decorations. However, windows can be difficult making the reparenting fail. For example, some snapshots of GTK+ set a parent-relative background, which means that its parent windows have to have the same depth as the window itself. This makes reparenting fail if transparency is used/supported. Make the failure mode... different, by checking if reparenting succeeded. If it failed, we print an error message and unmanage the window immediately. This means that those GTK+ windows just do not appear at all, instead of behaving weirdly. This idea of this patch came from i3. Related-to: https://github.com/awesomeWM/awesome/issues/2279 Signed-off-by: Uli Schlachter --- objects/client.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/objects/client.c b/objects/client.c index c7a0c8e8..e1c82e2d 100644 --- a/objects/client.c +++ b/objects/client.c @@ -1379,6 +1379,7 @@ client_update_properties(lua_State *L, int cidx, client_t *c) void client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_attributes_reply_t *wattr) { + xcb_void_cookie_t reparent_cookie; lua_State *L = globalconf_get_lua_State(); const uint32_t select_input_val[] = { CLIENT_SELECT_INPUT_EVENT_MASK }; @@ -1436,7 +1437,7 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_at globalconf.screen->root, XCB_CW_EVENT_MASK, no_event); - xcb_reparent_window(globalconf.connection, w, c->frame_window, 0, 0); + reparent_cookie = xcb_reparent_window_checked(globalconf.connection, w, c->frame_window, 0, 0); xcb_map_window(globalconf.connection, w); xcb_change_window_attributes(globalconf.connection, globalconf.screen->root, @@ -1531,6 +1532,16 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_at /* client is still on top of the stack; emit signal */ luaA_object_emit_signal(L, -1, "manage", 0); + + xcb_generic_error_t *error = xcb_request_check(globalconf.connection, reparent_cookie); + if (error != NULL) { + warn("Failed to manage window with name '%s', class '%s', instance '%s', because reparenting failed.", + NONULL(c->name), NONULL(c->class), NONULL(c->instance)); + event_handle((xcb_generic_event_t *) error); + p_delete(&error); + client_unmanage(c, true); + } + /* pop client */ lua_pop(L, 1); }