all repos — openbox @ 98304406432cda3a94c2a57f0812714a229ec77a

openbox fork - make it a bit more like ryudo

make restacking much better, yay

no more cludge using actions to raise windows. when a window changes layer it
uses add_nonintrusive now so it won't cover the focused window. this way
fullscreen windows when they drop down, don't cover up the new focus target.

fix add_nonintrusive so that if the window is focused it gets added to the top

add back support for ConfigureRequest restacking, this time properly though,
using all the detail and sibling modes. but when windows use this to raise they
are using some old business and we're going to assume they actually want to
activate instead. this means firefox works nicely. yay.

ubuntu's firefox has been made to just stop raising entirely though. !
Dana Jansens danakj@orodu.net
commit

98304406432cda3a94c2a57f0812714a229ec77a

parent

6412fba7fd1a30465cb01b0e3ebcdf47680e9f02

5 files changed, 113 insertions(+), 59 deletions(-)

jump to
M openbox/client.copenbox/client.c

@@ -451,7 +451,7 @@ Also if you don't have focus_new enabled, then it's going to get

raised to the top. Legacy begets legacy I guess? */ if (!client_restore_session_stacking(self)) - client_raise(self); + stacking_raise(CLIENT_AS_WINDOW(self)); } /* this has to happen before we try focus the window, but we want it to

@@ -2344,13 +2344,25 @@

for (it = self->transients; it; it = g_slist_next(it)) client_calc_layer_recursive(it->data, orig, self->layer, - raised ? raised : self->layer != old); + raised ? raised : self->layer > old); - if (!raised && self->layer != old) - if (orig->frame) { /* only restack if the original window is managed */ + /* restack. but only if the original window is managed. + + raised is used so that only the bottom-most window in the stacking + order is raised, the others will automatically come with it. + + also only the highest windows in the stacking order (no transients) + are lowered, cuz the rest come for free + */ + if (!raised && orig->frame) { + if (self->layer > old) { stacking_remove(CLIENT_AS_WINDOW(self)); - stacking_add(CLIENT_AS_WINDOW(self)); + stacking_add_nonintrusive(CLIENT_AS_WINDOW(self)); + } else if (self->layer < old && self->transients == NULL) { + stacking_remove(CLIENT_AS_WINDOW(self)); + stacking_add_nonintrusive(CLIENT_AS_WINDOW(self)); } + } } void client_calc_layer(ObClient *self)

@@ -3077,7 +3089,7 @@ if (!donthide)

client_showhide(self); /* raise if it was not already on the desktop */ if (old != DESKTOP_ALL) - client_raise(self); + stacking_raise(CLIENT_AS_WINDOW(self)); if (STRUT_EXISTS(self->strut)) screen_update_areas(); }

@@ -3302,7 +3314,7 @@ if (modal != self->modal) {

self->modal = modal; /* when a window changes modality, then its stacking order with its transients needs to change */ - client_raise(self); + stacking_raise(CLIENT_AS_WINDOW(self)); } if (iconic != self->iconic) client_iconify(self, iconic, FALSE);

@@ -3444,17 +3456,10 @@ with it */

return; if (self->shaded) client_shade(self, FALSE); + if (raise) + stacking_raise(CLIENT_AS_WINDOW(self)); client_focus(self); - - if (raise) { - /* we do this as an action here. this is rather important. this is - because we want the results from the focus change to take place - BEFORE we go about raising the window. when a fullscreen window - loses focus, we need this or else the raise wont be able to raise - above the to-lose-focus fullscreen window. */ - client_raise(self); - } } void client_activate(ObClient *self, gboolean here, gboolean user)

@@ -3508,16 +3513,6 @@

void client_bring_helper_windows(ObClient *self) { client_bring_helper_windows_recursive(self, self->desktop); -} - -void client_raise(ObClient *self) -{ - action_run_string("Raise", self, CurrentTime); -} - -void client_lower(ObClient *self) -{ - action_run_string("Lower", self, CurrentTime); } gboolean client_focused(ObClient *self)
M openbox/client.hopenbox/client.h

@@ -550,26 +550,6 @@

/*! Calculates the stacking layer for the client window */ void client_calc_layer(ObClient *self); -/*! Raises the client to the top of its stacking layer - Normally actions call to the client_* functions to make stuff go, but this - one is an exception. It just fires off an action, which will be queued. - This is because stacking order rules can be changed by focus state, and so - any time focus changes you have to wait for it to complete before you can - properly restart windows. As such, this only queues an action for later - execution, once the focus change has gone through. -*/ -void client_raise(ObClient *self); - -/*! Lowers the client to the bottom of its stacking layer - Normally actions call to the client_* functions to make stuff go, but this - one is an exception. It just fires off an action, which will be queued. - This is because stacking order rules can be changed by focus state, and so - any time focus changes you have to wait for it to complete before you can - properly restart windows. As such, this only queues an action for later - execution, once the focus change has gone through. -*/ -void client_lower(ObClient *self); - /*! Updates the window's transient status, and any parents of it */ void client_update_transient_for(ObClient *self); /*! Update the protocols that the window supports and adjusts things if they
M openbox/event.copenbox/event.c

@@ -1019,20 +1019,55 @@ client_configure_full(client, x, y, w, h, FALSE, TRUE, TRUE);

} if (e->xconfigurerequest.value_mask & CWStackMode) { + ObClient *sibling = NULL; + + /* get the sibling */ + if (e->xconfigurerequest.value_mask & CWSibling) { + ObWindow *win; + win = g_hash_table_lookup(window_map, + &e->xconfigurerequest.above); + if (WINDOW_IS_CLIENT(win)) + sibling = WINDOW_AS_CLIENT(win); + } + switch (e->xconfigurerequest.detail) { case Below: + ob_debug("ConfigureRequest Below for client %s sibling %s\n", + client->title, sibling ? sibling->title : "(all)"); + /* just lower it */ + stacking_lower(CLIENT_AS_WINDOW(client)); + break; case BottomIf: - /* Apps are so rude. And this is totally disconnected from - activation/focus. Bleh. */ - /*client_lower(client);*/ + ob_debug("ConfigureRequest BottomIf for client %s sibling " + "%s\n", + client->title, sibling ? sibling->title : "(all)"); + /* if this client occludes sibling (or anything if NULL), then + lower it to the bottom */ + if (stacking_occluded(sibling, client)) + stacking_lower(CLIENT_AS_WINDOW(client)); break; - case Above: + ob_debug("ConfigureRequest Above for client %s sibling %s\n", + client->title, sibling ? sibling->title : "(all)"); + /* activate it rather than just focus it */ + client_activate(client, FALSE, FALSE); + break; case TopIf: + ob_debug("ConfigureRequest TopIf for client %s sibling %s\n", + client->title, sibling ? sibling->title : "(all)"); + if (stacking_occluded(client, sibling)) + /* activate it rather than just focus it */ + client_activate(client, FALSE, FALSE); + case Opposite: + ob_debug("ConfigureRequest Opposite for client %s sibling " + "%s\n", + client->title, sibling ? sibling->title : "(all)"); + if (stacking_occluded(client, sibling)) + /* activate it rather than just focus it */ + client_activate(client, FALSE, FALSE); + else if (stacking_occluded(sibling, client)) + stacking_lower(CLIENT_AS_WINDOW(client)); default: - /* Apps are so rude. And this is totally disconnected from - activation/focus. Bleh. */ - /*client_raise(client);*/ break; } }

@@ -1601,7 +1636,7 @@

event_curtime = d->time; if (focus_client != d->client) { if (client_focus(d->client) && config_focus_raise) - client_raise(d->client); + stacking_raise(CLIENT_AS_WINDOW(d->client)); } event_curtime = old; return FALSE; /* no repeat */
M openbox/stacking.copenbox/stacking.c

@@ -416,7 +416,7 @@

/* insert above its highest parent (or its highest child !) */ it_below = find_highest_relative(client); - if (!it_below) { + if (!it_below && client != focus_client) { /* nothing to put it directly above, so try find the focused client to put it underneath it */ if (focus_client && focus_client->layer == client->layer) {

@@ -425,10 +425,16 @@ it_below = it_below->next;

} } if (!it_below) { - /* there is no window to put this directly above, so put it at the - bottom */ - stacking_list = g_list_prepend(stacking_list, win); - stacking_lower(win); + if (client == focus_client) { + /* it's focused so put it at the top */ + stacking_list = g_list_append(stacking_list, win); + stacking_raise(win); + } else { + /* there is no window to put this directly above, so put it at the + bottom */ + stacking_list = g_list_prepend(stacking_list, win); + stacking_lower(win); + } } else { /* make sure it's not in the wrong layer though ! */ for (; it_below; it_below = g_list_next(it_below))

@@ -453,3 +459,36 @@ do_restack(wins, it_below);

g_list_free(wins); } } + +gboolean stacking_occluded(ObClient *client, ObClient *sibling) +{ + GList *it; + gboolean obscured = FALSE; + gboolean found = FALSE; + + /* no need for any looping in this case */ + if (sibling && client->layer != sibling->layer) + return obscured; + + for (it = stacking_list; it; it = g_list_next(it)) + if (WINDOW_IS_CLIENT(it->data)) { + ObClient *c = it->data; + if (found) { + if (sibling != NULL) { + if (c == sibling) { + obscured = TRUE; + break; + } + } + else if (c->layer == client->layer) { + obscured = TRUE; + break; + } + else if (c->layer > client->layer) + break; /* we past its layer */ + } + else if (c == client) + found = TRUE; + } + return obscured; +}
M openbox/stacking.hopenbox/stacking.h

@@ -59,4 +59,9 @@ it should really ONLY be used to restore stacking orders from saved sessions

*/ void stacking_below(ObWindow *window, ObWindow *below); +/*! Returns TRUE if client is occluded by sibling. If sibling is NULL it tries + against all other clients. Otherwise, it returns FALSE. +*/ +gboolean stacking_occluded(struct _ObClient *client,struct _ObClient *sibling); + #endif