[mutter] Replace MetaStackWindow with a 64-bit "stack ID"



commit 73573a85de50d2d8659755a90ffd22fa2f1119bd
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Mon Sep 8 21:20:14 2014 -0400

    Replace MetaStackWindow with a 64-bit "stack ID"
    
    Putting X windows and pointers to MetaWindows into a union had a number of
    problems:
    
     - It caused awkward initialization and conditionalization
     - There was no way to refer to Wayland windows (represented by
       MetaWindow *) in the past, which is necessary for the MetaStackTracker
       algorithms
     - We never even cleaned up old MetaStackWindow so there could be
       records in MetaStackWindow pointing to freed MetaWindow.
    
    Replace MetaStackWindow with a 64-bit "stack ID" which is:
    
     - The XID for X Windows
     - a "window stamp" for Wayland windows - window stamps are assigned
       for all MetaWindow and are unique across the life of the process.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=736559

 src/core/display-private.h   |   24 +++
 src/core/display.c           |   64 +++++++
 src/core/frame.c             |   13 +-
 src/core/screen.c            |   16 +-
 src/core/stack-tracker.c     |  390 +++++++++++++++++-------------------------
 src/core/stack-tracker.h     |   66 +++-----
 src/core/stack.c             |  172 +++++++++----------
 src/core/window-private.h    |    1 +
 src/core/window.c            |    9 +
 src/tests/test-runner.c      |   22 +--
 src/wayland/window-wayland.c |   10 +-
 11 files changed, 373 insertions(+), 414 deletions(-)
---
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 59ce085..f137363 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -166,6 +166,7 @@ struct _MetaDisplay
   /*< private-ish >*/
   MetaScreen *screen;
   GHashTable *xids;
+  GHashTable *stamps;
   GHashTable *wayland_windows;
 
   /* serials of leave/unmap events that may
@@ -341,6 +342,29 @@ void        meta_display_register_x_window   (MetaDisplay *display,
 void        meta_display_unregister_x_window (MetaDisplay *display,
                                               Window       xwindow);
 
+/* Each MetaWindow is uniquely identified by a 64-bit "stamp"; unlike a
+ * a MetaWindow *, a stamp will never be recycled
+ */
+MetaWindow* meta_display_lookup_stamp     (MetaDisplay *display,
+                                           guint64      stamp);
+void        meta_display_register_stamp   (MetaDisplay *display,
+                                           guint64     *stampp,
+                                           MetaWindow  *window);
+void        meta_display_unregister_stamp (MetaDisplay *display,
+                                           guint64      stamp);
+
+/* A "stack id" is a XID or a stamp */
+
+#define META_STACK_ID_IS_X11(id) ((id) < G_GUINT64_CONSTANT(0x100000000))
+MetaWindow* meta_display_lookup_stack_id   (MetaDisplay *display,
+                                            guint64      stack_id);
+
+/* for debug logging only; returns a human-description of the stack
+ * ID - a small number of buffers are recycled, so the result must
+ * be used immediately or copied */
+const char *meta_display_describe_stack_id (MetaDisplay *display,
+                                            guint64      stack_id);
+
 void        meta_display_register_wayland_window   (MetaDisplay *display,
                                                     MetaWindow  *window);
 void        meta_display_unregister_wayland_window (MetaDisplay *display,
diff --git a/src/core/display.c b/src/core/display.c
index 38630d6..11cab2d 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -627,6 +627,8 @@ meta_display_open (void)
 
   display->xids = g_hash_table_new (meta_unsigned_long_hash,
                                         meta_unsigned_long_equal);
+  display->stamps = g_hash_table_new (g_int64_hash,
+                                      g_int64_equal);
   display->wayland_windows = g_hash_table_new (NULL, NULL);
 
   i = 0;
@@ -1581,6 +1583,68 @@ meta_display_unregister_wayland_window (MetaDisplay *display,
   g_hash_table_remove (display->wayland_windows, window);
 }
 
+MetaWindow*
+meta_display_lookup_stamp (MetaDisplay *display,
+                           guint64       stamp)
+{
+  return g_hash_table_lookup (display->stamps, &stamp);
+}
+
+void
+meta_display_register_stamp (MetaDisplay *display,
+                             guint64     *stampp,
+                             MetaWindow  *window)
+{
+  g_return_if_fail (g_hash_table_lookup (display->stamps, stampp) == NULL);
+
+  g_hash_table_insert (display->stamps, stampp, window);
+}
+
+void
+meta_display_unregister_stamp (MetaDisplay *display,
+                               guint64      stamp)
+{
+  g_return_if_fail (g_hash_table_lookup (display->stamps, &stamp) != NULL);
+
+  g_hash_table_remove (display->stamps, &stamp);
+}
+
+MetaWindow*
+meta_display_lookup_stack_id (MetaDisplay *display,
+                              guint64      stack_id)
+{
+  if (META_STACK_ID_IS_X11 (stack_id))
+    return meta_display_lookup_x_window (display, (Window)stack_id);
+  else
+    return meta_display_lookup_stamp (display, stack_id);
+}
+
+/* We return a pointer into a ring of static buffers. This is to make
+ * using this function for debug-logging convenient and avoid tempory
+ * strings that must be freed. */
+const char *
+meta_display_describe_stack_id (MetaDisplay *display,
+                                guint64      stack_id)
+{
+  /* 0x<64-bit: 16 characters> (<10 characters of title>)\0' */
+  static char buffer[5][32];
+  MetaWindow *window;
+  static int pos = 0;
+  char *result;
+
+  result = buffer[pos];
+  pos = (pos + 1) % 5;
+
+  window = meta_display_lookup_stack_id (display, stack_id);
+
+  if (window && window->title)
+    snprintf (result, sizeof(buffer[0]), "%#" G_GINT64_MODIFIER "x (%.10s)", stack_id, window->title);
+  else
+    snprintf (result, sizeof(buffer[0]), "%#" G_GINT64_MODIFIER "x", stack_id);
+
+  return result;
+}
+
 /* We store sync alarms in the window ID hash table, because they are
  * just more types of XIDs in the same global space, but we have
  * typesafe functions to register/unregister for readability.
diff --git a/src/core/frame.c b/src/core/frame.c
index 0ab7bee..1b39371 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -39,7 +39,6 @@ meta_window_ensure_frame (MetaWindow *window)
   XSetWindowAttributes attrs;
   Visual *visual;
   gulong create_serial;
-  MetaStackWindow stack_window;
 
   if (window->frame)
     return;
@@ -95,10 +94,8 @@ meta_window_ensure_frame (MetaWindow *window)
                                                frame->rect.height,
                                                frame->window->screen->number,
                                                 &create_serial);
-  stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
-  stack_window.x11.xwindow = frame->xwindow;
   meta_stack_tracker_record_add (window->screen->stack_tracker,
-                                 &stack_window,
+                                 frame->xwindow,
                                  create_serial);
 
   meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow);
@@ -132,9 +129,8 @@ meta_window_ensure_frame (MetaWindow *window)
       window->unmaps_pending += 1;
     }
 
-  stack_window.x11.xwindow = window->xwindow;
   meta_stack_tracker_record_remove (window->screen->stack_tracker,
-                                    &stack_window,
+                                    window->xwindow,
                                     XNextRequest (window->display->xdisplay));
   XReparentWindow (window->display->xdisplay,
                    window->xwindow,
@@ -179,7 +175,6 @@ meta_window_destroy_frame (MetaWindow *window)
 {
   MetaFrame *frame;
   MetaFrameBorders borders;
-  MetaStackWindow stack_window;
 
   if (window->frame == NULL)
     return;
@@ -206,10 +201,8 @@ meta_window_destroy_frame (MetaWindow *window)
                   "Incrementing unmaps_pending on %s for reparent back to root\n", window->desc);
       window->unmaps_pending += 1;
     }
-  stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
-  stack_window.x11.xwindow = window->xwindow;
   meta_stack_tracker_record_add (window->screen->stack_tracker,
-                                 &stack_window,
+                                 window->xwindow,
                                  XNextRequest (window->display->xdisplay));
   XReparentWindow (window->display->xdisplay,
                    window->xwindow,
diff --git a/src/core/screen.c b/src/core/screen.c
index 6051c5c..00a0a52 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -441,7 +441,6 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
   XSetWindowAttributes attributes;
   Window guard_window;
   gulong create_serial;
-  MetaStackWindow stack_window;
 
   attributes.event_mask = NoEventMask;
   attributes.override_redirect = True;
@@ -487,14 +486,12 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
       }
   }
 
-  stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
-  stack_window.x11.xwindow = guard_window;
   meta_stack_tracker_record_add (screen->stack_tracker,
-                                 &stack_window,
+                                 guard_window,
                                  create_serial);
 
   meta_stack_tracker_record_lower (screen->stack_tracker,
-                                   &stack_window,
+                                   guard_window,
                                    XNextRequest (xdisplay));
   XLowerWindow (xdisplay, guard_window);
   XMapWindow (xdisplay, guard_window);
@@ -884,19 +881,20 @@ meta_screen_create_guard_window (MetaScreen *screen)
 void
 meta_screen_manage_all_windows (MetaScreen *screen)
 {
-  MetaStackWindow *_children;
-  MetaStackWindow *children;
+  guint64 *_children;
+  guint64 *children;
   int n_children, i;
 
   meta_stack_freeze (screen->stack);
   meta_stack_tracker_get_stack (screen->stack_tracker, &_children, &n_children);
 
   /* Copy the stack as it will be modified as part of the loop */
-  children = g_memdup (_children, sizeof (MetaStackWindow) * n_children);
+  children = g_memdup (_children, sizeof (guint64) * n_children);
 
   for (i = 0; i < n_children; ++i)
     {
-      meta_window_x11_new (screen->display, children[i].x11.xwindow, TRUE,
+      g_assert (META_STACK_ID_IS_X11 (children[i]));
+      meta_window_x11_new (screen->display, children[i], TRUE,
                            META_COMP_EFFECT_NONE);
     }
 
diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c
index c692dda..afb38e4 100644
--- a/src/core/stack-tracker.c
+++ b/src/core/stack-tracker.c
@@ -96,29 +96,29 @@ union _MetaStackOp
   struct {
     MetaStackOpType type;
     gulong serial;
-    MetaStackWindow window;
+    guint64 window;
   } any;
   struct {
     MetaStackOpType type;
     gulong serial;
-    MetaStackWindow window;
+    guint64 window;
   } add;
   struct {
     MetaStackOpType type;
     gulong serial;
-    MetaStackWindow window;
+    guint64 window;
   } remove;
   struct {
     MetaStackOpType type;
     gulong serial;
-    MetaStackWindow window;
-    MetaStackWindow sibling;
+    guint64 window;
+    guint64 sibling;
   } raise_above;
   struct {
     MetaStackOpType type;
     gulong serial;
-    MetaStackWindow window;
-    MetaStackWindow sibling;
+    guint64 window;
+    guint64 sibling;
   } lower_below;
 };
 
@@ -157,95 +157,65 @@ struct _MetaStackTracker
   guint sync_stack_later;
 };
 
-static gboolean
-meta_stack_window_is_set (const MetaStackWindow *window)
-{
-  if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
-    return window->x11.xwindow == None ? FALSE : TRUE;
-  else
-    return window->wayland.meta_window ? TRUE : FALSE;
-}
-
-gboolean
-meta_stack_window_equal (const MetaStackWindow *a,
-                         const MetaStackWindow *b)
-{
-  if (a->any.type == b->any.type)
-    {
-      if (a->any.type == META_WINDOW_CLIENT_TYPE_X11)
-        return a->x11.xwindow == b->x11.xwindow;
-      else
-        return a->wayland.meta_window == b->wayland.meta_window;
-    }
-  else
-    return FALSE;
-}
-
-static char *
-get_window_id (MetaStackWindow *window)
+static inline const char *
+get_window_desc (MetaStackTracker *tracker,
+                 guint64           window)
 {
-  if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
-    return g_strdup_printf ("X11:%lx", window->x11.xwindow);
-  else
-    return g_strdup_printf ("Wayland:%p", window->wayland.meta_window);
+  return meta_display_describe_stack_id (tracker->screen->display, window);
 }
 
 static void
-meta_stack_op_dump (MetaStackOp *op,
-                   const char  *prefix,
-                   const char  *suffix)
+meta_stack_op_dump (MetaStackTracker *tracker,
+                    MetaStackOp      *op,
+                   const char       *prefix,
+                   const char       *suffix)
 {
-  char *window_id = get_window_id (&op->any.window);
+  const char *window_desc = get_window_desc (tracker, op->any.window);
 
   switch (op->any.type)
     {
     case STACK_OP_ADD:
       meta_topic (META_DEBUG_STACK, "%sADD(%s; %ld)%s",
-                 prefix, window_id, op->any.serial, suffix);
+                 prefix, window_desc, op->any.serial, suffix);
       break;
     case STACK_OP_REMOVE:
       meta_topic (META_DEBUG_STACK, "%sREMOVE(%s; %ld)%s",
-                 prefix, window_id, op->any.serial, suffix);
+                 prefix, window_desc, op->any.serial, suffix);
       break;
     case STACK_OP_RAISE_ABOVE:
       {
-        char *sibling_id = get_window_id (&op->raise_above.sibling);
         meta_topic (META_DEBUG_STACK, "%sRAISE_ABOVE(%s, %s; %ld)%s",
                     prefix,
-                    window_id, sibling_id,
+                    window_desc,
+                    get_window_desc (tracker, op->raise_above.sibling),
                     op->any.serial,
                     suffix);
-        g_free (sibling_id);
         break;
       }
     case STACK_OP_LOWER_BELOW:
       {
-        char *sibling_id = get_window_id (&op->lower_below.sibling);
         meta_topic (META_DEBUG_STACK, "%sLOWER_BELOW(%s, %s; %ld)%s",
                     prefix,
-                    window_id, sibling_id,
+                    window_desc,
+                    get_window_desc (tracker, op->lower_below.sibling),
                     op->any.serial,
                     suffix);
-        g_free (sibling_id);
         break;
       }
     }
-
-  g_free (window_id);
 }
 
 static void
-stack_dump (GArray *stack)
+stack_dump (MetaStackTracker *tracker,
+            GArray           *stack)
 {
   guint i;
 
   meta_push_no_msg_prefix ();
   for (i = 0; i < stack->len; i++)
     {
-      MetaStackWindow *window = &g_array_index (stack, MetaStackWindow, i);
-      char *window_id = get_window_id (window);
-      meta_topic (META_DEBUG_STACK, "  %s", window_id);
-      g_free (window_id);
+      guint64 window = g_array_index (stack, guint64, i);
+      meta_topic (META_DEBUG_STACK, "  %s", get_window_desc (tracker, window));
     }
   meta_topic (META_DEBUG_STACK, "\n");
   meta_pop_no_msg_prefix ();
@@ -260,20 +230,20 @@ meta_stack_tracker_dump (MetaStackTracker *tracker)
   meta_push_no_msg_prefix ();
   meta_topic (META_DEBUG_STACK, "  xserver_serial: %ld\n", tracker->xserver_serial);
   meta_topic (META_DEBUG_STACK, "  xserver_stack: ");
-  stack_dump (tracker->xserver_stack);
+  stack_dump (tracker, tracker->xserver_stack);
   meta_topic (META_DEBUG_STACK, "  verfied_stack: ");
-  stack_dump (tracker->verified_stack);
+  stack_dump (tracker, tracker->verified_stack);
   meta_topic (META_DEBUG_STACK, "  unverified_predictions: [");
   for (l = tracker->unverified_predictions->head; l; l = l->next)
     {
       MetaStackOp *op = l->data;
-      meta_stack_op_dump (op, "", l->next ? ", " : "");
+      meta_stack_op_dump (tracker, op, "", l->next ? ", " : "");
     }
   meta_topic (META_DEBUG_STACK, "]\n");
   if (tracker->predicted_stack)
     {
       meta_topic (META_DEBUG_STACK, "\n  predicted_stack: ");
-      stack_dump (tracker->predicted_stack);
+      stack_dump (tracker, tracker->predicted_stack);
     }
   meta_pop_no_msg_prefix ();
 }
@@ -285,23 +255,16 @@ meta_stack_op_free (MetaStackOp *op)
 }
 
 static int
-find_window (GArray *window_stack,
-             MetaStackWindow *window)
+find_window (GArray  *window_stack,
+             guint64  window)
 {
   guint i;
 
   for (i = 0; i < window_stack->len; i++)
     {
-      MetaStackWindow *current = &g_array_index (window_stack, MetaStackWindow, i);
-      if (current->any.type == window->any.type)
-        {
-          if (current->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
-              current->x11.xwindow == window->x11.xwindow)
-            return i;
-          else
-            if (current->wayland.meta_window == window->wayland.meta_window)
-              return i;
-        }
+      guint64 current = g_array_index (window_stack, guint64, i);
+      if (current == window)
+        return i;
     }
 
   return -1;
@@ -309,33 +272,30 @@ find_window (GArray *window_stack,
 
 /* Returns TRUE if stack was changed */
 static gboolean
-move_window_above (GArray          *stack,
-                   MetaStackWindow *window,
-                   int              old_pos,
-                   int              above_pos)
+move_window_above (GArray  *stack,
+                   guint64  window,
+                   int      old_pos,
+                   int      above_pos)
 {
-  /* Copy the window by-value before we start shifting things around
-   * in the stack in case window points into the stack itself. */
-  MetaStackWindow window_val = *window;
   int i;
 
   if (old_pos < above_pos)
     {
       for (i = old_pos; i < above_pos; i++)
-       g_array_index (stack, MetaStackWindow, i) =
-          g_array_index (stack, MetaStackWindow, i + 1);
+       g_array_index (stack, guint64, i) =
+          g_array_index (stack, guint64, i + 1);
 
-      g_array_index (stack, MetaStackWindow, above_pos) = window_val;
+      g_array_index (stack, guint64, above_pos) = window;
 
       return TRUE;
     }
   else if (old_pos > above_pos + 1)
     {
       for (i = old_pos; i > above_pos + 1; i--)
-       g_array_index (stack, MetaStackWindow, i) =
-          g_array_index (stack, MetaStackWindow, i - 1);
+       g_array_index (stack, guint64, i) =
+          g_array_index (stack, guint64, i - 1);
 
-      g_array_index (stack, MetaStackWindow, above_pos + 1) = window_val;
+      g_array_index (stack, guint64, above_pos + 1) = window;
 
       return TRUE;
     }
@@ -345,20 +305,19 @@ move_window_above (GArray          *stack,
 
 /* Returns TRUE if stack was changed */
 static gboolean
-meta_stack_op_apply (MetaStackOp *op,
-                    GArray      *stack)
+meta_stack_op_apply (MetaStackTracker *tracker,
+                     MetaStackOp      *op,
+                    GArray           *stack)
 {
   switch (op->any.type)
     {
     case STACK_OP_ADD:
       {
-       int old_pos = find_window (stack, &op->add.window);
+       int old_pos = find_window (stack, op->add.window);
        if (old_pos >= 0)
          {
-            char *window_id = get_window_id (&op->add.window);
            g_warning ("STACK_OP_ADD: window %s already in stack",
-                      window_id);
-            g_free (window_id);
+                      get_window_desc (tracker, op->add.window));
            return FALSE;
          }
 
@@ -367,13 +326,11 @@ meta_stack_op_apply (MetaStackOp *op,
       }
     case STACK_OP_REMOVE:
       {
-       int old_pos = find_window (stack, &op->remove.window);
+       int old_pos = find_window (stack, op->remove.window);
        if (old_pos < 0)
          {
-            char *window_id = get_window_id (&op->remove.window);
            g_warning ("STACK_OP_REMOVE: window %s not in stack",
-                      window_id);
-            g_free (window_id);
+                      get_window_desc (tracker, op->remove.window));
            return FALSE;
          }
 
@@ -382,26 +339,22 @@ meta_stack_op_apply (MetaStackOp *op,
       }
     case STACK_OP_RAISE_ABOVE:
       {
-       int old_pos = find_window (stack, &op->raise_above.window);
+       int old_pos = find_window (stack, op->raise_above.window);
        int above_pos;
        if (old_pos < 0)
          {
-            char *window_id = get_window_id (&op->raise_above.window);
            g_warning ("STACK_OP_RAISE_ABOVE: window %s not in stack",
-                      window_id);
-            g_free (window_id);
+                      get_window_desc (tracker, op->raise_above.window));
            return FALSE;
          }
 
-        if (meta_stack_window_is_set (&op->raise_above.sibling))
+        if (op->raise_above.sibling)
          {
-           above_pos = find_window (stack, &op->raise_above.sibling);
+           above_pos = find_window (stack, op->raise_above.sibling);
            if (above_pos < 0)
              {
-                char *sibling_id = get_window_id (&op->raise_above.sibling);
                g_warning ("STACK_OP_RAISE_ABOVE: sibling window %s not in stack",
-                          sibling_id);
-                g_free (sibling_id);
+                           get_window_desc (tracker, op->raise_above.sibling));
                return FALSE;
              }
          }
@@ -410,30 +363,26 @@ meta_stack_op_apply (MetaStackOp *op,
            above_pos = -1;
          }
 
-       return move_window_above (stack, &op->raise_above.window, old_pos, above_pos);
+       return move_window_above (stack, op->raise_above.window, old_pos, above_pos);
       }
     case STACK_OP_LOWER_BELOW:
       {
-       int old_pos = find_window (stack, &op->lower_below.window);
+       int old_pos = find_window (stack, op->lower_below.window);
        int above_pos;
        if (old_pos < 0)
          {
-            char *window_id = get_window_id (&op->lower_below.window);
            g_warning ("STACK_OP_LOWER_BELOW: window %s not in stack",
-                      window_id);
-            g_free (window_id);
+                      get_window_desc (tracker, op->lower_below.window));
            return FALSE;
          }
 
-        if (meta_stack_window_is_set (&op->lower_below.sibling))
+        if (op->lower_below.sibling)
          {
-           int below_pos = find_window (stack, &op->lower_below.sibling);
+           int below_pos = find_window (stack, op->lower_below.sibling);
            if (below_pos < 0)
              {
-                char *sibling_id = get_window_id (&op->lower_below.sibling);
                g_warning ("STACK_OP_LOWER_BELOW: sibling window %s not in stack",
-                          sibling_id);
-                g_free (sibling_id);
+                          get_window_desc (tracker, op->lower_below.sibling));
                return FALSE;
              }
 
@@ -444,7 +393,7 @@ meta_stack_op_apply (MetaStackOp *op,
            above_pos = stack->len - 1;
          }
 
-       return move_window_above (stack, &op->lower_below.window, old_pos, above_pos);
+       return move_window_above (stack, op->lower_below.window, old_pos, above_pos);
       }
     }
 
@@ -455,11 +404,11 @@ meta_stack_op_apply (MetaStackOp *op,
 static GArray *
 copy_stack (GArray *stack)
 {
-  GArray *copy = g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), stack->len);
+  GArray *copy = g_array_sized_new (FALSE, FALSE, sizeof (guint64), stack->len);
 
   g_array_set_size (copy, stack->len);
 
-  memcpy (copy->data, stack->data, sizeof (MetaStackWindow) * stack->len);
+  memcpy (copy->data, stack->data, sizeof (guint64) * stack->len);
 
   return copy;
 }
@@ -482,15 +431,11 @@ requery_xserver_stack (MetaStackTracker *tracker)
               screen->xroot,
               &ignored1, &ignored2, &children, &n_children);
 
-  tracker->xserver_stack = g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), n_children);
+  tracker->xserver_stack = g_array_sized_new (FALSE, FALSE, sizeof (guint64), n_children);
   g_array_set_size (tracker->xserver_stack, n_children);
 
   for (i = 0; i < n_children; i++)
-    {
-      MetaStackWindow *window = &g_array_index (tracker->xserver_stack, MetaStackWindow, i);
-      window->any.type = META_WINDOW_CLIENT_TYPE_X11;
-      window->x11.xwindow = children[i];
-    }
+    g_array_index (tracker->xserver_stack, guint64, i) = children[i];
 
   XFree (children);
 }
@@ -542,22 +487,22 @@ stack_tracker_apply_prediction (MetaStackTracker *tracker,
    * we can apply it immediately so long as it doesn't depend on any
    * unverified X operations...
    */
-  if (op->any.window.any.type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
+  if (!META_STACK_ID_IS_X11 (op->any.window) &&
       tracker->unverified_predictions->length == 0)
     {
-      if (meta_stack_op_apply (op, tracker->verified_stack))
+      if (meta_stack_op_apply (tracker, op, tracker->verified_stack))
         meta_stack_tracker_queue_sync_stack (tracker);
 
       free_at_end = TRUE;
     }
   else
     {
-      meta_stack_op_dump (op, "Predicting: ", "\n");
+      meta_stack_op_dump (tracker, op, "Predicting: ", "\n");
       g_queue_push_tail (tracker->unverified_predictions, op);
     }
 
   if (!tracker->predicted_stack ||
-      meta_stack_op_apply (op, tracker->predicted_stack))
+      meta_stack_op_apply (tracker, op, tracker->predicted_stack))
     meta_stack_tracker_queue_sync_stack (tracker);
 
   if (free_at_end)
@@ -567,38 +512,38 @@ stack_tracker_apply_prediction (MetaStackTracker *tracker,
 }
 
 void
-meta_stack_tracker_record_add (MetaStackTracker       *tracker,
-                               const MetaStackWindow  *window,
-                              gulong                  serial)
+meta_stack_tracker_record_add (MetaStackTracker *tracker,
+                               guint64           window,
+                              gulong            serial)
 {
   MetaStackOp *op = g_slice_new (MetaStackOp);
 
   op->any.type = STACK_OP_ADD;
   op->any.serial = serial;
-  op->any.window = *window;
+  op->any.window = window;
 
   stack_tracker_apply_prediction (tracker, op);
 }
 
 void
-meta_stack_tracker_record_remove (MetaStackTracker      *tracker,
-                                  const MetaStackWindow *window,
-                                 gulong                 serial)
+meta_stack_tracker_record_remove (MetaStackTracker *tracker,
+                                  guint64           window,
+                                 gulong            serial)
 {
   MetaStackOp *op = g_slice_new (MetaStackOp);
 
   op->any.type = STACK_OP_REMOVE;
   op->any.serial = serial;
-  op->any.window = *window;
+  op->any.window = window;
 
   stack_tracker_apply_prediction (tracker, op);
 }
 
 void
-meta_stack_tracker_record_restack_windows (MetaStackTracker       *tracker,
-                                           const MetaStackWindow  *windows,
-                                          int                     n_windows,
-                                          gulong                  serial)
+meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker,
+                                           const guint64    *windows,
+                                          int               n_windows,
+                                          gulong            serial)
 {
   int i;
   int n_x_windows = 0;
@@ -619,14 +564,14 @@ meta_stack_tracker_record_restack_windows (MetaStackTracker       *tracker,
    * events with intermediate serials, set n_complete rather than
    * removing the op from the queue.
    */
-  if (n_windows && windows[0].any.type == META_WINDOW_CLIENT_TYPE_X11)
+  if (n_windows && META_STACK_ID_IS_X11 (windows[0]))
     n_x_windows++;
   for (i = 0; i < n_windows - 1; i++)
     {
-      const MetaStackWindow *lower = &windows[i + 1];
+      guint64 lower = windows[i + 1];
       gboolean involves_x = FALSE;
 
-      if (lower->any.type == META_WINDOW_CLIENT_TYPE_X11)
+      if (META_STACK_ID_IS_X11 (lower))
         {
           n_x_windows++;
 
@@ -637,61 +582,49 @@ meta_stack_tracker_record_restack_windows (MetaStackTracker       *tracker,
             involves_x = TRUE;
         }
 
-      meta_stack_tracker_record_lower_below (tracker, lower, &windows[i],
+      meta_stack_tracker_record_lower_below (tracker, lower, windows[i],
                                              involves_x ? serial++ : 0);
     }
 }
 
 void
-meta_stack_tracker_record_raise_above (MetaStackTracker       *tracker,
-                                       const MetaStackWindow  *window,
-                                       const MetaStackWindow  *sibling,
-                                      gulong                  serial)
+meta_stack_tracker_record_raise_above (MetaStackTracker *tracker,
+                                       guint64           window,
+                                       guint64           sibling,
+                                      gulong            serial)
 {
   MetaStackOp *op = g_slice_new (MetaStackOp);
 
   op->any.type = STACK_OP_RAISE_ABOVE;
   op->any.serial = serial;
-  op->any.window = *window;
-  if (sibling)
-    op->raise_above.sibling = *sibling;
-  else
-    {
-      op->raise_above.sibling.any.type = META_WINDOW_CLIENT_TYPE_X11;
-      op->raise_above.sibling.x11.xwindow = None;
-    }
+  op->any.window = window;
+  op->raise_above.sibling = sibling;
 
   stack_tracker_apply_prediction (tracker, op);
 }
 
 void
-meta_stack_tracker_record_lower_below (MetaStackTracker       *tracker,
-                                       const MetaStackWindow  *window,
-                                       const MetaStackWindow  *sibling,
-                                      gulong                  serial)
+meta_stack_tracker_record_lower_below (MetaStackTracker *tracker,
+                                       guint64           window,
+                                       guint64           sibling,
+                                      gulong            serial)
 {
   MetaStackOp *op = g_slice_new (MetaStackOp);
 
   op->any.type = STACK_OP_LOWER_BELOW;
   op->any.serial = serial;
-  op->any.window = *window;
-  if (sibling)
-    op->lower_below.sibling = *sibling;
-  else
-    {
-      op->lower_below.sibling.any.type = META_WINDOW_CLIENT_TYPE_X11;
-      op->lower_below.sibling.x11.xwindow = None;
-    }
+  op->any.window = window;
+  op->lower_below.sibling = sibling;
 
   stack_tracker_apply_prediction (tracker, op);
 }
 
 void
-meta_stack_tracker_record_lower (MetaStackTracker       *tracker,
-                                 const MetaStackWindow  *window,
-                                gulong                  serial)
+meta_stack_tracker_record_lower (MetaStackTracker *tracker,
+                                 guint64           window,
+                                gulong            serial)
 {
-  meta_stack_tracker_record_raise_above (tracker, window, NULL, serial);
+  meta_stack_tracker_record_raise_above (tracker, window, None, serial);
 }
 
 /* @op is an operation derived from an X event from the server and we
@@ -720,7 +653,7 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker,
 
   /* Wayland operations don't need to be verified and shouldn't end up
    * passed to this api. */
-  g_return_val_if_fail (op->any.window.any.type == META_WINDOW_CLIENT_TYPE_X11, FALSE);
+  g_return_val_if_fail (META_STACK_ID_IS_X11 (op->any.window), FALSE);
 
   meta_topic (META_DEBUG_STACK, "Verifying predictions:\n");
 
@@ -737,69 +670,61 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker,
           if (current_op->any.serial > op->any.serial)
             break;
 
-          modified_stack |= meta_stack_op_apply (current_op, predicted_stack);
+          modified_stack |= meta_stack_op_apply (tracker, current_op, predicted_stack);
         }
     }
   else
     predicted_stack = tracker->verified_stack;
 
   meta_topic (META_DEBUG_STACK, "  predicted_stack: ");
-  stack_dump (predicted_stack);
+  stack_dump (tracker, predicted_stack);
 
   switch (op->any.type)
     {
     case STACK_OP_ADD:
-      if (!find_window (predicted_stack, &op->any.window))
+      if (!find_window (predicted_stack, op->any.window))
         {
-          char *window_id = get_window_id (&op->any.window);
           meta_topic (META_DEBUG_STACK, "Verify STACK_OP_ADD: window %s not found\n",
-                      window_id);
-          g_free (window_id);
+                      get_window_desc (tracker, op->any.window));
           goto not_verified;
         }
       break;
     case STACK_OP_REMOVE:
-      if (find_window (predicted_stack, &op->any.window))
+      if (find_window (predicted_stack, op->any.window))
         {
-          char *window_id = get_window_id (&op->any.window);
           meta_topic (META_DEBUG_STACK, "Verify STACK_OP_REMOVE: window %s was unexpectedly found\n",
-                      window_id);
-          g_free (window_id);
+                      get_window_desc (tracker, op->any.window));
           goto not_verified;
         }
       break;
     case STACK_OP_RAISE_ABOVE:
       {
         Window last_xwindow = None;
-        char *window_id;
         unsigned int i;
 
         /* This code is only intended for verifying operations based
          * on XEvents where we can assume the sibling refers to
          * another X window...  */
-        g_return_val_if_fail (op->raise_above.sibling.any.type ==
-                              META_WINDOW_CLIENT_TYPE_X11, FALSE);
+        g_return_val_if_fail (META_STACK_ID_IS_X11 (op->raise_above.sibling), FALSE);
 
         for (i = 0; i < predicted_stack->len; i++)
           {
-            MetaStackWindow *window = &g_array_index (predicted_stack, MetaStackWindow, i);
+            guint64 window = g_array_index (predicted_stack, guint64, i);
 
-            if (meta_stack_window_equal (window, &op->any.window))
+            if (window == op->any.window)
               {
-                if (last_xwindow == op->raise_above.sibling.x11.xwindow)
+                if (last_xwindow == op->raise_above.sibling)
                   goto verified;
                 else
                   goto not_verified;
               }
 
-            if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
-              last_xwindow = window->x11.xwindow;
+            if (META_STACK_ID_IS_X11 (window))
+              last_xwindow = window;
           }
 
-        window_id = get_window_id (&op->any.window);
         meta_topic (META_DEBUG_STACK, "Verify STACK_OP_RAISE_ABOVE: window %s not found\n",
-                    window_id);
-        g_free (window_id);
+                    get_window_desc (tracker, op->any.window));
         goto not_verified;
       }
     case STACK_OP_LOWER_BELOW:
@@ -861,7 +786,7 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
 {
   GList *l;
   unsigned int i, j;
-  MetaStackWindow *expected_xwindow;
+  guint64 expected_xwindow;
   gboolean modified_stack = FALSE;
 
   /* Overview of the algorithm:
@@ -896,29 +821,28 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
 
   for (l = tracker->unverified_predictions->head; l; l = l->next)
     {
-      meta_stack_op_apply (l->data, tracker->verified_stack);
+      meta_stack_op_apply (tracker, l->data, tracker->verified_stack);
       meta_stack_op_free (l->data);
     }
   g_queue_clear (tracker->unverified_predictions);
 
   j = 0;
-  expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
+  expected_xwindow = g_array_index (tracker->xserver_stack, guint64, j);
 
   for (i = 0; i < tracker->verified_stack->len; )
     {
-      MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
+      guint64 current = g_array_index (tracker->verified_stack, guint64, i);
 
-      if (current->any.type != META_WINDOW_CLIENT_TYPE_X11)
+      if (!META_STACK_ID_IS_X11 (current))
         {
           /* Progress i but not j */
           i++;
           continue;
         }
 
-      if (current->x11.xwindow != expected_xwindow->x11.xwindow)
+      if (current != expected_xwindow)
         {
-          MetaStackWindow new;
-          MetaStackWindow *expected;
+          guint64 expected;
           int expected_index;
 
           /* If the current window corresponds to a window that's not
@@ -947,17 +871,14 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
 
           if (expected_index >= 0)
             {
-              expected = &g_array_index (tracker->verified_stack,
-                                         MetaStackWindow, expected_index);
+              expected = g_array_index (tracker->verified_stack,
+                                        guint64, expected_index);
             }
           else
             {
-              new.any.type = META_WINDOW_CLIENT_TYPE_X11;
-              new.x11.xwindow = expected_xwindow->x11.xwindow;
-
-              g_array_append_val (tracker->verified_stack, new);
+              g_array_append_val (tracker->verified_stack, expected_xwindow);
 
-              expected = &new;
+              expected = expected_xwindow;
               expected_index = tracker->verified_stack->len - 1;
             }
 
@@ -981,7 +902,7 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
       i++;
 
       j++;
-      expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
+      expected_xwindow = g_array_index (tracker->xserver_stack, guint64, j);
 
       if (j >= tracker->xserver_stack->len)
         break;
@@ -991,9 +912,9 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
    * xserver_stack and so we can remove them. */
   while (i < tracker->verified_stack->len)
     {
-      MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
+      guint64 current = g_array_index (tracker->verified_stack, guint64, i);
 
-      if (current->any.type == META_WINDOW_CLIENT_TYPE_X11)
+      if (META_STACK_ID_IS_X11 (current))
         g_array_remove_index (tracker->verified_stack, i);
       else
         i++;
@@ -1005,8 +926,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
    * entries in xserver_stack then append them all to the end */
   for (; j < tracker->xserver_stack->len; j++)
     {
-      MetaStackWindow *current = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
-      g_array_append_val (tracker->verified_stack, *current);
+      guint64 current = g_array_index (tracker->xserver_stack, guint64, j);
+      g_array_append_val (tracker->verified_stack, current);
 
       modified_stack = TRUE;
     }
@@ -1034,7 +955,7 @@ stack_tracker_event_received (MetaStackTracker *tracker,
   if (op->any.serial < tracker->xserver_serial)
     return;
 
-  meta_stack_op_dump (op, "Stack op event received: ", "\n");
+  meta_stack_op_dump (tracker, op, "Stack op event received: ", "\n");
 
   tracker->xserver_serial = op->any.serial;
 
@@ -1047,7 +968,7 @@ stack_tracker_event_received (MetaStackTracker *tracker,
    *
    * TODO: remove tracker->xserver_stack.
    */
-  meta_stack_op_apply (op, tracker->xserver_stack);
+  meta_stack_op_apply (tracker, op, tracker->xserver_stack);
 
   if (!stack_tracker_verify_predictions (tracker, op))
     resync_verified_stack_with_xserver_stack (tracker);
@@ -1063,8 +984,7 @@ meta_stack_tracker_create_event (MetaStackTracker    *tracker,
 
   op.any.type = STACK_OP_ADD;
   op.any.serial = event->serial;
-  op.add.window.any.type = META_WINDOW_CLIENT_TYPE_X11;
-  op.add.window.x11.xwindow = event->window;
+  op.add.window = event->window;
 
   stack_tracker_event_received (tracker, &op);
 }
@@ -1077,8 +997,7 @@ meta_stack_tracker_destroy_event (MetaStackTracker    *tracker,
 
   op.any.type = STACK_OP_REMOVE;
   op.any.serial = event->serial;
-  op.remove.window.any.type = META_WINDOW_CLIENT_TYPE_X11;
-  op.remove.window.x11.xwindow = event->window;
+  op.remove.window = event->window;
 
   stack_tracker_event_received (tracker, &op);
 }
@@ -1093,8 +1012,7 @@ meta_stack_tracker_reparent_event (MetaStackTracker    *tracker,
 
       op.any.type = STACK_OP_ADD;
       op.any.serial = event->serial;
-      op.add.window.any.type = META_WINDOW_CLIENT_TYPE_X11;
-      op.add.window.x11.xwindow = event->window;
+      op.add.window = event->window;
 
       stack_tracker_event_received (tracker, &op);
     }
@@ -1104,8 +1022,7 @@ meta_stack_tracker_reparent_event (MetaStackTracker    *tracker,
 
       op.any.type = STACK_OP_REMOVE;
       op.any.serial = event->serial;
-      op.remove.window.any.type = META_WINDOW_CLIENT_TYPE_X11;
-      op.remove.window.x11.xwindow = event->window;
+      op.remove.window = event->window;
 
       stack_tracker_event_received (tracker, &op);
     }
@@ -1119,10 +1036,8 @@ meta_stack_tracker_configure_event (MetaStackTracker    *tracker,
 
   op.any.type = STACK_OP_RAISE_ABOVE;
   op.any.serial = event->serial;
-  op.raise_above.window.any.type = META_WINDOW_CLIENT_TYPE_X11;
-  op.raise_above.window.x11.xwindow = event->window;
-  op.raise_above.sibling.any.type = META_WINDOW_CLIENT_TYPE_X11;
-  op.raise_above.sibling.x11.xwindow = event->above;
+  op.raise_above.window = event->window;
+  op.raise_above.sibling = event->above;
 
   stack_tracker_event_received (tracker, &op);
 }
@@ -1146,7 +1061,7 @@ meta_stack_tracker_configure_event (MetaStackTracker    *tracker,
  */
 void
 meta_stack_tracker_get_stack (MetaStackTracker *tracker,
-                              MetaStackWindow **windows,
+                              guint64         **windows,
                              int              *n_windows)
 {
   GArray *stack;
@@ -1165,7 +1080,7 @@ meta_stack_tracker_get_stack (MetaStackTracker *tracker,
           for (l = tracker->unverified_predictions->head; l; l = l->next)
             {
               MetaStackOp *op = l->data;
-              meta_stack_op_apply (op, tracker->predicted_stack);
+              meta_stack_op_apply (tracker, op, tracker->predicted_stack);
             }
         }
 
@@ -1176,7 +1091,7 @@ meta_stack_tracker_get_stack (MetaStackTracker *tracker,
   meta_stack_tracker_dump (tracker);
 
   if (windows)
-    *windows = (MetaStackWindow *)stack->data;
+    *windows = (guint64 *)stack->data;
   if (n_windows)
     *n_windows = stack->len;
 }
@@ -1191,7 +1106,7 @@ meta_stack_tracker_get_stack (MetaStackTracker *tracker,
 void
 meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
 {
-  MetaStackWindow *windows;
+  guint64 *windows;
   GList *meta_windows;
   int n_windows;
   int i;
@@ -1207,12 +1122,12 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
   meta_windows = NULL;
   for (i = 0; i < n_windows; i++)
     {
-      MetaStackWindow *window = &windows[i];
+      guint64 window = windows[i];
 
-      if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
+      if (META_STACK_ID_IS_X11 (window))
         {
           MetaWindow *meta_window =
-            meta_display_lookup_x_window (tracker->screen->display, windows[i].x11.xwindow);
+            meta_display_lookup_x_window (tracker->screen->display, (Window)window);
 
           /* When mapping back from xwindow to MetaWindow we have to be a bit careful;
            * children of the root could include unmapped windows created by toolkits
@@ -1221,12 +1136,13 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
            * see window-prop.c:reload_net_wm_user_time_window() for registration.)
            */
           if (meta_window &&
-              (windows[i].x11.xwindow == meta_window->xwindow ||
-               (meta_window->frame && windows[i].x11.xwindow == meta_window->frame->xwindow)))
+              ((Window)window == meta_window->xwindow ||
+               (meta_window->frame && (Window)window == meta_window->frame->xwindow)))
             meta_windows = g_list_prepend (meta_windows, meta_window);
         }
       else
-        meta_windows = g_list_prepend (meta_windows, window->wayland.meta_window);
+        meta_windows = g_list_prepend (meta_windows,
+                                       meta_display_lookup_stamp (tracker->screen->display, window));
     }
 
   meta_compositor_sync_stack (tracker->screen->display->compositor,
diff --git a/src/core/stack-tracker.h b/src/core/stack-tracker.h
index f74400e..d54d914 100644
--- a/src/core/stack-tracker.h
+++ b/src/core/stack-tracker.h
@@ -39,51 +39,33 @@
 
 typedef struct _MetaStackTracker MetaStackTracker;
 
-typedef union _MetaStackWindow
-{
-  struct {
-    MetaWindowClientType type;
-  } any;
-  struct {
-    MetaWindowClientType type;
-    Window xwindow;
-  } x11;
-  struct {
-    MetaWindowClientType type;
-    MetaWindow *meta_window;
-  } wayland;
-} MetaStackWindow;
-
-gboolean meta_stack_window_equal (const MetaStackWindow *a,
-                                  const MetaStackWindow *b);
-
 MetaStackTracker *meta_stack_tracker_new  (MetaScreen       *screen);
 void              meta_stack_tracker_free (MetaStackTracker *tracker);
 
 /* These functions are called when we make an X call that changes the
  * stacking order; this allows MetaStackTracker to predict stacking
  * order before it receives events back from the X server */
-void meta_stack_tracker_record_add             (MetaStackTracker      *tracker,
-                                                const MetaStackWindow *window,
-                                                gulong                 serial);
-void meta_stack_tracker_record_remove          (MetaStackTracker      *tracker,
-                                                const MetaStackWindow *window,
-                                                gulong                 serial);
-void meta_stack_tracker_record_restack_windows (MetaStackTracker      *tracker,
-                                                const MetaStackWindow *windows,
-                                               int                    n_windows,
-                                                gulong                 serial);
-void meta_stack_tracker_record_raise_above     (MetaStackTracker      *tracker,
-                                                const MetaStackWindow *window,
-                                                const MetaStackWindow *sibling,
-                                                gulong                 serial);
-void meta_stack_tracker_record_lower_below    (MetaStackTracker       *tracker,
-                                               const MetaStackWindow  *window,
-                                               const MetaStackWindow  *sibling,
-                                               gulong                  serial);
-void meta_stack_tracker_record_lower           (MetaStackTracker      *tracker,
-                                                const MetaStackWindow *window,
-                                                gulong                 serial);
+void meta_stack_tracker_record_add             (MetaStackTracker *tracker,
+                                                guint64           window,
+                                                gulong            serial);
+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,
+                                                gulong            serial);
+void meta_stack_tracker_record_lower_below    (MetaStackTracker  *tracker,
+                                               guint64            window,
+                                               guint64            sibling,
+                                               gulong             serial);
+void meta_stack_tracker_record_lower           (MetaStackTracker *tracker,
+                                                guint64           window,
+                                                gulong            serial);
 
 /* These functions are used to update the stack when we get events
  * reflecting changes to the stacking order */
@@ -96,9 +78,9 @@ void meta_stack_tracker_reparent_event  (MetaStackTracker    *tracker,
 void meta_stack_tracker_configure_event (MetaStackTracker    *tracker,
                                         XConfigureEvent     *event);
 
-void meta_stack_tracker_get_stack  (MetaStackTracker      *tracker,
-                                    MetaStackWindow      **windows,
-                                    int                   *n_entries);
+void meta_stack_tracker_get_stack  (MetaStackTracker *tracker,
+                                    guint64         **windows,
+                                    int              *n_entries);
 
 void meta_stack_tracker_sync_stack       (MetaStackTracker *tracker);
 void meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker);
diff --git a/src/core/stack.c b/src/core/stack.c
index 3e26540..2ea144a 100644
--- a/src/core/stack.c
+++ b/src/core/stack.c
@@ -1030,12 +1030,12 @@ stack_ensure_sorted (MetaStack *stack)
   stack_do_resort (stack);
 }
 
-static MetaStackWindow *
+static guint64
 find_top_most_managed_window (MetaScreen *screen,
-                              const MetaStackWindow *ignore)
+                              guint64     ignore)
 {
   MetaStackTracker *stack_tracker = screen->stack_tracker;
-  MetaStackWindow *windows;
+  guint64 *windows;
   int n_windows;
   int i;
 
@@ -1048,12 +1048,9 @@ find_top_most_managed_window (MetaScreen *screen,
    */
   for (i = n_windows -1; i >= 0; i--)
     {
-      MetaStackWindow *other_window = &windows[i];
+      guint64 other_window = windows[i];
 
-      if (other_window->any.type == ignore->any.type &&
-          ((other_window->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
-            other_window->x11.xwindow == ignore->x11.xwindow) ||
-           other_window->wayland.meta_window == ignore->wayland.meta_window))
+      if (other_window == ignore)
         {
           /* Do nothing. This means we're already the topmost managed
            * window, but it DOES NOT mean we are already just above
@@ -1067,10 +1064,10 @@ find_top_most_managed_window (MetaScreen *screen,
         }
       else
         {
-          if (other_window->any.type == META_WINDOW_CLIENT_TYPE_X11)
+          if (META_STACK_ID_IS_X11 (other_window))
             {
               MetaWindow *other = meta_display_lookup_x_window (screen->display,
-                                                                other_window->x11.xwindow);
+                                                                other_window);
 
               if (other != NULL && !other->override_redirect)
                 return other_window;
@@ -1085,7 +1082,7 @@ find_top_most_managed_window (MetaScreen *screen,
         }
     }
 
-  return NULL;
+  return 0;
 }
 
 /* When moving an X window we sometimes need an X based sibling.
@@ -1094,17 +1091,17 @@ find_top_most_managed_window (MetaScreen *screen,
  * otherwise it searches downwards looking for the nearest X window.
  *
  * If no X based sibling could be found return NULL. */
-static MetaStackWindow *
+static Window
 find_x11_sibling_downwards (MetaScreen *screen,
-                            MetaStackWindow *sibling)
+                            guint64     sibling)
 {
   MetaStackTracker *stack_tracker = screen->stack_tracker;
-  MetaStackWindow *windows;
+  guint64 *windows;
   int n_windows;
   int i;
 
-  if (sibling->any.type == META_WINDOW_CLIENT_TYPE_X11)
-    return sibling;
+  if (META_STACK_ID_IS_X11 (sibling))
+    return (Window)sibling;
 
   meta_stack_tracker_get_stack (stack_tracker,
                                 &windows, &n_windows);
@@ -1114,16 +1111,16 @@ find_x11_sibling_downwards (MetaScreen *screen,
    */
 
   for (i = n_windows - 1; i >= 0; i--)
-    if (meta_stack_window_equal (&windows[i], sibling))
+    if (windows[i] == sibling)
       break;
 
   for (; i >= 0; i--)
     {
-      if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11)
-        return &windows[i];
+      if (META_STACK_ID_IS_X11 (windows[i]))
+        return (Window)windows[i];
     }
 
-  return NULL;
+  return None;
 }
 
 /**
@@ -1150,20 +1147,20 @@ find_x11_sibling_downwards (MetaScreen *screen,
  */
 static void
 raise_window_relative_to_managed_windows (MetaScreen *screen,
-                                          const MetaStackWindow *window)
+                                          guint64     stack_id)
 {
   gulong serial = 0;
-  MetaStackWindow *sibling;
+  guint64 sibling;
 
-  sibling = find_top_most_managed_window (screen, window);
+  sibling = find_top_most_managed_window (screen, stack_id);
   if (!sibling)
     {
-      if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
+      if (META_STACK_ID_IS_X11 (stack_id))
         {
           serial = XNextRequest (screen->display->xdisplay);
           meta_error_trap_push (screen->display);
           XLowerWindow (screen->display->xdisplay,
-                        window->x11.xwindow);
+                        stack_id);
           meta_error_trap_pop (screen->display);
         }
 
@@ -1171,31 +1168,31 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
        * to be sure we're below any override redirect windows.
        */
       meta_stack_tracker_record_lower (screen->stack_tracker,
-                                       window,
+                                       stack_id,
                                        serial);
       return;
     }
 
   /* window is the topmost managed child */
   meta_topic (META_DEBUG_STACK,
-              "Moving 0x%lx above topmost managed child window 0x%lx\n",
-              window->any.type == META_WINDOW_CLIENT_TYPE_X11 ? window->x11.xwindow: 0,
-              sibling->any.type == META_WINDOW_CLIENT_TYPE_X11 ? sibling->x11.xwindow: 0);
+              "Moving %s above topmost managed child window %s\n",
+              meta_display_describe_stack_id (screen->display, stack_id),
+              meta_display_describe_stack_id (screen->display, sibling));
 
-  if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
+  if (META_STACK_ID_IS_X11 (stack_id))
     {
       XWindowChanges changes;
-      MetaStackWindow *x11_sibling = find_x11_sibling_downwards (screen, sibling);
+      Window x11_sibling = find_x11_sibling_downwards (screen, sibling);
       serial = XNextRequest (screen->display->xdisplay);
 
       if (x11_sibling)
         {
-          changes.sibling = x11_sibling->x11.xwindow;
+          changes.sibling = x11_sibling;
           changes.stack_mode = Above;
 
           meta_error_trap_push (screen->display);
           XConfigureWindow (screen->display->xdisplay,
-                            window->x11.xwindow,
+                            (Window)stack_id,
                             CWSibling | CWStackMode,
                             &changes);
           meta_error_trap_pop (screen->display);
@@ -1207,13 +1204,13 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
            */
           meta_error_trap_push (screen->display);
           XLowerWindow (screen->display->xdisplay,
-                        window->x11.xwindow);
+                        (Window)stack_id);
           meta_error_trap_pop (screen->display);
         }
     }
 
   meta_stack_tracker_record_raise_above (screen->stack_tracker,
-                                         window,
+                                         stack_id,
                                          sibling,
                                          serial);
 }
@@ -1239,9 +1236,8 @@ stack_sync_to_xserver (MetaStack *stack)
   GArray *all_root_children_stacked; /* wayland OR x11 */
   GList *tmp;
   GArray *x11_hidden;
-  GArray *x11_hidden_stack_windows;
+  GArray *x11_hidden_stack_ids;
   int n_override_redirect = 0;
-  MetaStackWindow guard_stack_window;
 
   /* Bail out if frozen */
   if (stack->freeze_count > 0)
@@ -1258,10 +1254,10 @@ 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 (MetaStackWindow));
+  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_windows = g_array_new (FALSE, FALSE, sizeof (MetaStackWindow));
+  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
@@ -1275,9 +1271,7 @@ stack_sync_to_xserver (MetaStack *stack)
     {
       MetaWindow *w = tmp->data;
       Window top_level_window;
-      MetaStackWindow stack_window;
-
-      stack_window.any.type = w->client_type;
+      guint64 stack_id;
 
       meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
                  w->layer, w->stack_position, w->desc);
@@ -1294,9 +1288,9 @@ stack_sync_to_xserver (MetaStack *stack)
        top_level_window = w->xwindow;
 
       if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
-        stack_window.x11.xwindow = top_level_window;
+        stack_id = top_level_window;
       else
-        stack_window.wayland.meta_window = w;
+        stack_id = w->stamp;
 
       /* We don't restack hidden windows along with the rest, though they are
        * reflected in the _NET hints. Hidden windows all get pushed below
@@ -1305,18 +1299,15 @@ stack_sync_to_xserver (MetaStack *stack)
        {
           if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
             {
-              MetaStackWindow stack_window;
-
-              stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
-              stack_window.x11.xwindow = top_level_window;
+              guint64 stack_id = top_level_window;
 
-              g_array_append_val (x11_hidden_stack_windows, stack_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_window);
+      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)
@@ -1356,7 +1347,7 @@ stack_sync_to_xserver (MetaStack *stack)
                                x11_root_children_stacked->len);
             }
           meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
-                                                     (MetaStackWindow *) all_root_children_stacked->data,
+                                                     (guint64 *) all_root_children_stacked->data,
                                                      all_root_children_stacked->len,
                                                      serial);
         }
@@ -1369,34 +1360,31 @@ stack_sync_to_xserver (MetaStack *stack)
        * was saved, then we may have inefficiency, but I don't think things
        * break...
        */
-      const MetaStackWindow *old_stack = (MetaStackWindow *) stack->last_all_root_children_stacked->data;
-      const MetaStackWindow *new_stack = (MetaStackWindow *) all_root_children_stacked->data;
+      const guint64 *old_stack = (guint64 *) stack->last_all_root_children_stacked->data;
+      const guint64 *new_stack = (guint64 *) all_root_children_stacked->data;
       const int old_len = stack->last_all_root_children_stacked->len;
       const int new_len = all_root_children_stacked->len;
-      const MetaStackWindow *oldp = old_stack;
-      const MetaStackWindow *newp = new_stack;
-      const MetaStackWindow *old_end = old_stack + old_len;
-      const MetaStackWindow *new_end = new_stack + new_len;
+      const guint64 *oldp = old_stack;
+      const guint64 *newp = new_stack;
+      const guint64 *old_end = old_stack + old_len;
+      const guint64 *new_end = new_stack + new_len;
       Window last_xwindow = None;
-      const MetaStackWindow *last_window = NULL;
+      guint64 last_window = 0;
 
       while (oldp != old_end &&
              newp != new_end)
         {
-          if (meta_stack_window_equal (oldp, newp))
+          if (*oldp == *newp)
             {
               /* Stacks are the same here, move on */
               ++oldp;
-              if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
-                last_xwindow = newp->x11.xwindow;
-              last_window = newp;
+              if (META_STACK_ID_IS_X11 (*newp))
+                last_xwindow = (Window)*newp;
+              last_window = *newp;
               ++newp;
             }
-          else if ((oldp->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
-                    meta_display_lookup_x_window (stack->screen->display,
-                                                  oldp->x11.xwindow) == NULL) ||
-                   (oldp->any.type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
-                    oldp->wayland.meta_window == NULL))
+          else if (meta_display_lookup_stack_id (stack->screen->display,
+                                                 *oldp) == NULL)
             {
               /* *oldp is no longer known to us (probably destroyed),
                * so we can just skip it
@@ -1408,12 +1396,12 @@ stack_sync_to_xserver (MetaStack *stack)
               /* Move *newp below the last_window */
               if (!last_window)
                 {
-                  meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n",
-                              newp->x11.xwindow);
+                  meta_topic (META_DEBUG_STACK, "Using window %s as topmost (but leaving it in-place)\n",
+                              meta_display_describe_stack_id (stack->screen->display, *newp));
 
-                  raise_window_relative_to_managed_windows (stack->screen, newp);
+                  raise_window_relative_to_managed_windows (stack->screen, *newp);
                 }
-              else if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
+              else if (META_STACK_ID_IS_X11 (*newp) &&
                        last_xwindow == None)
                 {
                   /* In this case we have an X window that we need to
@@ -1432,10 +1420,10 @@ stack_sync_to_xserver (MetaStack *stack)
                    * know last_window isn't an X window).
                    */
 
-                  raise_window_relative_to_managed_windows (stack->screen, newp);
+                  raise_window_relative_to_managed_windows (stack->screen, *newp);
 
                   meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
-                                                         newp, last_window,
+                                                         *newp, last_window,
                                                          0); /* no x request serial */
                 }
               else
@@ -1447,11 +1435,11 @@ stack_sync_to_xserver (MetaStack *stack)
                    * unmanaging last_xwindow, we'll fix it up.
                    */
 
-                  meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n",
-                              newp->any.type == META_WINDOW_CLIENT_TYPE_X11 ? newp->x11.xwindow : 0,
+                  meta_topic (META_DEBUG_STACK, "Placing window %s below 0x%lx\n",
+                              meta_display_describe_stack_id (stack->screen->display, *newp),
                               last_xwindow);
 
-                  if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
+                  if (META_STACK_ID_IS_X11 (*newp))
                     {
                       XWindowChanges changes;
                       serial = XNextRequest (stack->screen->display->xdisplay);
@@ -1460,26 +1448,26 @@ stack_sync_to_xserver (MetaStack *stack)
                       changes.stack_mode = Below;
 
                       XConfigureWindow (stack->screen->display->xdisplay,
-                                        newp->x11.xwindow,
+                                        (Window)*newp,
                                         CWSibling | CWStackMode,
                                         &changes);
                     }
 
                   meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
-                                                         newp, last_window,
+                                                         *newp, last_window,
                                                          serial);
                 }
 
-              if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
-                last_xwindow = newp->x11.xwindow;
-              last_window = newp;
+              if (META_STACK_ID_IS_X11 (*newp))
+                last_xwindow = *newp;
+              last_window = *newp;
               ++newp;
             }
         }
 
       if (newp != new_end)
         {
-          const MetaStackWindow *x_ref;
+          const guint64 *x_ref;
           unsigned long serial = 0;
 
           /* Restack remaining windows */
@@ -1490,7 +1478,7 @@ stack_sync_to_xserver (MetaStack *stack)
            * as a reference point for re-stacking remaining X windows */
           if (newp != new_stack)
             for (x_ref = newp - 1;
-                 x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11 && x_ref > new_stack;
+                 META_STACK_ID_IS_X11 (*x_ref) && x_ref > new_stack;
                  x_ref--)
               ;
           else
@@ -1499,16 +1487,16 @@ stack_sync_to_xserver (MetaStack *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 (x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11)
+          if (META_STACK_ID_IS_X11 (*x_ref))
             {
               for (x_ref = newp;
-                   x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11 && x_ref < new_end;
+                   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 (x_ref->any.type == META_WINDOW_CLIENT_TYPE_X11)
+          if (META_STACK_ID_IS_X11 (*x_ref))
             {
               int i;
 
@@ -1516,7 +1504,7 @@ stack_sync_to_xserver (MetaStack *stack)
                 {
                   Window *reference = &g_array_index (x11_root_children_stacked, Window, i);
 
-                  if (*reference == x_ref->x11.xwindow)
+                  if (*reference == (Window)*x_ref)
                     {
                       int n = x11_root_children_stacked->len - i;
 
@@ -1545,21 +1533,19 @@ stack_sync_to_xserver (MetaStack *stack)
     }
 
   /* Push hidden X windows to the bottom of the stack under the guard window */
-  guard_stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
-  guard_stack_window.x11.xwindow = stack->screen->guard_window;
   meta_stack_tracker_record_lower (stack->screen->stack_tracker,
-                                   &guard_stack_window,
+                                   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,
-                                             (MetaStackWindow *)x11_hidden_stack_windows->data,
-                                             x11_hidden_stack_windows->len,
+                                             (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);
-  g_array_free (x11_hidden_stack_windows, TRUE);
+  g_array_free (x11_hidden_stack_ids, TRUE);
 
   meta_error_trap_pop (stack->screen->display);
   /* on error, a window was destroyed; it should eventually
diff --git a/src/core/window-private.h b/src/core/window-private.h
index aa47d09..73174f2 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -92,6 +92,7 @@ struct _MetaWindow
 
   MetaDisplay *display;
   MetaScreen *screen;
+  guint64 stamp;
   const MetaMonitorInfo *monitor;
   MetaWorkspace *workspace;
   MetaWindowClientType client_type;
diff --git a/src/core/window.c b/src/core/window.c
index 956f0c3..abf6694 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -71,6 +71,10 @@
 
 static int destroying_windows_disallowed = 0;
 
+// Each window has a "stamp" which is a non-recycled 64-bit ID. They
+// start after the end of the XID space so that, for stacking
+// we can keep a guint64 that represents one or the other
+static guint64 next_window_stamp = G_GUINT64_CONSTANT(0x100000000);
 
 static void     invalidate_work_areas     (MetaWindow     *window);
 static void     set_wm_state              (MetaWindow     *window);
@@ -642,6 +646,7 @@ meta_window_class_init (MetaWindowClass *klass)
 static void
 meta_window_init (MetaWindow *self)
 {
+  self->stamp = next_window_stamp++;
   meta_prefs_add_listener (prefs_changed_callback, self);
 }
 
@@ -803,6 +808,8 @@ _meta_window_shared_new (MetaDisplay         *display,
    * type
    */
   window->display = display;
+  meta_display_register_stamp (window->display, &window->stamp, window);
+
   window->workspace = NULL;
 
   window->sync_request_counter = None;
@@ -1239,6 +1246,8 @@ meta_window_unmanage (MetaWindow  *window,
     meta_bug ("Tried to destroy window %s while destruction was not allowed\n",
               window->desc);
 
+  meta_display_unregister_stamp (window->display, window->stamp);
+
   window->unmanaging = TRUE;
 
   if (meta_prefs_get_attach_modal_dialogs ())
diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
index 83c6ee4..7b2dae1 100644
--- a/src/tests/test-runner.c
+++ b/src/tests/test-runner.c
@@ -512,7 +512,7 @@ test_case_assert_stacking (TestCase *test,
                            GError  **error)
 {
   MetaDisplay *display = meta_get_display ();
-  MetaStackWindow *windows;
+  guint64 *windows;
   int n_windows;
   GString *stack_string = g_string_new (NULL);
   GString *expected_string = g_string_new (NULL);
@@ -521,22 +521,14 @@ test_case_assert_stacking (TestCase *test,
   meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows);
   for (i = 0; i < n_windows; i++)
     {
-      MetaWindow *window;
-
-      if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11)
-        window = meta_display_lookup_x_window (display,
-                                               windows[i].x11.xwindow);
-      else
-        window = windows[i].wayland.meta_window;
-
+      MetaWindow *window = meta_display_lookup_stack_id (display, windows[i]);
       if (window != NULL && window->title)
         {
-
           /* See comment in meta_ui_new() about why the dummy window for GTK+ theming
            * is managed as a MetaWindow.
            */
-          if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11 &&
-              meta_ui_window_is_dummy (display->screen->ui, windows[i].x11.xwindow))
+          if (META_STACK_ID_IS_X11 (windows[i]) &&
+              meta_ui_window_is_dummy (display->screen->ui, windows[i]))
             continue;
 
           if (stack_string->len > 0)
@@ -579,18 +571,18 @@ test_case_check_xserver_stacking (TestCase *test,
   GString *x11_string = g_string_new (NULL);
   int i;
 
-  MetaStackWindow *windows;
+  guint64 *windows;
   int n_windows;
   meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows);
 
   for (i = 0; i < n_windows; i++)
     {
-      if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11)
+      if (META_STACK_ID_IS_X11 (windows[i]))
         {
           if (local_string->len > 0)
             g_string_append_c (local_string, ' ');
 
-          g_string_append_printf (local_string, "%#lx", windows[i].x11.xwindow);
+          g_string_append_printf (local_string, "%#lx", (Window)windows[i]);
         }
     }
 
diff --git a/src/wayland/window-wayland.c b/src/wayland/window-wayland.c
index 3733bca..9a82b35 100644
--- a/src/wayland/window-wayland.c
+++ b/src/wayland/window-wayland.c
@@ -60,11 +60,8 @@ meta_window_wayland_manage (MetaWindow *window)
   meta_display_register_wayland_window (display, window);
 
   {
-    MetaStackWindow stack_window;
-    stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND;
-    stack_window.wayland.meta_window = window;
     meta_stack_tracker_record_add (window->screen->stack_tracker,
-                                   &stack_window,
+                                   window->stamp,
                                    0);
   }
 }
@@ -73,11 +70,8 @@ static void
 meta_window_wayland_unmanage (MetaWindow *window)
 {
   {
-    MetaStackWindow stack_window;
-    stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND;
-    stack_window.wayland.meta_window = window;
     meta_stack_tracker_record_remove (window->screen->stack_tracker,
-                                      &stack_window,
+                                      window->stamp,
                                       0);
   }
 


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