[mutter] Move manipulation of the X stack to MetaStackTracker



commit 34573660665ba4134451cc82a596367dbf3989d0
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Tue Sep 9 15:44:26 2014 -0400

    Move manipulation of the X stack to MetaStackTracker
    
    Since MetaStackTracker is the code that knows about the current X stacking order
    and the relationship between X windows and Wayland windows, it's cleaner to
    encapsulate stack manipulation in MetaStackTracker rather than have the calling
    code make the X calls and only call into MetaStackTracker to inform it about
    the changes.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=736559

 src/core/screen.c        |    6 +-
 src/core/stack-tracker.c |  195 ++++++++++++++++++++++++++++++++-----------
 src/core/stack-tracker.h |   18 +++-
 src/core/stack.c         |  211 ++++------------------------------------------
 4 files changed, 180 insertions(+), 250 deletions(-)
---
diff --git a/src/core/screen.c b/src/core/screen.c
index 00a0a52..2152c41 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -490,10 +490,8 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
                                  guard_window,
                                  create_serial);
 
-  meta_stack_tracker_record_lower (screen->stack_tracker,
-                                   guard_window,
-                                   XNextRequest (xdisplay));
-  XLowerWindow (xdisplay, guard_window);
+  meta_stack_tracker_lower (screen->stack_tracker,
+                            guard_window);
   XMapWindow (xdisplay, guard_window);
   return guard_window;
 }
diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c
index c3ec5cc..4ef4026 100644
--- a/src/core/stack-tracker.c
+++ b/src/core/stack-tracker.c
@@ -39,6 +39,7 @@
 #include "frame.h"
 #include "screen-private.h"
 #include "stack-tracker.h"
+#include <meta/errors.h>
 #include <meta/util.h>
 
 #include <meta/compositor.h>
@@ -590,54 +591,6 @@ meta_stack_tracker_record_remove (MetaStackTracker *tracker,
 }
 
 void
-meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker,
-                                           const guint64    *windows,
-                                          int               n_windows,
-                                          gulong            serial)
-{
-  int i;
-  int n_x_windows = 0;
-
-  /* XRestackWindows() isn't actually a X requests - it's broken down
-   * by XLib into a series of XConfigureWindow(StackMode=below); we
-   * mirror that here.
-   *
-   * Since there may be a mixture of X and wayland windows in the
-   * stack it's ambiguous which operations we should associate with an
-   * X serial number. One thing we do know though is that there will
-   * be (n_x_window - 1) X requests made.
-   *
-   * Aside: Having a separate StackOp for this would be possible to
-   * get some extra efficiency in memory allocation and in applying
-   * the op, at the expense of a code complexity. Implementation hint
-   * for that - keep op->restack_window.n_complete, and when receiving
-   * events with intermediate serials, set n_complete rather than
-   * removing the op from the queue.
-   */
-  if (n_windows && META_STACK_ID_IS_X11 (windows[0]))
-    n_x_windows++;
-  for (i = 0; i < n_windows - 1; i++)
-    {
-      guint64 lower = windows[i + 1];
-      gboolean involves_x = FALSE;
-
-      if (META_STACK_ID_IS_X11 (lower))
-        {
-          n_x_windows++;
-
-          /* Since the first X window is a reference point we only
-           * assoicate a serial number with the operations involving
-           * later X windows. */
-          if (n_x_windows > 1)
-            involves_x = TRUE;
-        }
-
-      meta_stack_tracker_record_lower_below (tracker, lower, windows[i],
-                                             involves_x ? serial++ : 0);
-    }
-}
-
-void
 meta_stack_tracker_record_raise_above (MetaStackTracker *tracker,
                                        guint64           window,
                                        guint64           sibling,
@@ -960,3 +913,149 @@ meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker)
     }
 }
 
+/* When moving an X window we sometimes need an X based sibling.
+ *
+ * If the given sibling is X based this function returns it back
+ * otherwise it searches downwards looking for the nearest X window.
+ *
+ * If no X based sibling could be found return NULL. */
+static Window
+find_x11_sibling_downwards (MetaStackTracker *tracker,
+                            guint64           sibling)
+{
+  guint64 *windows;
+  int n_windows;
+  int i;
+
+  if (META_STACK_ID_IS_X11 (sibling))
+    return (Window)sibling;
+
+  meta_stack_tracker_get_stack (tracker,
+                                &windows, &n_windows);
+
+  /* NB: Children are in order from bottom to top and we
+   * want to search downwards for the nearest X window.
+   */
+
+  for (i = n_windows - 1; i >= 0; i--)
+    if (windows[i] == sibling)
+      break;
+
+  for (; i >= 0; i--)
+    {
+      if (META_STACK_ID_IS_X11 (windows[i]))
+        return (Window)windows[i];
+    }
+
+  return None;
+}
+
+static Window
+find_x11_sibling_upwards (MetaStackTracker *tracker,
+                          guint64           sibling)
+{
+  guint64 *windows;
+  int n_windows;
+  int i;
+
+  if (META_STACK_ID_IS_X11 (sibling))
+    return (Window)sibling;
+
+  meta_stack_tracker_get_stack (tracker,
+                                &windows, &n_windows);
+
+  for (i = 0; i < n_windows; i++)
+    if (windows[i] == sibling)
+      break;
+
+  for (; i < n_windows; i++)
+    {
+      if (META_STACK_ID_IS_X11 (windows[i]))
+        return (Window)windows[i];
+    }
+
+  return None;
+}
+
+void
+meta_stack_tracker_lower_below (MetaStackTracker *tracker,
+                                guint64           window,
+                                guint64           sibling)
+{
+  gulong serial = 0;
+
+  if (META_STACK_ID_IS_X11 (window))
+    {
+      XWindowChanges changes;
+      serial = XNextRequest (tracker->screen->display->xdisplay);
+
+      meta_error_trap_push (tracker->screen->display);
+
+      changes.sibling = sibling ? find_x11_sibling_upwards (tracker,sibling) : None;
+      changes.stack_mode = changes.sibling ? Below : Above;
+
+      XConfigureWindow (tracker->screen->display->xdisplay,
+                        window,
+                        (changes.sibling ? CWSibling : 0) | CWStackMode,
+                        &changes);
+
+      meta_error_trap_pop (tracker->screen->display);
+    }
+
+  meta_stack_tracker_record_lower_below (tracker,
+                                         window, sibling,
+                                         serial);
+}
+
+void
+meta_stack_tracker_lower (MetaStackTracker *tracker,
+                          guint64           window)
+{
+  meta_stack_tracker_raise_above (tracker, window, None);
+}
+
+void
+meta_stack_tracker_raise_above (MetaStackTracker *tracker,
+                                guint64           window,
+                                guint64           sibling)
+{
+  gulong serial = 0;
+
+  if (META_STACK_ID_IS_X11 (window))
+    {
+      XWindowChanges changes;
+      serial = XNextRequest (tracker->screen->display->xdisplay);
+
+      meta_error_trap_push (tracker->screen->display);
+
+      changes.sibling = sibling ? find_x11_sibling_downwards (tracker, sibling) : None;
+      changes.stack_mode = changes.sibling ? Above : Below;
+
+      XConfigureWindow (tracker->screen->display->xdisplay,
+                        (Window)window,
+                        (changes.sibling ? CWSibling : 0) | CWStackMode,
+                        &changes);
+
+      meta_error_trap_pop (tracker->screen->display);
+    }
+
+  meta_stack_tracker_record_raise_above (tracker, window,
+                                         sibling, serial);
+}
+
+void
+meta_stack_tracker_restack_windows (MetaStackTracker *tracker,
+                                    const guint64    *windows,
+                                    int               n_windows)
+{
+  int i;
+
+  /* XRestackWindows() isn't actually a X requests - it's broken down
+   * by XLib into a series of XConfigureWindow(StackMode=below); we
+   * just do the same here directly. The main disadvantage of  is that
+   * we allocate individual ops for each lower, and also that we are
+   * grabbing the libX11 lock separately for individual component.
+   */
+  for (i = 0; i < n_windows - 1; i++)
+    meta_stack_tracker_lower_below (tracker, windows[i + 1], windows[i]);
+}
diff --git a/src/core/stack-tracker.h b/src/core/stack-tracker.h
index d54d914..1c9ee8f 100644
--- a/src/core/stack-tracker.h
+++ b/src/core/stack-tracker.h
@@ -51,10 +51,6 @@ void meta_stack_tracker_record_add             (MetaStackTracker *tracker,
 void meta_stack_tracker_record_remove          (MetaStackTracker *tracker,
                                                 guint64           window,
                                                 gulong            serial);
-void meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker,
-                                                const guint64    *windows,
-                                               int               n_windows,
-                                                gulong            serial);
 void meta_stack_tracker_record_raise_above     (MetaStackTracker *tracker,
                                                 guint64           window,
                                                 guint64           sibling,
@@ -67,6 +63,20 @@ void meta_stack_tracker_record_lower           (MetaStackTracker *tracker,
                                                 guint64           window,
                                                 gulong            serial);
 
+/* We also have functions that also go ahead and do the work
+ */
+void meta_stack_tracker_raise_above     (MetaStackTracker *tracker,
+                                         guint64           window,
+                                         guint64           sibling);
+void meta_stack_tracker_lower_below     (MetaStackTracker  *tracker,
+                                         guint64            window,
+                                         guint64            sibling);
+void meta_stack_tracker_lower           (MetaStackTracker *tracker,
+                                         guint64           window);
+void meta_stack_tracker_restack_windows (MetaStackTracker *tracker,
+                                         const guint64    *windows,
+                                         int               n_windows);
+
 /* These functions are used to update the stack when we get events
  * reflecting changes to the stacking order */
 void meta_stack_tracker_create_event    (MetaStackTracker    *tracker,
diff --git a/src/core/stack.c b/src/core/stack.c
index 2ea144a..f335fe4 100644
--- a/src/core/stack.c
+++ b/src/core/stack.c
@@ -1085,44 +1085,6 @@ find_top_most_managed_window (MetaScreen *screen,
   return 0;
 }
 
-/* When moving an X window we sometimes need an X based sibling.
- *
- * If the given sibling is X based this function returns it back
- * otherwise it searches downwards looking for the nearest X window.
- *
- * If no X based sibling could be found return NULL. */
-static Window
-find_x11_sibling_downwards (MetaScreen *screen,
-                            guint64     sibling)
-{
-  MetaStackTracker *stack_tracker = screen->stack_tracker;
-  guint64 *windows;
-  int n_windows;
-  int i;
-
-  if (META_STACK_ID_IS_X11 (sibling))
-    return (Window)sibling;
-
-  meta_stack_tracker_get_stack (stack_tracker,
-                                &windows, &n_windows);
-
-  /* NB: Children are in order from bottom to top and we
-   * want to search downwards for the nearest X window.
-   */
-
-  for (i = n_windows - 1; i >= 0; i--)
-    if (windows[i] == sibling)
-      break;
-
-  for (; i >= 0; i--)
-    {
-      if (META_STACK_ID_IS_X11 (windows[i]))
-        return (Window)windows[i];
-    }
-
-  return None;
-}
-
 /**
  * raise_window_relative_to_managed_windows:
  *
@@ -1149,27 +1111,15 @@ static void
 raise_window_relative_to_managed_windows (MetaScreen *screen,
                                           guint64     stack_id)
 {
-  gulong serial = 0;
   guint64 sibling;
 
   sibling = find_top_most_managed_window (screen, stack_id);
   if (!sibling)
     {
-      if (META_STACK_ID_IS_X11 (stack_id))
-        {
-          serial = XNextRequest (screen->display->xdisplay);
-          meta_error_trap_push (screen->display);
-          XLowerWindow (screen->display->xdisplay,
-                        stack_id);
-          meta_error_trap_pop (screen->display);
-        }
-
       /* No sibling to use, just lower ourselves to the bottom
        * to be sure we're below any override redirect windows.
        */
-      meta_stack_tracker_record_lower (screen->stack_tracker,
-                                       stack_id,
-                                       serial);
+      meta_stack_tracker_lower (screen->stack_tracker, stack_id);
       return;
     }
 
@@ -1179,40 +1129,8 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
               meta_display_describe_stack_id (screen->display, stack_id),
               meta_display_describe_stack_id (screen->display, sibling));
 
-  if (META_STACK_ID_IS_X11 (stack_id))
-    {
-      XWindowChanges changes;
-      Window x11_sibling = find_x11_sibling_downwards (screen, sibling);
-      serial = XNextRequest (screen->display->xdisplay);
-
-      if (x11_sibling)
-        {
-          changes.sibling = x11_sibling;
-          changes.stack_mode = Above;
-
-          meta_error_trap_push (screen->display);
-          XConfigureWindow (screen->display->xdisplay,
-                            (Window)stack_id,
-                            CWSibling | CWStackMode,
-                            &changes);
-          meta_error_trap_pop (screen->display);
-        }
-      else
-        {
-          /* No sibling to use, just lower ourselves to the bottom
-           * to be sure we're below any override redirect windows.
-           */
-          meta_error_trap_push (screen->display);
-          XLowerWindow (screen->display->xdisplay,
-                        (Window)stack_id);
-          meta_error_trap_pop (screen->display);
-        }
-    }
-
-  meta_stack_tracker_record_raise_above (screen->stack_tracker,
-                                         stack_id,
-                                         sibling,
-                                         serial);
+  meta_stack_tracker_raise_above (screen->stack_tracker,
+                                  stack_id, sibling);
 }
 
 /**
@@ -1232,10 +1150,8 @@ static void
 stack_sync_to_xserver (MetaStack *stack)
 {
   GArray *x11_stacked;
-  GArray *x11_root_children_stacked;
   GArray *all_root_children_stacked; /* wayland OR x11 */
   GList *tmp;
-  GArray *x11_hidden;
   GArray *x11_hidden_stack_ids;
   int n_override_redirect = 0;
 
@@ -1255,14 +1171,11 @@ stack_sync_to_xserver (MetaStack *stack)
   x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
 
   all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
-  x11_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
-
   x11_hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
-  x11_hidden = g_array_new (FALSE, FALSE, sizeof (Window));
 
   /* The screen guard window sits above all hidden windows and acts as
    * a barrier to input reaching these windows. */
-  g_array_append_val (x11_hidden, stack->screen->guard_window);
+  g_array_append_val (x11_hidden_stack_ids, stack->screen->guard_window);
 
   meta_topic (META_DEBUG_STACK, "Top to bottom: ");
   meta_push_no_msg_prefix ();
@@ -1302,16 +1215,11 @@ stack_sync_to_xserver (MetaStack *stack)
               guint64 stack_id = top_level_window;
 
               g_array_append_val (x11_hidden_stack_ids, stack_id);
-              g_array_append_val (x11_hidden, top_level_window);
             }
          continue;
        }
 
       g_array_append_val (all_root_children_stacked, stack_id);
-
-      /* build XRestackWindows() array from top to bottom */
-      if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
-        g_array_append_val (x11_root_children_stacked, top_level_window);
     }
 
   meta_topic (META_DEBUG_STACK, "\n");
@@ -1338,18 +1246,9 @@ stack_sync_to_xserver (MetaStack *stack)
 
       if (all_root_children_stacked->len > 1)
         {
-          gulong serial = 0;
-          if (x11_root_children_stacked->len > 1)
-            {
-              serial = XNextRequest (stack->screen->display->xdisplay);
-              XRestackWindows (stack->screen->display->xdisplay,
-                               (Window *) x11_root_children_stacked->data,
-                               x11_root_children_stacked->len);
-            }
-          meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
-                                                     (guint64 *) all_root_children_stacked->data,
-                                                     all_root_children_stacked->len,
-                                                     serial);
+          meta_stack_tracker_restack_windows (stack->screen->stack_tracker,
+                                              (guint64 *) all_root_children_stacked->data,
+                                              all_root_children_stacked->len);
         }
     }
   else if (all_root_children_stacked->len > 0)
@@ -1428,8 +1327,6 @@ stack_sync_to_xserver (MetaStack *stack)
                 }
               else
                 {
-                  gulong serial = 0;
-
                   /* This means that if last_xwindow is dead, but not
                    * *newp, then we fail to restack *newp; but on
                    * unmanaging last_xwindow, we'll fix it up.
@@ -1439,23 +1336,8 @@ stack_sync_to_xserver (MetaStack *stack)
                               meta_display_describe_stack_id (stack->screen->display, *newp),
                               last_xwindow);
 
-                  if (META_STACK_ID_IS_X11 (*newp))
-                    {
-                      XWindowChanges changes;
-                      serial = XNextRequest (stack->screen->display->xdisplay);
-
-                      changes.sibling = last_xwindow;
-                      changes.stack_mode = Below;
-
-                      XConfigureWindow (stack->screen->display->xdisplay,
-                                        (Window)*newp,
-                                        CWSibling | CWStackMode,
-                                        &changes);
-                    }
-
-                  meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
-                                                         *newp, last_window,
-                                                         serial);
+                  meta_stack_tracker_lower_below (stack->screen->stack_tracker,
+                                                  *newp, last_window);
                 }
 
               if (META_STACK_ID_IS_X11 (*newp))
@@ -1467,84 +1349,27 @@ stack_sync_to_xserver (MetaStack *stack)
 
       if (newp != new_end)
         {
-          const guint64 *x_ref;
-          unsigned long serial = 0;
-
           /* Restack remaining windows */
           meta_topic (META_DEBUG_STACK, "Restacking remaining %d windows\n",
                       (int) (new_end - newp));
 
-          /* rewind until we find the last stacked X window that we can use
-           * as a reference point for re-stacking remaining X windows */
-          if (newp != new_stack)
-            for (x_ref = newp - 1;
-                 META_STACK_ID_IS_X11 (*x_ref) && x_ref > new_stack;
-                 x_ref--)
-              ;
-          else
-            x_ref = new_stack;
-
-          /* If we didn't find an X window looking backwards then walk forwards
-           * through the remaining windows to find the first remaining X window
-           * instead. */
-          if (META_STACK_ID_IS_X11 (*x_ref))
-            {
-              for (x_ref = newp;
-                   META_STACK_ID_IS_X11 (*x_ref) && x_ref < new_end;
-                   x_ref++)
-                ;
-            }
-
-          /* If there are any X windows remaining unstacked then restack them */
-          if (META_STACK_ID_IS_X11 (*x_ref))
-            {
-              int i;
-
-              for (i = x11_root_children_stacked->len - 1; i; i--)
-                {
-                  Window *reference = &g_array_index (x11_root_children_stacked, Window, i);
-
-                  if (*reference == (Window)*x_ref)
-                    {
-                      int n = x11_root_children_stacked->len - i;
-
-                      /* There's no point restacking if there's only one X window */
-                      if (n == 1)
-                        break;
-
-                      serial = XNextRequest (stack->screen->display->xdisplay);
-                      XRestackWindows (stack->screen->display->xdisplay,
-                                       reference, n);
-                      break;
-                    }
-                }
-            }
-
           /* We need to include an already-stacked window
            * in the restack call, so we get in the proper position
            * with respect to it.
            */
           if (newp != new_stack)
-            newp = MIN (newp - 1, x_ref);
-          meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
-                                                     newp, new_end - newp,
-                                                     serial);
+            --newp;
+          meta_stack_tracker_restack_windows (stack->screen->stack_tracker,
+                                              newp, new_end - newp);
         }
     }
 
   /* Push hidden X windows to the bottom of the stack under the guard window */
-  meta_stack_tracker_record_lower (stack->screen->stack_tracker,
-                                   stack->screen->guard_window,
-                                   XNextRequest (stack->screen->display->xdisplay));
-  XLowerWindow (stack->screen->display->xdisplay, stack->screen->guard_window);
-  meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
-                                             (guint64 *)x11_hidden_stack_ids->data,
-                                             x11_hidden_stack_ids->len,
-                                             XNextRequest (stack->screen->display->xdisplay));
-  XRestackWindows (stack->screen->display->xdisplay,
-                  (Window *)x11_hidden->data,
-                  x11_hidden->len);
-  g_array_free (x11_hidden, TRUE);
+  meta_stack_tracker_lower (stack->screen->stack_tracker,
+                            stack->screen->guard_window);
+  meta_stack_tracker_restack_windows (stack->screen->stack_tracker,
+                                      (guint64 *)x11_hidden_stack_ids->data,
+                                      x11_hidden_stack_ids->len);
   g_array_free (x11_hidden_stack_ids, TRUE);
 
   meta_error_trap_pop (stack->screen->display);
@@ -1576,8 +1401,6 @@ stack_sync_to_xserver (MetaStack *stack)
     free_last_all_root_children_stacked_cache (stack);
   stack->last_all_root_children_stacked = all_root_children_stacked;
 
-  g_array_free (x11_root_children_stacked, TRUE);
-
   /* That was scary... */
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]