]> Dogcows Code - chaz/openbox/commitdiff
make restacking much better, yay
authorDana Jansens <danakj@orodu.net>
Thu, 10 May 2007 00:57:35 +0000 (00:57 +0000)
committerDana Jansens <danakj@orodu.net>
Thu, 10 May 2007 00:57:35 +0000 (00:57 +0000)
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. !

openbox/client.c
openbox/client.h
openbox/event.c
openbox/stacking.c
openbox/stacking.h

index 0c4cce1f50be47e9a6f489790b2cb2b2ef9c6299..4c88daf7fc3b78f57c83d5cda5ab71ccf636d805 100644 (file)
@@ -451,7 +451,7 @@ void client_manage(Window window)
            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 @@ static void client_calc_layer_recursive(ObClient *self, ObClient *orig,
     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_nonintrusive(CLIENT_AS_WINDOW(self));
+        } else if (self->layer < old && self->transients == NULL) {
             stacking_remove(CLIENT_AS_WINDOW(self));
-            stacking_add(CLIENT_AS_WINDOW(self));
+            stacking_add_nonintrusive(CLIENT_AS_WINDOW(self));
         }
+    }
 }
 
 void client_calc_layer(ObClient *self)
@@ -3077,7 +3089,7 @@ void client_set_desktop_recursive(ObClient *self,
             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 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
         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 @@ static void client_present(ObClient *self, gboolean here, gboolean raise)
         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)
@@ -3510,16 +3515,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)
 {
     return self == focus_client;
index 30d40510f509cf83057a6197f2ebadc3009294fa..5a837391fefefb9f2efe0a102abd2551b0906ae9 100644 (file)
@@ -550,26 +550,6 @@ void client_bring_helper_windows(ObClient *self);
 /*! 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
index 566739c96262d8713de665d7f6de0901cf19cf6d..0c594d6bcba135d02d133ee4806ced76e6d6f224 100644 (file)
@@ -1019,20 +1019,55 @@ static void event_handle_client(ObClient *client, XEvent *e)
         }
 
         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 @@ static gboolean focus_delay_func(gpointer data)
     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 */
index 18747b9c80512a8bba55e78788085e7f7ca0cca2..afad8ad0918a77e6328378580eaa3122dfd3fd50 100644 (file)
@@ -416,7 +416,7 @@ void stacking_add_nonintrusive(ObWindow *win)
     /* 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 @@ void stacking_add_nonintrusive(ObWindow *win)
         }
     }
     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 @@ void stacking_add_nonintrusive(ObWindow *win)
         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;
+}
index 2391f650aee80e73a456c0924e3e209bd55d94a5..70e4b2d4e3a81bc470fba56edd9e71137269fe0f 100644 (file)
@@ -59,4 +59,9 @@ void stacking_lower(ObWindow *window);
 */
 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
This page took 0.035091 seconds and 4 git commands to generate.