support for transients of groups
This commit is contained in:
parent
3cbf5bfa7c
commit
e6cc69ca04
3 changed files with 87 additions and 30 deletions
|
@ -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,16 +585,34 @@ 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue