support for transients of groups

This commit is contained in:
Dana Jansens 2003-04-07 08:43:33 +00:00
parent 3cbf5bfa7c
commit e6cc69ca04
3 changed files with 87 additions and 30 deletions

View file

@ -286,16 +286,30 @@ void client_unmanage(Client *client)
influence */ influence */
screen_update_struts(); screen_update_struts();
/* tell our parent that we're gone */ /* tell our parent(s) that we're gone */
if (client->transient_for != NULL) 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 = client->transient_for->transients =
g_slist_remove(client->transient_for->transients, client); g_slist_remove(client->transient_for->transients, client);
}
/* tell our transients that we're gone */ /* tell our transients that we're gone */
for (it = client->transients; it != NULL; it = it->next) { for (it = client->transients; it != NULL; it = it->next) {
if (((Client*)it->data)->transient_for != TRAN_GROUP) {
((Client*)it->data)->transient_for = NULL; ((Client*)it->data)->transient_for = NULL;
client_calc_layer(it->data); client_calc_layer(it->data);
} }
}
/* remove from its group */
if (client->group)
group_remove(client->group, client);
/* dispatch the unmapped event */ /* dispatch the unmapped event */
dispatch_client(Event_Client_Unmapped, client, 0, 0); dispatch_client(Event_Client_Unmapped, client, 0, 0);
@ -320,10 +334,6 @@ void client_unmanage(Client *client)
XMapWindow(ob_display, client->window); 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 */ /* free all data allocated in the client struct */
g_slist_free(client->transients); g_slist_free(client->transients);
for (j = 0; j < client->nicons; ++j) for (j = 0; j < client->nicons; ++j)
@ -560,15 +570,14 @@ void client_update_transient_for(Client *self)
c = g_hash_table_lookup(client_map, &t); c = g_hash_table_lookup(client_map, &t);
g_assert(c != self);/* if this happens then we need to check for it*/ 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 /* not transient to a client, see if it is transient for a
group */ group */
if (/*t == _group->leader() || */ if (t == self->group->leader ||
t == None || t == None ||
t == ob_root) { t == ob_root) {
/* window is a transient for its group! */ /* window is a transient for its group! */
/* XXX: for now this is treated as non-transient. c = TRAN_GROUP;
this needs to be fixed! */
} }
} }
} else } else
@ -576,17 +585,35 @@ void client_update_transient_for(Client *self)
/* if anything has changed... */ /* if anything has changed... */
if (c != self->transient_for) { 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 */ /* remove from old parent */
self->transient_for->transients = self->transient_for->transients =
g_slist_remove(self->transient_for->transients, self); g_slist_remove(self->transient_for->transients, self);
}
self->transient_for = c; 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 */ /* add to new parent */
self->transient_for->transients = self->transient_for->transients =
g_slist_append(self->transient_for->transients, self); g_slist_append(self->transient_for->transients, self);
} }
} }
}
static void client_get_mwm_hints(Client *self) static void client_get_mwm_hints(Client *self)
{ {
@ -944,16 +971,22 @@ void client_update_wmhints(Client *self)
if (hints->flags & XUrgencyHint) if (hints->flags & XUrgencyHint)
ur = TRUE; ur = TRUE;
if (hints->flags & WindowGroupHint) { if (!(hints->flags & WindowGroupHint))
if (hints->window_group != hints->window_group = None; /* no group */
(self->group ? self->group->leader : None)) { /* did the group state change? */
if (hints->window_group != (self->group ? self->group->leader : None)){
/* remove from the old group if there was one */ /* remove from the old group if there was one */
if (self->group != NULL) if (self->group != NULL)
group_remove(self->group, self); group_remove(self->group, self);
if (hints->window_group != None)
self->group = group_add(hints->window_group, self); 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);
} }
} else /* no group! */
self->group = None;
if (hints->flags & IconPixmapHint) { if (hints->flags & IconPixmapHint) {
client_update_kwm_icon(self); client_update_kwm_icon(self);
@ -1219,7 +1252,7 @@ void client_calc_layer(Client *self)
/* are we fullscreen, or do we have a fullscreen transient parent? */ /* are we fullscreen, or do we have a fullscreen transient parent? */
c = self; c = self;
fs = FALSE; fs = FALSE;
while (c) { while (c && c != TRAN_GROUP) { /* XXX do smthng with the TRAN_GROUP case?*/
if (c->fullscreen) { if (c->fullscreen) {
fs = TRUE; fs = TRUE;
break; break;
@ -1999,7 +2032,9 @@ gboolean client_focus(Client *self)
XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce); XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce);
} }
#ifdef DEBUG_FOCUS
g_message("focusing %lx", self->window); g_message("focusing %lx", self->window);
#endif
/* Cause the FocusIn to come back to us. Important for desktop switches, /* 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 since otherwise we'll have no FocusIn on the queue and send it off to

View file

@ -9,6 +9,10 @@
struct Frame; struct Frame;
struct Group; 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 */ /*! Holds an icon in ARGB format */
typedef struct Icon { typedef struct Icon {
unsigned long width, height; unsigned long width, height;

View file

@ -2,6 +2,7 @@
#include "prop.h" #include "prop.h"
#include "focus.h" #include "focus.h"
#include "client.h" #include "client.h"
#include "group.h"
#include "frame.h" #include "frame.h"
#include <glib.h> #include <glib.h>
@ -85,11 +86,24 @@ void stacking_lower(Client *client)
g_assert(stacking_list != NULL); /* this would be bad */ g_assert(stacking_list != NULL); /* this would be bad */
it = g_list_last(stacking_list);
if (client->modal && client->transient_for) { 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;
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 */ /* don't let a modal window lower below its transient_for */
it = g_list_find(stacking_list, client->transient_for); it = g_list_find(stacking_list, client->transient_for);
}
g_assert(it != NULL); g_assert(it != NULL);
wins[0] = (it == stacking_list ? focus_backup : wins[0] = (it == stacking_list ? focus_backup :
@ -100,6 +114,10 @@ void stacking_lower(Client *client)
stacking_list = g_list_remove(stacking_list, client); stacking_list = g_list_remove(stacking_list, client);
stacking_list = g_list_insert_before(stacking_list, it, client); stacking_list = g_list_insert_before(stacking_list, it, client);
} else { } else {
lower_no_parent:
it = g_list_last(stacking_list);
while (it != stacking_list) { while (it != stacking_list) {
Client *c = it->data; Client *c = it->data;
if (client->layer <= c->layer) if (client->layer <= c->layer)