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 <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2018-07-22 22:05:11 +02:00 committed by Emmanuel Lepage Vallée
parent 3e24303f15
commit 6c27f4295b
1 changed files with 12 additions and 1 deletions

View File

@ -1379,6 +1379,7 @@ client_update_properties(lua_State *L, int cidx, client_t *c)
void void
client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_attributes_reply_t *wattr) 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(); lua_State *L = globalconf_get_lua_State();
const uint32_t select_input_val[] = { CLIENT_SELECT_INPUT_EVENT_MASK }; 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, globalconf.screen->root,
XCB_CW_EVENT_MASK, XCB_CW_EVENT_MASK,
no_event); 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_map_window(globalconf.connection, w);
xcb_change_window_attributes(globalconf.connection, xcb_change_window_attributes(globalconf.connection,
globalconf.screen->root, 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 */ /* client is still on top of the stack; emit signal */
luaA_object_emit_signal(L, -1, "manage", 0); 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 */ /* pop client */
lua_pop(L, 1); lua_pop(L, 1);
} }