Merge pull request #707 from psychon/bullet_proof_transient_for

Bullet proof transient_for
This commit is contained in:
Daniel Hahler 2016-02-28 22:09:04 +01:00
commit 43f485b6cf
3 changed files with 37 additions and 15 deletions

View File

@ -211,6 +211,32 @@ DO_CLIENT_SET_STRING_PROPERTY(role)
DO_CLIENT_SET_STRING_PROPERTY(machine) DO_CLIENT_SET_STRING_PROPERTY(machine)
#undef DO_CLIENT_SET_STRING_PROPERTY #undef DO_CLIENT_SET_STRING_PROPERTY
void
client_find_transient_for(client_t *c)
{
int counter;
client_t *tc, *tmp;
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++)
{
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 void
client_set_class_instance(lua_State *L, int cidx, const char *class, const char *instance) client_set_class_instance(lua_State *L, int cidx, const char *class, const char *instance)
{ {
@ -634,6 +660,11 @@ HANDLE_GEOM(height)
/* update all properties */ /* update all properties */
client_update_properties(L, -1, c); 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 */ /* Then check clients hints */
ewmh_client_check_hints(c); ewmh_client_check_hints(c);

View File

@ -121,6 +121,8 @@ struct client_t
uint32_t pid; uint32_t pid;
/** Window it is transient for */ /** Window it is transient for */
client_t *transient_for; client_t *transient_for;
/** Value of WM_TRANSIENT_FOR */
xcb_window_t transient_for_window;
/** Titelbar information */ /** Titelbar information */
struct { struct {
/** The size of this bar. */ /** The size of this bar. */
@ -181,6 +183,7 @@ void client_restore_enterleave_events(void);
void client_refresh_partial(client_t *, int16_t, int16_t, uint16_t, uint16_t); void client_refresh_partial(client_t *, int16_t, int16_t, uint16_t, uint16_t);
void client_class_setup(lua_State *); void client_class_setup(lua_State *);
void client_send_configure(client_t *); void client_send_configure(client_t *);
void client_find_transient_for(client_t *);
drawable_t *client_get_drawable(client_t *, int, int); drawable_t *client_get_drawable(client_t *, int, int);
drawable_t *client_get_drawable_offset(client_t *, int *, int *); drawable_t *client_get_drawable_offset(client_t *, int *, int *);

View File

@ -105,32 +105,20 @@ property_update_wm_transient_for(client_t *c, xcb_get_property_cookie_t cookie)
{ {
lua_State *L = globalconf_get_lua_State(); lua_State *L = globalconf_get_lua_State();
xcb_window_t trans; xcb_window_t trans;
int counter;
client_t *tc, *tmp;
if(!xcb_icccm_get_wm_transient_for_reply(globalconf.connection, if(!xcb_icccm_get_wm_transient_for_reply(globalconf.connection,
cookie, cookie,
&trans, NULL)) &trans, NULL))
return; return;
tmp = tc = client_getbywin(trans); c->transient_for_window = trans;
luaA_object_push(L, c); luaA_object_push(L, c);
client_set_type(L, -1, WINDOW_TYPE_DIALOG); client_set_type(L, -1, WINDOW_TYPE_DIALOG);
client_set_above(L, -1, false); 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); lua_pop(L, 1);
client_find_transient_for(c);
} }
xcb_get_property_cookie_t xcb_get_property_cookie_t