add client_search_top_transient.
keep transients all on the same desktop together. use client_search_top_transient where possible in client.c
This commit is contained in:
parent
d2a628a487
commit
0719843c68
2 changed files with 128 additions and 98 deletions
220
openbox/client.c
220
openbox/client.c
|
@ -1494,8 +1494,8 @@ static StackLayer calc_layer(Client *self)
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calc_recursive(Client *self, Client *orig, StackLayer l,
|
static void client_calc_layer_recursive(Client *self, Client *orig,
|
||||||
gboolean raised)
|
StackLayer l, gboolean raised)
|
||||||
{
|
{
|
||||||
StackLayer old, own;
|
StackLayer old, own;
|
||||||
GSList *it;
|
GSList *it;
|
||||||
|
@ -1505,7 +1505,8 @@ static void calc_recursive(Client *self, Client *orig, StackLayer l,
|
||||||
self->layer = l > own ? l : own;
|
self->layer = l > own ? l : own;
|
||||||
|
|
||||||
for (it = self->transients; it; it = it->next)
|
for (it = self->transients; it; it = it->next)
|
||||||
calc_recursive(it->data, orig, l, raised ? raised : l != old);
|
client_calc_layer_recursive(it->data, orig,
|
||||||
|
l, raised ? raised : l != old);
|
||||||
|
|
||||||
if (!raised && l != old)
|
if (!raised && l != old)
|
||||||
if (orig->frame) { /* only restack if the original window is managed */
|
if (orig->frame) { /* only restack if the original window is managed */
|
||||||
|
@ -1523,24 +1524,11 @@ void client_calc_layer(Client *self)
|
||||||
orig = self;
|
orig = self;
|
||||||
|
|
||||||
/* transients take on the layer of their parents */
|
/* transients take on the layer of their parents */
|
||||||
if (self->transient_for) {
|
self = client_search_top_transient(self);
|
||||||
if (self->transient_for != TRAN_GROUP) {
|
|
||||||
self = self->transient_for;
|
|
||||||
} else {
|
|
||||||
GSList *it;
|
|
||||||
|
|
||||||
for (it = self->group->members; it; it = it->next)
|
|
||||||
if (it->data != self &&
|
|
||||||
!((Client*)it->data)->transient_for) {
|
|
||||||
self = it->data;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
l = calc_layer(self);
|
l = calc_layer(self);
|
||||||
|
|
||||||
calc_recursive(self, orig, l, FALSE);
|
client_calc_layer_recursive(self, orig, l, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean client_should_show(Client *self)
|
gboolean client_should_show(Client *self)
|
||||||
|
@ -1883,74 +1871,76 @@ void client_fullscreen(Client *self, gboolean fs, gboolean savearea)
|
||||||
client_focus(self);
|
client_focus(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_iconify(Client *self, gboolean iconic, gboolean curdesk)
|
static void client_iconify_recursive(Client *self,
|
||||||
|
gboolean iconic, gboolean curdesk)
|
||||||
{
|
{
|
||||||
GSList *it;
|
GSList *it;
|
||||||
|
gboolean changed = FALSE;
|
||||||
|
|
||||||
/* move up the transient chain as far as possible first */
|
|
||||||
if (self->transient_for) {
|
if (self->iconic != iconic) {
|
||||||
if (self->transient_for != TRAN_GROUP) {
|
g_message("%sconifying window: 0x%lx", (iconic ? "I" : "Uni"),
|
||||||
if (self->transient_for->iconic != iconic) {
|
self->window);
|
||||||
client_iconify(self->transient_for, iconic, curdesk);
|
|
||||||
return;
|
self->iconic = iconic;
|
||||||
|
|
||||||
|
if (iconic) {
|
||||||
|
if (self->functions & Func_Iconify) {
|
||||||
|
self->wmstate = IconicState;
|
||||||
|
self->ignore_unmaps++;
|
||||||
|
/* we unmap the client itself so that we can get MapRequest
|
||||||
|
events, and because the ICCCM tells us to! */
|
||||||
|
XUnmapWindow(ob_display, self->window);
|
||||||
|
|
||||||
|
/* update the focus lists.. iconic windows go to the bottom of
|
||||||
|
the list, put the new iconic window at the 'top of the
|
||||||
|
bottom'. */
|
||||||
|
focus_order_to_top(self);
|
||||||
|
|
||||||
|
changed = TRUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GSList *it;
|
if (curdesk)
|
||||||
|
client_set_desktop(self, screen_desktop, FALSE);
|
||||||
|
self->wmstate = self->shaded ? IconicState : NormalState;
|
||||||
|
XMapWindow(ob_display, self->window);
|
||||||
|
|
||||||
for (it = self->group->members; it; it = it->next) {
|
/* this puts it after the current focused window */
|
||||||
Client *c = it->data;
|
focus_order_remove(self);
|
||||||
if (c != self && c->iconic != iconic &&
|
focus_order_add_new(self);
|
||||||
!c->transient_for) {
|
|
||||||
client_iconify(it->data, iconic, curdesk);
|
/* this is here cuz with the VIDMODE extension, the viewport can
|
||||||
break;
|
change while a fullscreen window is iconic, and when it
|
||||||
}
|
uniconifies, it would be nice if it did so to the new position
|
||||||
}
|
of the viewport */
|
||||||
if (it != NULL) return;
|
client_reconfigure(self);
|
||||||
|
|
||||||
|
changed = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->iconic == iconic) return; /* nothing to do */
|
if (changed) {
|
||||||
|
client_change_state(self);
|
||||||
|
client_showhide(self);
|
||||||
|
screen_update_areas();
|
||||||
|
|
||||||
g_message("%sconifying window: 0x%lx", (iconic ? "I" : "Uni"),
|
dispatch_client(iconic ? Event_Client_Unmapped : Event_Client_Mapped,
|
||||||
self->window);
|
self, 0, 0);
|
||||||
|
|
||||||
self->iconic = iconic;
|
|
||||||
|
|
||||||
if (iconic) {
|
|
||||||
self->wmstate = IconicState;
|
|
||||||
self->ignore_unmaps++;
|
|
||||||
/* we unmap the client itself so that we can get MapRequest events,
|
|
||||||
and because the ICCCM tells us to! */
|
|
||||||
XUnmapWindow(ob_display, self->window);
|
|
||||||
|
|
||||||
/* update the focus lists.. iconic windows go to the bottom of the
|
|
||||||
list, put the new iconic window at the 'top of the bottom'. */
|
|
||||||
focus_order_to_top(self);
|
|
||||||
} else {
|
|
||||||
if (curdesk)
|
|
||||||
client_set_desktop(self, screen_desktop, FALSE);
|
|
||||||
self->wmstate = self->shaded ? IconicState : NormalState;
|
|
||||||
XMapWindow(ob_display, self->window);
|
|
||||||
|
|
||||||
/* this puts it after the current focused window */
|
|
||||||
focus_order_remove(self);
|
|
||||||
focus_order_add_new(self);
|
|
||||||
|
|
||||||
/* this is here cuz with the VIDMODE extension, the viewport can change
|
|
||||||
while a fullscreen window is iconic, and when it uniconifies, it
|
|
||||||
would be nice if it did so to the new position of the viewport */
|
|
||||||
client_reconfigure(self);
|
|
||||||
}
|
}
|
||||||
client_change_state(self);
|
|
||||||
client_showhide(self);
|
|
||||||
screen_update_areas();
|
|
||||||
|
|
||||||
dispatch_client(iconic ? Event_Client_Unmapped : Event_Client_Mapped,
|
|
||||||
self, 0, 0);
|
|
||||||
|
|
||||||
/* iconify all transients */
|
/* iconify all transients */
|
||||||
for (it = self->transients; it != NULL; it = it->next)
|
for (it = self->transients; it != NULL; it = it->next)
|
||||||
if (it->data != self) client_iconify(it->data, iconic, curdesk);
|
if (it->data != self) client_iconify_recursive(it->data,
|
||||||
|
iconic, curdesk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_iconify(Client *self, gboolean iconic, gboolean curdesk)
|
||||||
|
{
|
||||||
|
/* move up the transient chain as far as possible first */
|
||||||
|
self = client_search_top_transient(self);
|
||||||
|
|
||||||
|
client_iconify_recursive(client_search_top_transient(self),
|
||||||
|
iconic, curdesk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_maximize(Client *self, gboolean max, int dir, gboolean savearea)
|
void client_maximize(Client *self, gboolean max, int dir, gboolean savearea)
|
||||||
|
@ -2101,39 +2091,53 @@ void client_kill(Client *self)
|
||||||
XKillClient(ob_display, self->window);
|
XKillClient(ob_display, self->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_set_desktop(Client *self, guint target, gboolean donthide)
|
void client_set_desktop_recursive(Client *self,
|
||||||
|
guint target, gboolean donthide)
|
||||||
{
|
{
|
||||||
guint old;
|
guint old;
|
||||||
|
GSList *it;
|
||||||
|
|
||||||
if (target == self->desktop) return;
|
if (target != self->desktop) {
|
||||||
|
|
||||||
g_message("Setting desktop %u", target+1);
|
g_message("Setting desktop %u", target+1);
|
||||||
|
|
||||||
g_assert(target < screen_num_desktops || target == DESKTOP_ALL);
|
g_assert(target < screen_num_desktops || target == DESKTOP_ALL);
|
||||||
|
|
||||||
/* remove from the old desktop(s) */
|
/* remove from the old desktop(s) */
|
||||||
focus_order_remove(self);
|
focus_order_remove(self);
|
||||||
|
|
||||||
old = self->desktop;
|
old = self->desktop;
|
||||||
self->desktop = target;
|
self->desktop = target;
|
||||||
PROP_SET32(self->window, net_wm_desktop, cardinal, target);
|
PROP_SET32(self->window, net_wm_desktop, cardinal, target);
|
||||||
/* the frame can display the current desktop state */
|
/* the frame can display the current desktop state */
|
||||||
frame_adjust_state(self->frame);
|
frame_adjust_state(self->frame);
|
||||||
/* 'move' the window to the new desktop */
|
/* 'move' the window to the new desktop */
|
||||||
if (!donthide)
|
if (!donthide)
|
||||||
client_showhide(self);
|
client_showhide(self);
|
||||||
/* raise if it was not already on the desktop */
|
/* raise if it was not already on the desktop */
|
||||||
if (old != DESKTOP_ALL)
|
if (old != DESKTOP_ALL)
|
||||||
stacking_raise(CLIENT_AS_WINDOW(self));
|
stacking_raise(CLIENT_AS_WINDOW(self));
|
||||||
screen_update_areas();
|
screen_update_areas();
|
||||||
|
|
||||||
/* add to the new desktop(s) */
|
/* add to the new desktop(s) */
|
||||||
if (config_focus_new)
|
if (config_focus_new)
|
||||||
focus_order_to_top(self);
|
focus_order_to_top(self);
|
||||||
else
|
else
|
||||||
focus_order_to_bottom(self);
|
focus_order_to_bottom(self);
|
||||||
|
|
||||||
dispatch_client(Event_Client_Desktop, self, target, old);
|
dispatch_client(Event_Client_Desktop, self, target, old);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move all transients */
|
||||||
|
for (it = self->transients; it != NULL; it = it->next)
|
||||||
|
if (it->data != self) client_set_desktop_recursive(it->data,
|
||||||
|
target, donthide);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_set_desktop(Client *self, guint target, gboolean donthide)
|
||||||
|
{
|
||||||
|
client_set_desktop_recursive(client_search_top_transient(self),
|
||||||
|
target, donthide);
|
||||||
}
|
}
|
||||||
|
|
||||||
Client *client_search_modal_child(Client *self)
|
Client *client_search_modal_child(Client *self)
|
||||||
|
@ -2575,3 +2579,27 @@ guint client_xinerama_area(Client *self)
|
||||||
g_assert(i < screen_num_xin_areas);
|
g_assert(i < screen_num_xin_areas);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Client *client_search_top_transient(Client *self)
|
||||||
|
{
|
||||||
|
/* move up the transient chain as far as possible */
|
||||||
|
if (self->transient_for) {
|
||||||
|
if (self->transient_for != TRAN_GROUP) {
|
||||||
|
return client_search_top_transient(self->transient_for);
|
||||||
|
} else {
|
||||||
|
GSList *it;
|
||||||
|
|
||||||
|
for (it = self->group->members; it; it = it->next) {
|
||||||
|
Client *c = it->data;
|
||||||
|
|
||||||
|
/* checking transient_for prevents infinate loops! */
|
||||||
|
if (c != self && !c->transient_for)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (it)
|
||||||
|
return it->data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
|
@ -496,6 +496,8 @@ Client *client_search_focus_tree_full(Client *self);
|
||||||
*/
|
*/
|
||||||
Client *client_search_modal_child(Client *self);
|
Client *client_search_modal_child(Client *self);
|
||||||
|
|
||||||
|
Client *client_search_top_transient(Client *self);
|
||||||
|
|
||||||
/*! Return the "closest" client in the given direction */
|
/*! Return the "closest" client in the given direction */
|
||||||
Client *client_find_directional(Client *c, Direction dir);
|
Client *client_find_directional(Client *c, Direction dir);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue