[mutter] Move stack tracking and guard_window outside of MetaScreen



commit 98d912ba5f288f08ef459fb195e5653cd7866d8e
Author: Armin Krezović <krezovic armin gmail com>
Date:   Sat Aug 26 19:03:51 2017 +0200

    Move stack tracking and guard_window outside of MetaScreen
    
    Move stack, stack_tracker to MetaDisplay guard_window to MetaX11Display
    
    https://bugzilla.gnome.org/show_bug.cgi?id=759538

 src/compositor/compositor.c           |   2 +-
 src/core/display-private.h            |  11 ++-
 src/core/display.c                    |  53 +++++++++++-
 src/core/edge-resistance.c            |   2 +-
 src/core/frame.c                      |   6 +-
 src/core/keybindings.c                |   6 +-
 src/core/screen-private.h             |  12 ---
 src/core/screen.c                     | 152 ++--------------------------------
 src/core/stack-tracker.c              |  42 +++++-----
 src/core/stack-tracker.h              |   4 +-
 src/core/stack.c                      |  40 ++++-----
 src/core/stack.h                      |  12 +--
 src/core/window.c                     |  60 +++++++-------
 src/core/workspace.c                  |   2 +-
 src/tests/test-runner.c               |   6 +-
 src/wayland/meta-window-wayland.c     |   4 +-
 src/wayland/meta-xwayland-selection.c |   2 +-
 src/x11/events.c                      |   8 +-
 src/x11/group.c                       |   6 +-
 src/x11/meta-x11-display-private.h    |   7 ++
 src/x11/meta-x11-display.c            | 127 ++++++++++++++++++++++++++++
 src/x11/window-x11.c                  |   2 +-
 22 files changed, 300 insertions(+), 266 deletions(-)
---
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index f43d2da1b..694b27e3f 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -966,7 +966,7 @@ on_top_window_actor_destroyed (MetaWindowActor *window_actor,
   compositor->top_window_actor = NULL;
   compositor->windows = g_list_remove (compositor->windows, window_actor);
 
-  meta_stack_tracker_queue_sync_stack (compositor->display->screen->stack_tracker);
+  meta_stack_tracker_queue_sync_stack (compositor->display->stack_tracker);
 }
 
 void
diff --git a/src/core/display-private.h b/src/core/display-private.h
index aa4af0794..e025b2316 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -37,6 +37,7 @@
 #include "keybindings-private.h"
 #include "startup-notification-private.h"
 #include "meta-gesture-tracker-private.h"
+#include "stack-tracker.h"
 #include <meta/prefs.h>
 #include <meta/barrier.h>
 #include <clutter/clutter.h>
@@ -244,6 +245,9 @@ struct _MetaDisplay
 
   MetaRectangle rect;  /* Size of screen; rect.x & rect.y are always 0 */
   MetaCursor current_cursor;
+
+  MetaStack *stack;
+  MetaStackTracker *stack_tracker;
 };
 
 struct _MetaDisplayClass
@@ -270,8 +274,9 @@ gboolean      meta_display_open                (void);
 void          meta_display_close               (MetaDisplay *display,
                                                 guint32      timestamp);
 
-void meta_display_unmanage_windows (MetaDisplay *display,
-                                    guint32      timestamp);
+void meta_display_manage_all_windows (MetaDisplay *display);
+void meta_display_unmanage_windows   (MetaDisplay *display,
+                                      guint32      timestamp);
 
 /* Utility function to compare the stacking of two windows */
 int           meta_display_stack_cmp           (const void *a,
@@ -426,4 +431,6 @@ void meta_display_foreach_window (MetaDisplay           *display,
                                   MetaDisplayWindowFunc  func,
                                   gpointer               data);
 
+void meta_display_restacked (MetaDisplay *display);
+
 #endif
diff --git a/src/core/display.c b/src/core/display.c
index 9193b3eef..2e7e6d064 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -137,6 +137,7 @@ enum
   SHOW_OSD,
   PAD_MODE_SWITCH,
   MONITORS_CHANGED,
+  RESTACKED,
   LAST_SIGNAL
 };
 
@@ -433,6 +434,13 @@ meta_display_class_init (MetaDisplayClass *klass)
                   0, NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
 
+  display_signals[RESTACKED] =
+    g_signal_new ("restacked",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
   g_object_class_install_property (object_class,
                                    PROP_FOCUS_WINDOW,
                                    g_param_spec_object ("focus-window",
@@ -709,6 +717,9 @@ meta_display_open (void)
 
   xdisplay = display->x11_display->xdisplay;
 
+  display->stack = meta_stack_new (display);
+  display->stack_tracker = meta_stack_tracker_new (display);
+
   display->focus_serial = 0;
   display->server_focus_window = None;
   display->server_focus_serial = 0;
@@ -820,7 +831,7 @@ meta_display_open (void)
 
   enable_compositor (display);
 
-  meta_screen_create_guard_window (screen);
+  meta_x11_display_create_guard_window (display->x11_display);
 
   /* Set up touch support */
   display->gesture_tracker = meta_gesture_tracker_new ();
@@ -831,7 +842,7 @@ meta_display_open (void)
    * we start out with no windows.
    */
   if (!meta_is_wayland_compositor ())
-    meta_screen_manage_all_windows (screen);
+    meta_display_manage_all_windows (display);
 
   if (old_active_xwindow != None)
     {
@@ -985,6 +996,10 @@ meta_display_close (MetaDisplay *display,
   g_clear_object (&display->startup_notification);
   g_clear_object (&display->gesture_tracker);
 
+  g_clear_pointer (&display->stack, (GDestroyNotify) meta_stack_free);
+  g_clear_pointer (&display->stack_tracker,
+                   (GDestroyNotify) meta_stack_tracker_free);
+
   if (display->focus_timeout_id)
     g_source_remove (display->focus_timeout_id);
   display->focus_timeout_id = 0;
@@ -1251,7 +1266,7 @@ window_raise_with_delay_callback (void *data)
   /* If we aren't already on top, check whether the pointer is inside
    * the window and raise the window if so.
    */
-  if (meta_stack_get_top (window->screen->stack) != window)
+  if (meta_stack_get_top (window->display->stack) != window)
     {
       if (meta_window_has_pointer (window))
        meta_window_raise (window);
@@ -2564,6 +2579,30 @@ meta_display_unmanage_screen (MetaDisplay *display,
   meta_display_close (display, timestamp);
 }
 
+void
+meta_display_manage_all_windows (MetaDisplay *display)
+{
+  guint64 *_children;
+  guint64 *children;
+  int n_children, i;
+
+  meta_stack_freeze (display->stack);
+  meta_stack_tracker_get_stack (display->stack_tracker, &_children, &n_children);
+
+  /* Copy the stack as it will be modified as part of the loop */
+  children = g_memdup (_children, sizeof (guint64) * n_children);
+
+  for (i = 0; i < n_children; ++i)
+    {
+      g_assert (META_STACK_ID_IS_X11 (children[i]));
+      meta_window_x11_new (display, children[i], TRUE,
+                           META_COMP_EFFECT_NONE);
+    }
+
+  g_free (children);
+  meta_stack_thaw (display->stack);
+}
+
 void
 meta_display_unmanage_windows (MetaDisplay *display,
                                guint32      timestamp)
@@ -2602,7 +2641,7 @@ meta_display_stack_cmp (const void *a,
   MetaWindow *aw = (void*) a;
   MetaWindow *bw = (void*) b;
 
-  return meta_stack_windows_cmp (aw->screen->stack, aw, bw);
+  return meta_stack_windows_cmp (aw->display->stack, aw, bw);
 }
 
 /**
@@ -3209,3 +3248,9 @@ on_monitors_changed (MetaMonitorManager *monitor_manager,
 {
   g_signal_emit (display, display_signals[MONITORS_CHANGED], 0);
 }
+
+void
+meta_display_restacked (MetaDisplay *display)
+{
+  g_signal_emit (display, display_signals[RESTACKED], 0);
+}
diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c
index 56a667842..47ac4d1e0 100644
--- a/src/core/edge-resistance.c
+++ b/src/core/edge-resistance.c
@@ -1009,7 +1009,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
    * 1st: Get the list of relevant windows, from bottom to top
    */
   stacked_windows =
-    meta_stack_list_windows (display->screen->stack,
+    meta_stack_list_windows (display->stack,
                              display->screen->active_workspace);
 
   /*
diff --git a/src/core/frame.c b/src/core/frame.c
index 1fb885d06..be1f4e2bf 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -76,7 +76,7 @@ meta_window_ensure_frame (MetaWindow *window)
                                           &create_serial);
   frame->xwindow = frame->ui_frame->xwindow;
 
-  meta_stack_tracker_record_add (window->screen->stack_tracker,
+  meta_stack_tracker_record_add (window->display->stack_tracker,
                                  frame->xwindow,
                                  create_serial);
 
@@ -98,7 +98,7 @@ meta_window_ensure_frame (MetaWindow *window)
       window->unmaps_pending += 1;
     }
 
-  meta_stack_tracker_record_remove (window->screen->stack_tracker,
+  meta_stack_tracker_record_remove (window->display->stack_tracker,
                                     window->xwindow,
                                     XNextRequest (x11_display->xdisplay));
   XReparentWindow (x11_display->xdisplay,
@@ -185,7 +185,7 @@ meta_window_destroy_frame (MetaWindow *window)
                   "Incrementing unmaps_pending on %s for reparent back to root\n", window->desc);
       window->unmaps_pending += 1;
     }
-  meta_stack_tracker_record_add (window->screen->stack_tracker,
+  meta_stack_tracker_record_add (window->display->stack_tracker,
                                  window->xwindow,
                                  XNextRequest (x11_display->xdisplay));
   XReparentWindow (x11_display->xdisplay,
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index a7c18eb47..cfcf5fa55 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -3454,7 +3454,7 @@ handle_raise_or_lower (MetaDisplay     *display,
   MetaWindow *above = NULL;
 
   /* Check if top */
-  if (meta_stack_get_top (window->screen->stack) == window)
+  if (meta_stack_get_top (window->display->stack) == window)
     {
       meta_window_lower (window);
       return;
@@ -3462,7 +3462,7 @@ handle_raise_or_lower (MetaDisplay     *display,
 
   /* else check if windows in same layer are intersecting it */
 
-  above = meta_stack_get_above (window->screen->stack, window, TRUE);
+  above = meta_stack_get_above (window->display->stack, window, TRUE);
 
   while (above)
     {
@@ -3481,7 +3481,7 @@ handle_raise_or_lower (MetaDisplay     *display,
             }
         }
 
-      above = meta_stack_get_above (window->screen->stack, above, TRUE);
+      above = meta_stack_get_above (window->display->stack, above, TRUE);
     }
 
   /* window is not obscured */
diff --git a/src/core/screen-private.h b/src/core/screen-private.h
index 4c853f2da..bf2fbb0fe 100644
--- a/src/core/screen-private.h
+++ b/src/core/screen-private.h
@@ -59,9 +59,6 @@ struct _MetaScreen
 
   GList *workspaces;
 
-  MetaStack *stack;
-  MetaStackTracker *stack_tracker;
-
   Window wm_sn_selection_window;
   Atom wm_sn_atom;
   guint32 wm_sn_timestamp;
@@ -84,11 +81,6 @@ struct _MetaScreen
 
   int closing;
 
-  /* Instead of unmapping withdrawn windows we can leave them mapped
-   * and restack them below a guard window. When using a compositor
-   * this allows us to provide live previews of unmapped windows */
-  Window guard_window;
-
   Window composite_overlay_window;
 };
 
@@ -96,7 +88,6 @@ struct _MetaScreenClass
 {
   GObjectClass parent_class;
 
-  void (*restacked)         (MetaScreen *);
   void (*workareas_changed) (MetaScreen *);
 };
 
@@ -150,7 +141,6 @@ void     meta_screen_update_showing_desktop_hint          (MetaScreen *screen);
 
 gboolean meta_screen_apply_startup_properties (MetaScreen *screen,
                                                MetaWindow *window);
-void     meta_screen_restacked (MetaScreen *screen);
 
 void     meta_screen_workspace_switched (MetaScreen         *screen,
                                          int                 from,
@@ -159,8 +149,6 @@ void     meta_screen_workspace_switched (MetaScreen         *screen,
 
 void meta_screen_set_active_workspace_hint (MetaScreen *screen);
 
-void meta_screen_create_guard_window (MetaScreen *screen);
-
 gboolean meta_screen_handle_xevent (MetaScreen *screen,
                                     XEvent     *xevent);
 
diff --git a/src/core/screen.c b/src/core/screen.c
index 26bae29fe..70aa9169d 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -79,7 +79,6 @@ enum
 
 enum
 {
-  RESTACKED,
   WORKSPACE_ADDED,
   WORKSPACE_REMOVED,
   WORKSPACE_SWITCHED,
@@ -156,14 +155,6 @@ meta_screen_class_init (MetaScreenClass *klass)
   object_class->set_property = meta_screen_set_property;
   object_class->finalize = meta_screen_finalize;
 
-  screen_signals[RESTACKED] =
-    g_signal_new ("restacked",
-                  G_TYPE_FROM_CLASS (object_class),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (MetaScreenClass, restacked),
-                  NULL, NULL, NULL,
-                  G_TYPE_NONE, 0);
-
   pspec = g_param_spec_int ("n-workspaces",
                             "N Workspaces",
                             "Number of workspaces",
@@ -481,75 +472,6 @@ reload_logical_monitors (MetaScreen *screen)
   screen->has_xinerama_indices = FALSE;
 }
 
-/* The guard window allows us to leave minimized windows mapped so
- * that compositor code may provide live previews of them.
- * Instead of being unmapped/withdrawn, they get pushed underneath
- * the guard window. We also select events on the guard window, which
- * should effectively be forwarded to events on the background actor,
- * providing that the scene graph is set up correctly.
- */
-static Window
-create_guard_window (Display *xdisplay, MetaScreen *screen)
-{
-  XSetWindowAttributes attributes;
-  MetaX11Display *x11_display = screen->display->x11_display;
-  Window guard_window;
-  gulong create_serial;
-
-  attributes.event_mask = NoEventMask;
-  attributes.override_redirect = True;
-
-  /* We have to call record_add() after we have the new window ID,
-   * so save the serial for the CreateWindow request until then */
-  create_serial = XNextRequest(xdisplay);
-  guard_window =
-    XCreateWindow (xdisplay,
-                   x11_display->xroot,
-                  0, /* x */
-                  0, /* y */
-                   screen->display->rect.width,
-                   screen->display->rect.height,
-                  0, /* border width */
-                  0, /* depth */
-                  InputOnly, /* class */
-                  CopyFromParent, /* visual */
-                  CWEventMask|CWOverrideRedirect,
-                  &attributes);
-
-  /* https://bugzilla.gnome.org/show_bug.cgi?id=710346 */
-  XStoreName (xdisplay, guard_window, "mutter guard window");
-
-  {
-    if (!meta_is_wayland_compositor ())
-      {
-        MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
-        Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
-        unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
-        XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
-
-        XISetMask (mask.mask, XI_ButtonPress);
-        XISetMask (mask.mask, XI_ButtonRelease);
-        XISetMask (mask.mask, XI_Motion);
-
-        /* Sync on the connection we created the window on to
-         * make sure it's created before we select on it on the
-         * backend connection. */
-        XSync (xdisplay, False);
-
-        XISelectEvents (backend_xdisplay, guard_window, &mask, 1);
-      }
-  }
-
-  meta_stack_tracker_record_add (screen->stack_tracker,
-                                 guard_window,
-                                 create_serial);
-
-  meta_stack_tracker_lower (screen->stack_tracker,
-                            guard_window);
-  XMapWindow (xdisplay, guard_window);
-  return guard_window;
-}
-
 static Window
 take_manager_selection (MetaDisplay *display,
                         Window       xroot,
@@ -695,7 +617,6 @@ meta_screen_new (MetaDisplay *display,
   screen->columns_of_workspaces = -1;
   screen->vertical_workspaces = FALSE;
   screen->starting_corner = META_SCREEN_TOPLEFT;
-  screen->guard_window = None;
 
   /* If we're a Wayland compositor, then we don't grab the COW, since it
    * will map it. */
@@ -740,9 +661,6 @@ meta_screen_new (MetaDisplay *display,
 
   screen->tile_preview_timeout_id = 0;
 
-  screen->stack = meta_stack_new (screen);
-  screen->stack_tracker = meta_stack_tracker_new (screen);
-
   meta_prefs_add_listener (prefs_changed_callback, screen);
 
   meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
@@ -803,9 +721,6 @@ meta_screen_free (MetaScreen *screen,
 
   meta_ui_free (screen->ui);
 
-  meta_stack_free (screen->stack);
-  meta_stack_tracker_free (screen->stack_tracker);
-
   unset_wm_check_hint (screen);
 
   XDestroyWindow (x11_display->xdisplay,
@@ -822,39 +737,6 @@ meta_screen_free (MetaScreen *screen,
   g_object_unref (screen);
 }
 
-void
-meta_screen_create_guard_window (MetaScreen *screen)
-{
-  MetaX11Display *x11_display = screen->display->x11_display;
-
-  if (screen->guard_window == None)
-    screen->guard_window = create_guard_window (x11_display->xdisplay, screen);
-}
-
-void
-meta_screen_manage_all_windows (MetaScreen *screen)
-{
-  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 (guint64) * n_children);
-
-  for (i = 0; i < n_children; ++i)
-    {
-      g_assert (META_STACK_ID_IS_X11 (children[i]));
-      meta_window_x11_new (screen->display, children[i], TRUE,
-                           META_COMP_EFFECT_NONE);
-    }
-
-  g_free (children);
-  meta_stack_thaw (screen->stack);
-}
-
 static void
 prefs_changed_callback (MetaPreference pref,
                         gpointer       data)
@@ -1291,7 +1173,7 @@ meta_screen_get_mouse_window (MetaScreen  *screen,
 
   meta_cursor_tracker_get_pointer (cursor_tracker, &x, &y, NULL);
 
-  window = meta_stack_get_default_focus_window_at_point (screen->stack,
+  window = meta_stack_get_default_focus_window_at_point (screen->display->stack,
                                                          screen->active_workspace,
                                                          not_this_one,
                                                          x, y);
@@ -2023,27 +1905,9 @@ meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout)
 void
 meta_screen_on_monitors_changed (MetaScreen *screen)
 {
-  MetaDisplay *display = screen->display;
-
   reload_logical_monitors (screen);
   set_desktop_geometry_hint (screen);
 
-  /* Resize the guard window to fill the screen again. */
-  if (screen->guard_window != None)
-    {
-      XWindowChanges changes;
-
-      changes.x = 0;
-      changes.y = 0;
-      changes.width = display->rect.width;
-      changes.height = display->rect.height;
-
-      XConfigureWindow(display->x11_display->xdisplay,
-                       screen->guard_window,
-                       CWX | CWY | CWWidth | CWHeight,
-                       &changes);
-    }
-
   meta_screen_queue_check_fullscreen (screen);
 }
 
@@ -2363,12 +2227,6 @@ meta_screen_focus_default_window (MetaScreen *screen,
                                        timestamp);
 }
 
-void
-meta_screen_restacked (MetaScreen *screen)
-{
-  g_signal_emit (screen, screen_signals[RESTACKED], 0);
-}
-
 void
 meta_screen_workspace_switched (MetaScreen         *screen,
                                 int                 from,
@@ -2430,9 +2288,9 @@ check_fullscreen_func (gpointer data)
    * however we make an exception for maximized windows above the fullscreen
    * one, as in that case window+chrome fully obscure the fullscreen window.
    */
-  for (window = meta_stack_get_top (screen->stack);
+  for (window = meta_stack_get_top (screen->display->stack);
        window;
-       window = meta_stack_get_below (screen->stack, window, FALSE))
+       window = meta_stack_get_below (screen->display->stack, window, FALSE))
     {
       gboolean covers_monitors = FALSE;
 
@@ -2506,9 +2364,9 @@ check_fullscreen_func (gpointer data)
     {
       /* DOCK window stacking depends on the monitor's fullscreen
          status so we need to trigger a re-layering. */
-      MetaWindow *window = meta_stack_get_top (screen->stack);
+      MetaWindow *window = meta_stack_get_top (screen->display->stack);
       if (window)
-        meta_stack_update_layer (screen->stack, window);
+        meta_stack_update_layer (screen->display->stack, window);
 
       g_signal_emit (screen, screen_signals[IN_FULLSCREEN_CHANGED], 0, NULL);
     }
diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c
index a5ef6de45..f6372dba7 100644
--- a/src/core/stack-tracker.c
+++ b/src/core/stack-tracker.c
@@ -37,7 +37,7 @@
 #include <string.h>
 
 #include "frame.h"
-#include "screen-private.h"
+#include "display-private.h"
 #include "stack-tracker.h"
 #include <meta/errors.h>
 #include <meta/util.h>
@@ -142,7 +142,7 @@ union _MetaStackOp
 
 struct _MetaStackTracker
 {
-  MetaScreen *screen;
+  MetaDisplay *display;
 
   /* This is the serial of the last request we made that was reflected
    * in xserver_stack
@@ -177,7 +177,7 @@ static inline const char *
 get_window_desc (MetaStackTracker *tracker,
                  guint64           window)
 {
-  return meta_display_describe_stack_id (tracker->screen->display, window);
+  return meta_display_describe_stack_id (tracker->display, window);
 }
 
 static void
@@ -478,16 +478,16 @@ copy_stack (GArray *stack)
 static void
 query_xserver_stack (MetaStackTracker *tracker)
 {
-  MetaScreen *screen = tracker->screen;
+  MetaX11Display *x11_display = tracker->display->x11_display;
   Window ignored1, ignored2;
   Window *children;
   guint n_children;
   guint i;
 
-  tracker->xserver_serial = XNextRequest (screen->display->x11_display->xdisplay);
+  tracker->xserver_serial = XNextRequest (x11_display->xdisplay);
 
-  XQueryTree (screen->display->x11_display->xdisplay,
-              screen->display->x11_display->xroot,
+  XQueryTree (x11_display->xdisplay,
+              x11_display->xroot,
               &ignored1, &ignored2, &children, &n_children);
 
   tracker->verified_stack = g_array_sized_new (FALSE, FALSE, sizeof (guint64), n_children);
@@ -500,12 +500,12 @@ query_xserver_stack (MetaStackTracker *tracker)
 }
 
 MetaStackTracker *
-meta_stack_tracker_new (MetaScreen *screen)
+meta_stack_tracker_new (MetaDisplay *display)
 {
   MetaStackTracker *tracker;
 
   tracker = g_new0 (MetaStackTracker, 1);
-  tracker->screen = screen;
+  tracker->display = display;
 
   query_xserver_stack (tracker);
 
@@ -851,7 +851,7 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
 
       if (META_STACK_ID_IS_X11 (window))
         {
-          MetaX11Display *x11_display = tracker->screen->display->x11_display;
+          MetaX11Display *x11_display = tracker->display->x11_display;
           MetaWindow *meta_window =
             meta_x11_display_lookup_x_window (x11_display, (Window)window);
 
@@ -868,14 +868,14 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
         }
       else
         meta_windows = g_list_prepend (meta_windows,
-                                       meta_display_lookup_stamp (tracker->screen->display, window));
+                                       meta_display_lookup_stamp (tracker->display, window));
     }
 
-  meta_compositor_sync_stack (tracker->screen->display->compositor,
+  meta_compositor_sync_stack (tracker->display->compositor,
                               meta_windows);
   g_list_free (meta_windows);
 
-  meta_screen_restacked (tracker->screen);
+  meta_display_restacked (tracker->display);
 }
 
 static gboolean
@@ -980,7 +980,7 @@ meta_stack_tracker_lower_below (MetaStackTracker *tracker,
                                 guint64           sibling)
 {
   gulong serial = 0;
-  MetaX11Display *x11_display = tracker->screen->display->x11_display;
+  MetaX11Display *x11_display = tracker->display->x11_display;
 
   if (META_STACK_ID_IS_X11 (window))
     {
@@ -1015,7 +1015,7 @@ meta_stack_tracker_raise_above (MetaStackTracker *tracker,
                                 guint64           sibling)
 {
   gulong serial = 0;
-  MetaX11Display *x11_display = tracker->screen->display->x11_display;
+  MetaX11Display *x11_display = tracker->display->x11_display;
 
   if (META_STACK_ID_IS_X11 (window))
     {
@@ -1062,7 +1062,7 @@ meta_stack_tracker_keep_override_redirect_on_top (MetaStackTracker *tracker)
 
   for (i = n_windows - 1; i >= 0; i--)
     {
-      window = meta_display_lookup_stack_id (tracker->screen->display, stack[i]);
+      window = meta_display_lookup_stack_id (tracker->display, stack[i]);
       if (window && window->layer != META_LAYER_OVERRIDE_REDIRECT)
         break;
     }
@@ -1071,7 +1071,7 @@ meta_stack_tracker_keep_override_redirect_on_top (MetaStackTracker *tracker)
 
   for (i -= 1; i >= 0; i--)
     {
-      window = meta_display_lookup_stack_id (tracker->screen->display, stack[i]);
+      window = meta_display_lookup_stack_id (tracker->display, stack[i]);
       if (window && window->layer == META_LAYER_OVERRIDE_REDIRECT)
         {
           meta_stack_tracker_raise_above (tracker, stack[i], stack[topmost_non_or]);
@@ -1103,9 +1103,9 @@ meta_stack_tracker_restack_managed (MetaStackTracker *tracker,
   old_pos = n_windows - 1;
   for (old_pos = n_windows - 1; old_pos >= 0; old_pos--)
     {
-      MetaWindow *old_window = meta_display_lookup_stack_id (tracker->screen->display, windows[old_pos]);
+      MetaWindow *old_window = meta_display_lookup_stack_id (tracker->display, windows[old_pos]);
       if ((old_window && !old_window->override_redirect && !old_window->unmanaging) ||
-          windows[old_pos] == tracker->screen->guard_window)
+          windows[old_pos] == tracker->display->x11_display->guard_window)
         break;
     }
   g_assert (old_pos >= 0);
@@ -1124,7 +1124,7 @@ meta_stack_tracker_restack_managed (MetaStackTracker *tracker,
 
   while (old_pos >= 0 && new_pos >= 0)
     {
-      if (windows[old_pos] == tracker->screen->guard_window)
+      if (windows[old_pos] == tracker->display->x11_display->guard_window)
         break;
 
       if (windows[old_pos] == managed[new_pos])
@@ -1134,7 +1134,7 @@ meta_stack_tracker_restack_managed (MetaStackTracker *tracker,
           continue;
         }
 
-      MetaWindow *old_window = meta_display_lookup_stack_id (tracker->screen->display, windows[old_pos]);
+      MetaWindow *old_window = meta_display_lookup_stack_id (tracker->display, windows[old_pos]);
       if (!old_window || old_window->override_redirect || old_window->unmanaging)
         {
           old_pos--;
diff --git a/src/core/stack-tracker.h b/src/core/stack-tracker.h
index 12015ae23..e93b95b21 100644
--- a/src/core/stack-tracker.h
+++ b/src/core/stack-tracker.h
@@ -34,12 +34,12 @@
 #ifndef META_STACK_TRACKER_H
 #define META_STACK_TRACKER_H
 
-#include <meta/screen.h>
+#include <meta/display.h>
 #include <meta/window.h>
 
 typedef struct _MetaStackTracker MetaStackTracker;
 
-MetaStackTracker *meta_stack_tracker_new  (MetaScreen       *screen);
+MetaStackTracker *meta_stack_tracker_new  (MetaDisplay      *display);
 void              meta_stack_tracker_free (MetaStackTracker *tracker);
 
 /* These functions are called when we make an X call that changes the
diff --git a/src/core/stack.c b/src/core/stack.c
index 217ba44ae..fc3b2ecfc 100644
--- a/src/core/stack.c
+++ b/src/core/stack.c
@@ -61,14 +61,14 @@ static void stack_do_resort           (MetaStack *stack);
 
 static void stack_ensure_sorted (MetaStack *stack);
 
-MetaStack*
-meta_stack_new (MetaScreen *screen)
+MetaStack *
+meta_stack_new (MetaDisplay *display)
 {
   MetaStack *stack;
 
   stack = g_new (MetaStack, 1);
 
-  stack->screen = screen;
+  stack->display = display;
   stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window));
 
   stack->sorted = NULL;
@@ -945,7 +945,7 @@ stack_do_resort (MetaStack *stack)
   stack->sorted = g_list_sort (stack->sorted,
                                (GCompareFunc) compare_window_position);
 
-  meta_screen_queue_check_fullscreen (stack->screen);
+  meta_screen_queue_check_fullscreen (stack->display->screen);
 
   stack->need_resort = FALSE;
 }
@@ -1052,7 +1052,7 @@ stack_sync_to_xserver (MetaStack *stack)
 
   /* The screen guard window sits above all hidden windows and acts as
    * a barrier to input reaching these windows. */
-  guint64 guard_window_id = stack->screen->guard_window;
+  guint64 guard_window_id = stack->display->x11_display->guard_window;
   g_array_append_val (hidden_stack_ids, guard_window_id);
 
   /* Sync to server */
@@ -1060,25 +1060,25 @@ stack_sync_to_xserver (MetaStack *stack)
   meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
               all_root_children_stacked->len);
 
-  meta_stack_tracker_restack_managed (stack->screen->stack_tracker,
+  meta_stack_tracker_restack_managed (stack->display->stack_tracker,
                                       (guint64 *)all_root_children_stacked->data,
                                       all_root_children_stacked->len);
-  meta_stack_tracker_restack_at_bottom (stack->screen->stack_tracker,
+  meta_stack_tracker_restack_at_bottom (stack->display->stack_tracker,
                                         (guint64 *)hidden_stack_ids->data,
                                         hidden_stack_ids->len);
 
   /* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */
 
-  XChangeProperty (stack->screen->display->x11_display->xdisplay,
-                   stack->screen->display->x11_display->xroot,
-                   stack->screen->display->x11_display->atom__NET_CLIENT_LIST,
+  XChangeProperty (stack->display->x11_display->xdisplay,
+                   stack->display->x11_display->xroot,
+                   stack->display->x11_display->atom__NET_CLIENT_LIST,
                    XA_WINDOW,
                    32, PropModeReplace,
                    (unsigned char *)stack->xwindows->data,
                    stack->xwindows->len);
-  XChangeProperty (stack->screen->display->x11_display->xdisplay,
-                   stack->screen->display->x11_display->xroot,
-                   stack->screen->display->x11_display->atom__NET_CLIENT_LIST_STACKING,
+  XChangeProperty (stack->display->x11_display->xdisplay,
+                   stack->display->x11_display->xroot,
+                   stack->display->x11_display->atom__NET_CLIENT_LIST_STACKING,
                    XA_WINDOW,
                    32, PropModeReplace,
                    (unsigned char *)x11_stacked->data,
@@ -1411,10 +1411,10 @@ meta_window_set_stack_position_no_sync (MetaWindow *window,
   int low, high, delta;
   GList *tmp;
 
-  g_return_if_fail (window->screen->stack != NULL);
+  g_return_if_fail (window->display->stack != NULL);
   g_return_if_fail (window->stack_position >= 0);
   g_return_if_fail (position >= 0);
-  g_return_if_fail (position < window->screen->stack->n_positions);
+  g_return_if_fail (position < window->display->stack->n_positions);
 
   if (position == window->stack_position)
     {
@@ -1423,8 +1423,8 @@ meta_window_set_stack_position_no_sync (MetaWindow *window,
       return;
     }
 
-  window->screen->stack->need_resort = TRUE;
-  window->screen->stack->need_constrain = TRUE;
+  window->display->stack->need_resort = TRUE;
+  window->display->stack->need_constrain = TRUE;
 
   if (position < window->stack_position)
     {
@@ -1439,7 +1439,7 @@ meta_window_set_stack_position_no_sync (MetaWindow *window,
       delta = -1;
     }
 
-  tmp = window->screen->stack->sorted;
+  tmp = window->display->stack->sorted;
   while (tmp != NULL)
     {
       MetaWindow *w = tmp->data;
@@ -1463,7 +1463,7 @@ meta_window_set_stack_position (MetaWindow *window,
                                 int         position)
 {
   meta_window_set_stack_position_no_sync (window, position);
-  stack_sync_to_xserver (window->screen->stack);
-  meta_stack_update_window_tile_matches (window->screen->stack,
+  stack_sync_to_xserver (window->display->stack);
+  meta_stack_update_window_tile_matches (window->display->stack,
                                          window->screen->active_workspace);
 }
diff --git a/src/core/stack.h b/src/core/stack.h
index e82be0abe..d97606742 100644
--- a/src/core/stack.h
+++ b/src/core/stack.h
@@ -40,7 +40,7 @@
  * by layer, then by stack_position within each layer.
  */
 
-#include "screen-private.h"
+#include "display-private.h"
 
 /**
  * A sorted list of windows bearing some level of resemblance to the stack of
@@ -51,8 +51,8 @@
  */
 struct _MetaStack
 {
-  /** The MetaScreen containing this stack. */
-  MetaScreen *screen;
+  /** The MetaDisplay containing this stack. */
+  MetaDisplay *display;
 
   /**
    * A sequence of all the Windows (X handles, not MetaWindows) of the windows
@@ -123,13 +123,13 @@ struct _MetaStack
 
 /**
  * meta_stack_new:
- * @screen: The MetaScreen which will be the parent of this stack.
+ * @display: The MetaDisplay which will be the parent of this stack.
  *
  * Creates and initialises a MetaStack.
  *
- * Returns: The new screen.
+ * Returns: The new stack.
  */
-MetaStack *meta_stack_new       (MetaScreen     *screen);
+MetaStack *meta_stack_new       (MetaDisplay    *display);
 
 /**
  * meta_stack_free:
diff --git a/src/core/window.c b/src/core/window.c
index 342d9650e..3f7224f59 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -982,7 +982,7 @@ _meta_window_shared_new (MetaDisplay         *display,
   window->override_redirect = attrs->override_redirect;
 
   /* avoid tons of stack updates */
-  meta_stack_freeze (window->screen->stack);
+  meta_stack_freeze (window->display->stack);
 
   window->rect.x = attrs->x;
   window->rect.y = attrs->y;
@@ -1300,7 +1300,7 @@ _meta_window_shared_new (MetaDisplay         *display,
    * means restacking it.
    */
   if (meta_window_is_stackable (window))
-    meta_stack_add (window->screen->stack,
+    meta_stack_add (window->display->stack,
                     window);
   else if (window->override_redirect)
     window->layer = META_LAYER_OVERRIDE_REDIRECT; /* otherwise set by MetaStack */
@@ -1318,14 +1318,14 @@ _meta_window_shared_new (MetaDisplay         *display,
   window->known_to_compositor = TRUE;
 
   /* Sync stack changes */
-  meta_stack_thaw (window->screen->stack);
+  meta_stack_thaw (window->display->stack);
 
   /* Usually the we'll have queued a stack sync anyways, because we've
    * added a new frame window or restacked. But if an undecorated
    * window is mapped, already stacked in the right place, then we
    * might need to do this explicitly.
    */
-  meta_stack_tracker_queue_sync_stack (window->screen->stack_tracker);
+  meta_stack_tracker_queue_sync_stack (window->display->stack_tracker);
 
   /* disable show desktop mode unless we're a desktop component */
   maybe_leave_show_desktop_mode (window);
@@ -1444,11 +1444,11 @@ meta_window_unmanage (MetaWindow  *window,
        * other windows in its group to a higher layer
        */
 
-      meta_stack_freeze (window->screen->stack);
+      meta_stack_freeze (window->display->stack);
       group = meta_window_get_group (window);
       if (group)
         meta_group_update_layers (group);
-      meta_stack_thaw (window->screen->stack);
+      meta_stack_thaw (window->display->stack);
     }
 
   meta_display_remove_pending_pings_for_window (window->display, window);
@@ -1537,13 +1537,13 @@ meta_window_unmanage (MetaWindow  *window,
     }
 
   if (meta_window_is_in_stack (window))
-    meta_stack_remove (window->screen->stack, window);
+    meta_stack_remove (window->display->stack, window);
 
   /* If an undecorated window is being withdrawn, that will change the
    * stack as presented to the compositing manager, without actually
    * changing the stacking order of X windows.
    */
-  meta_stack_tracker_queue_sync_stack (window->screen->stack_tracker);
+  meta_stack_tracker_queue_sync_stack (window->display->stack_tracker);
 
   if (window->display->autoraise_window == window)
     meta_display_remove_autoraise_callback (window->display);
@@ -1701,7 +1701,7 @@ implement_showing (MetaWindow *window,
 
   /* Some windows are not stackable until being showed, so add those now. */
   if (meta_window_is_stackable (window) && !meta_window_is_in_stack (window))
-    meta_stack_add (window->screen->stack, window);
+    meta_stack_add (window->display->stack, window);
 
   if (!showing)
     {
@@ -1743,7 +1743,7 @@ stackcmp (gconstpointer a, gconstpointer b)
   if (aw->screen != bw->screen)
     return 0; /* don't care how they sort with respect to each other */
   else
-    return meta_stack_windows_cmp (aw->screen->stack,
+    return meta_stack_windows_cmp (aw->display->stack,
                                    aw, bw);
 }
 
@@ -2460,9 +2460,9 @@ meta_window_show (MetaWindow *window)
 
   if (window->hidden)
     {
-      meta_stack_freeze (window->screen->stack);
+      meta_stack_freeze (window->display->stack);
       window->hidden = FALSE;
-      meta_stack_thaw (window->screen->stack);
+      meta_stack_thaw (window->display->stack);
       did_show = TRUE;
     }
 
@@ -2591,9 +2591,9 @@ meta_window_hide (MetaWindow *window)
 
   if (!window->hidden)
     {
-      meta_stack_freeze (window->screen->stack);
+      meta_stack_freeze (window->display->stack);
       window->hidden = TRUE;
-      meta_stack_thaw (window->screen->stack);
+      meta_stack_thaw (window->display->stack);
 
       did_hide = TRUE;
     }
@@ -3412,10 +3412,10 @@ meta_window_make_fullscreen_internal (MetaWindow  *window)
 
       window->fullscreen = TRUE;
 
-      meta_stack_freeze (window->screen->stack);
+      meta_stack_freeze (window->display->stack);
 
       meta_window_raise (window);
-      meta_stack_thaw (window->screen->stack);
+      meta_stack_thaw (window->display->stack);
 
       meta_window_recalc_features (window);
       set_net_wm_state (window);
@@ -4035,7 +4035,7 @@ meta_window_move_resize_internal (MetaWindow          *window,
 
   meta_window_foreach_transient (window, maybe_move_attached_dialog, NULL);
 
-  meta_stack_update_window_tile_matches (window->screen->stack,
+  meta_stack_update_window_tile_matches (window->display->stack,
                                          window->screen->active_workspace);
 }
 
@@ -4962,13 +4962,15 @@ meta_window_raise (MetaWindow  *window)
    * constraints in stack.c then magically take care of raising all
    * the child windows appropriately.
    */
-  if (window->screen->stack == ancestor->screen->stack)
-    meta_stack_raise (window->screen->stack, ancestor);
+  if (window->display->stack == ancestor->display->stack)
+    {
+      meta_stack_raise (window->display->stack, ancestor);
+    }
   else
     {
       meta_warning (
                     "Either stacks aren't per screen or some window has a weird "
-                    "transient_for hint; window->screen->stack != "
+                    "transient_for hint; window->display->stack != "
                     "ancestor->screen->stack.  window = %s, ancestor = %s.\n",
                     window->desc, ancestor->desc);
       /* We could raise the window here, but don't want to do that twice and
@@ -4982,7 +4984,7 @@ meta_window_raise (MetaWindow  *window)
    * correct child.  See bug 307875.
    */
   if (window != ancestor)
-    meta_stack_raise (window->screen->stack, window);
+    meta_stack_raise (window->display->stack, window);
 
   g_signal_emit (window, window_signals[RAISED], 0);
 }
@@ -4995,7 +4997,7 @@ meta_window_lower (MetaWindow  *window)
   meta_topic (META_DEBUG_WINDOW_OPS,
               "Lowering window %s\n", window->desc);
 
-  meta_stack_lower (window->screen->stack, window);
+  meta_stack_lower (window->display->stack, window);
 }
 
 /*
@@ -6856,13 +6858,13 @@ meta_window_update_layer (MetaWindow *window)
 {
   MetaGroup *group;
 
-  meta_stack_freeze (window->screen->stack);
+  meta_stack_freeze (window->display->stack);
   group = meta_window_get_group (window);
   if (group)
     meta_group_update_layers (group);
   else
-    meta_stack_update_layer (window->screen->stack, window);
-  meta_stack_thaw (window->screen->stack);
+    meta_stack_update_layer (window->display->stack, window);
+  meta_stack_thaw (window->display->stack);
 }
 
 /* ensure_mru_position_after ensures that window appears after
@@ -7051,7 +7053,7 @@ void
 meta_window_set_demands_attention (MetaWindow *window)
 {
   MetaRectangle candidate_rect, other_rect;
-  GList *stack = window->screen->stack->sorted;
+  GList *stack = window->display->stack->sorted;
   MetaWindow *other_window;
   gboolean obscured = FALSE;
 
@@ -7740,7 +7742,7 @@ meta_window_find_tile_match (MetaWindow   *window,
   else
     return NULL;
 
-  stack = window->screen->stack;
+  stack = window->display->stack;
 
   for (match = meta_stack_get_top (stack);
        match;
@@ -7759,7 +7761,7 @@ meta_window_find_tile_match (MetaWindow   *window,
       MetaWindow *above, *bottommost, *topmost;
       MetaRectangle above_rect, bottommost_rect, topmost_rect;
 
-      if (meta_stack_windows_cmp (window->screen->stack, match, window) > 0)
+      if (meta_stack_windows_cmp (window->display->stack, match, window) > 0)
         {
           topmost = match;
           bottommost = window;
@@ -7939,7 +7941,7 @@ meta_window_set_transient_for (MetaWindow *window,
 
   /* update stacking constraints */
   if (!window->override_redirect)
-    meta_stack_update_transient (window->screen->stack, window);
+    meta_stack_update_transient (window->display->stack, window);
 
   /* possibly change its group. We treat being a window's transient as
    * equivalent to making it your group leader, to work around shortcomings
diff --git a/src/core/workspace.c b/src/core/workspace.c
index 24a9f92d3..5b44ce3d2 100644
--- a/src/core/workspace.c
+++ b/src/core/workspace.c
@@ -1367,7 +1367,7 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
         }
     }
 
-  window = meta_stack_get_default_focus_window (workspace->screen->stack,
+  window = meta_stack_get_default_focus_window (workspace->screen->display->stack,
                                                 workspace,
                                                 not_this_one);
 
diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
index 2eb45b9b5..2471cf3a6 100644
--- a/src/tests/test-runner.c
+++ b/src/tests/test-runner.c
@@ -213,7 +213,7 @@ test_case_assert_stacking (TestCase *test,
   GString *expected_string = g_string_new (NULL);
   int i;
 
-  meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows);
+  meta_stack_tracker_get_stack (display->stack_tracker, &windows, &n_windows);
   for (i = 0; i < n_windows; i++)
     {
       MetaWindow *window = meta_display_lookup_stack_id (display, windows[i]);
@@ -234,7 +234,7 @@ test_case_assert_stacking (TestCase *test,
           else
             g_string_append_printf (stack_string, "(%s)", window->title);
         }
-      else if (windows[i] == display->screen->guard_window)
+      else if (windows[i] == display->x11_display->guard_window)
         {
           if (stack_string->len > 0)
             g_string_append_c (stack_string, ' ');
@@ -285,7 +285,7 @@ test_case_check_xserver_stacking (TestCase *test,
 
   guint64 *windows;
   int n_windows;
-  meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows);
+  meta_stack_tracker_get_stack (display->stack_tracker, &windows, &n_windows);
 
   for (i = 0; i < n_windows; i++)
     {
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index 3e82d3f78..e50af5c94 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -88,7 +88,7 @@ meta_window_wayland_manage (MetaWindow *window)
   meta_display_register_wayland_window (display, window);
 
   {
-    meta_stack_tracker_record_add (window->screen->stack_tracker,
+    meta_stack_tracker_record_add (window->display->stack_tracker,
                                    window->stamp,
                                    0);
   }
@@ -100,7 +100,7 @@ static void
 meta_window_wayland_unmanage (MetaWindow *window)
 {
   {
-    meta_stack_tracker_record_remove (window->screen->stack_tracker,
+    meta_stack_tracker_record_remove (window->display->stack_tracker,
                                       window->stamp,
                                       0);
   }
diff --git a/src/wayland/meta-xwayland-selection.c b/src/wayland/meta-xwayland-selection.c
index f5fc257b6..e46d08ad9 100644
--- a/src/wayland/meta-xwayland-selection.c
+++ b/src/wayland/meta-xwayland-selection.c
@@ -1344,7 +1344,7 @@ pick_drop_surface (MetaWaylandCompositor *compositor,
   ClutterPoint pos;
 
   clutter_event_get_coords (event, &pos.x, &pos.y);
-  focus_window = meta_stack_get_default_focus_window_at_point (display->screen->stack,
+  focus_window = meta_stack_get_default_focus_window_at_point (display->stack,
                                                                NULL, NULL,
                                                                pos.x, pos.y);
   return focus_window ? focus_window->surface : NULL;
diff --git a/src/x11/events.c b/src/x11/events.c
index 18d530de2..f19e829e0 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -1285,7 +1285,7 @@ handle_other_xevent (MetaDisplay *display,
     case CreateNotify:
       {
         if (event->xcreatewindow.parent == x11_display->xroot)
-          meta_stack_tracker_create_event (display->screen->stack_tracker,
+          meta_stack_tracker_create_event (display->stack_tracker,
                                            &event->xcreatewindow);
       }
       break;
@@ -1293,7 +1293,7 @@ handle_other_xevent (MetaDisplay *display,
     case DestroyNotify:
       {
         if (event->xdestroywindow.event == x11_display->xroot)
-          meta_stack_tracker_destroy_event (display->screen->stack_tracker,
+          meta_stack_tracker_destroy_event (display->stack_tracker,
                                             &event->xdestroywindow);
       }
       if (window)
@@ -1411,7 +1411,7 @@ handle_other_xevent (MetaDisplay *display,
     case ReparentNotify:
       {
         if (event->xreparent.event == x11_display->xroot)
-          meta_stack_tracker_reparent_event (display->screen->stack_tracker,
+          meta_stack_tracker_reparent_event (display->stack_tracker,
                                              &event->xreparent);
       }
       break;
@@ -1420,7 +1420,7 @@ handle_other_xevent (MetaDisplay *display,
         {
           if (event->xconfigure.event == x11_display->xroot &&
               event->xconfigure.window != display->screen->composite_overlay_window)
-            meta_stack_tracker_configure_event (display->screen->stack_tracker,
+            meta_stack_tracker_configure_event (display->stack_tracker,
                                                 &event->xconfigure);
         }
 
diff --git a/src/x11/group.c b/src/x11/group.c
index a867a470d..b69586de7 100644
--- a/src/x11/group.c
+++ b/src/x11/group.c
@@ -276,10 +276,10 @@ meta_group_update_layers (MetaGroup *group)
        * but doesn't hurt anything. have to handle
        * groups that span 2 screens.
        */
-      meta_stack_freeze (window->screen->stack);
-      frozen_stacks = g_slist_prepend (frozen_stacks, window->screen->stack);
+      meta_stack_freeze (window->display->stack);
+      frozen_stacks = g_slist_prepend (frozen_stacks, window->display->stack);
 
-      meta_stack_update_layer (window->screen->stack,
+      meta_stack_update_layer (window->display->stack,
                                window);
 
       tmp = tmp->next;
diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h
index e2a255fdc..a0cee7123 100644
--- a/src/x11/meta-x11-display-private.h
+++ b/src/x11/meta-x11-display-private.h
@@ -61,6 +61,11 @@ struct _MetaX11Display
 #include "x11/atomnames.h"
 #undef item
 
+  /* Instead of unmapping withdrawn windows we can leave them mapped
+   * and restack them below a guard window. When using a compositor
+   * this allows us to provide live previews of unmapped windows */
+  Window guard_window;
+
   GHashTable *xids;
 
   /* Managed by group.c */
@@ -144,4 +149,6 @@ void meta_x11_display_set_alarm_filter (MetaX11Display *x11_display,
                                         MetaAlarmFilter filter,
                                         gpointer        data);
 
+void meta_x11_display_create_guard_window (MetaX11Display *x11_display);
+
 #endif /* META_X11_DISPLAY_PRIVATE_H */
diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
index f13620918..61be15d0a 100644
--- a/src/x11/meta-x11-display.c
+++ b/src/x11/meta-x11-display.c
@@ -64,6 +64,9 @@ G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT)
 static char *get_screen_name (Display *xdisplay,
                               int      number);
 
+static void on_monitors_changed (MetaDisplay    *display,
+                                 MetaX11Display *x11_display);
+
 static void update_cursor_theme (MetaX11Display *x11_display);
 
 static void
@@ -71,6 +74,26 @@ meta_x11_display_dispose (GObject *object)
 {
   MetaX11Display *x11_display = META_X11_DISPLAY (object);
 
+  if (x11_display->guard_window != None)
+    {
+      MetaStackTracker *stack_tracker = x11_display->display->stack_tracker;
+
+      if (stack_tracker)
+        {
+          unsigned long serial;
+
+          serial = XNextRequest (x11_display->xdisplay);
+          meta_stack_tracker_record_remove (stack_tracker,
+                                            x11_display->guard_window,
+                                            serial);
+        }
+
+      XUnmapWindow (x11_display->xdisplay, x11_display->guard_window);
+      XDestroyWindow (x11_display->xdisplay, x11_display->guard_window);
+
+      x11_display->guard_window = None;
+    }
+
   if (x11_display->prop_hooks)
     {
       meta_x11_display_free_window_prop_hooks (x11_display);
@@ -425,12 +448,19 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
                                         meta_unsigned_long_equal);
 
   x11_display->groups_by_leader = NULL;
+  x11_display->guard_window = None;
 
   x11_display->prop_hooks = NULL;
   meta_x11_display_init_window_prop_hooks (x11_display);
   x11_display->group_prop_hooks = NULL;
   meta_x11_display_init_group_prop_hooks (x11_display);
 
+  g_signal_connect_object (display,
+                           "monitors-changed",
+                           G_CALLBACK (on_monitors_changed),
+                           x11_display,
+                           0);
+
   return x11_display;
 }
 
@@ -659,3 +689,100 @@ meta_x11_display_set_alarm_filter (MetaX11Display *x11_display,
   x11_display->alarm_filter = filter;
   x11_display->alarm_filter_data = data;
 }
+
+/* The guard window allows us to leave minimized windows mapped so
+ * that compositor code may provide live previews of them.
+ * Instead of being unmapped/withdrawn, they get pushed underneath
+ * the guard window. We also select events on the guard window, which
+ * should effectively be forwarded to events on the background actor,
+ * providing that the scene graph is set up correctly.
+ */
+static Window
+create_guard_window (MetaX11Display *x11_display)
+{
+  XSetWindowAttributes attributes;
+  Window guard_window;
+  gulong create_serial;
+
+  attributes.event_mask = NoEventMask;
+  attributes.override_redirect = True;
+
+  /* We have to call record_add() after we have the new window ID,
+   * so save the serial for the CreateWindow request until then */
+  create_serial = XNextRequest (x11_display->xdisplay);
+  guard_window =
+    XCreateWindow (x11_display->xdisplay,
+                   x11_display->xroot,
+                   0, /* x */
+                   0, /* y */
+                   x11_display->display->rect.width,
+                   x11_display->display->rect.height,
+                   0, /* border width */
+                   0, /* depth */
+                   InputOnly, /* class */
+                   CopyFromParent, /* visual */
+                   CWEventMask | CWOverrideRedirect,
+                   &attributes);
+
+  /* https://bugzilla.gnome.org/show_bug.cgi?id=710346 */
+  XStoreName (x11_display->xdisplay, guard_window, "mutter guard window");
+
+  {
+    if (!meta_is_wayland_compositor ())
+      {
+        MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
+        Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
+        unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
+        XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
+
+        XISetMask (mask.mask, XI_ButtonPress);
+        XISetMask (mask.mask, XI_ButtonRelease);
+        XISetMask (mask.mask, XI_Motion);
+
+        /* Sync on the connection we created the window on to
+         * make sure it's created before we select on it on the
+         * backend connection. */
+        XSync (x11_display->xdisplay, False);
+
+        XISelectEvents (backend_xdisplay, guard_window, &mask, 1);
+      }
+  }
+
+  meta_stack_tracker_record_add (x11_display->display->stack_tracker,
+                                 guard_window,
+                                 create_serial);
+
+  meta_stack_tracker_lower (x11_display->display->stack_tracker,
+                            guard_window);
+
+  XMapWindow (x11_display->xdisplay, guard_window);
+  return guard_window;
+}
+
+void
+meta_x11_display_create_guard_window (MetaX11Display *x11_display)
+{
+  if (x11_display->guard_window == None)
+    x11_display->guard_window = create_guard_window (x11_display);
+}
+
+static void
+on_monitors_changed (MetaDisplay    *display,
+                     MetaX11Display *x11_display)
+{
+  /* Resize the guard window to fill the screen again. */
+  if (x11_display->guard_window != None)
+    {
+      XWindowChanges changes;
+
+      changes.x = 0;
+      changes.y = 0;
+      changes.width = display->rect.width;
+      changes.height = display->rect.height;
+
+      XConfigureWindow (x11_display->xdisplay,
+                        x11_display->guard_window,
+                        CWX | CWY | CWWidth | CWHeight,
+                        &changes);
+    }
+}
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index 66bc8ae19..16b09b565 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -2984,7 +2984,7 @@ is_our_xwindow (MetaDisplay       *display,
   if (xwindow == screen->wm_cm_selection_window)
     return TRUE;
 
-  if (xwindow == screen->guard_window)
+  if (xwindow == display->x11_display->guard_window)
     return TRUE;
 
   if (xwindow == screen->composite_overlay_window)


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