Watch stacking changes on managed windows also, as this can change the "above" relati...
authorDana Jansens <danakj@orodu.net>
Sun, 27 Jun 2010 13:35:56 +0000 (09:35 -0400)
committerDana Jansens <danakj@orodu.net>
Sun, 27 Jun 2010 13:50:01 +0000 (09:50 -0400)
openbox/event.c
openbox/stacking.c
openbox/stacking.h

index bf404d37d532dd73d69acd3113801d6a5dbe1179..2a233708d894b908e939821752c837ec1a46b66e 100644 (file)
@@ -1809,28 +1809,26 @@ static void event_handle_window(ObWindow *wi, XEvent *e)
             RECT_SET(wi->area, x, y, w, h);
         }
 
-        /* set the top window's area/border */
         if (e->xconfigure.window == window_top(wi)) {
+            /* set the top window's area/border */
             XConfigureEvent const *xe = &e->xconfigure;
             RECT_SET(wi->toparea, xe->x, xe->y, xe->width, xe->height);
             wi->topborder = xe->border_width;
+
+            /* fix the stacking order */
+            if (e->xconfigure.above != wi->above) {
+                stacking_above_notify(wi, e->xconfigure.above);
+                wi->above = e->xconfigure.above;
+            }
         }
 
         break;
     case CreateNotify:
         if (e->xcreatewindow.parent == obt_root(ob_screen))
-            /* we actually only care about tracking above for unmanaged
-               windows, and they are only created by create or reparent
-               events, at which time they become the top-most, so we don't
-               bother tracking above for all windows in this function */
             wi->above = window_top(stacking_topmost_window());
         break;
     case ReparentNotify:
         if (e->xreparent.parent == obt_root(ob_screen))
-            /* we actually only care about tracking above for unmanaged
-               windows, and they are only created by create or reparent
-               events, at which time they become the top-most, so we don't
-               bother tracking above for all windows in this function */
             wi->above = window_top(stacking_topmost_window());
         break;
     case MapNotify:
@@ -1914,13 +1912,6 @@ static void event_handle_unmanaged(ObUnmanaged *um, XEvent *e)
                          e->xconfigurerequest.value_mask, &xwc);
         obt_display_ignore_errors(FALSE);
         break;
-    case ConfigureNotify:
-        if (e->xconfigure.above != UNMANAGED_AS_WINDOW(um)->above) {
-            ob_debug("ConfigureNotify changed stacking order for "
-                     "unmanaged 0x%lx", window_top(um));
-            stacking_unmanaged_above_notify(um, e->xconfigure.above);
-            UNMANAGED_AS_WINDOW(um)->above = e->xconfigure.above;
-        }
     }
 }
 
index 6e9e8e8142a9ee2395b6ecfd73306061f9639c78..17583449676815ef58ec17b78939592d4de8cf8a 100644 (file)
@@ -807,64 +807,111 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
     return ret;
 }
 
-void stacking_unmanaged_above_notify(ObUnmanaged *win, Window above)
+void stacking_above_notify(ObWindow *win, Window above)
 {
     GList *aboveit, *winit, *uit, *mit;
     ObUNode *un, *an;
+    gboolean last;
+
+    if (!WINDOW_IS_UNMANAGED(win)) {
+        GList *belowme;
+        /* a managed window moved, so any unmanaged that were above it before
+           no longer are.
+           on the other hand, the unmanaged that were above @above before
+           are now above this window */
+        winit = g_hash_table_lookup(stacking_map, &window_top(win));
+        belowme = winit->next;
+
+        /* find the unmanaged windows that were above me */
+        for (uit = stacking_ulist; uit; uit = g_list_next(uit))
+            if (((ObUNode*)uit->data)->belowme == winit) break;
+        /* change them to be above what i used to be above */
+        while (uit && ((ObUNode*)uit->data)->belowme == winit) {
+            ((ObUNode*)uit->data)->belowme = belowme;
+            uit = g_list_next(uit);
+        }
 
-    g_assert(WINDOW_IS_UNMANAGED(win));
-
-    winit = g_hash_table_lookup(stacking_umap, &window_top(win));
-
-    if (!above) {
-        /* at the very bottom of the stacking order */
-        stacking_ulist = g_list_remove_link(stacking_ulist, winit);
-        stacking_ulist = list_insert_link_before(stacking_ulist, NULL, winit);
-        un = winit->data;
-        un->belowme = NULL;
-    }
-    else if ((aboveit = g_hash_table_lookup(stacking_map, &above))) {
-        /* directly above a managed window, so put it at the bottom of
-           any siblings which are also above it */
-
-        stacking_ulist = g_list_remove_link(stacking_ulist, winit);
-        un = winit->data;
-        un->belowme = aboveit;
-
-        /* go through the managed windows in the stacking list from top to
-           bottom.
-           follow along in the list of unmanaged windows, until we come to the
-           managed window @winit is now above.  then keep moving through the
-           unmanaged windows until we find something above a different
-           managed window, and insert @winit into the unmanaged list before it.
-        */
-        mit = stacking_list;
-        uit = stacking_ulist;
-        for (; mit; mit = g_list_next(mit)) {
-            /* skip thru the unmanged windows above 'mit' */
-            while (uit && ((ObUNode*)uit->data)->belowme == mit)
-                uit = g_list_next(uit);
-            if (mit == aboveit) {
-                /* @win is above 'mit', so stick it in the unmanaged list
-                   before 'uit' (the first window above something lower in the
-                   managed stacking list */
-                stacking_ulist = list_insert_link_before(stacking_ulist,
-                                                         uit, winit);
-                break; /* done */
+        /* find who i am now above and tell them so */
+        if (!above) {
+            /* unmanaged that used to be above nothing */
+            uit = g_list_last(stacking_ulist);
+            while (uit && ((ObUNode*)uit->data)->belowme == NULL) {
+                ((ObUNode*)uit->data)->belowme = winit;
+                uit = g_list_previous(uit);
+            }
+        }
+        else if ((aboveit = g_hash_table_lookup(stacking_map, &above))) {
+            /* find unmanaged windows above managed 'aboveit' */
+            for (uit = stacking_ulist; uit; uit = g_list_next(uit))
+                if (((ObUNode*)uit->data)->belowme == aboveit) break;
+            while (uit && ((ObUNode*)uit->data)->belowme == aboveit)
+                ((ObUNode*)uit->data)->belowme = winit;
+        }
+        else if ((uit = g_hash_table_lookup(stacking_umap, &above))) {
+            /* change unmanaged windows above unmanaged 'uit' */
+            aboveit = ((ObUNode*)uit->data)->belowme;
+            uit = g_list_previous(uit);
+            while (uit && ((ObUNode*)uit->data)->belowme == aboveit) {
+                ((ObUNode*)uit->data)->belowme = winit;
+                uit = g_list_previous(uit);
             }
         }
     }
-    else if ((aboveit = g_hash_table_lookup(stacking_umap, &above))) {
-        /* directly above another unmanaged window, put it in that position
-           in the stacking_ulist */
-
-        stacking_ulist = g_list_remove_link(stacking_ulist, winit);
-        stacking_ulist = list_insert_link_before(stacking_ulist,
-                                                 aboveit, winit);
-        /* we share the same neighbour in stacking_list */
-        un = winit->data;
-        an = aboveit->data;
-        un->belowme = an->belowme;
+    else {
+        winit = g_hash_table_lookup(stacking_umap, &window_top(win));
+
+        if (!above) {
+            /* at the very bottom of the stacking order */
+            stacking_ulist = g_list_remove_link(stacking_ulist, winit);
+            stacking_ulist = list_insert_link_before(stacking_ulist,
+                                                     NULL, winit);
+            un = winit->data;
+            un->belowme = NULL;
+        }
+        else if ((aboveit = g_hash_table_lookup(stacking_map, &above))) {
+            /* directly above a managed window, so put it at the bottom of
+               any siblings which are also above it */
+
+            stacking_ulist = g_list_remove_link(stacking_ulist, winit);
+            un = winit->data;
+            un->belowme = aboveit;
+
+            /* go through the managed windows in the stacking list from top to
+               bottom.
+               follow along in the list of unmanaged windows, until we come to
+               the managed window @winit is now above.  then keep moving
+               through the unmanaged windows until we find something above a
+               different managed window, and insert @winit into the unmanaged
+               list before it.
+            */
+            mit = stacking_list;
+            uit = stacking_ulist;
+            for (; mit; mit = g_list_next(mit)) {
+                /* skip thru the unmanged windows above 'mit' */
+                while (uit && ((ObUNode*)uit->data)->belowme == mit)
+                    uit = g_list_next(uit);
+                if (mit == aboveit) {
+                    /* @win is above 'mit', so stick it in the unmanaged list
+                       before 'uit' (the first window above something lower in
+                       the managed stacking list */
+                    stacking_ulist = list_insert_link_before(stacking_ulist,
+                                                             uit, winit);
+                    break; /* done */
+                }
+            }
+        }
+        else if ((aboveit = g_hash_table_lookup(stacking_umap, &above))) {
+            /* directly above another unmanaged window, put it in that position
+               in the stacking_ulist */
+
+            stacking_ulist = g_list_remove_link(stacking_ulist, winit);
+            stacking_ulist = list_insert_link_before(stacking_ulist,
+                                                     aboveit, winit);
+            /* we share the same neighbour in stacking_list */
+            un = winit->data;
+            an = aboveit->data;
+            un->belowme = an->belowme;
+        }
     }
 }
 
index 6058786d9eed5b82eb313776df9dcbe2a3c74fdb..1c0ace228a716570d1377bbf342f7c90b8731885 100644 (file)
@@ -90,7 +90,7 @@ gboolean stacking_restack_request(struct _ObClient *client,
                                   struct _ObClient *sibling,
                                   gint detail);
 
-void stacking_unmanaged_above_notify(struct _ObUnmanaged *win, Window above);
+void stacking_above_notify(struct _ObWindow *win, Window above);
 
 ObStackingIter* stacking_iter_head(void);
 ObStackingIter* stacking_iter_tail(void);