all repos — openbox @ e6cc69ca04f6b275f56e1e0feef731518e0709a3

openbox fork - make it a bit more like ryudo

support for transients of groups
Dana Jansens danakj@orodu.net
commit

e6cc69ca04f6b275f56e1e0feef731518e0709a3

parent

3cbf5bfa7c42c8dace6ca3f31fe48078eeb66382

3 files changed, 87 insertions(+), 30 deletions(-)

jump to
M openbox/client.copenbox/client.c

@@ -286,16 +286,30 @@ /* once the client is out of the list, update the struts to remove it's

influence */ screen_update_struts(); - /* tell our parent that we're gone */ - if (client->transient_for != NULL) + /* tell our parent(s) that we're gone */ + if (client->transient_for == TRAN_GROUP) { /* transient of group */ + GSList *it; + + for (it = client->group->members; it; it = it->next) + if (it->data != client) + ((Client*)it->data)->transients = + g_slist_remove(((Client*)it->data)->transients, client); + } else if (client->transient_for) { /* transient of window */ client->transient_for->transients = g_slist_remove(client->transient_for->transients, client); + } /* tell our transients that we're gone */ for (it = client->transients; it != NULL; it = it->next) { - ((Client*)it->data)->transient_for = NULL; - client_calc_layer(it->data); + if (((Client*)it->data)->transient_for != TRAN_GROUP) { + ((Client*)it->data)->transient_for = NULL; + client_calc_layer(it->data); + } } + + /* remove from its group */ + if (client->group) + group_remove(client->group, client); /* dispatch the unmapped event */ dispatch_client(Event_Client_Unmapped, client, 0, 0);

@@ -319,10 +333,6 @@ bad, since we will no longer be managing the window on restart */

if (client->iconic) XMapWindow(ob_display, client->window); } - - /* remoev from its group */ - if (client->group) - group_remove(client->group, client); /* free all data allocated in the client struct */ g_slist_free(client->transients);

@@ -560,15 +570,14 @@ self->transient = TRUE;

c = g_hash_table_lookup(client_map, &t); g_assert(c != self);/* if this happens then we need to check for it*/ - if (!c /*XXX: && _group*/) { + if (!c && self->group) { /* not transient to a client, see if it is transient for a group */ - if (/*t == _group->leader() || */ + if (t == self->group->leader || t == None || t == ob_root) { /* window is a transient for its group! */ - /* XXX: for now this is treated as non-transient. - this needs to be fixed! */ + c = TRAN_GROUP; } } } else

@@ -576,15 +585,33 @@ self->transient = FALSE;

/* if anything has changed... */ if (c != self->transient_for) { - if (self->transient_for) + if (self->transient_for == TRAN_GROUP) { /* transient of group */ + GSList *it; + + /* remove from old parents */ + for (it = self->group->members; it; it = it->next) + if (it->data != self) + ((Client*)it->data)->transients = + g_slist_remove(((Client*)it->data)->transients, self); + } else if (self->transient_for != NULL) { /* transient of window */ /* remove from old parent */ self->transient_for->transients = g_slist_remove(self->transient_for->transients, self); + } self->transient_for = c; - if (self->transient_for) + if (self->transient_for == TRAN_GROUP) { /* transient of group */ + GSList *it; + + /* add to new parents */ + for (it = self->group->members; it; it = it->next) + if (it->data != self) + ((Client*)it->data)->transients = + g_slist_append(((Client*)it->data)->transients, self); + } else if (self->transient_for != NULL) { /* transient of window */ /* add to new parent */ self->transient_for->transients = g_slist_append(self->transient_for->transients, self); + } } }

@@ -944,16 +971,22 @@

if (hints->flags & XUrgencyHint) ur = TRUE; - if (hints->flags & WindowGroupHint) { - if (hints->window_group != - (self->group ? self->group->leader : None)) { - /* remove from the old group if there was one */ - if (self->group != NULL) - group_remove(self->group, self); - self->group = group_add(hints->window_group, self); - } - } else /* no group! */ - self->group = None; + if (!(hints->flags & WindowGroupHint)) + hints->window_group = None; /* no group */ + /* did the group state change? */ + if (hints->window_group != (self->group ? self->group->leader : None)){ + /* remove from the old group if there was one */ + if (self->group != NULL) + group_remove(self->group, self); + if (hints->window_group != None) + self->group = group_add(hints->window_group, self); + + /* because the self->transient flag wont change from this call, + we don't need to update the window's type and such, only its + transient_for, and the transients lists of other windows in the + group may be affected */ + client_update_transient_for(self); + } if (hints->flags & IconPixmapHint) { client_update_kwm_icon(self);

@@ -1219,7 +1252,7 @@

/* are we fullscreen, or do we have a fullscreen transient parent? */ c = self; fs = FALSE; - while (c) { + while (c && c != TRAN_GROUP) { /* XXX do smthng with the TRAN_GROUP case?*/ if (c->fullscreen) { fs = TRUE; break;

@@ -1999,7 +2032,9 @@ ce.xclient.data.l[4] = 0l;

XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce); } +#ifdef DEBUG_FOCUS g_message("focusing %lx", self->window); +#endif /* Cause the FocusIn to come back to us. Important for desktop switches, since otherwise we'll have no FocusIn on the queue and send it off to
M openbox/client.hopenbox/client.h

@@ -9,6 +9,10 @@

struct Frame; struct Group; +/* The value in client.transient_for indicating it is a transient for its + group instead of for a single window */ +#define TRAN_GROUP ((void*)~0l) + /*! Holds an icon in ARGB format */ typedef struct Icon { unsigned long width, height;
M openbox/stacking.copenbox/stacking.c

@@ -2,6 +2,7 @@ #include "openbox.h"

#include "prop.h" #include "focus.h" #include "client.h" +#include "group.h" #include "frame.h" #include <glib.h>

@@ -85,12 +86,25 @@ GList *it;

g_assert(stacking_list != NULL); /* this would be bad */ - it = g_list_last(stacking_list); + if (client->modal && client->transient_for) { + if (client->transient_for == TRAN_GROUP) { + /* don't let a modal of the group lower below any other windows + in the group */ + for (it = stacking_list; it; it = it->next) { + GSList *sit; + Client *c = it->data; - if (client->modal && client->transient_for) { - /* don't let a modal window lower below its transient_for */ - it = g_list_find(stacking_list, client->transient_for); - g_assert(it != NULL); + for (sit = c->group->members; sit; sit = sit->next) + if (sit->data == it->data) break; + if (sit) break; /* got it */ + } + if (it == NULL) + goto lower_no_parent; + } else { + /* don't let a modal window lower below its transient_for */ + it = g_list_find(stacking_list, client->transient_for); + } + g_assert(it != NULL); wins[0] = (it == stacking_list ? focus_backup : ((Client*)it->prev->data)->frame->window);

@@ -100,6 +114,10 @@

stacking_list = g_list_remove(stacking_list, client); stacking_list = g_list_insert_before(stacking_list, it, client); } else { + lower_no_parent: + + it = g_list_last(stacking_list); + while (it != stacking_list) { Client *c = it->data; if (client->layer <= c->layer)