[mutter] Move workspace handling to MetaDisplay and MetaX11Display



commit b7c3dada81eec424662caab621d86788597aaa83
Author: Armin Krezović <krezovic armin gmail com>
Date:   Sat Aug 26 21:39:46 2017 +0200

    Move workspace handling to MetaDisplay and MetaX11Display
    
    https://bugzilla.gnome.org/show_bug.cgi?id=759538

 src/core/constraints.c             |    6 +-
 src/core/core.c                    |   16 +-
 src/core/display-private.h         |   44 ++
 src/core/display.c                 |  993 ++++++++++++++++++++++++++++++-
 src/core/edge-resistance.c         |    6 +-
 src/core/keybindings.c             |   28 +-
 src/core/screen-private.h          |   53 +-
 src/core/screen.c                  | 1125 +-----------------------------------
 src/core/stack.c                   |   14 +-
 src/core/window.c                  |   86 +--
 src/core/workspace-private.h       |    4 +-
 src/core/workspace.c               |  136 +++--
 src/meta/display.h                 |   42 ++
 src/meta/screen.h                  |   42 --
 src/meta/workspace.h               |    2 +-
 src/x11/events.c                   |   21 +-
 src/x11/meta-x11-display-private.h |    8 +
 src/x11/meta-x11-display.c         |  106 ++++
 src/x11/window-props.c             |    2 +-
 src/x11/window-x11.c               |    8 +-
 20 files changed, 1349 insertions(+), 1393 deletions(-)
---
diff --git a/src/core/constraints.c b/src/core/constraints.c
index f5360ef9d..d90e7230c 100644
--- a/src/core/constraints.c
+++ b/src/core/constraints.c
@@ -412,7 +412,7 @@ setup_constraint_info (ConstraintInfo      *info,
                             &info->entire_monitor);
     }
 
-  cur_workspace = window->screen->active_workspace;
+  cur_workspace = window->display->active_workspace;
   info->usable_screen_region   =
     meta_workspace_get_onscreen_region (cur_workspace);
   info->usable_monitor_region =
@@ -499,7 +499,7 @@ place_window_if_needed(MetaWindow     *window,
       meta_window_get_work_area_for_logical_monitor (window,
                                                      logical_monitor,
                                                      &info->work_area_monitor);
-      cur_workspace = window->screen->active_workspace;
+      cur_workspace = window->display->active_workspace;
       info->usable_monitor_region =
         meta_workspace_get_onmonitor_region (cur_workspace, logical_monitor);
 
@@ -965,7 +965,7 @@ constrain_maximization (MetaWindow         *window,
         direction = META_DIRECTION_HORIZONTAL;
       else
         direction = META_DIRECTION_VERTICAL;
-      active_workspace_struts = window->screen->active_workspace->all_struts;
+      active_workspace_struts = window->display->active_workspace->all_struts;
 
       target_size = info->current;
       meta_rectangle_expand_to_avoiding_struts (&target_size,
diff --git a/src/core/core.c b/src/core/core.c
index d0caeca7a..15949fa6e 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -87,22 +87,22 @@ lower_window_and_transients (MetaWindow *window,
        * Do extra sanity checks to avoid possible race conditions.
        * (Borrowed from window.c.)
        */
-      if (window->screen->active_workspace &&
+      if (window->display->active_workspace &&
           meta_window_located_on_workspace (window,
-                                            window->screen->active_workspace))
+                                            window->display->active_workspace))
         {
           GList* link;
-          link = g_list_find (window->screen->active_workspace->mru_list,
+          link = g_list_find (window->display->active_workspace->mru_list,
                               window);
           g_assert (link);
 
-          window->screen->active_workspace->mru_list =
-            g_list_remove_link (window->screen->active_workspace->mru_list,
+          window->display->active_workspace->mru_list =
+            g_list_remove_link (window->display->active_workspace->mru_list,
                                 link);
           g_list_free (link);
 
-          window->screen->active_workspace->mru_list =
-            g_list_append (window->screen->active_workspace->mru_list,
+          window->display->active_workspace->mru_list =
+            g_list_append (window->display->active_workspace->mru_list,
                            window);
         }
     }
@@ -123,7 +123,7 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
   * the focus window, assume that's always the case. (Typically,
   * this will be invoked via keyboard action or by a mouse action;
   * in either case the window or a modal child will have been focused.) */
-  meta_workspace_focus_default_window (window->screen->active_workspace,
+  meta_workspace_focus_default_window (window->display->active_workspace,
                                        NULL,
                                        timestamp);
 }
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 48a9c93cf..5ab6791fd 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -245,6 +245,16 @@ struct _MetaDisplay
 
   guint work_area_later;
   guint check_fullscreen_later;
+
+  MetaWorkspace *active_workspace;
+
+  GList *workspaces;
+
+  int rows_of_workspaces;
+  int columns_of_workspaces;
+  MetaDisplayCorner starting_corner;
+  guint vertical_workspaces : 1;
+  guint workspace_layout_overridden : 1;
 };
 
 struct _MetaDisplayClass
@@ -434,4 +444,38 @@ void meta_display_queue_check_fullscreen (MetaDisplay *display);
 MetaWindow *meta_display_get_pointer_window (MetaDisplay *display,
                                              MetaWindow  *not_this_one);
 
+void meta_display_init_workspaces         (MetaDisplay *display);
+void meta_display_update_workspace_layout (MetaDisplay *display);
+
+typedef struct MetaWorkspaceLayout MetaWorkspaceLayout;
+
+struct MetaWorkspaceLayout
+{
+  int rows;
+  int cols;
+  int *grid;
+  int grid_area;
+  int current_row;
+  int current_col;
+};
+
+void meta_display_calc_workspace_layout (MetaDisplay         *display,
+                                         int                  num_workspaces,
+                                         int                  current_space,
+                                         MetaWorkspaceLayout *layout);
+void meta_display_free_workspace_layout (MetaWorkspaceLayout *layout);
+
+void meta_display_minimize_all_on_active_workspace_except (MetaDisplay *display,
+                                                           MetaWindow *keep);
+
+/* Show/hide the desktop (temporarily hide all windows) */
+void     meta_display_show_desktop        (MetaDisplay *display,
+                                           guint32      timestamp);
+void     meta_display_unshow_desktop      (MetaDisplay *display);
+
+void     meta_display_workspace_switched (MetaDisplay        *display,
+                                          int                 from,
+                                          int                 to,
+                                          MetaMotionDirection direction);
+
 #endif
diff --git a/src/core/display.c b/src/core/display.c
index d00229cab..a0bdab91f 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -138,6 +138,9 @@ enum
   PAD_MODE_SWITCH,
   WINDOW_ENTERED_MONITOR,
   WINDOW_LEFT_MONITOR,
+  WORKSPACE_ADDED,
+  WORKSPACE_REMOVED,
+  WORKSPACE_SWITCHED,
   IN_FULLSCREEN_CHANGED,
   STARTUP_SEQUENCE_CHANGED,
   MONITORS_CHANGED,
@@ -149,7 +152,8 @@ enum
 enum {
   PROP_0,
 
-  PROP_FOCUS_WINDOW
+  PROP_FOCUS_WINDOW,
+  PROP_N_WORKSPACES
 };
 
 static guint display_signals [LAST_SIGNAL] = { 0 };
@@ -171,6 +175,10 @@ static void on_monitors_changed (MetaMonitorManager *monitor_manager,
 static void    prefs_changed_callback    (MetaPreference pref,
                                           void          *data);
 
+static void set_workspace_names   (MetaDisplay *display);
+static void update_num_workspaces (MetaDisplay *display,
+                                   guint32     timestamp);
+
 static int mru_cmp (gconstpointer a,
                     gconstpointer b);
 
@@ -187,6 +195,9 @@ meta_display_get_property(GObject         *object,
     case PROP_FOCUS_WINDOW:
       g_value_set_object (value, display->focus_window);
       break;
+    case PROP_N_WORKSPACES:
+      g_value_set_int (value, meta_display_get_n_workspaces (display));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -446,6 +457,38 @@ meta_display_class_init (MetaDisplayClass *klass)
                   G_TYPE_INT,
                   META_TYPE_WINDOW);
 
+  display_signals[WORKSPACE_ADDED] =
+    g_signal_new ("workspace-added",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE,
+                  1,
+                  G_TYPE_INT);
+
+  display_signals[WORKSPACE_REMOVED] =
+    g_signal_new ("workspace-removed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE,
+                  1,
+                  G_TYPE_INT);
+
+  display_signals[WORKSPACE_SWITCHED] =
+    g_signal_new ("workspace-switched",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE,
+                  3,
+                  G_TYPE_INT,
+                  G_TYPE_INT,
+                  META_TYPE_MOTION_DIRECTION);
+
   display_signals[IN_FULLSCREEN_CHANGED] =
     g_signal_new ("in-fullscreen-changed",
                   G_TYPE_FROM_CLASS (klass),
@@ -488,6 +531,15 @@ meta_display_class_init (MetaDisplayClass *klass)
                                                         "Currently focused window",
                                                         META_TYPE_WINDOW,
                                                         G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_N_WORKSPACES,
+                                   g_param_spec_int ("n-workspaces",
+                                                     "N Workspaces",
+                                                     "Number of workspaces",
+                                                     1, G_MAXINT, 1,
+                                                     G_PARAM_READABLE));
+
 }
 
 
@@ -629,6 +681,18 @@ on_startup_notification_changed (MetaStartupNotification *sn,
   g_signal_emit_by_name (display, "startup-sequence-changed", sequence);
 }
 
+static void
+reload_logical_monitors (MetaDisplay *display)
+{
+  GList *l;
+
+  for (l = display->workspaces; l != NULL; l = l->next)
+    {
+      MetaWorkspace *space = l->data;
+      meta_workspace_invalidate_work_area (space);
+    }
+}
+
 /**
  * meta_display_open:
  *
@@ -694,6 +758,13 @@ meta_display_open (void)
   display->grab_tile_mode = META_TILE_NONE;
   display->grab_tile_monitor_number = -1;
 
+  display->active_workspace = NULL;
+  display->workspaces = NULL;
+  display->rows_of_workspaces = 1;
+  display->columns_of_workspaces = -1;
+  display->vertical_workspaces = FALSE;
+  display->starting_corner = META_DISPLAY_TOPLEFT;
+
   display->grab_edge_resistance_data = NULL;
 
   meta_display_init_keys (display);
@@ -729,6 +800,15 @@ meta_display_open (void)
   display->stack = meta_stack_new (display);
   display->stack_tracker = meta_stack_tracker_new (display);
 
+  reload_logical_monitors (display);
+
+  meta_display_update_workspace_layout (display);
+
+  /* There must be at least one workspace at all times,
+   * so create that required workspace.
+   */
+  meta_workspace_new (display);
+
   meta_bell_init (display);
 
   display->last_focus_time = timestamp;
@@ -762,7 +842,7 @@ meta_display_open (void)
   g_signal_connect (display->startup_notification, "changed",
                     G_CALLBACK (on_startup_notification_changed), display);
 
-  meta_screen_init_workspaces (screen);
+  meta_display_init_workspaces (display);
 
   enable_compositor (display);
 
@@ -2496,6 +2576,21 @@ prefs_changed_callback (MetaPreference pref,
     {
       meta_display_reload_cursor (display);
     }
+  else if ((pref == META_PREF_NUM_WORKSPACES ||
+            pref == META_PREF_DYNAMIC_WORKSPACES) &&
+            !meta_prefs_get_dynamic_workspaces ())
+    {
+      /* GSettings doesn't provide timestamps, but luckily update_num_workspaces
+       * often doesn't need it...
+       */
+      guint32 timestamp =
+        meta_display_get_current_time_roundtrip (display);
+      update_num_workspaces (display, timestamp);
+    }
+  else if (pref == META_PREF_WORKSPACE_NAMES)
+    {
+      set_workspace_names (display);
+    }
 }
 
 void
@@ -2993,12 +3088,12 @@ on_monitors_changed_internal (MetaMonitorManager *monitor_manager,
   MetaBackend *backend;
   MetaCursorRenderer *cursor_renderer;
 
-  meta_screen_on_monitors_changed (display->screen);
-
   meta_monitor_manager_get_screen_size (monitor_manager,
                                         &display->rect.width,
                                         &display->rect.height);
 
+  reload_logical_monitors (display);
+
   /* Fix up monitor for all windows on this display */
   meta_display_foreach_window (display, META_LIST_INCLUDE_OVERRIDE_REDIRECT,
                                (MetaDisplayWindowFunc)
@@ -3264,17 +3359,16 @@ static void
 set_work_area_hint (MetaDisplay *display)
 {
   MetaX11Display *x11_display = display->x11_display;
-  MetaScreen *screen = display->screen;
   int num_workspaces;
   GList *l;
   unsigned long *data, *tmp;
   MetaRectangle area;
 
-  num_workspaces = meta_screen_get_n_workspaces (screen);
+  num_workspaces = meta_display_get_n_workspaces (display);
   data = g_new (unsigned long, num_workspaces * 4);
   tmp = data;
 
-  for (l = screen->workspaces; l; l = l->next)
+  for (l = display->workspaces; l; l = l->next)
     {
       MetaWorkspace *workspace = l->data;
 
@@ -3639,9 +3733,892 @@ meta_display_get_pointer_window (MetaDisplay *display,
   meta_cursor_tracker_get_pointer (cursor_tracker, &x, &y, NULL);
 
   window = meta_stack_get_default_focus_window_at_point (display->stack,
-                                                         display->screen->active_workspace,
+                                                         display->active_workspace,
                                                          not_this_one,
                                                          x, y);
 
   return window;
 }
+
+void
+meta_display_init_workspaces (MetaDisplay *display)
+{
+  MetaWorkspace *current_workspace;
+  uint32_t current_workspace_index = 0;
+  guint32 timestamp;
+
+  g_return_if_fail (META_IS_DISPLAY (display));
+
+  timestamp = display->x11_display->wm_sn_timestamp;
+
+  /* Get current workspace */
+  if (meta_prop_get_cardinal (display->x11_display,
+                              display->x11_display->xroot,
+                              display->x11_display->atom__NET_CURRENT_DESKTOP,
+                              &current_workspace_index))
+    meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
+                  (int) current_workspace_index);
+  else
+    meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
+
+  update_num_workspaces (display, timestamp);
+
+  set_workspace_names (display);
+
+  /* Switch to the _NET_CURRENT_DESKTOP workspace */
+  current_workspace = meta_display_get_workspace_by_index (display,
+                                                           current_workspace_index);
+
+  if (current_workspace != NULL)
+    meta_workspace_activate (current_workspace, timestamp);
+  else
+    meta_workspace_activate (display->workspaces->data, timestamp);
+}
+
+int
+meta_display_get_n_workspaces (MetaDisplay *display)
+{
+  return g_list_length (display->workspaces);
+}
+
+/**
+ * meta_display_get_workspace_by_index:
+ * @display: a #MetaDisplay
+ * @index: index of one of the display's workspaces
+ *
+ * Gets the workspace object for one of a display's workspaces given the workspace
+ * index. It's valid to call this function with an out-of-range index and it
+ * will robustly return %NULL.
+ *
+ * Return value: (transfer none): the workspace object with specified index, or %NULL
+ *   if the index is out of range.
+ */
+MetaWorkspace *
+meta_display_get_workspace_by_index (MetaDisplay  *display,
+                                     int           idx)
+{
+  return g_list_nth_data (display->workspaces, idx);
+}
+
+void
+meta_display_remove_workspace (MetaDisplay   *display,
+                               MetaWorkspace *workspace,
+                               guint32        timestamp)
+{
+  GList *l;
+  GList *next;
+  MetaWorkspace *neighbour = NULL;
+  int index;
+  gboolean active_index_changed;
+  int new_num;
+
+  l = g_list_find (display->workspaces, workspace);
+  if (!l)
+    return;
+
+  next = l->next;
+
+  if (l->prev)
+    neighbour = l->prev->data;
+  else if (l->next)
+    neighbour = l->next->data;
+  else
+    {
+      /* Cannot remove the only workspace! */
+      return;
+    }
+
+  meta_workspace_relocate_windows (workspace, neighbour);
+
+  if (workspace == display->active_workspace)
+    meta_workspace_activate (neighbour, timestamp);
+
+  /* To emit the signal after removing the workspace */
+  index = meta_workspace_index (workspace);
+  active_index_changed = index < meta_display_get_active_workspace_index (display);
+
+  /* This also removes the workspace from the displays list */
+  meta_workspace_remove (workspace);
+
+  new_num = g_list_length (display->workspaces);
+
+  meta_x11_display_set_number_of_spaces_hint (display->x11_display, new_num);
+
+  if (!meta_prefs_get_dynamic_workspaces ())
+    meta_prefs_set_num_workspaces (new_num);
+
+  /* If deleting a workspace before the current workspace, the active
+   * workspace index changes, so we need to update that hint */
+  if (active_index_changed)
+      meta_x11_display_set_active_workspace_hint (display->x11_display);
+
+  for (l = next; l; l = l->next)
+    {
+      MetaWorkspace *w = l->data;
+
+      meta_workspace_index_changed (w);
+    }
+
+  meta_display_queue_workarea_recalc (display);
+
+  g_signal_emit (display, display_signals[WORKSPACE_REMOVED], 0, index);
+  g_object_notify (G_OBJECT (display), "n-workspaces");
+}
+
+/**
+ * meta_display_append_new_workspace:
+ * @display: a #MetaDisplay
+ * @activate: %TRUE if the workspace should be switched to after creation
+ * @timestamp: if switching to a new workspace, timestamp to be used when
+ *   focusing a window on the new workspace. (Doesn't hurt to pass a valid
+ *   timestamp when available even if not switching workspaces.)
+ *
+ * Append a new workspace to the display and (optionally) switch to that
+ * display.
+ *
+ * Return value: (transfer none): the newly appended workspace.
+ */
+MetaWorkspace *
+meta_display_append_new_workspace (MetaDisplay *display,
+                                   gboolean     activate,
+                                   guint32      timestamp)
+{
+  MetaWorkspace *w;
+  int new_num;
+
+  /* This also adds the workspace to the display list */
+  w = meta_workspace_new (display);
+
+  if (!w)
+    return NULL;
+
+  if (activate)
+    meta_workspace_activate (w, timestamp);
+
+  new_num = g_list_length (display->workspaces);
+
+  meta_x11_display_set_number_of_spaces_hint (display->x11_display, new_num);
+
+  if (!meta_prefs_get_dynamic_workspaces ())
+    meta_prefs_set_num_workspaces (new_num);
+
+  meta_display_queue_workarea_recalc (display);
+
+  g_signal_emit (display, display_signals[WORKSPACE_ADDED],
+                 0, meta_workspace_index (w));
+  g_object_notify (G_OBJECT (display), "n-workspaces");
+
+  return w;
+}
+
+static void
+update_num_workspaces (MetaDisplay *display,
+                       guint32     timestamp)
+{
+  int new_num, old_num;
+  GList *l;
+  int i;
+  GList *extras;
+  MetaWorkspace *last_remaining;
+  gboolean need_change_space;
+
+  if (meta_prefs_get_dynamic_workspaces ())
+    {
+      int n_items;
+      uint32_t *list;
+
+      n_items = 0;
+      list = NULL;
+
+      if (meta_prop_get_cardinal_list (display->x11_display,
+                                       display->x11_display->xroot,
+                                       display->x11_display->atom__NET_NUMBER_OF_DESKTOPS,
+                                       &list, &n_items))
+        {
+          new_num = list[0];
+          meta_XFree (list);
+        }
+      else
+        {
+          new_num = 1;
+        }
+    }
+  else
+    {
+      new_num = meta_prefs_get_num_workspaces ();
+    }
+
+  g_assert (new_num > 0);
+
+  if (g_list_length (display->workspaces) == (guint) new_num)
+    return;
+
+  last_remaining = NULL;
+  extras = NULL;
+  i = 0;
+  for (l = display->workspaces; l != NULL; l = l->next)
+    {
+      MetaWorkspace *w = l->data;
+
+      if (i >= new_num)
+        extras = g_list_prepend (extras, w);
+      else
+        last_remaining = w;
+
+      ++i;
+    }
+  old_num = i;
+
+  g_assert (last_remaining);
+
+  /* Get rid of the extra workspaces by moving all their windows
+   * to last_remaining, then activating last_remaining if
+   * one of the removed workspaces was active. This will be a bit
+   * wacky if the config tool for changing number of workspaces
+   * is on a removed workspace ;-)
+   */
+  need_change_space = FALSE;
+  for (l = extras; l != NULL; l = l->next)
+    {
+      MetaWorkspace *w = l->data;
+
+      meta_workspace_relocate_windows (w, last_remaining);
+
+      if (w == display->active_workspace)
+        need_change_space = TRUE;
+    }
+
+  if (need_change_space)
+    meta_workspace_activate (last_remaining, timestamp);
+
+  /* Should now be safe to free the workspaces */
+  for (l = extras; l != NULL; l = l->next)
+    {
+      MetaWorkspace *w = l->data;
+
+      meta_workspace_remove (w);
+    }
+
+  g_list_free (extras);
+
+  for (i = old_num; i < new_num; i++)
+    meta_workspace_new (display);
+
+  meta_x11_display_set_number_of_spaces_hint (display->x11_display, new_num);
+
+  meta_display_queue_workarea_recalc (display);
+
+  for (i = old_num; i < new_num; i++)
+    g_signal_emit (display, display_signals[WORKSPACE_ADDED], 0, i);
+
+  g_object_notify (G_OBJECT (display), "n-workspaces");
+}
+
+#define _NET_WM_ORIENTATION_HORZ 0
+#define _NET_WM_ORIENTATION_VERT 1
+
+#define _NET_WM_TOPLEFT     0
+#define _NET_WM_TOPRIGHT    1
+#define _NET_WM_BOTTOMRIGHT 2
+#define _NET_WM_BOTTOMLEFT  3
+
+void
+meta_display_update_workspace_layout (MetaDisplay *display)
+{
+  uint32_t *list;
+  int n_items;
+
+  if (display->workspace_layout_overridden)
+    return;
+
+  list = NULL;
+  n_items = 0;
+
+  if (meta_prop_get_cardinal_list (display->x11_display,
+                                   display->x11_display->xroot,
+                                   display->x11_display->atom__NET_DESKTOP_LAYOUT,
+                                   &list, &n_items))
+    {
+      if (n_items == 3 || n_items == 4)
+        {
+          int cols, rows;
+
+          switch (list[0])
+            {
+            case _NET_WM_ORIENTATION_HORZ:
+              display->vertical_workspaces = FALSE;
+              break;
+            case _NET_WM_ORIENTATION_VERT:
+              display->vertical_workspaces = TRUE;
+              break;
+            default:
+              meta_warning ("Someone set a weird orientation in _NET_DESKTOP_LAYOUT\n");
+              break;
+            }
+
+          cols = list[1];
+          rows = list[2];
+
+          if (rows <= 0 && cols <= 0)
+            {
+              meta_warning ("Columns = %d rows = %d in _NET_DESKTOP_LAYOUT makes no sense\n", rows, cols);
+            }
+          else
+            {
+              if (rows > 0)
+                display->rows_of_workspaces = rows;
+              else
+                display->rows_of_workspaces = -1;
+
+              if (cols > 0)
+                display->columns_of_workspaces = cols;
+              else
+                display->columns_of_workspaces = -1;
+            }
+
+          if (n_items == 4)
+            {
+              switch (list[3])
+                {
+                case _NET_WM_TOPLEFT:
+                  display->starting_corner = META_DISPLAY_TOPLEFT;
+                  break;
+                case _NET_WM_TOPRIGHT:
+                  display->starting_corner = META_DISPLAY_TOPRIGHT;
+                  break;
+                case _NET_WM_BOTTOMRIGHT:
+                  display->starting_corner = META_DISPLAY_BOTTOMRIGHT;
+                  break;
+                case _NET_WM_BOTTOMLEFT:
+                  display->starting_corner = META_DISPLAY_BOTTOMLEFT;
+                  break;
+                default:
+                  meta_warning ("Someone set a weird starting corner in _NET_DESKTOP_LAYOUT\n");
+                  break;
+                }
+            }
+          else
+            display->starting_corner = META_DISPLAY_TOPLEFT;
+        }
+      else
+        {
+          meta_warning ("Someone set _NET_DESKTOP_LAYOUT to %d integers instead of 4 "
+                        "(3 is accepted for backwards compat)\n", n_items);
+        }
+
+      meta_XFree (list);
+    }
+
+  meta_verbose ("Workspace layout rows = %d cols = %d orientation = %d starting corner = %u\n",
+                display->rows_of_workspaces,
+                display->columns_of_workspaces,
+                display->vertical_workspaces,
+                display->starting_corner);
+}
+
+/**
+ * meta_display_override_workspace_layout:
+ * @display: a #MetaDisplay
+ * @starting_corner: the corner at which the first workspace is found
+ * @vertical_layout: if %TRUE the workspaces are laid out in columns rather than rows
+ * @n_rows: number of rows of workspaces, or -1 to determine the number of rows from
+ *   @n_columns and the total number of workspaces
+ * @n_columns: number of columns of workspaces, or -1 to determine the number of columns from
+ *   @n_rows and the total number of workspaces
+ *
+ * Explicitly set the layout of workspaces. Once this has been called, the contents of the
+ * _NET_DESKTOP_LAYOUT property on the root window are completely ignored.
+ */
+void
+meta_display_override_workspace_layout (MetaDisplay       *display,
+                                        MetaDisplayCorner  starting_corner,
+                                        gboolean           vertical_layout,
+                                        int                n_rows,
+                                        int                n_columns)
+{
+  g_return_if_fail (META_IS_DISPLAY (display));
+  g_return_if_fail (n_rows > 0 || n_columns > 0);
+  g_return_if_fail (n_rows != 0 && n_columns != 0);
+
+  display->workspace_layout_overridden = TRUE;
+  display->vertical_workspaces = vertical_layout != FALSE;
+  display->starting_corner = starting_corner;
+  display->rows_of_workspaces = n_rows;
+  display->columns_of_workspaces = n_columns;
+
+  /* In theory we should remove _NET_DESKTOP_LAYOUT from _NET_SUPPORTED at this
+   * point, but it's unlikely that anybody checks that, and it's unlikely that
+   * anybody who checks that handles changes, so we'd probably just create
+   * a race condition. And it's hard to implement with the code in set_supported_hint()
+   */
+}
+
+static void
+set_workspace_names (MetaDisplay *display)
+{
+  /* This updates names on root window when the pref changes,
+   * note we only get prefs change notify if things have
+   * really changed.
+   */
+  MetaX11Display *x11_display = display->x11_display;
+  GString *flattened;
+  int i;
+  int n_spaces;
+
+  /* flatten to nul-separated list */
+  n_spaces = meta_display_get_n_workspaces (display);
+  flattened = g_string_new ("");
+  i = 0;
+  while (i < n_spaces)
+    {
+      const char *name;
+
+      name = meta_prefs_get_workspace_name (i);
+
+      if (name)
+        g_string_append_len (flattened, name,
+                             strlen (name) + 1);
+      else
+        g_string_append_len (flattened, "", 1);
+
+      ++i;
+    }
+
+  meta_error_trap_push (x11_display);
+  XChangeProperty (x11_display->xdisplay,
+                   x11_display->xroot,
+                   x11_display->atom__NET_DESKTOP_NAMES,
+                  x11_display->atom_UTF8_STRING,
+                   8, PropModeReplace,
+                  (unsigned char *)flattened->str, flattened->len);
+  meta_error_trap_pop (x11_display);
+
+  g_string_free (flattened, TRUE);
+}
+
+#ifdef WITH_VERBOSE_MODE
+static const char *
+meta_display_corner_to_string (MetaDisplayCorner corner)
+{
+  switch (corner)
+    {
+    case META_DISPLAY_TOPLEFT:
+      return "TopLeft";
+    case META_DISPLAY_TOPRIGHT:
+      return "TopRight";
+    case META_DISPLAY_BOTTOMLEFT:
+      return "BottomLeft";
+    case META_DISPLAY_BOTTOMRIGHT:
+      return "BottomRight";
+    }
+
+  return "Unknown";
+}
+#endif /* WITH_VERBOSE_MODE */
+
+void
+meta_display_calc_workspace_layout (MetaDisplay         *display,
+                                    int                  num_workspaces,
+                                    int                  current_space,
+                                    MetaWorkspaceLayout *layout)
+{
+  int rows, cols;
+  int grid_area;
+  int *grid;
+  int i, r, c;
+  int current_row, current_col;
+
+  rows = display->rows_of_workspaces;
+  cols = display->columns_of_workspaces;
+  if (rows <= 0 && cols <= 0)
+    cols = num_workspaces;
+
+  if (rows <= 0)
+    rows = num_workspaces / cols + ((num_workspaces % cols) > 0 ? 1 : 0);
+  if (cols <= 0)
+    cols = num_workspaces / rows + ((num_workspaces % rows) > 0 ? 1 : 0);
+
+  /* paranoia */
+  if (rows < 1)
+    rows = 1;
+  if (cols < 1)
+    cols = 1;
+
+  g_assert (rows != 0 && cols != 0);
+
+  grid_area = rows * cols;
+
+  meta_verbose ("Getting layout rows = %d cols = %d current = %d "
+                "num_spaces = %d vertical = %s corner = %s\n",
+                rows, cols, current_space, num_workspaces,
+                display->vertical_workspaces ? "(true)" : "(false)",
+                meta_display_corner_to_string (display->starting_corner));
+
+  /* ok, we want to setup the distances in the workspace array to go
+   * in each direction. Remember, there are many ways that a workspace
+   * array can be setup.
+   * see http://www.freedesktop.org/standards/wm-spec/1.2/html/x109.html
+   * and look at the _NET_DESKTOP_LAYOUT section for details.
+   * For instance:
+   */
+  /* starting_corner = META_DISPLAY_TOPLEFT
+   *  vertical_workspaces = 0                 vertical_workspaces=1
+   *       1234                                    1357
+   *       5678                                    2468
+   *
+   * starting_corner = META_DISPLAY_TOPRIGHT
+   *  vertical_workspaces = 0                 vertical_workspaces=1
+   *       4321                                    7531
+   *       8765                                    8642
+   *
+   * starting_corner = META_DISPLAY_BOTTOMLEFT
+   *  vertical_workspaces = 0                 vertical_workspaces=1
+   *       5678                                    2468
+   *       1234                                    1357
+   *
+   * starting_corner = META_DISPLAY_BOTTOMRIGHT
+   *  vertical_workspaces = 0                 vertical_workspaces=1
+   *       8765                                    8642
+   *       4321                                    7531
+   *
+   */
+  /* keep in mind that we could have a ragged layout, e.g. the "8"
+   * in the above grids could be missing
+   */
+
+
+  grid = g_new (int, grid_area);
+
+  current_row = -1;
+  current_col = -1;
+  i = 0;
+
+  switch (display->starting_corner)
+    {
+    case META_DISPLAY_TOPLEFT:
+      if (display->vertical_workspaces)
+        {
+          c = 0;
+          while (c < cols)
+            {
+              r = 0;
+              while (r < rows)
+                {
+                  grid[r*cols+c] = i;
+                  ++i;
+                  ++r;
+                }
+              ++c;
+            }
+        }
+      else
+        {
+          r = 0;
+          while (r < rows)
+            {
+              c = 0;
+              while (c < cols)
+                {
+                  grid[r*cols+c] = i;
+                  ++i;
+                  ++c;
+                }
+              ++r;
+            }
+        }
+      break;
+    case META_DISPLAY_TOPRIGHT:
+      if (display->vertical_workspaces)
+        {
+          c = cols - 1;
+          while (c >= 0)
+            {
+              r = 0;
+              while (r < rows)
+                {
+                  grid[r*cols+c] = i;
+                  ++i;
+                  ++r;
+                }
+              --c;
+            }
+        }
+      else
+        {
+          r = 0;
+          while (r < rows)
+            {
+              c = cols - 1;
+              while (c >= 0)
+                {
+                  grid[r*cols+c] = i;
+                  ++i;
+                  --c;
+                }
+              ++r;
+            }
+        }
+      break;
+    case META_DISPLAY_BOTTOMLEFT:
+      if (display->vertical_workspaces)
+        {
+          c = 0;
+          while (c < cols)
+            {
+              r = rows - 1;
+              while (r >= 0)
+                {
+                  grid[r*cols+c] = i;
+                  ++i;
+                  --r;
+                }
+              ++c;
+            }
+        }
+      else
+        {
+          r = rows - 1;
+          while (r >= 0)
+            {
+              c = 0;
+              while (c < cols)
+                {
+                  grid[r*cols+c] = i;
+                  ++i;
+                  ++c;
+                }
+              --r;
+            }
+        }
+      break;
+    case META_DISPLAY_BOTTOMRIGHT:
+      if (display->vertical_workspaces)
+        {
+          c = cols - 1;
+          while (c >= 0)
+            {
+              r = rows - 1;
+              while (r >= 0)
+                {
+                  grid[r*cols+c] = i;
+                  ++i;
+                  --r;
+                }
+              --c;
+            }
+        }
+      else
+        {
+          r = rows - 1;
+          while (r >= 0)
+            {
+              c = cols - 1;
+              while (c >= 0)
+                {
+                  grid[r*cols+c] = i;
+                  ++i;
+                  --c;
+                }
+              --r;
+            }
+        }
+      break;
+    }
+
+  if (i != grid_area)
+    meta_bug ("did not fill in the whole workspace grid in %s (%d filled)\n",
+              G_STRFUNC, i);
+
+  current_row = 0;
+  current_col = 0;
+  r = 0;
+  while (r < rows)
+    {
+      c = 0;
+      while (c < cols)
+        {
+          if (grid[r*cols+c] == current_space)
+            {
+              current_row = r;
+              current_col = c;
+            }
+          else if (grid[r*cols+c] >= num_workspaces)
+            {
+              /* flag nonexistent spaces with -1 */
+              grid[r*cols+c] = -1;
+            }
+          ++c;
+        }
+      ++r;
+    }
+
+  layout->rows = rows;
+  layout->cols = cols;
+  layout->grid = grid;
+  layout->grid_area = grid_area;
+  layout->current_row = current_row;
+  layout->current_col = current_col;
+
+#ifdef WITH_VERBOSE_MODE
+  if (meta_is_verbose ())
+    {
+      r = 0;
+      while (r < layout->rows)
+        {
+          meta_verbose (" ");
+          meta_push_no_msg_prefix ();
+          c = 0;
+          while (c < layout->cols)
+            {
+              if (r == layout->current_row &&
+                  c == layout->current_col)
+                meta_verbose ("*%2d ", layout->grid[r*layout->cols+c]);
+              else
+                meta_verbose ("%3d ", layout->grid[r*layout->cols+c]);
+              ++c;
+            }
+          meta_verbose ("\n");
+          meta_pop_no_msg_prefix ();
+          ++r;
+        }
+    }
+#endif /* WITH_VERBOSE_MODE */
+}
+
+void
+meta_display_free_workspace_layout (MetaWorkspaceLayout *layout)
+{
+  g_free (layout->grid);
+}
+
+static void
+queue_windows_showing (MetaDisplay *display)
+{
+  GSList *windows, *l;
+
+  /* Must operate on all windows on display instead of just on the
+   * active_workspace's window list, because the active_workspace's
+   * window list may not contain the on_all_workspace windows.
+   */
+  windows = meta_display_list_windows (display, META_LIST_DEFAULT);
+
+  for (l = windows; l != NULL; l = l->next)
+    {
+      MetaWindow *w = l->data;
+      meta_window_queue (w, META_QUEUE_CALC_SHOWING);
+    }
+
+  g_slist_free (windows);
+}
+
+void
+meta_display_minimize_all_on_active_workspace_except (MetaDisplay *display,
+                                                      MetaWindow  *keep)
+{
+  GList *l;
+
+  for (l = display->active_workspace->windows; l != NULL; l = l->next)
+    {
+      MetaWindow *w = l->data;
+
+      if (w->has_minimize_func && w != keep)
+       meta_window_minimize (w);
+    }
+}
+
+void
+meta_display_show_desktop (MetaDisplay *display,
+                           guint32      timestamp)
+{
+  GList *l;
+
+  if (display->active_workspace->showing_desktop)
+    return;
+
+  display->active_workspace->showing_desktop = TRUE;
+
+  queue_windows_showing (display);
+
+  /* Focus the most recently used META_WINDOW_DESKTOP window, if there is one;
+   * see bug 159257.
+   */
+  for (l = display->active_workspace->mru_list; l != NULL; l = l->next)
+    {
+      MetaWindow *w = l->data;
+
+      if (w->type == META_WINDOW_DESKTOP)
+        {
+          meta_window_focus (w, timestamp);
+          break;
+        }
+    }
+
+  meta_x11_display_update_showing_desktop_hint (display->x11_display);
+}
+
+void
+meta_display_unshow_desktop (MetaDisplay *display)
+{
+  if (!display->active_workspace->showing_desktop)
+    return;
+
+  display->active_workspace->showing_desktop = FALSE;
+
+  queue_windows_showing (display);
+
+  meta_x11_display_update_showing_desktop_hint (display->x11_display);
+}
+
+/**
+ * meta_display_get_workspaces: (skip)
+ * @display: a #MetaDisplay
+ *
+ * Returns: (transfer none) (element-type Meta.Workspace): The workspaces for @display
+ */
+GList *
+meta_display_get_workspaces (MetaDisplay *display)
+{
+  return display->workspaces;
+}
+
+int
+meta_display_get_active_workspace_index (MetaDisplay *display)
+{
+  MetaWorkspace *active = display->active_workspace;
+
+  if (!active)
+    return -1;
+
+  return meta_workspace_index (active);
+}
+
+/**
+ * meta_display_get_active_workspace:
+ * @display: A #MetaDisplay
+ *
+ * Returns: (transfer none): The current workspace
+ */
+MetaWorkspace *
+meta_display_get_active_workspace (MetaDisplay *display)
+{
+  return display->active_workspace;
+}
+
+void
+meta_display_focus_default_window (MetaDisplay *display,
+                                   guint32      timestamp)
+{
+  meta_workspace_focus_default_window (display->active_workspace,
+                                       NULL,
+                                       timestamp);
+}
+
+void
+meta_display_workspace_switched (MetaDisplay        *display,
+                                 int                 from,
+                                 int                 to,
+                                 MetaMotionDirection direction)
+{
+  g_signal_emit (display, display_signals[WORKSPACE_SWITCHED], 0,
+                 from, to, direction);
+}
diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c
index 47ac4d1e0..1983904b4 100644
--- a/src/core/edge-resistance.c
+++ b/src/core/edge-resistance.c
@@ -1010,7 +1010,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
    */
   stacked_windows =
     meta_stack_list_windows (display->stack,
-                             display->screen->active_workspace);
+                             display->active_workspace);
 
   /*
    * 2nd: we need to separate that stacked list into a list of windows that
@@ -1168,8 +1168,8 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
    */
   cache_edges (display,
                edges,
-               display->screen->active_workspace->monitor_edges,
-               display->screen->active_workspace->screen_edges);
+               display->active_workspace->monitor_edges,
+               display->active_workspace->screen_edges);
   g_list_free (edges);
 
   /*
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 5e68a4b09..85fb98910 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -2752,8 +2752,8 @@ handle_switch_to_last_workspace (MetaDisplay     *display,
                                  MetaKeyBinding *binding,
                                  gpointer        dummy)
 {
-    gint target = meta_screen_get_n_workspaces(screen) - 1;
-    MetaWorkspace *workspace = meta_screen_get_workspace_by_index (screen, target);
+    gint target = meta_display_get_n_workspaces(display) - 1;
+    MetaWorkspace *workspace = meta_display_get_workspace_by_index (display, target);
     meta_workspace_activate (workspace, event->time);
 }
 
@@ -2774,12 +2774,12 @@ handle_switch_to_workspace (MetaDisplay     *display,
        * current workspace.
        */
 
-      workspace = meta_workspace_get_neighbor (screen->active_workspace,
+      workspace = meta_workspace_get_neighbor (display->active_workspace,
                                                which);
     }
   else
     {
-      workspace = meta_screen_get_workspace_by_index (screen, which);
+      workspace = meta_display_get_workspace_by_index (display, which);
     }
 
   if (workspace)
@@ -3016,15 +3016,15 @@ handle_show_desktop (MetaDisplay     *display,
                      MetaKeyBinding  *binding,
                      gpointer         dummy)
 {
-  if (screen->active_workspace->showing_desktop)
+  if (display->active_workspace->showing_desktop)
     {
-      meta_screen_unshow_desktop (screen);
-      meta_workspace_focus_default_window (screen->active_workspace,
+      meta_display_unshow_desktop (display);
+      meta_workspace_focus_default_window (display->active_workspace,
                                            NULL,
                                            event->time);
     }
   else
-    meta_screen_show_desktop (screen, event->time);
+    meta_display_show_desktop (display, event->time);
 }
 
 static void
@@ -3122,7 +3122,7 @@ do_choose_window (MetaDisplay     *display,
 
   window = meta_display_get_tab_next (display,
                                       type,
-                                      screen->active_workspace,
+                                      display->active_workspace,
                                       NULL,
                                       backward);
 
@@ -3357,8 +3357,8 @@ handle_move_to_workspace_last (MetaDisplay     *display,
   if (window->always_sticky)
     return;
 
-  which = meta_screen_get_n_workspaces (screen) - 1;
-  workspace = meta_screen_get_workspace_by_index (screen, which);
+  which = meta_display_get_n_workspaces (display) - 1;
+  workspace = meta_display_get_workspace_by_index (display, which);
   meta_window_change_workspace (window, workspace);
 }
 
@@ -3389,12 +3389,12 @@ handle_move_to_workspace  (MetaDisplay     *display,
   workspace = NULL;
   if (flip)
     {
-      workspace = meta_workspace_get_neighbor (screen->active_workspace,
+      workspace = meta_workspace_get_neighbor (display->active_workspace,
                                                which);
     }
   else
     {
-      workspace = meta_screen_get_workspace_by_index (screen, which);
+      workspace = meta_display_get_workspace_by_index (display, which);
     }
 
   if (workspace)
@@ -3406,7 +3406,7 @@ handle_move_to_workspace  (MetaDisplay     *display,
           meta_topic (META_DEBUG_FOCUS,
                       "Resetting mouse_mode to FALSE due to "
                       "handle_move_to_workspace() call with flip set.\n");
-          meta_display_clear_mouse_mode (workspace->screen->display);
+          meta_display_clear_mouse_mode (workspace->display);
           meta_workspace_activate_with_focus (workspace,
                                               window,
                                               event->time);
diff --git a/src/core/screen-private.h b/src/core/screen-private.h
index bc9406cd4..8e746e5a7 100644
--- a/src/core/screen-private.h
+++ b/src/core/screen-private.h
@@ -46,16 +46,6 @@ struct _MetaScreen
 
   MetaDisplay *display;
 
-  MetaWorkspace *active_workspace;
-
-  GList *workspaces;
-
-  int rows_of_workspaces;
-  int columns_of_workspaces;
-  MetaScreenCorner starting_corner;
-  guint vertical_workspaces : 1;
-  guint workspace_layout_overridden : 1;
-
   int closing;
 };
 
@@ -68,48 +58,7 @@ MetaScreen*   meta_screen_new                 (MetaDisplay                *displ
                                                guint32                     timestamp);
 void          meta_screen_free                (MetaScreen                 *screen,
                                                guint32                     timestamp);
-void          meta_screen_init_workspaces     (MetaScreen                 *screen);
-void          meta_screen_manage_all_windows  (MetaScreen                 *screen);
-
-void          meta_screen_update_workspace_layout (MetaScreen             *screen);
-void          meta_screen_update_workspace_names  (MetaScreen             *screen);
-
-typedef struct MetaWorkspaceLayout MetaWorkspaceLayout;
-
-struct MetaWorkspaceLayout
-{
-  int rows;
-  int cols;
-  int *grid;
-  int grid_area;
-  int current_row;
-  int current_col;
-};
-
-void meta_screen_calc_workspace_layout (MetaScreen          *screen,
-                                        int                  num_workspaces,
-                                        int                  current_space,
-                                        MetaWorkspaceLayout *layout);
-void meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout);
-
-void     meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen,
-                                                              MetaWindow *keep);
-
-/* Show/hide the desktop (temporarily hide all windows) */
-void     meta_screen_show_desktop        (MetaScreen *screen,
-                                          guint32     timestamp);
-void     meta_screen_unshow_desktop      (MetaScreen *screen);
 
-/* Update whether the destkop is being shown for the current active_workspace */
-void     meta_screen_update_showing_desktop_hint          (MetaScreen *screen);
-
-void     meta_screen_workspace_switched (MetaScreen         *screen,
-                                         int                 from,
-                                         int                 to,
-                                         MetaMotionDirection direction);
-
-void meta_screen_set_active_workspace_hint (MetaScreen *screen);
-
-void meta_screen_on_monitors_changed (MetaScreen *screen);
+void          meta_screen_manage_all_windows  (MetaScreen                 *screen);
 
 #endif
diff --git a/src/core/screen.c b/src/core/screen.c
index 003d082c5..f9da8102d 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -63,28 +63,6 @@
 #include "backends/x11/meta-backend-x11.h"
 #include "backends/meta-cursor-sprite-xcursor.h"
 
-static void update_num_workspaces  (MetaScreen *screen,
-                                    guint32     timestamp);
-static void set_workspace_names    (MetaScreen *screen);
-static void prefs_changed_callback (MetaPreference pref,
-                                    gpointer       data);
-
-enum
-{
-  PROP_N_WORKSPACES = 1,
-};
-
-enum
-{
-  WORKSPACE_ADDED,
-  WORKSPACE_REMOVED,
-  WORKSPACE_SWITCHED,
-
-  LAST_SIGNAL
-};
-
-static guint screen_signals[LAST_SIGNAL] = { 0 };
-
 G_DEFINE_TYPE (MetaScreen, meta_screen, G_TYPE_OBJECT);
 
 static void
@@ -111,13 +89,12 @@ meta_screen_get_property (GObject      *object,
                           GValue       *value,
                           GParamSpec   *pspec)
 {
+#if 0
   MetaScreen *screen = META_SCREEN (object);
+#endif
 
   switch (prop_id)
     {
-    case PROP_N_WORKSPACES:
-      g_value_set_int (value, meta_screen_get_n_workspaces (screen));
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -134,53 +111,10 @@ static void
 meta_screen_class_init (MetaScreenClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GParamSpec   *pspec;
 
   object_class->get_property = meta_screen_get_property;
   object_class->set_property = meta_screen_set_property;
   object_class->finalize = meta_screen_finalize;
-
-  pspec = g_param_spec_int ("n-workspaces",
-                            "N Workspaces",
-                            "Number of workspaces",
-                            1, G_MAXINT, 1,
-                            G_PARAM_READABLE);
-
-  screen_signals[WORKSPACE_ADDED] =
-    g_signal_new ("workspace-added",
-                  G_TYPE_FROM_CLASS (klass),
-                  G_SIGNAL_RUN_LAST,
-                  0,
-                  NULL, NULL, NULL,
-                  G_TYPE_NONE,
-                  1,
-                  G_TYPE_INT);
-
-  screen_signals[WORKSPACE_REMOVED] =
-    g_signal_new ("workspace-removed",
-                  G_TYPE_FROM_CLASS (klass),
-                  G_SIGNAL_RUN_LAST,
-                  0,
-                  NULL, NULL, NULL,
-                  G_TYPE_NONE,
-                  1,
-                  G_TYPE_INT);
-
-  screen_signals[WORKSPACE_SWITCHED] =
-    g_signal_new ("workspace-switched",
-                  G_TYPE_FROM_CLASS (klass),
-                  G_SIGNAL_RUN_LAST,
-                  0,
-                  NULL, NULL, NULL,
-                  G_TYPE_NONE,
-                  3,
-                  G_TYPE_INT,
-                  G_TYPE_INT,
-                  META_TYPE_MOTION_DIRECTION);
-
-  g_object_class_install_property (object_class,
-                                   PROP_N_WORKSPACES,
-                                   pspec);
 }
 
 static void
@@ -188,18 +122,6 @@ meta_screen_init (MetaScreen *screen)
 {
 }
 
-static void
-reload_logical_monitors (MetaScreen *screen)
-{
-  GList *l;
-
-  for (l = screen->workspaces; l != NULL; l = l->next)
-    {
-      MetaWorkspace *space = l->data;
-      meta_workspace_invalidate_work_area (space);
-    }
-}
-
 MetaScreen*
 meta_screen_new (MetaDisplay *display,
                  guint32      timestamp)
@@ -218,24 +140,6 @@ meta_screen_new (MetaDisplay *display,
 
   screen->display = display;
 
-  screen->active_workspace = NULL;
-  screen->workspaces = NULL;
-  screen->rows_of_workspaces = 1;
-  screen->columns_of_workspaces = -1;
-  screen->vertical_workspaces = FALSE;
-  screen->starting_corner = META_SCREEN_TOPLEFT;
-
-  reload_logical_monitors (screen);
-
-  meta_screen_update_workspace_layout (screen);
-
-  /* Screens must have at least one workspace at all times,
-   * so create that required workspace.
-   */
-  meta_workspace_new (screen);
-
-  meta_prefs_add_listener (prefs_changed_callback, screen);
-
   meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
                 number, display->x11_display->screen_name,
                 xroot);
@@ -243,957 +147,15 @@ meta_screen_new (MetaDisplay *display,
   return screen;
 }
 
-void
-meta_screen_init_workspaces (MetaScreen *screen)
-{
-  MetaDisplay *display = screen->display;
-  MetaWorkspace *current_workspace;
-  uint32_t current_workspace_index = 0;
-  guint32 timestamp;
-
-  g_return_if_fail (META_IS_SCREEN (screen));
-
-  timestamp = screen->display->x11_display->wm_sn_timestamp;
-
-  /* Get current workspace */
-  if (meta_prop_get_cardinal (display->x11_display,
-                              display->x11_display->xroot,
-                              display->x11_display->atom__NET_CURRENT_DESKTOP,
-                              &current_workspace_index))
-    meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
-                  (int) current_workspace_index);
-  else
-    meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
-
-  update_num_workspaces (screen, timestamp);
-
-  set_workspace_names (screen);
-
-  /* Switch to the _NET_CURRENT_DESKTOP workspace */
-  current_workspace = meta_screen_get_workspace_by_index (screen,
-                                                          current_workspace_index);
-
-  if (current_workspace != NULL)
-    meta_workspace_activate (current_workspace, timestamp);
-  else
-    meta_workspace_activate (screen->workspaces->data, timestamp);
-}
-
 void
 meta_screen_free (MetaScreen *screen,
                   guint32     timestamp)
 {
   screen->closing += 1;
 
-  meta_prefs_remove_listener (prefs_changed_callback, screen);
-
   g_object_unref (screen);
 }
 
-static void
-prefs_changed_callback (MetaPreference pref,
-                        gpointer       data)
-{
-  MetaScreen *screen = data;
-
-  if ((pref == META_PREF_NUM_WORKSPACES ||
-       pref == META_PREF_DYNAMIC_WORKSPACES) &&
-      !meta_prefs_get_dynamic_workspaces ())
-    {
-      /* GSettings doesn't provide timestamps, but luckily update_num_workspaces
-       * often doesn't need it...
-       */
-      guint32 timestamp =
-        meta_display_get_current_time_roundtrip (screen->display);
-      update_num_workspaces (screen, timestamp);
-    }
-  else if (pref == META_PREF_WORKSPACE_NAMES)
-    {
-      set_workspace_names (screen);
-    }
-}
-
-int
-meta_screen_get_n_workspaces (MetaScreen *screen)
-{
-  return g_list_length (screen->workspaces);
-}
-
-/**
- * meta_screen_get_workspace_by_index:
- * @screen: a #MetaScreen
- * @index: index of one of the screen's workspaces
- *
- * Gets the workspace object for one of a screen's workspaces given the workspace
- * index. It's valid to call this function with an out-of-range index and it
- * will robustly return %NULL.
- *
- * Return value: (transfer none): the workspace object with specified index, or %NULL
- *   if the index is out of range.
- */
-MetaWorkspace*
-meta_screen_get_workspace_by_index (MetaScreen  *screen,
-                                    int          idx)
-{
-  return g_list_nth_data (screen->workspaces, idx);
-}
-
-static void
-set_number_of_spaces_hint (MetaScreen *screen,
-                           int         n_spaces)
-{
-  MetaX11Display *x11_display = screen->display->x11_display;
-  unsigned long data[1];
-
-  if (screen->closing > 0)
-    return;
-
-  data[0] = n_spaces;
-
-  meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %lu\n", data[0]);
-
-  meta_error_trap_push (x11_display);
-  XChangeProperty (x11_display->xdisplay,
-                   x11_display->xroot,
-                   x11_display->atom__NET_NUMBER_OF_DESKTOPS,
-                   XA_CARDINAL,
-                   32, PropModeReplace, (guchar*) data, 1);
-  meta_error_trap_pop (x11_display);
-}
-
-void
-meta_screen_remove_workspace (MetaScreen *screen, MetaWorkspace *workspace,
-                              guint32 timestamp)
-{
-  GList         *l;
-  GList         *next;
-  MetaWorkspace *neighbour = NULL;
-  int            index;
-  gboolean       active_index_changed;
-  int            new_num;
-
-  l = g_list_find (screen->workspaces, workspace);
-  if (!l)
-    return;
-
-  next = l->next;
-
-  if (l->prev)
-    neighbour = l->prev->data;
-  else if (l->next)
-    neighbour = l->next->data;
-  else
-    {
-      /* Cannot remove the only workspace! */
-      return;
-    }
-
-  meta_workspace_relocate_windows (workspace, neighbour);
-
-  if (workspace == screen->active_workspace)
-    meta_workspace_activate (neighbour, timestamp);
-
-  /* To emit the signal after removing the workspace */
-  index = meta_workspace_index (workspace);
-  active_index_changed = index < meta_screen_get_active_workspace_index (screen);
-
-  /* This also removes the workspace from the screens list */
-  meta_workspace_remove (workspace);
-
-  new_num = g_list_length (screen->workspaces);
-
-  set_number_of_spaces_hint (screen, new_num);
-
-  if (!meta_prefs_get_dynamic_workspaces ())
-    meta_prefs_set_num_workspaces (new_num);
-
-  /* If deleting a workspace before the current workspace, the active
-   * workspace index changes, so we need to update that hint */
-  if (active_index_changed)
-      meta_screen_set_active_workspace_hint (screen);
-
-  for (l = next; l != NULL; l = l->next)
-    {
-      MetaWorkspace *w = l->data;
-      meta_workspace_index_changed (w);
-    }
-
-  meta_display_queue_workarea_recalc (screen->display);
-
-  g_signal_emit (screen, screen_signals[WORKSPACE_REMOVED], 0, index);
-  g_object_notify (G_OBJECT (screen), "n-workspaces");
-}
-
-/**
- * meta_screen_append_new_workspace:
- * @screen: a #MetaScreen
- * @activate: %TRUE if the workspace should be switched to after creation
- * @timestamp: if switching to a new workspace, timestamp to be used when
- *   focusing a window on the new workspace. (Doesn't hurt to pass a valid
- *   timestamp when available even if not switching workspaces.)
- *
- * Append a new workspace to the screen and (optionally) switch to that
- * screen.
- *
- * Return value: (transfer none): the newly appended workspace.
- */
-MetaWorkspace *
-meta_screen_append_new_workspace (MetaScreen *screen, gboolean activate,
-                                  guint32 timestamp)
-{
-  MetaWorkspace *w;
-  int new_num;
-
-  /* This also adds the workspace to the screen list */
-  w = meta_workspace_new (screen);
-
-  if (!w)
-    return NULL;
-
-  if (activate)
-    meta_workspace_activate (w, timestamp);
-
-  new_num = g_list_length (screen->workspaces);
-
-  set_number_of_spaces_hint (screen, new_num);
-
-  if (!meta_prefs_get_dynamic_workspaces ())
-    meta_prefs_set_num_workspaces (new_num);
-
-  meta_display_queue_workarea_recalc (screen->display);
-
-  g_signal_emit (screen, screen_signals[WORKSPACE_ADDED],
-                 0, meta_workspace_index (w));
-  g_object_notify (G_OBJECT (screen), "n-workspaces");
-
-  return w;
-}
-
-
-static void
-update_num_workspaces (MetaScreen *screen,
-                       guint32     timestamp)
-{
-  MetaDisplay *display = screen->display;
-  int new_num, old_num;
-  GList *l;
-  int i;
-  GList *extras;
-  MetaWorkspace *last_remaining;
-  gboolean need_change_space;
-
-  if (meta_prefs_get_dynamic_workspaces ())
-    {
-      int n_items;
-      uint32_t *list;
-
-      n_items = 0;
-      list = NULL;
-
-      if (meta_prop_get_cardinal_list (display->x11_display,
-                                       display->x11_display->xroot,
-                                       display->x11_display->atom__NET_NUMBER_OF_DESKTOPS,
-                                       &list, &n_items))
-        {
-          new_num = list[0];
-          meta_XFree (list);
-        }
-      else
-        {
-          new_num = 1;
-        }
-    }
-  else
-    {
-      new_num = meta_prefs_get_num_workspaces ();
-    }
-
-  g_assert (new_num > 0);
-
-  if (g_list_length (screen->workspaces) == (guint) new_num)
-    {
-      if (screen->display->display_opening)
-        set_number_of_spaces_hint (screen, new_num);
-      return;
-    }
-
-  last_remaining = NULL;
-  extras = NULL;
-  i = 0;
-  for (l = screen->workspaces; l != NULL; l = l->next)
-    {
-      MetaWorkspace *w = l->data;
-
-      if (i >= new_num)
-        extras = g_list_prepend (extras, w);
-      else
-        last_remaining = w;
-
-      ++i;
-    }
-  old_num = i;
-
-  g_assert (last_remaining);
-
-  /* Get rid of the extra workspaces by moving all their windows
-   * to last_remaining, then activating last_remaining if
-   * one of the removed workspaces was active. This will be a bit
-   * wacky if the config tool for changing number of workspaces
-   * is on a removed workspace ;-)
-   */
-  need_change_space = FALSE;
-  for (l = extras; l != NULL; l = l->next)
-    {
-      MetaWorkspace *w = l->data;
-
-      meta_workspace_relocate_windows (w, last_remaining);
-
-      if (w == screen->active_workspace)
-        need_change_space = TRUE;
-    }
-
-  if (need_change_space)
-    meta_workspace_activate (last_remaining, timestamp);
-
-  /* Should now be safe to free the workspaces */
-  for (l = extras; l != NULL; l = l->next)
-    {
-      MetaWorkspace *w = l->data;
-
-      meta_workspace_remove (w);
-    }
-
-  g_list_free (extras);
-
-  for (i = old_num; i < new_num; i++)
-    meta_workspace_new (screen);
-
-  set_number_of_spaces_hint (screen, new_num);
-
-  meta_display_queue_workarea_recalc (display);
-
-  for (i = old_num; i < new_num; i++)
-    g_signal_emit (screen, screen_signals[WORKSPACE_ADDED], 0, i);
-
-  g_object_notify (G_OBJECT (screen), "n-workspaces");
-}
-
-#define _NET_WM_ORIENTATION_HORZ 0
-#define _NET_WM_ORIENTATION_VERT 1
-
-#define _NET_WM_TOPLEFT     0
-#define _NET_WM_TOPRIGHT    1
-#define _NET_WM_BOTTOMRIGHT 2
-#define _NET_WM_BOTTOMLEFT  3
-
-void
-meta_screen_update_workspace_layout (MetaScreen *screen)
-{
-  uint32_t *list;
-  int n_items;
-  MetaDisplay *display = screen->display;
-
-  if (screen->workspace_layout_overridden)
-    return;
-
-  list = NULL;
-  n_items = 0;
-
-  if (meta_prop_get_cardinal_list (display->x11_display,
-                                   display->x11_display->xroot,
-                                   display->x11_display->atom__NET_DESKTOP_LAYOUT,
-                                   &list, &n_items))
-    {
-      if (n_items == 3 || n_items == 4)
-        {
-          int cols, rows;
-
-          switch (list[0])
-            {
-            case _NET_WM_ORIENTATION_HORZ:
-              screen->vertical_workspaces = FALSE;
-              break;
-            case _NET_WM_ORIENTATION_VERT:
-              screen->vertical_workspaces = TRUE;
-              break;
-            default:
-              meta_warning ("Someone set a weird orientation in _NET_DESKTOP_LAYOUT\n");
-              break;
-            }
-
-          cols = list[1];
-          rows = list[2];
-
-          if (rows <= 0 && cols <= 0)
-            {
-              meta_warning ("Columns = %d rows = %d in _NET_DESKTOP_LAYOUT makes no sense\n", rows, cols);
-            }
-          else
-            {
-              if (rows > 0)
-                screen->rows_of_workspaces = rows;
-              else
-                screen->rows_of_workspaces = -1;
-
-              if (cols > 0)
-                screen->columns_of_workspaces = cols;
-              else
-                screen->columns_of_workspaces = -1;
-            }
-
-          if (n_items == 4)
-            {
-              switch (list[3])
-                {
-                  case _NET_WM_TOPLEFT:
-                    screen->starting_corner = META_SCREEN_TOPLEFT;
-                    break;
-                  case _NET_WM_TOPRIGHT:
-                    screen->starting_corner = META_SCREEN_TOPRIGHT;
-                    break;
-                  case _NET_WM_BOTTOMRIGHT:
-                    screen->starting_corner = META_SCREEN_BOTTOMRIGHT;
-                    break;
-                  case _NET_WM_BOTTOMLEFT:
-                    screen->starting_corner = META_SCREEN_BOTTOMLEFT;
-                    break;
-                  default:
-                    meta_warning ("Someone set a weird starting corner in _NET_DESKTOP_LAYOUT\n");
-                    break;
-                }
-            }
-          else
-            screen->starting_corner = META_SCREEN_TOPLEFT;
-        }
-      else
-        {
-          meta_warning ("Someone set _NET_DESKTOP_LAYOUT to %d integers instead of 4 "
-                        "(3 is accepted for backwards compat)\n", n_items);
-        }
-
-      meta_XFree (list);
-    }
-
-  meta_verbose ("Workspace layout rows = %d cols = %d orientation = %d starting corner = %u\n",
-                screen->rows_of_workspaces,
-                screen->columns_of_workspaces,
-                screen->vertical_workspaces,
-                screen->starting_corner);
-}
-
-/**
- * meta_screen_override_workspace_layout:
- * @screen: a #MetaScreen
- * @starting_corner: the corner at which the first workspace is found
- * @vertical_layout: if %TRUE the workspaces are laid out in columns rather than rows
- * @n_rows: number of rows of workspaces, or -1 to determine the number of rows from
- *   @n_columns and the total number of workspaces
- * @n_columns: number of columns of workspaces, or -1 to determine the number of columns from
- *   @n_rows and the total number of workspaces
- *
- * Explicitly set the layout of workspaces. Once this has been called, the contents of the
- * _NET_DESKTOP_LAYOUT property on the root window are completely ignored.
- */
-void
-meta_screen_override_workspace_layout (MetaScreen      *screen,
-                                       MetaScreenCorner starting_corner,
-                                       gboolean         vertical_layout,
-                                       int              n_rows,
-                                       int              n_columns)
-{
-  g_return_if_fail (META_IS_SCREEN (screen));
-  g_return_if_fail (n_rows > 0 || n_columns > 0);
-  g_return_if_fail (n_rows != 0 && n_columns != 0);
-
-  screen->workspace_layout_overridden = TRUE;
-  screen->vertical_workspaces = vertical_layout != FALSE;
-  screen->starting_corner = starting_corner;
-  screen->rows_of_workspaces = n_rows;
-  screen->columns_of_workspaces = n_columns;
-
-  /* In theory we should remove _NET_DESKTOP_LAYOUT from _NET_SUPPORTED at this
-   * point, but it's unlikely that anybody checks that, and it's unlikely that
-   * anybody who checks that handles changes, so we'd probably just create
-   * a race condition. And it's hard to implement with the code in set_supported_hint()
-   */
-}
-
-static void
-set_workspace_names (MetaScreen *screen)
-{
-  /* This updates names on root window when the pref changes,
-   * note we only get prefs change notify if things have
-   * really changed.
-   */
-  MetaX11Display *x11_display = screen->display->x11_display;
-  GString *flattened;
-  int i;
-  int n_spaces;
-
-  /* flatten to nul-separated list */
-  n_spaces = meta_screen_get_n_workspaces (screen);
-  flattened = g_string_new ("");
-  i = 0;
-  while (i < n_spaces)
-    {
-      const char *name;
-
-      name = meta_prefs_get_workspace_name (i);
-
-      if (name)
-        g_string_append_len (flattened, name,
-                             strlen (name) + 1);
-      else
-        g_string_append_len (flattened, "", 1);
-
-      ++i;
-    }
-
-  meta_error_trap_push (x11_display);
-  XChangeProperty (x11_display->xdisplay,
-                   x11_display->xroot,
-                   x11_display->atom__NET_DESKTOP_NAMES,
-                   x11_display->atom_UTF8_STRING,
-                   8, PropModeReplace,
-                  (unsigned char *)flattened->str, flattened->len);
-  meta_error_trap_pop (x11_display);
-
-  g_string_free (flattened, TRUE);
-}
-
-void
-meta_screen_update_workspace_names (MetaScreen *screen)
-{
-  MetaX11Display *x11_display = screen->display->x11_display;
-  char **names;
-  int n_names;
-  int i;
-
-  /* this updates names in prefs when the root window property changes,
-   * iff the new property contents don't match what's already in prefs
-   */
-
-  names = NULL;
-  n_names = 0;
-  if (!meta_prop_get_utf8_list (x11_display,
-                                x11_display->xroot,
-                                x11_display->atom__NET_DESKTOP_NAMES,
-                                &names, &n_names))
-    {
-      meta_verbose ("Failed to get workspace names from root window\n");
-      return;
-    }
-
-  i = 0;
-  while (i < n_names)
-    {
-      meta_topic (META_DEBUG_PREFS,
-                  "Setting workspace %d name to \"%s\" due to _NET_DESKTOP_NAMES change\n",
-                  i, names[i] ? names[i] : "null");
-      meta_prefs_change_workspace_name (i, names[i]);
-
-      ++i;
-    }
-
-  g_strfreev (names);
-}
-
-#ifdef WITH_VERBOSE_MODE
-static const char *
-meta_screen_corner_to_string (MetaScreenCorner corner)
-{
-  switch (corner)
-    {
-    case META_SCREEN_TOPLEFT:
-      return "TopLeft";
-    case META_SCREEN_TOPRIGHT:
-      return "TopRight";
-    case META_SCREEN_BOTTOMLEFT:
-      return "BottomLeft";
-    case META_SCREEN_BOTTOMRIGHT:
-      return "BottomRight";
-    }
-
-  return "Unknown";
-}
-#endif /* WITH_VERBOSE_MODE */
-
-void
-meta_screen_calc_workspace_layout (MetaScreen          *screen,
-                                   int                  num_workspaces,
-                                   int                  current_space,
-                                   MetaWorkspaceLayout *layout)
-{
-  int rows, cols;
-  int grid_area;
-  int *grid;
-  int i, r, c;
-  int current_row, current_col;
-
-  rows = screen->rows_of_workspaces;
-  cols = screen->columns_of_workspaces;
-  if (rows <= 0 && cols <= 0)
-    cols = num_workspaces;
-
-  if (rows <= 0)
-    rows = num_workspaces / cols + ((num_workspaces % cols) > 0 ? 1 : 0);
-  if (cols <= 0)
-    cols = num_workspaces / rows + ((num_workspaces % rows) > 0 ? 1 : 0);
-
-  /* paranoia */
-  if (rows < 1)
-    rows = 1;
-  if (cols < 1)
-    cols = 1;
-
-  g_assert (rows != 0 && cols != 0);
-
-  grid_area = rows * cols;
-
-  meta_verbose ("Getting layout rows = %d cols = %d current = %d "
-                "num_spaces = %d vertical = %s corner = %s\n",
-                rows, cols, current_space, num_workspaces,
-                screen->vertical_workspaces ? "(true)" : "(false)",
-                meta_screen_corner_to_string (screen->starting_corner));
-
-  /* ok, we want to setup the distances in the workspace array to go
-   * in each direction. Remember, there are many ways that a workspace
-   * array can be setup.
-   * see http://www.freedesktop.org/standards/wm-spec/1.2/html/x109.html
-   * and look at the _NET_DESKTOP_LAYOUT section for details.
-   * For instance:
-   */
-  /* starting_corner = META_SCREEN_TOPLEFT
-   *  vertical_workspaces = 0                 vertical_workspaces=1
-   *       1234                                    1357
-   *       5678                                    2468
-   *
-   * starting_corner = META_SCREEN_TOPRIGHT
-   *  vertical_workspaces = 0                 vertical_workspaces=1
-   *       4321                                    7531
-   *       8765                                    8642
-   *
-   * starting_corner = META_SCREEN_BOTTOMLEFT
-   *  vertical_workspaces = 0                 vertical_workspaces=1
-   *       5678                                    2468
-   *       1234                                    1357
-   *
-   * starting_corner = META_SCREEN_BOTTOMRIGHT
-   *  vertical_workspaces = 0                 vertical_workspaces=1
-   *       8765                                    8642
-   *       4321                                    7531
-   *
-   */
-  /* keep in mind that we could have a ragged layout, e.g. the "8"
-   * in the above grids could be missing
-   */
-
-
-  grid = g_new (int, grid_area);
-
-  current_row = -1;
-  current_col = -1;
-  i = 0;
-
-  switch (screen->starting_corner)
-    {
-    case META_SCREEN_TOPLEFT:
-      if (screen->vertical_workspaces)
-        {
-          c = 0;
-          while (c < cols)
-            {
-              r = 0;
-              while (r < rows)
-                {
-                  grid[r*cols+c] = i;
-                  ++i;
-                  ++r;
-                }
-              ++c;
-            }
-        }
-      else
-        {
-          r = 0;
-          while (r < rows)
-            {
-              c = 0;
-              while (c < cols)
-                {
-                  grid[r*cols+c] = i;
-                  ++i;
-                  ++c;
-                }
-              ++r;
-            }
-        }
-      break;
-    case META_SCREEN_TOPRIGHT:
-      if (screen->vertical_workspaces)
-        {
-          c = cols - 1;
-          while (c >= 0)
-            {
-              r = 0;
-              while (r < rows)
-                {
-                  grid[r*cols+c] = i;
-                  ++i;
-                  ++r;
-                }
-              --c;
-            }
-        }
-      else
-        {
-          r = 0;
-          while (r < rows)
-            {
-              c = cols - 1;
-              while (c >= 0)
-                {
-                  grid[r*cols+c] = i;
-                  ++i;
-                  --c;
-                }
-              ++r;
-            }
-        }
-      break;
-    case META_SCREEN_BOTTOMLEFT:
-      if (screen->vertical_workspaces)
-        {
-          c = 0;
-          while (c < cols)
-            {
-              r = rows - 1;
-              while (r >= 0)
-                {
-                  grid[r*cols+c] = i;
-                  ++i;
-                  --r;
-                }
-              ++c;
-            }
-        }
-      else
-        {
-          r = rows - 1;
-          while (r >= 0)
-            {
-              c = 0;
-              while (c < cols)
-                {
-                  grid[r*cols+c] = i;
-                  ++i;
-                  ++c;
-                }
-              --r;
-            }
-        }
-      break;
-    case META_SCREEN_BOTTOMRIGHT:
-      if (screen->vertical_workspaces)
-        {
-          c = cols - 1;
-          while (c >= 0)
-            {
-              r = rows - 1;
-              while (r >= 0)
-                {
-                  grid[r*cols+c] = i;
-                  ++i;
-                  --r;
-                }
-              --c;
-            }
-        }
-      else
-        {
-          r = rows - 1;
-          while (r >= 0)
-            {
-              c = cols - 1;
-              while (c >= 0)
-                {
-                  grid[r*cols+c] = i;
-                  ++i;
-                  --c;
-                }
-              --r;
-            }
-        }
-      break;
-    }
-
-  if (i != grid_area)
-    meta_bug ("did not fill in the whole workspace grid in %s (%d filled)\n",
-              G_STRFUNC, i);
-
-  current_row = 0;
-  current_col = 0;
-  r = 0;
-  while (r < rows)
-    {
-      c = 0;
-      while (c < cols)
-        {
-          if (grid[r*cols+c] == current_space)
-            {
-              current_row = r;
-              current_col = c;
-            }
-          else if (grid[r*cols+c] >= num_workspaces)
-            {
-              /* flag nonexistent spaces with -1 */
-              grid[r*cols+c] = -1;
-            }
-          ++c;
-        }
-      ++r;
-    }
-
-  layout->rows = rows;
-  layout->cols = cols;
-  layout->grid = grid;
-  layout->grid_area = grid_area;
-  layout->current_row = current_row;
-  layout->current_col = current_col;
-
-#ifdef WITH_VERBOSE_MODE
-  if (meta_is_verbose ())
-    {
-      r = 0;
-      while (r < layout->rows)
-        {
-          meta_verbose (" ");
-          meta_push_no_msg_prefix ();
-          c = 0;
-          while (c < layout->cols)
-            {
-              if (r == layout->current_row &&
-                  c == layout->current_col)
-                meta_verbose ("*%2d ", layout->grid[r*layout->cols+c]);
-              else
-                meta_verbose ("%3d ", layout->grid[r*layout->cols+c]);
-              ++c;
-            }
-          meta_verbose ("\n");
-          meta_pop_no_msg_prefix ();
-          ++r;
-        }
-    }
-#endif /* WITH_VERBOSE_MODE */
-}
-
-void
-meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout)
-{
-  g_free (layout->grid);
-}
-
-void
-meta_screen_on_monitors_changed (MetaScreen *screen)
-{
-  reload_logical_monitors (screen);
-}
-
-void
-meta_screen_update_showing_desktop_hint (MetaScreen *screen)
-{
-  MetaX11Display *x11_display = screen->display->x11_display;
-  unsigned long data[1];
-
-  data[0] = screen->active_workspace->showing_desktop ? 1 : 0;
-
-  meta_error_trap_push (x11_display);
-  XChangeProperty (x11_display->xdisplay,
-                   x11_display->xroot,
-                   x11_display->atom__NET_SHOWING_DESKTOP,
-                   XA_CARDINAL,
-                   32, PropModeReplace, (guchar*) data, 1);
-  meta_error_trap_pop (x11_display);
-}
-
-static void
-queue_windows_showing (MetaScreen *screen)
-{
-  GSList *windows, *l;
-
-  /* Must operate on all windows on display instead of just on the
-   * active_workspace's window list, because the active_workspace's
-   * window list may not contain the on_all_workspace windows.
-   */
-  windows = meta_display_list_windows (screen->display, META_LIST_DEFAULT);
-
-  for (l = windows; l != NULL; l = l->next)
-    {
-      MetaWindow *w = l->data;
-      meta_window_queue (w, META_QUEUE_CALC_SHOWING);
-    }
-
-  g_slist_free (windows);
-}
-
-void
-meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen,
-                                                     MetaWindow *keep)
-{
-  GList *l;
-
-  for (l = screen->active_workspace->windows; l != NULL; l = l->next)
-    {
-      MetaWindow *w = l->data;
-
-      if (w->has_minimize_func && w != keep)
-       meta_window_minimize (w);
-    }
-}
-
-void
-meta_screen_show_desktop (MetaScreen *screen,
-                          guint32     timestamp)
-{
-  GList *l;
-
-  if (screen->active_workspace->showing_desktop)
-    return;
-
-  screen->active_workspace->showing_desktop = TRUE;
-
-  queue_windows_showing (screen);
-
-  /* Focus the most recently used META_WINDOW_DESKTOP window, if there is one;
-   * see bug 159257.
-   */
-  for (l = screen->active_workspace->mru_list; l != NULL; l = l->next)
-    {
-      MetaWindow *w = l->data;
-
-      if (w->type == META_WINDOW_DESKTOP)
-        {
-          meta_window_focus (w, timestamp);
-          break;
-        }
-    }
-
-  meta_screen_update_showing_desktop_hint (screen);
-}
-
-void
-meta_screen_unshow_desktop (MetaScreen *screen)
-{
-  if (!screen->active_workspace->showing_desktop)
-    return;
-
-  screen->active_workspace->showing_desktop = FALSE;
-
-  queue_windows_showing (screen);
-
-  meta_screen_update_showing_desktop_hint (screen);
-}
-
 /**
  * meta_screen_get_display:
  * @screen: A #MetaScreen
@@ -1207,86 +169,3 @@ meta_screen_get_display (MetaScreen *screen)
 {
   return screen->display;
 }
-
-/**
- * meta_screen_get_workspaces: (skip)
- * @screen: a #MetaScreen
- *
- * Returns: (transfer none) (element-type Meta.Workspace): The workspaces for @screen
- */
-GList *
-meta_screen_get_workspaces (MetaScreen *screen)
-{
-  return screen->workspaces;
-}
-
-int
-meta_screen_get_active_workspace_index (MetaScreen *screen)
-{
-  MetaWorkspace *active = screen->active_workspace;
-
-  if (!active)
-    return -1;
-
-  return meta_workspace_index (active);
-}
-
-/**
- * meta_screen_get_active_workspace:
- * @screen: A #MetaScreen
- *
- * Returns: (transfer none): The current workspace
- */
-MetaWorkspace *
-meta_screen_get_active_workspace (MetaScreen *screen)
-{
-  return screen->active_workspace;
-}
-
-void
-meta_screen_focus_default_window (MetaScreen *screen,
-                                  guint32     timestamp)
-{
-  meta_workspace_focus_default_window (screen->active_workspace,
-                                       NULL,
-                                       timestamp);
-}
-
-void
-meta_screen_workspace_switched (MetaScreen         *screen,
-                                int                 from,
-                                int                 to,
-                                MetaMotionDirection direction)
-{
-  g_signal_emit (screen, screen_signals[WORKSPACE_SWITCHED], 0,
-                 from, to, direction);
-}
-
-void
-meta_screen_set_active_workspace_hint (MetaScreen *screen)
-{
-  MetaX11Display *x11_display = screen->display->x11_display;
-
-  unsigned long data[1];
-
-  /* this is because we destroy the spaces in order,
-   * so we always end up setting a current desktop of
-   * 0 when closing a screen, so lose the current desktop
-   * on restart. By doing this we keep the current
-   * desktop on restart.
-   */
-  if (screen->closing > 0)
-    return;
-
-  data[0] = meta_workspace_index (screen->active_workspace);
-
-  meta_verbose ("Setting _NET_CURRENT_DESKTOP to %lu\n", data[0]);
-
-  meta_error_trap_push (x11_display);
-  XChangeProperty (x11_display->xdisplay,
-                   x11_display->xroot,
-                   x11_display->atom__NET_CURRENT_DESKTOP,
-                   XA_CARDINAL,
-                   32, PropModeReplace, (guchar*) data, 1);
-  meta_error_trap_pop (x11_display);
-}
diff --git a/src/core/stack.c b/src/core/stack.c
index a9cd9aa32..2e64698db 100644
--- a/src/core/stack.c
+++ b/src/core/stack.c
@@ -117,7 +117,7 @@ meta_stack_add (MetaStack  *stack,
               window->desc, window->stack_position);
 
   stack_sync_to_xserver (stack);
-  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
+  meta_stack_update_window_tile_matches (stack, window->display->active_workspace);
 }
 
 void
@@ -153,7 +153,7 @@ meta_stack_remove (MetaStack  *stack,
     }
 
   stack_sync_to_xserver (stack);
-  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
+  meta_stack_update_window_tile_matches (stack, window->display->active_workspace);
 }
 
 void
@@ -163,7 +163,7 @@ meta_stack_update_layer (MetaStack  *stack,
   stack->need_relayer = TRUE;
 
   stack_sync_to_xserver (stack);
-  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
+  meta_stack_update_window_tile_matches (stack, window->display->active_workspace);
 }
 
 void
@@ -173,7 +173,7 @@ meta_stack_update_transient (MetaStack  *stack,
   stack->need_constrain = TRUE;
 
   stack_sync_to_xserver (stack);
-  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
+  meta_stack_update_window_tile_matches (stack, window->display->active_workspace);
 }
 
 /* raise/lower within a layer */
@@ -202,7 +202,7 @@ meta_stack_raise (MetaStack  *stack,
   meta_window_set_stack_position_no_sync (window, max_stack_position);
 
   stack_sync_to_xserver (stack);
-  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
+  meta_stack_update_window_tile_matches (stack, window->display->active_workspace);
 }
 
 void
@@ -230,7 +230,7 @@ meta_stack_lower (MetaStack  *stack,
   meta_window_set_stack_position_no_sync (window, min_stack_position);
 
   stack_sync_to_xserver (stack);
-  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
+  meta_stack_update_window_tile_matches (stack, window->display->active_workspace);
 }
 
 void
@@ -1465,5 +1465,5 @@ meta_window_set_stack_position (MetaWindow *window,
   meta_window_set_stack_position_no_sync (window, position);
   stack_sync_to_xserver (window->display->stack);
   meta_stack_update_window_tile_matches (window->display->stack,
-                                         window->screen->active_workspace);
+                                         window->display->active_workspace);
 }
diff --git a/src/core/window.c b/src/core/window.c
index 97a78601d..2a1c20d3c 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -689,7 +689,7 @@ maybe_leave_show_desktop_mode (MetaWindow *window)
 {
   gboolean is_desktop_or_dock;
 
-  if (!window->screen->active_workspace->showing_desktop)
+  if (!window->display->active_workspace->showing_desktop)
     return;
 
   /* If the window is a transient for the dock or desktop, don't
@@ -706,9 +706,9 @@ maybe_leave_show_desktop_mode (MetaWindow *window)
 
   if (!is_desktop_or_dock)
     {
-      meta_screen_minimize_all_on_active_workspace_except (window->screen,
-                                                           window);
-      meta_screen_unshow_desktop (window->screen);
+      meta_display_minimize_all_on_active_workspace_except (window->display,
+                                                            window);
+      meta_display_unshow_desktop (window->display);
     }
 }
 
@@ -1244,8 +1244,8 @@ _meta_window_shared_new (MetaDisplay         *display,
                       "Window %s is initially on space %d\n",
                       window->desc, window->initial_workspace);
 
-          workspace = meta_screen_get_workspace_by_index (window->screen,
-                                                          window->initial_workspace);
+          workspace = meta_display_get_workspace_by_index (window->display,
+                                                           window->initial_workspace);
         }
 
       set_workspace_state (window, on_all_workspaces, workspace);
@@ -1284,7 +1284,7 @@ _meta_window_shared_new (MetaDisplay         *display,
                       "Putting window %s on active workspace\n",
                       window->desc);
 
-          set_workspace_state (window, FALSE, window->screen->active_workspace);
+          set_workspace_state (window, FALSE, window->display->active_workspace);
         }
 
       meta_window_update_struts (window);
@@ -1470,7 +1470,7 @@ meta_window_unmanage (MetaWindow  *window,
       meta_topic (META_DEBUG_FOCUS,
                   "Focusing default window since we're unmanaging %s\n",
                   window->desc);
-      meta_workspace_focus_default_window (window->screen->active_workspace, NULL, timestamp);
+      meta_workspace_focus_default_window (window->display->active_workspace, NULL, timestamp);
     }
   else
     {
@@ -1516,7 +1516,7 @@ meta_window_unmanage (MetaWindow  *window,
   g_assert (window->workspace == NULL);
 
 #ifndef G_DISABLE_CHECKS
-  tmp = window->screen->workspaces;
+  tmp = window->display->workspaces;
   while (tmp != NULL)
     {
       MetaWorkspace *workspace = tmp->data;
@@ -1647,7 +1647,7 @@ meta_window_showing_on_its_workspace (MetaWindow *window)
                                 &is_desktop_or_dock);
 
   if (window->on_all_workspaces)
-    workspace_of_window = window->screen->active_workspace;
+    workspace_of_window = window->display->active_workspace;
   else if (window->workspace)
     workspace_of_window = window->workspace;
   else /* This only seems to be needed for startup */
@@ -1687,7 +1687,7 @@ meta_window_should_be_showing (MetaWindow  *window)
 
   /* Windows should be showing if they're located on the
    * active workspace and they're showing on their own workspace. */
-  return (meta_window_located_on_workspace (window, window->screen->active_workspace) &&
+  return (meta_window_located_on_workspace (window, window->display->active_workspace) &&
           meta_window_showing_on_its_workspace (window));
 }
 
@@ -2630,11 +2630,11 @@ meta_window_hide (MetaWindow *window)
        * We also pass in NULL if we are in the process of hiding all non-desktop
        * windows to avoid unexpected changes to the stacking order.
        */
-      if (my_workspace == window->screen->active_workspace &&
+      if (my_workspace == window->display->active_workspace &&
           !my_workspace->showing_desktop)
         not_this_one = window;
 
-      meta_workspace_focus_default_window (window->screen->active_workspace,
+      meta_workspace_focus_default_window (window->display->active_workspace,
                                            not_this_one,
                                            timestamp);
     }
@@ -3641,7 +3641,7 @@ meta_window_activate_full (MetaWindow     *window,
 
   /* Get window on current or given workspace */
   if (workspace == NULL)
-    workspace = window->screen->active_workspace;
+    workspace = window->display->active_workspace;
 
   /* For non-transient windows, we just set up a pulsing indicator,
      rather than move windows or workspaces.
@@ -3869,8 +3869,8 @@ meta_window_update_monitor (MetaWindow *window,
        */
       if (meta_prefs_get_workspaces_only_on_primary () && user_op &&
           meta_window_is_on_primary_monitor (window)  &&
-          window->screen->active_workspace != window->workspace)
-        meta_window_change_workspace (window, window->screen->active_workspace);
+          window->display->active_workspace != window->workspace)
+        meta_window_change_workspace (window, window->display->active_workspace);
 
       meta_window_main_monitor_changed (window, old);
 
@@ -4036,7 +4036,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->display->stack,
-                                         window->screen->active_workspace);
+                                         window->display->active_workspace);
 }
 
 /**
@@ -4642,8 +4642,8 @@ meta_window_focus (MetaWindow  *window,
       meta_topic (META_DEBUG_FOCUS,
                   "%s has %s as a modal transient, so focusing it instead.\n",
                   window->desc, modal_transient->desc);
-      if (!meta_window_located_on_workspace (modal_transient, window->screen->active_workspace))
-        meta_window_change_workspace (modal_transient, window->screen->active_workspace);
+      if (!meta_window_located_on_workspace (modal_transient, window->display->active_workspace))
+        meta_window_change_workspace (modal_transient, window->display->active_workspace);
       window = modal_transient;
     }
 
@@ -4714,7 +4714,7 @@ set_workspace_state (MetaWindow    *window,
   else if (window->on_all_workspaces)
     {
       GList *l;
-      for (l = window->screen->workspaces; l != NULL; l = l->next)
+      for (l = window->display->workspaces; l != NULL; l = l->next)
         {
           MetaWorkspace *ws = l->data;
           meta_workspace_remove_window (ws, window);
@@ -4729,7 +4729,7 @@ set_workspace_state (MetaWindow    *window,
   else if (window->on_all_workspaces)
     {
       GList *l;
-      for (l = window->screen->workspaces; l != NULL; l = l->next)
+      for (l = window->display->workspaces; l != NULL; l = l->next)
         {
           MetaWorkspace *ws = l->data;
           meta_workspace_add_window (ws, window);
@@ -4786,7 +4786,7 @@ meta_window_on_all_workspaces_changed (MetaWindow *window)
     {
       /* We're coming out of the sticky state. Put the window on
        * the currently active workspace. */
-      workspace = window->screen->active_workspace;
+      workspace = window->display->active_workspace;
     }
 
   set_workspace_state (window, on_all_workspaces, workspace);
@@ -5010,7 +5010,7 @@ meta_window_change_workspace_by_index (MetaWindow *window,
                                        gboolean    append)
 {
   MetaWorkspace *workspace;
-  MetaScreen    *screen;
+  MetaDisplay   *display;
 
   g_return_if_fail (!window->override_redirect);
 
@@ -5020,13 +5020,13 @@ meta_window_change_workspace_by_index (MetaWindow *window,
       return;
     }
 
-  screen = window->screen;
+  display = window->display;
 
   workspace =
-    meta_screen_get_workspace_by_index (screen, space_index);
+    meta_display_get_workspace_by_index (display, space_index);
 
   if (!workspace && append)
-    workspace = meta_screen_append_new_workspace (screen, FALSE, CurrentTime);
+    workspace = meta_display_append_new_workspace (display, FALSE, CurrentTime);
 
   if (workspace)
     meta_window_change_workspace (window, workspace);
@@ -5140,22 +5140,22 @@ meta_window_set_focused_internal (MetaWindow *window,
        * list only if the window is actually on the active
        * workspace.
        */
-      if (window->screen->active_workspace &&
+      if (window->display->active_workspace &&
           meta_window_located_on_workspace (window,
-                                            window->screen->active_workspace))
+                                            window->display->active_workspace))
         {
           GList* link;
-          link = g_list_find (window->screen->active_workspace->mru_list,
+          link = g_list_find (window->display->active_workspace->mru_list,
                               window);
           g_assert (link);
 
-          window->screen->active_workspace->mru_list =
-            g_list_remove_link (window->screen->active_workspace->mru_list,
+          window->display->active_workspace->mru_list =
+            g_list_remove_link (window->display->active_workspace->mru_list,
                                 link);
           g_list_free (link);
 
-          window->screen->active_workspace->mru_list =
-            g_list_prepend (window->screen->active_workspace->mru_list,
+          window->display->active_workspace->mru_list =
+            g_list_prepend (window->display->active_workspace->mru_list,
                             window);
         }
 
@@ -5399,7 +5399,7 @@ GList*
 meta_window_get_workspaces (MetaWindow *window)
 {
   if (window->on_all_workspaces)
-    return window->screen->workspaces;
+    return window->display->workspaces;
   else if (window->workspace != NULL)
     return window->workspace->list_containing_self;
   else if (window->constructing)
@@ -5764,7 +5764,7 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window)
 
   /* Get the basic info we need */
   meta_window_get_frame_rect (window, &frame_rect);
-  onscreen_region = window->screen->active_workspace->screen_region;
+  onscreen_region = window->display->active_workspace->screen_region;
 
   /* Extend the region (just in case the window is too big to fit on the
    * screen), then shove the window on screen, then return the region to
@@ -5816,7 +5816,7 @@ meta_window_titlebar_is_onscreen (MetaWindow *window)
    * them overlaps with the titlebar sufficiently to consider it onscreen.
    */
   is_onscreen = FALSE;
-  onscreen_region = window->screen->active_workspace->screen_region;
+  onscreen_region = window->display->active_workspace->screen_region;
   while (onscreen_region)
     {
       MetaRectangle *spanning_rect = onscreen_region->data;
@@ -6885,7 +6885,7 @@ ensure_mru_position_after (MetaWindow *window,
   GList* window_position;
   GList* after_this_one_position;
 
-  active_mru_list         = window->screen->active_workspace->mru_list;
+  active_mru_list         = window->display->active_workspace->mru_list;
   window_position         = g_list_find (active_mru_list, window);
   after_this_one_position = g_list_find (active_mru_list, after_this_one);
 
@@ -6898,12 +6898,12 @@ ensure_mru_position_after (MetaWindow *window,
 
   if (g_list_length (window_position) > g_list_length (after_this_one_position))
     {
-      window->screen->active_workspace->mru_list =
-        g_list_delete_link (window->screen->active_workspace->mru_list,
+      window->display->active_workspace->mru_list =
+        g_list_delete_link (window->display->active_workspace->mru_list,
                             window_position);
 
-      window->screen->active_workspace->mru_list =
-        g_list_insert_before (window->screen->active_workspace->mru_list,
+      window->display->active_workspace->mru_list =
+        g_list_insert_before (window->display->active_workspace->mru_list,
                               after_this_one_position->next,
                               window);
     }
@@ -7056,7 +7056,7 @@ meta_window_set_demands_attention (MetaWindow *window)
   MetaWindow *other_window;
   gboolean obscured = FALSE;
 
-  MetaWorkspace *workspace = window->screen->active_workspace;
+  MetaWorkspace *workspace = window->display->active_workspace;
 
   if (window->wm_state_demands_attention)
     return;
@@ -7257,7 +7257,7 @@ MetaWorkspace *
 meta_window_get_workspace (MetaWindow *window)
 {
   if (window->on_all_workspaces)
-    return window->screen->active_workspace;
+    return window->display->active_workspace;
   else
     return window->workspace;
 }
diff --git a/src/core/workspace-private.h b/src/core/workspace-private.h
index 54d9db01f..f63be9550 100644
--- a/src/core/workspace-private.h
+++ b/src/core/workspace-private.h
@@ -37,7 +37,7 @@
 struct _MetaWorkspace
 {
   GObject parent_instance;
-  MetaScreen *screen;
+  MetaDisplay *display;
 
   GList *windows;
 
@@ -72,7 +72,7 @@ struct _MetaWorkspaceClass
   GObjectClass parent_class;
 };
 
-MetaWorkspace* meta_workspace_new           (MetaScreen    *screen);
+MetaWorkspace* meta_workspace_new           (MetaDisplay   *display);
 void           meta_workspace_remove        (MetaWorkspace *workspace);
 void           meta_workspace_add_window    (MetaWorkspace *workspace,
                                              MetaWindow    *window);
diff --git a/src/core/workspace.c b/src/core/workspace.c
index ea036bdc9..adb926081 100644
--- a/src/core/workspace.c
+++ b/src/core/workspace.c
@@ -34,7 +34,7 @@
 #include <config.h>
 #include "backends/meta-backend-private.h"
 #include "backends/meta-logical-monitor.h"
-#include "screen-private.h"
+#include "x11/meta-x11-display-private.h"
 #include <meta/workspace.h>
 #include "workspace-private.h"
 #include "boxes-private.h"
@@ -223,16 +223,16 @@ meta_workspace_init (MetaWorkspace *workspace)
 }
 
 MetaWorkspace*
-meta_workspace_new (MetaScreen *screen)
+meta_workspace_new (MetaDisplay *display)
 {
   MetaWorkspace *workspace;
   GSList *windows, *l;
 
   workspace = g_object_new (META_TYPE_WORKSPACE, NULL);
 
-  workspace->screen = screen;
-  workspace->screen->workspaces =
-    g_list_append (workspace->screen->workspaces, workspace);
+  workspace->display = display;
+  workspace->display->workspaces =
+    g_list_append (workspace->display->workspaces, workspace);
   workspace->windows = NULL;
   workspace->mru_list = NULL;
 
@@ -253,7 +253,7 @@ meta_workspace_new (MetaScreen *screen)
   workspace->showing_desktop = FALSE;
 
   /* make sure sticky windows are in our mru_list */
-  windows = meta_display_list_windows (screen->display, META_LIST_SORTED);
+  windows = meta_display_list_windows (display, META_LIST_SORTED);
   for (l = windows; l; l = l->next)
     if (meta_window_located_on_workspace (l->data, workspace))
       meta_workspace_add_window (workspace, l->data);
@@ -319,12 +319,12 @@ assert_workspace_empty (MetaWorkspace *workspace)
 void
 meta_workspace_remove (MetaWorkspace *workspace)
 {
-  g_return_if_fail (workspace != workspace->screen->active_workspace);
+  g_return_if_fail (workspace != workspace->display->active_workspace);
 
   assert_workspace_empty (workspace);
 
-  workspace->screen->workspaces =
-    g_list_remove (workspace->screen->workspaces, workspace);
+  workspace->display->workspaces =
+    g_list_remove (workspace->display->workspaces, workspace);
 
   meta_workspace_clear_logical_monitor_data (workspace);
 
@@ -439,14 +439,14 @@ workspace_switch_sound(MetaWorkspace *from,
   int i, nw, x, y, fi, ti;
   const char *e;
 
-  nw = meta_screen_get_n_workspaces(from->screen);
+  nw = meta_display_get_n_workspaces(from->display);
   fi = meta_workspace_index(from);
   ti = meta_workspace_index(to);
 
-  meta_screen_calc_workspace_layout(from->screen,
-                                    nw,
-                                    fi,
-                                    &layout);
+  meta_display_calc_workspace_layout(from->display,
+                                     nw,
+                                     fi,
+                                     &layout);
 
   for (i = 0; i < nw; i++)
     if (layout.grid[i] == ti)
@@ -489,7 +489,7 @@ workspace_switch_sound(MetaWorkspace *from,
                   NULL);
 
  finish:
-  meta_screen_free_workspace_layout (&layout);
+  meta_display_free_workspace_layout (&layout);
 #endif /* HAVE_LIBCANBERRA */
 }
 
@@ -519,7 +519,6 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
 {
   MetaWorkspace  *old;
   MetaWindow     *move_window;
-  MetaScreen     *screen;
   MetaDisplay    *display;
   MetaCompositor *comp;
   MetaWorkspaceLayout layout1, layout2;
@@ -529,36 +528,36 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
   meta_verbose ("Activating workspace %d\n",
                 meta_workspace_index (workspace));
 
-  if (workspace->screen->active_workspace == workspace)
+  if (workspace->display->active_workspace == workspace)
     return;
 
   /* Free any cached pointers to the workspaces's edges from
    * a current resize or move operation */
-  meta_display_cleanup_edges (workspace->screen->display);
+  meta_display_cleanup_edges (workspace->display);
 
-  if (workspace->screen->active_workspace)
-    workspace_switch_sound (workspace->screen->active_workspace, workspace);
+  if (workspace->display->active_workspace)
+    workspace_switch_sound (workspace->display->active_workspace, workspace);
 
   /* Note that old can be NULL; e.g. when starting up */
-  old = workspace->screen->active_workspace;
+  old = workspace->display->active_workspace;
 
-  workspace->screen->active_workspace = workspace;
+  workspace->display->active_workspace = workspace;
 
-  meta_screen_set_active_workspace_hint (workspace->screen);
+  meta_x11_display_set_active_workspace_hint (workspace->display->x11_display);
 
   /* If the "show desktop" mode is active for either the old workspace
    * or the new one *but not both*, then update the
    * _net_showing_desktop hint
    */
   if (old && (old->showing_desktop != workspace->showing_desktop))
-    meta_screen_update_showing_desktop_hint (workspace->screen);
+    meta_x11_display_update_showing_desktop_hint (workspace->display->x11_display);
 
   if (old == NULL)
     return;
 
   move_window = NULL;
-  if (meta_grab_op_is_moving (workspace->screen->display->grab_op))
-    move_window = workspace->screen->display->grab_window;
+  if (meta_grab_op_is_moving (workspace->display->grab_op))
+    move_window = workspace->display->grab_window;
 
   if (move_window != NULL)
     {
@@ -579,19 +578,18 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
    /*
     * Notify the compositor that the active workspace is changing.
     */
-   screen = workspace->screen;
-   display = meta_screen_get_display (screen);
+   display = workspace->display;
    comp = meta_display_get_compositor (display);
    direction = 0;
 
    current_space = meta_workspace_index (old);
    new_space     = meta_workspace_index (workspace);
-   num_workspaces = meta_screen_get_n_workspaces (workspace->screen);
-   meta_screen_calc_workspace_layout (workspace->screen, num_workspaces,
-                                      current_space, &layout1);
+   num_workspaces = meta_display_get_n_workspaces (workspace->display);
+   meta_display_calc_workspace_layout (workspace->display, num_workspaces,
+                                       current_space, &layout1);
 
-   meta_screen_calc_workspace_layout (workspace->screen, num_workspaces,
-                                      new_space, &layout2);
+   meta_display_calc_workspace_layout (workspace->display, num_workspaces,
+                                       new_space, &layout2);
 
    if (meta_get_locale_direction () == META_LOCALE_DIRECTION_RTL)
      {
@@ -628,8 +626,8 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
          direction = META_MOTION_UP_LEFT;
      }
 
-   meta_screen_free_workspace_layout (&layout1);
-   meta_screen_free_workspace_layout (&layout2);
+   meta_display_free_workspace_layout (&layout1);
+   meta_display_free_workspace_layout (&layout2);
 
    meta_compositor_switch_workspace (comp, old, workspace, direction);
 
@@ -653,7 +651,7 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
     }
 
    /* Emit switched signal from screen.c */
-   meta_screen_workspace_switched (screen, current_space, new_space, direction);
+   meta_display_workspace_switched (display, current_space, new_space, direction);
 }
 
 void
@@ -668,7 +666,7 @@ meta_workspace_index (MetaWorkspace *workspace)
 {
   int ret;
 
-  ret = g_list_index (workspace->screen->workspaces, workspace);
+  ret = g_list_index (workspace->display->workspaces, workspace);
 
   if (ret < 0)
     meta_bug ("Workspace does not exist to index!\n");
@@ -704,7 +702,7 @@ meta_workspace_list_windows (MetaWorkspace *workspace)
   GSList *display_windows, *l;
   GList *workspace_windows;
 
-  display_windows = meta_display_list_windows (workspace->screen->display,
+  display_windows = meta_display_list_windows (workspace->display,
                                                META_LIST_DEFAULT);
 
   workspace_windows = NULL;
@@ -741,8 +739,8 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
 
   /* If we are in the middle of a resize or move operation, we
    * might have cached pointers to the workspace's edges */
-  if (workspace == workspace->screen->active_workspace)
-    meta_display_cleanup_edges (workspace->screen->display);
+  if (workspace == workspace->display->active_workspace)
+    meta_display_cleanup_edges (workspace->display);
 
   meta_workspace_clear_logical_monitor_data (workspace);
 
@@ -768,7 +766,7 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
 
   g_list_free (windows);
 
-  meta_display_queue_workarea_recalc (workspace->screen->display);
+  meta_display_queue_workarea_recalc (workspace->display);
 }
 
 static MetaStrut *
@@ -849,13 +847,13 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
 
   workspace->screen_region =
     meta_rectangle_get_minimal_spanning_set_for_region (
-      &workspace->screen->display->rect,
+      &workspace->display->rect,
       workspace->all_struts);
 
   /* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
    *         monitors.
    */
-  work_area = workspace->screen->display->rect;  /* start with the screen */
+  work_area = workspace->display->rect;  /* start with the screen */
   if (workspace->screen_region == NULL)
     work_area = meta_rect (0, 0, -1, -1);
   else
@@ -872,7 +870,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
                     work_area.width, MIN_SANE_AREA);
       if (work_area.width < 1)
         {
-          work_area.x = (workspace->screen->display->rect.width - MIN_SANE_AREA)/2;
+          work_area.x = (workspace->display->rect.width - MIN_SANE_AREA)/2;
           work_area.width = MIN_SANE_AREA;
         }
       else
@@ -889,7 +887,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
                     work_area.height, MIN_SANE_AREA);
       if (work_area.height < 1)
         {
-          work_area.y = (workspace->screen->display->rect.height - MIN_SANE_AREA)/2;
+          work_area.y = (workspace->display->rect.height - MIN_SANE_AREA)/2;
           work_area.height = MIN_SANE_AREA;
         }
       else
@@ -956,7 +954,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
   g_assert (workspace->screen_edges    == NULL);
   g_assert (workspace->monitor_edges  == NULL);
   workspace->screen_edges =
-    meta_rectangle_find_onscreen_edges (&workspace->screen->display->rect,
+    meta_rectangle_find_onscreen_edges (&workspace->display->rect,
                                         workspace->all_struts);
   tmp = NULL;
   for (l = logical_monitors; l; l = l->next)
@@ -1007,7 +1005,7 @@ meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
   MetaBackend *backend = meta_get_backend ();
   MetaMonitorManager *monitor_manager =
     meta_backend_get_monitor_manager (backend);
-  MetaScreen *screen = workspace->screen;
+  MetaDisplay *display = workspace->display;
   GSList *l;
 
   for (l = struts; l; l = l->next)
@@ -1036,7 +1034,7 @@ meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
                                                                  META_DISPLAY_DOWN))
             continue;
 
-          strut->rect.height = screen->display->rect.height - strut->rect.y;
+          strut->rect.height = display->rect.height - strut->rect.y;
           break;
         case META_SIDE_LEFT:
           if (meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
@@ -1053,7 +1051,7 @@ meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
                                                                  META_DISPLAY_RIGHT))
             continue;
 
-          strut->rect.width = screen->display->rect.width - strut->rect.x;
+          strut->rect.width = display->rect.width - strut->rect.x;
           break;
         }
     }
@@ -1199,9 +1197,9 @@ meta_workspace_get_neighbor (MetaWorkspace      *workspace,
   gboolean ltr;
 
   current_space = meta_workspace_index (workspace);
-  num_workspaces = meta_screen_get_n_workspaces (workspace->screen);
-  meta_screen_calc_workspace_layout (workspace->screen, num_workspaces,
-                                     current_space, &layout);
+  num_workspaces = meta_display_get_n_workspaces (workspace->display);
+  meta_display_calc_workspace_layout (workspace->display, num_workspaces,
+                                      current_space, &layout);
 
   meta_verbose ("Getting neighbor of %d in direction %s\n",
                 current_space, meta_motion_direction_to_string (direction));
@@ -1246,9 +1244,9 @@ meta_workspace_get_neighbor (MetaWorkspace      *workspace,
   meta_verbose ("Neighbor workspace is %d at row %d col %d\n",
                 i, layout.current_row, layout.current_col);
 
-  meta_screen_free_workspace_layout (&layout);
+  meta_display_free_workspace_layout (&layout);
 
-  return meta_screen_get_workspace_by_index (workspace->screen, i);
+  return meta_display_get_workspace_by_index (workspace->display, i);
 }
 
 const char*
@@ -1262,19 +1260,17 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
                                      MetaWindow    *not_this_one,
                                      guint32        timestamp)
 {
-  MetaDisplay *display = workspace->screen->display;
-
   if (timestamp == CurrentTime)
     meta_warning ("CurrentTime used to choose focus window; "
                   "focus window may not be correct.\n");
 
   if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
-      !workspace->screen->display->mouse_mode)
+      !workspace->display->mouse_mode)
     focus_ancestor_or_top_window (workspace, not_this_one, timestamp);
   else
     {
       MetaWindow * window;
-      window = meta_display_get_pointer_window (workspace->screen->display, not_this_one);
+      window = meta_display_get_pointer_window (workspace->display, not_this_one);
       if (window &&
           window->type != META_WINDOW_DOCK &&
           window->type != META_WINDOW_DESKTOP)
@@ -1299,10 +1295,10 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
               meta_window_focus (window, timestamp);
             }
 
-          if (workspace->screen->display->autoraise_window != window &&
+          if (workspace->display->autoraise_window != window &&
               meta_prefs_get_auto_raise ())
             {
-              meta_display_queue_autoraise_callback (display, window);
+              meta_display_queue_autoraise_callback (workspace->display, window);
             }
         }
       else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_SLOPPY)
@@ -1312,7 +1308,7 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
           meta_topic (META_DEBUG_FOCUS,
                       "Setting focus to no_focus_window, since no valid "
                       "window to focus found.\n");
-          meta_x11_display_focus_the_no_focus_window (display->x11_display,
+          meta_x11_display_focus_the_no_focus_window (workspace->display->x11_display,
                                                       timestamp);
         }
     }
@@ -1334,7 +1330,6 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
                               MetaWindow    *not_this_one,
                               guint32        timestamp)
 {
-  MetaDisplay *display = workspace->screen->display;
   MetaWindow *window = NULL;
 
   if (not_this_one)
@@ -1368,7 +1363,7 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
         }
     }
 
-  window = meta_stack_get_default_focus_window (display->stack,
+  window = meta_stack_get_default_focus_window (workspace->display->stack,
                                                 workspace,
                                                 not_this_one);
 
@@ -1386,22 +1381,21 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
   else
     {
       meta_topic (META_DEBUG_FOCUS, "No MRU window to focus found; focusing no_focus_window.\n");
-      meta_x11_display_focus_the_no_focus_window (display->x11_display,
+      meta_x11_display_focus_the_no_focus_window (workspace->display->x11_display,
                                                   timestamp);
     }
 }
 
 /**
- * meta_workspace_get_screen:
+ * meta_workspace_get_display:
  * @workspace: a #MetaWorkspace
  *
- * Gets the #MetaScreen that the workspace is part of.
+ * Gets the #MetaDisplay that the workspace is part of.
  *
- * Return value: (transfer none): the #MetaScreen for the workspace
+ * Return value: (transfer none): the #MetaDisplay for the workspace
  */
-MetaScreen *
-meta_workspace_get_screen (MetaWorkspace *workspace)
+MetaDisplay *
+meta_workspace_get_display (MetaWorkspace *workspace)
 {
-  return workspace->screen;
+  return workspace->display;
 }
-
diff --git a/src/meta/display.h b/src/meta/display.h
index 50366cbff..aa263066f 100644
--- a/src/meta/display.h
+++ b/src/meta/display.h
@@ -208,4 +208,46 @@ int meta_display_get_monitor_neighbor_index (MetaDisplay         *display,
                                              int                  which_monitor,
                                              MetaDisplayDirection dir);
 
+GList *meta_display_get_workspaces (MetaDisplay *display);
+
+int meta_display_get_n_workspaces (MetaDisplay *display);
+
+MetaWorkspace* meta_display_get_workspace_by_index (MetaDisplay *display,
+                                                   int           index);
+void meta_display_remove_workspace (MetaDisplay   *display,
+                                    MetaWorkspace *workspace,
+                                    guint32        timestamp);
+
+MetaWorkspace *meta_display_append_new_workspace (MetaDisplay *display,
+                                                  gboolean     activate,
+                                                  guint32      timestamp);
+
+int meta_display_get_active_workspace_index (MetaDisplay *display);
+
+MetaWorkspace *meta_display_get_active_workspace (MetaDisplay *display);
+
+void meta_display_focus_default_window (MetaDisplay *display,
+                                        guint32      timestamp);
+
+/**
+ * MetaDisplayCorner:
+ * @META_DISPLAY_TOPLEFT: top-left corner
+ * @META_DISPLAY_TOPRIGHT: top-right corner
+ * @META_DISPLAY_BOTTOMLEFT: bottom-left corner
+ * @META_DISPLAY_BOTTOMRIGHT: bottom-right corner
+ */
+typedef enum
+{
+  META_DISPLAY_TOPLEFT,
+  META_DISPLAY_TOPRIGHT,
+  META_DISPLAY_BOTTOMLEFT,
+  META_DISPLAY_BOTTOMRIGHT
+} MetaDisplayCorner;
+
+void meta_display_override_workspace_layout (MetaDisplay       *display,
+                                             MetaDisplayCorner starting_corner,
+                                             gboolean          vertical_layout,
+                                             int               n_rows,
+                                             int               n_columns);
+
 #endif
diff --git a/src/meta/screen.h b/src/meta/screen.h
index 57f3b60fd..ec9162efd 100644
--- a/src/meta/screen.h
+++ b/src/meta/screen.h
@@ -38,46 +38,4 @@ GType meta_screen_get_type (void);
 
 MetaDisplay *meta_screen_get_display (MetaScreen *screen);
 
-GList *meta_screen_get_workspaces (MetaScreen *screen);
-
-int meta_screen_get_n_workspaces (MetaScreen *screen);
-
-MetaWorkspace* meta_screen_get_workspace_by_index (MetaScreen    *screen,
-                                                   int            index);
-void meta_screen_remove_workspace (MetaScreen    *screen,
-                                   MetaWorkspace *workspace,
-                                   guint32        timestamp);
-
-MetaWorkspace *meta_screen_append_new_workspace (MetaScreen    *screen,
-                                                 gboolean       activate,
-                                                 guint32        timestamp);
-
-int meta_screen_get_active_workspace_index (MetaScreen *screen);
-
-MetaWorkspace * meta_screen_get_active_workspace (MetaScreen *screen);
-
-void meta_screen_focus_default_window (MetaScreen *screen,
-                                       guint32     timestamp);
-
-/**
- * MetaScreenCorner:
- * @META_SCREEN_TOPLEFT: top-left corner
- * @META_SCREEN_TOPRIGHT: top-right corner
- * @META_SCREEN_BOTTOMLEFT: bottom-left corner
- * @META_SCREEN_BOTTOMRIGHT: bottom-right corner
- */
-typedef enum
-{
-  META_SCREEN_TOPLEFT,
-  META_SCREEN_TOPRIGHT,
-  META_SCREEN_BOTTOMLEFT,
-  META_SCREEN_BOTTOMRIGHT
-} MetaScreenCorner;
-
-void meta_screen_override_workspace_layout (MetaScreen      *screen,
-                                            MetaScreenCorner starting_corner,
-                                            gboolean         vertical_layout,
-                                            int              n_rows,
-                                            int              n_columns);
-
 #endif
diff --git a/src/meta/workspace.h b/src/meta/workspace.h
index 005e9c9af..d83a3891f 100644
--- a/src/meta/workspace.h
+++ b/src/meta/workspace.h
@@ -37,7 +37,7 @@ typedef struct _MetaWorkspaceClass   MetaWorkspaceClass;
 GType meta_workspace_get_type (void);
 
 int  meta_workspace_index (MetaWorkspace *workspace);
-MetaScreen *meta_workspace_get_screen (MetaWorkspace *workspace);
+MetaDisplay *meta_workspace_get_display (MetaWorkspace *workspace);
 GList* meta_workspace_list_windows (MetaWorkspace *workspace);
 void meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace,
                                                int            which_monitor,
diff --git a/src/x11/events.c b/src/x11/events.c
index e4fa77801..375d72f08 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -843,7 +843,6 @@ handle_input_xevent (MetaX11Display *x11_display,
   Window modified;
   MetaWindow *window;
   MetaDisplay *display = x11_display->display;
-  MetaScreen *screen = display->screen;
 
   if (input_event == NULL)
     return FALSE;
@@ -912,7 +911,7 @@ handle_input_xevent (MetaX11Display *x11_display,
                           "Focus got set to None, probably due to "
                           "brain-damage in the X protocol (see bug "
                           "125492).  Setting the default focus window.\n");
-              meta_workspace_focus_default_window (screen->active_workspace,
+              meta_workspace_focus_default_window (display->active_workspace,
                                                    NULL,
                                                    meta_x11_display_get_current_time_roundtrip 
(x11_display));
             }
@@ -924,7 +923,7 @@ handle_input_xevent (MetaX11Display *x11_display,
                           "Focus got set to root window, probably due to "
                           "gnome-session logout dialog usage (see bug "
                           "153220).  Setting the default focus window.\n");
-              meta_workspace_focus_default_window (screen->active_workspace,
+              meta_workspace_focus_default_window (display->active_workspace,
                                                    NULL,
                                                    meta_x11_display_get_current_time_roundtrip 
(x11_display));
             }
@@ -1398,12 +1397,12 @@ handle_other_xevent (MetaX11Display *x11_display,
       if (window->minimized)
         {
           meta_window_unminimize (window);
-          if (window->workspace != window->screen->active_workspace)
+          if (window->workspace != window->display->active_workspace)
             {
               meta_verbose ("Changing workspace due to MapRequest mapped = %d minimized = %d\n",
                             window->mapped, window->minimized);
               meta_window_change_workspace (window,
-                                            window->screen->active_workspace);
+                                            window->display->active_workspace);
             }
         }
       break;
@@ -1488,10 +1487,10 @@ handle_other_xevent (MetaX11Display *x11_display,
           {
             if (event->xproperty.atom ==
                 x11_display->atom__NET_DESKTOP_LAYOUT)
-              meta_screen_update_workspace_layout (display->screen);
+              meta_display_update_workspace_layout (display);
             else if (event->xproperty.atom ==
                      x11_display->atom__NET_DESKTOP_NAMES)
-              meta_screen_update_workspace_names (display->screen);
+              meta_x11_display_update_workspace_names (x11_display);
 
             /* we just use this property as a sentinel to avoid
              * certain race conditions.  See the comment for the
@@ -1552,7 +1551,7 @@ handle_other_xevent (MetaX11Display *x11_display,
                                 "specified timestamp of %u\n",
                                 space, time);
 
-                  workspace = meta_screen_get_workspace_by_index (display->screen, space);
+                  workspace = meta_display_get_workspace_by_index (display, space);
 
                   /* Handle clients using the older version of the spec... */
                   if (time == 0 && workspace)
@@ -1593,11 +1592,11 @@ handle_other_xevent (MetaX11Display *x11_display,
                                 showing_desktop ? "show" : "hide");
 
                   if (showing_desktop)
-                    meta_screen_show_desktop (display->screen, timestamp);
+                    meta_display_show_desktop (display, timestamp);
                   else
                     {
-                      meta_screen_unshow_desktop (display->screen);
-                      meta_workspace_focus_default_window (display->screen->active_workspace, NULL, 
timestamp);
+                      meta_display_unshow_desktop (display);
+                      meta_workspace_focus_default_window (display->active_workspace, NULL, timestamp);
                     }
                 }
               else if (event->xclient.message_type ==
diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h
index 72e68d544..09bf2a082 100644
--- a/src/x11/meta-x11-display-private.h
+++ b/src/x11/meta-x11-display-private.h
@@ -202,4 +202,12 @@ int meta_x11_display_logical_monitor_to_xinerama_index (MetaX11Display     *x11_
 MetaLogicalMonitor *meta_x11_display_xinerama_index_to_logical_monitor (MetaX11Display *x11_display,
                                                                         int             xinerama_index);
 
+/* Update whether the destkop is being shown for the current active_workspace */
+void meta_x11_display_update_showing_desktop_hint (MetaX11Display *x11_display);
+void meta_x11_display_update_workspace_names      (MetaX11Display *x11_display);
+
+void meta_x11_display_set_active_workspace_hint   (MetaX11Display *x11_display);
+void meta_x11_display_set_number_of_spaces_hint   (MetaX11Display *x11_display,
+                                                   int             n_spaces);
+
 #endif /* META_X11_DISPLAY_PRIVATE_H */
diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
index 7460873d5..64a0d0fc5 100644
--- a/src/x11/meta-x11-display.c
+++ b/src/x11/meta-x11-display.c
@@ -53,6 +53,7 @@
 #include "backends/x11/meta-backend-x11.h"
 #include "core/frame.h"
 #include "core/util-private.h"
+#include "core/workspace-private.h"
 #include "meta/errors.h"
 #include "meta/main.h"
 
@@ -1562,3 +1563,108 @@ meta_x11_display_xinerama_index_to_logical_monitor (MetaX11Display *x11_display,
 
   return NULL;
 }
+
+void
+meta_x11_display_update_showing_desktop_hint (MetaX11Display *x11_display)
+{
+  MetaDisplay *display = x11_display->display;
+  unsigned long data[1];
+
+  data[0] = display->active_workspace->showing_desktop ? 1 : 0;
+
+  meta_error_trap_push (x11_display);
+  XChangeProperty (x11_display->xdisplay,
+                   x11_display->xroot,
+                   x11_display->atom__NET_SHOWING_DESKTOP,
+                   XA_CARDINAL,
+                   32, PropModeReplace, (guchar*) data, 1);
+  meta_error_trap_pop (x11_display);
+}
+
+void
+meta_x11_display_update_workspace_names (MetaX11Display *x11_display)
+{
+  char **names;
+  int n_names;
+  int i;
+
+  /* this updates names in prefs when the root window property changes,
+   * iff the new property contents don't match what's already in prefs
+   */
+
+  names = NULL;
+  n_names = 0;
+  if (!meta_prop_get_utf8_list (x11_display,
+                                x11_display->xroot,
+                                x11_display->atom__NET_DESKTOP_NAMES,
+                                &names, &n_names))
+    {
+      meta_verbose ("Failed to get workspace names from root window\n");
+      return;
+    }
+
+  i = 0;
+  while (i < n_names)
+    {
+      meta_topic (META_DEBUG_PREFS,
+                  "Setting workspace %d name to \"%s\" due to _NET_DESKTOP_NAMES change\n",
+                  i, names[i] ? names[i] : "null");
+      meta_prefs_change_workspace_name (i, names[i]);
+
+      ++i;
+    }
+
+  g_strfreev (names);
+}
+
+
+void
+meta_x11_display_set_active_workspace_hint (MetaX11Display *x11_display)
+{
+  MetaDisplay *display = x11_display->display;
+
+  unsigned long data[1];
+
+  /* this is because we destroy the spaces in order,
+   * so we always end up setting a current desktop of
+   * 0 when closing a screen, so lose the current desktop
+   * on restart. By doing this we keep the current
+   * desktop on restart.
+   */
+  if (display->closing > 0)
+    return;
+
+  data[0] = meta_workspace_index (display->active_workspace);
+
+  meta_verbose ("Setting _NET_CURRENT_DESKTOP to %lu\n", data[0]);
+
+  meta_error_trap_push (x11_display);
+  XChangeProperty (x11_display->xdisplay,
+                   x11_display->xroot,
+                   x11_display->atom__NET_CURRENT_DESKTOP,
+                   XA_CARDINAL,
+                   32, PropModeReplace, (guchar*) data, 1);
+  meta_error_trap_pop (x11_display);
+}
+
+void
+meta_x11_display_set_number_of_spaces_hint (MetaX11Display *x11_display,
+                                            int             n_spaces)
+{
+  unsigned long data[1];
+
+  if (x11_display->display->closing > 0)
+    return;
+
+  data[0] = n_spaces;
+
+  meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %lu\n", data[0]);
+
+  meta_error_trap_push (x11_display);
+  XChangeProperty (x11_display->xdisplay,
+                   x11_display->xroot,
+                   x11_display->atom__NET_NUMBER_OF_DESKTOPS,
+                   XA_CARDINAL,
+                   32, PropModeReplace, (guchar*) data, 1);
+  meta_error_trap_pop (x11_display);
+}
diff --git a/src/x11/window-props.c b/src/x11/window-props.c
index 1461f999b..5f8ee647c 100644
--- a/src/x11/window-props.c
+++ b/src/x11/window-props.c
@@ -1049,7 +1049,7 @@ reload_net_startup_id (MetaWindow    *window,
         if (window->initial_timestamp_set)
           timestamp = window->initial_timestamp;
         if (window->initial_workspace_set)
-          workspace = meta_screen_get_workspace_by_index (window->screen, window->initial_workspace);
+          workspace = meta_display_get_workspace_by_index (window->display, window->initial_workspace);
 
         meta_window_activate_with_workspace (window, timestamp, workspace);
       }
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index d297b554d..6b070cedb 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -445,8 +445,8 @@ meta_window_apply_session_info (MetaWindow *window,
           MetaWorkspace *space;
 
           space =
-            meta_screen_get_workspace_by_index (window->screen,
-                                                GPOINTER_TO_INT (tmp->data));
+            meta_display_get_workspace_by_index (window->display,
+                                                 GPOINTER_TO_INT (tmp->data));
 
           if (space)
             spaces = g_slist_prepend (spaces, space);
@@ -2409,8 +2409,8 @@ meta_window_x11_client_message (MetaWindow *window,
                     window->desc, space);
 
       workspace =
-        meta_screen_get_workspace_by_index (window->screen,
-                                            space);
+        meta_display_get_workspace_by_index (window->display,
+                                             space);
 
       if (workspace)
         meta_window_change_workspace (window, workspace);


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