client_get_all(self);
client_restore_session_state(self);
+ client_calc_layer(self);
+
{
Time t = sn_app_started(self->startup_id, self->class);
if (t) self->user_time = t;
/* This is focus stealing prevention, if a user_time has been set */
ob_debug("Want to focus new window 0x%x with time %u (last time %u)\n",
self->window, self->user_time, client_last_user_time);
- if (!self->user_time || self->user_time >= client_last_user_time)
+ if (!self->user_time || self->user_time >= client_last_user_time ||
+ client_search_focus_parent(self) != NULL)
{
/* since focus can change the stacking orders, if we focus the
window then the standard raise it gets is not enough, we need
netstate[num++] = prop_atoms.ob_wm_state_undecorated;
PROP_SETA32(self->window, net_wm_state, atom, netstate, num);
- client_calc_layer(self);
-
if (self->frame)
frame_adjust_state(self->frame);
}
}
static void client_calc_layer_recursive(ObClient *self, ObClient *orig,
- ObStackingLayer l, gboolean raised)
+ ObStackingLayer min, gboolean raised)
{
ObStackingLayer old, own;
GSList *it;
old = self->layer;
own = calc_layer(self);
- self->layer = l > own ? l : own;
+ self->layer = MAX(own, min);
+
+ ob_debug("layer for %s: %d\n", self->title, self->layer);
for (it = self->transients; it; it = g_slist_next(it))
client_calc_layer_recursive(it->data, orig,
- l, raised ? raised : l != old);
+ self->layer,
+ raised ? raised : self->layer != old);
- if (!raised && l != old)
+ if (!raised && self->layer != old)
if (orig->frame) { /* only restack if the original window is managed */
stacking_remove(CLIENT_AS_WINDOW(self));
stacking_add(CLIENT_AS_WINDOW(self));
void client_calc_layer(ObClient *self)
{
- ObStackingLayer l;
ObClient *orig;
+ GSList *it;
orig = self;
/* transients take on the layer of their parents */
- self = client_search_top_transient(self);
-
- l = calc_layer(self);
+ it = client_search_top_transients(self);
- client_calc_layer_recursive(self, orig, l, FALSE);
+ for (; it; it = g_slist_next(it))
+ client_calc_layer_recursive(it->data, orig, 0, FALSE);
}
gboolean client_should_show(ObClient *self)
self->fullscreen == fs) return; /* already done */
self->fullscreen = fs;
- client_change_state(self); /* change the state hints on the client,
- and adjust out layer/stacking */
+ client_change_state(self); /* change the state hints on the client */
+ client_calc_layer(self); /* and adjust out layer/stacking */
if (fs) {
if (savearea)
void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk)
{
+ GSList *it;
+
/* move up the transient chain as far as possible first */
- self = client_search_top_transient(self);
+ it = client_search_top_transients(self);
- client_iconify_recursive(client_search_top_transient(self),
- iconic, curdesk);
+ for (; it; it = g_slist_next(it))
+ client_iconify_recursive(it->data, iconic, curdesk);
}
void client_maximize(ObClient *self, gboolean max, gint dir, gboolean savearea)
void client_set_desktop(ObClient *self, guint target, gboolean donthide)
{
- client_set_desktop_recursive(client_search_top_transient(self),
- target, donthide);
+ GSList *it;
+
+ it = client_search_top_transients(self);
+
+ for(; it; it = g_slist_next(it))
+ client_set_desktop_recursive(it->data, target, donthide);
}
ObClient *client_search_modal_child(ObClient *self)
if (demands_attention != self->demands_attention)
client_hilite(self, demands_attention);
- client_calc_layer(self);
client_change_state(self); /* change the hint to reflect these changes */
}
ObClient *client_focus_target(ObClient *self)
{
- ObClient *child;
-
- /* if we have a modal child, then focus it, not us */
- child = client_search_modal_child(client_search_top_transient(self));
+ ObClient *child = NULL;
+
+ child = client_search_modal_child(self);
if (child) return child;
return self;
}
return most;
}
-ObClient *client_search_top_transient(ObClient *self)
+GSList *client_search_top_transients(ObClient *self)
{
- /* move up the transient chain as far as possible */
- if (self->transient_for) {
- if (self->transient_for != OB_TRAN_GROUP) {
- return client_search_top_transient(self->transient_for);
- } else {
+ GSList *ret = NULL;
+
+ /* move up the direct transient chain as far as possible */
+ while (self->transient_for && self->transient_for != OB_TRAN_GROUP)
+ self = self->transient_for;
+
+ if (!self->transient_for)
+ ret = g_slist_prepend(ret, self);
+ else {
GSList *it;
g_assert(self->group);
for (it = self->group->members; it; it = g_slist_next(it)) {
ObClient *c = it->data;
- /* checking transient_for prevents infinate loops! */
- if (c != self && !c->transient_for)
- break;
+ if (!c->transient_for)
+ ret = g_slist_prepend(ret, c);
}
- if (it)
- return it->data;
- }
+
+ if (ret == NULL) /* no group parents */
+ ret = g_slist_prepend(ret, self);
}
- return self;
+ return ret;
}
ObClient *client_search_focus_parent(ObClient *self)
}
}
-static GList *pick_windows(ObClient *top, ObClient *selected, gboolean raise)
+static GList *pick_windows_recur(ObClient *top, ObClient *selected,
+ gboolean raise)
{
GList *ret = NULL;
GList *it, *next, *prev;
if (!c->modal) {
if (!sel_child) {
- trans = g_list_concat(trans,
- pick_windows(c, selected, raise));
+ trans = g_list_concat
+ (trans, pick_windows_recur(c, selected, raise));
} else {
- trans_sel = g_list_concat(trans_sel,
- pick_windows(c, selected,
- raise));
+ trans_sel = g_list_concat
+ (trans_sel, pick_windows_recur(c, selected, raise));
}
} else {
if (!sel_child) {
- modals = g_list_concat(modals,
- pick_windows(c, selected, raise));
+ modals = g_list_concat
+ (modals, pick_windows_recur(c, selected, raise));
} else {
- modal_sel = g_list_concat(modal_sel,
- pick_windows(c, selected,
- raise));
+ modal_sel = g_list_concat
+ (modal_sel, pick_windows_recur(c, selected, raise));
}
}
/* if we dont have a prev then start back at the beginning,
return ret;
}
-static GList *pick_group_windows(ObClient *top, ObClient *selected,
- gboolean raise, gboolean normal)
+static GList *pick_group_windows_recur(ObClient *top, ObClient *selected,
+ gboolean raise, gboolean normal)
{
GList *ret = NULL;
GList *it, *next, *prev;
(normal && t == OB_CLIENT_TYPE_NORMAL)))
{
ret = g_list_concat(ret,
- pick_windows(sit->data,
- selected, raise));
+ pick_windows_recur(sit->data,
+ selected, raise));
/* if we dont have a prev then start back at the beginning,
otherwise skip back to the prev's next */
next = prev ? g_list_next(prev) : stacking_list;
return ret;
}
+static GList *pick_windows(ObClient *selected, gboolean raise, gboolean group)
+{
+ GList *it;
+ GSList *top, *top_it;
+ GSList *top_reorder = NULL;
+ GList *ret = NULL;
+
+ top = client_search_top_transients(selected);
+
+ /* go thru stacking list backwords so we can use g_slist_prepend */
+ for (it = g_list_last(stacking_list); it && top;
+ it = g_list_previous(it))
+ if ((top_it = g_slist_find(top, it->data))) {
+ top_reorder = g_slist_prepend(top_reorder, top_it->data);
+ top = g_slist_delete_link(top, top_it);
+ }
+ g_assert(top == NULL);
+
+ for (top_it = top_reorder; top_it; top_it = g_slist_next(top_it))
+ ret = g_list_concat(ret,
+ pick_windows_recur(top_it->data, selected, raise));
+
+ for (top_it = top_reorder; top_it; top_it = g_slist_next(top_it))
+ ret = g_list_concat(ret,
+ pick_group_windows_recur(top_it->data,
+ selected, raise, group));
+ return ret;
+}
+
void stacking_raise(ObWindow *window, gboolean group)
{
GList *wins;
if (WINDOW_IS_CLIENT(window)) {
- ObClient *c;
ObClient *selected;
selected = WINDOW_AS_CLIENT(window);
- c = client_search_top_transient(selected);
- wins = pick_windows(c, selected, TRUE);
- wins = g_list_concat(wins,
- pick_group_windows(c, selected, TRUE, group));
+ wins = pick_windows(selected, TRUE, group);
} else {
wins = g_list_append(NULL, window);
stacking_list = g_list_remove(stacking_list, window);
GList *wins;
if (WINDOW_IS_CLIENT(window)) {
- ObClient *c;
ObClient *selected;
selected = WINDOW_AS_CLIENT(window);
- c = client_search_top_transient(selected);
- wins = pick_windows(c, selected, FALSE);
- wins = g_list_concat(pick_group_windows(c, selected, FALSE, group),
- wins);
+ wins = pick_windows(selected, FALSE, group);
} else {
wins = g_list_append(NULL, window);
stacking_list = g_list_remove(stacking_list, window);
{
ObClient *client;
ObClient *parent = NULL;
- GList *it_before = NULL;
+ GList *it_below = NULL;
if (!WINDOW_IS_CLIENT(win)) {
stacking_add(win); /* no special rules for others */
}
}
- if (!(it_before = g_list_find(stacking_list, parent))) {
+ if (!(it_below = g_list_find(stacking_list, parent))) {
/* no parent to put above, try find the focused client to go
under */
if (focus_client && focus_client->layer == client->layer) {
- if ((it_before = g_list_find(stacking_list, focus_client)))
- it_before = it_before->next;
+ if ((it_below = g_list_find(stacking_list, focus_client)))
+ it_below = it_below->next;
}
}
- if (!it_before) {
+ if (!it_below) {
/* out of ideas, just add it normally... */
stacking_add(win);
} else {
- GList *it;
-
/* make sure it's not in the wrong layer though ! */
- while (it_before && client->layer < ((ObClient*)it_before->data)->layer)
- it_before = g_list_next(it_before);
- while (it_before != stacking_list &&
- client->layer > ((ObClient*)g_list_previous(it_before)->data)->layer)
- it_before = g_list_previous(it_before);
+ for (; it_below; it_below = g_list_next(it_below))
+ {
+ /* stop when the window is not in a higher layer than the window
+ it is going above (it_below) */
+ if (client->layer >= window_layer(it_below->data))
+ break;
+ }
+ for (; it_below != stacking_list;
+ it_below = g_list_previous(it_below))
+ {
+ /* stop when the window is not in a lower layer than the
+ window it is going under (it_above) */
+ GList *it_above = g_list_previous(it_below);
+ if (client->layer <= window_layer(it_above->data))
+ break;
+ }
GList *wins = g_list_append(NULL, win);
- do_restack(wins, it_before);
+ do_restack(wins, it_below);
g_list_free(wins);
}
}