From 9907f804b2851d49972a7c6d2a2be860b85a7345 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Mon, 22 Feb 2016 21:02:47 +0100 Subject: [PATCH 1/2] Refactor setting of c->transient_for This creates a new helper function for setting the transient_for property of a client. This is a preparation for a following commit. No behaviour changes intended. Signed-off-by: Uli Schlachter --- objects/client.c | 26 ++++++++++++++++++++++++++ objects/client.h | 1 + property.c | 18 ++---------------- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/objects/client.c b/objects/client.c index e5fd066bf..d193661a3 100644 --- a/objects/client.c +++ b/objects/client.c @@ -211,6 +211,32 @@ DO_CLIENT_SET_STRING_PROPERTY(role) DO_CLIENT_SET_STRING_PROPERTY(machine) #undef DO_CLIENT_SET_STRING_PROPERTY +void +client_find_transient_for(client_t *c, xcb_window_t trans) +{ + int counter; + client_t *tc, *tmp; + + tmp = tc = client_getbywin(trans); + + /* Verify that there are no loops in the transient_for relation after we are done */ + for(counter = 0; tmp != NULL && counter <= globalconf.stack.len; counter++) + { + if (tmp == c) + /* We arrived back at the client we started from, so there is a loop */ + counter = globalconf.stack.len+1; + tmp = tmp->transient_for; + } + if (counter <= globalconf.stack.len) + { + lua_State *L = globalconf_get_lua_State(); + + luaA_object_push(L, c); + client_set_transient_for(L, -1, tc); + lua_pop(L, 1); + } +} + void client_set_class_instance(lua_State *L, int cidx, const char *class, const char *instance) { diff --git a/objects/client.h b/objects/client.h index 86a28c9c2..c330bc123 100644 --- a/objects/client.h +++ b/objects/client.h @@ -181,6 +181,7 @@ void client_restore_enterleave_events(void); void client_refresh_partial(client_t *, int16_t, int16_t, uint16_t, uint16_t); void client_class_setup(lua_State *); void client_send_configure(client_t *); +void client_find_transient_for(client_t *, xcb_window_t); drawable_t *client_get_drawable(client_t *, int, int); drawable_t *client_get_drawable_offset(client_t *, int *, int *); diff --git a/property.c b/property.c index 8069884ca..0aab8e4a6 100644 --- a/property.c +++ b/property.c @@ -105,32 +105,18 @@ property_update_wm_transient_for(client_t *c, xcb_get_property_cookie_t cookie) { lua_State *L = globalconf_get_lua_State(); xcb_window_t trans; - int counter; - client_t *tc, *tmp; if(!xcb_icccm_get_wm_transient_for_reply(globalconf.connection, cookie, &trans, NULL)) return; - tmp = tc = client_getbywin(trans); - luaA_object_push(L, c); client_set_type(L, -1, WINDOW_TYPE_DIALOG); client_set_above(L, -1, false); - - /* Verify that there are no loops in the transient_for relation after we are done */ - for(counter = 0; tmp != NULL && counter <= globalconf.stack.len; counter++) - { - if (tmp == c) - /* We arrived back at the client we started from, so there is a loop */ - counter = globalconf.stack.len+1; - tmp = tmp->transient_for; - } - if (counter <= globalconf.stack.len) - client_set_transient_for(L, -1, tc); - lua_pop(L, 1); + + client_find_transient_for(c, trans); } xcb_get_property_cookie_t From d598a4115a0285bb18e24fcc83505a8476cea286 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Mon, 22 Feb 2016 21:09:25 +0100 Subject: [PATCH 2/2] Update transient_for when a new window appears When we manage the transient before the main window, the client object's .transient_for property would stay nil. This happens because the property points to a window which we don't know (yet) and thus is ignored. Fix this by remembering the value of WM_TRANSIENT_FOR and checking in client_manage() if the new client is the "missing window we did not find before". Fixes: https://github.com/awesomeWM/awesome/issues/181 Signed-off-by: Uli Schlachter --- objects/client.c | 9 +++++++-- objects/client.h | 4 +++- property.c | 4 +++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/objects/client.c b/objects/client.c index d193661a3..e9e3d8333 100644 --- a/objects/client.c +++ b/objects/client.c @@ -212,12 +212,12 @@ DO_CLIENT_SET_STRING_PROPERTY(machine) #undef DO_CLIENT_SET_STRING_PROPERTY void -client_find_transient_for(client_t *c, xcb_window_t trans) +client_find_transient_for(client_t *c) { int counter; client_t *tc, *tmp; - tmp = tc = client_getbywin(trans); + tmp = tc = client_getbywin(c->transient_for_window); /* Verify that there are no loops in the transient_for relation after we are done */ for(counter = 0; tmp != NULL && counter <= globalconf.stack.len; counter++) @@ -660,6 +660,11 @@ HANDLE_GEOM(height) /* update all properties */ client_update_properties(L, -1, c); + /* check if this is a TRANSIENT_FOR of another client */ + foreach(oc, globalconf.clients) + if ((*oc)->transient_for_window == w) + client_find_transient_for(*oc); + /* Then check clients hints */ ewmh_client_check_hints(c); diff --git a/objects/client.h b/objects/client.h index c330bc123..f921646e8 100644 --- a/objects/client.h +++ b/objects/client.h @@ -121,6 +121,8 @@ struct client_t uint32_t pid; /** Window it is transient for */ client_t *transient_for; + /** Value of WM_TRANSIENT_FOR */ + xcb_window_t transient_for_window; /** Titelbar information */ struct { /** The size of this bar. */ @@ -181,7 +183,7 @@ void client_restore_enterleave_events(void); void client_refresh_partial(client_t *, int16_t, int16_t, uint16_t, uint16_t); void client_class_setup(lua_State *); void client_send_configure(client_t *); -void client_find_transient_for(client_t *, xcb_window_t); +void client_find_transient_for(client_t *); drawable_t *client_get_drawable(client_t *, int, int); drawable_t *client_get_drawable_offset(client_t *, int *, int *); diff --git a/property.c b/property.c index 0aab8e4a6..d48747c19 100644 --- a/property.c +++ b/property.c @@ -111,12 +111,14 @@ property_update_wm_transient_for(client_t *c, xcb_get_property_cookie_t cookie) &trans, NULL)) return; + c->transient_for_window = trans; + luaA_object_push(L, c); client_set_type(L, -1, WINDOW_TYPE_DIALOG); client_set_above(L, -1, false); lua_pop(L, 1); - client_find_transient_for(c, trans); + client_find_transient_for(c); } xcb_get_property_cookie_t