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 */
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) {
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);
@ -320,10 +334,6 @@ void client_unmanage(Client *client)
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);
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);
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,17 +585,35 @@ void client_update_transient_for(Client *self)
/* 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);
}
}
}
static void client_get_mwm_hints(Client *self)
{
@ -944,16 +971,22 @@ void client_update_wmhints(Client *self)
if (hints->flags & XUrgencyHint)
ur = TRUE;
if (hints->flags & WindowGroupHint) {
if (hints->window_group !=
(self->group ? self->group->leader : 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);
}
} else /* no group! */
self->group = None;
if (hints->flags & IconPixmapHint) {
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? */
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 @@ gboolean client_focus(Client *self)
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

View file

@ -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;

View file

@ -2,6 +2,7 @@
#include "prop.h"
#include "focus.h"
#include "client.h"
#include "group.h"
#include "frame.h"
#include <glib.h>
@ -85,11 +86,24 @@ void stacking_lower(Client *client)
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;
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 :
@ -100,6 +114,10 @@ void stacking_lower(Client *client)
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)