[mutter/wip/xwayland-on-demand: 31/32] Move workspace related code from MetaDisplay to MetaWorkspaceManager



commit 114bfc04ef3e26b6ec258b771171b3a3789076e5
Author: Armin Krezović <krezovic armin gmail com>
Date:   Sun Aug 27 21:02:40 2017 +0200

    Move workspace related code from MetaDisplay to MetaWorkspaceManager

 src/core/constraints.c                    |    8 +-
 src/core/core.c                           |   20 +-
 src/core/display-private.h                |   52 --
 src/core/display.c                        |  768 +----------------------------
 src/core/edge-resistance.c                |    8 +-
 src/core/keybindings.c                    |   34 +-
 src/core/meta-workspace-manager-private.h |   43 ++
 src/core/meta-workspace-manager.c         |  781 +++++++++++++++++++++++++++++
 src/core/stack.c                          |   25 +-
 src/core/window.c                         |  109 +++--
 src/core/workspace-private.h              |    3 +-
 src/core/workspace.c                      |   81 ++--
 src/meta/display.h                        |   24 -
 src/meta/meta-workspace-manager.h         |   22 +
 src/x11/events.c                          |   19 +-
 src/x11/meta-x11-display.c                |   68 ++--
 src/x11/window-props.c                    |    5 +-
 src/x11/window-x11.c                      |   11 +-
 18 files changed, 1085 insertions(+), 996 deletions(-)
---
diff --git a/src/core/constraints.c b/src/core/constraints.c
index 1e61d85..cf0bef0 100644
--- a/src/core/constraints.c
+++ b/src/core/constraints.c
@@ -24,6 +24,7 @@
 #include <config.h>
 #include "boxes-private.h"
 #include "constraints.h"
+#include "meta-workspace-manager-private.h"
 #include "workspace-private.h"
 #include "place.h"
 #include <meta/prefs.h>
@@ -412,7 +413,7 @@ setup_constraint_info (ConstraintInfo      *info,
                             &info->entire_monitor);
     }
 
-  cur_workspace = window->display->active_workspace;
+  cur_workspace = window->display->workspace_manager->active_workspace;
   info->usable_screen_region   =
     meta_workspace_get_onscreen_region (cur_workspace);
   info->usable_monitor_region =
@@ -499,7 +500,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->display->active_workspace;
+      cur_workspace = window->display->workspace_manager->active_workspace;
       info->usable_monitor_region =
         meta_workspace_get_onmonitor_region (cur_workspace, logical_monitor);
 
@@ -926,6 +927,7 @@ constrain_maximization (MetaWindow         *window,
                         ConstraintPriority  priority,
                         gboolean            check_only)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   MetaRectangle target_size;
   MetaRectangle min_size, max_size;
   gboolean hminbad, vminbad;
@@ -965,7 +967,7 @@ constrain_maximization (MetaWindow         *window,
         direction = META_DIRECTION_HORIZONTAL;
       else
         direction = META_DIRECTION_VERTICAL;
-      active_workspace_struts = window->display->active_workspace->all_struts;
+      active_workspace_struts = workspace_manager->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 8aeebe5..7b7f130 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -24,6 +24,7 @@
 #include <config.h>
 #include "core.h"
 #include "frame.h"
+#include "meta-workspace-manager-private.h"
 #include "workspace-private.h"
 #include <meta/prefs.h>
 #include <meta/meta-x11-errors.h>
@@ -77,6 +78,8 @@ static gboolean
 lower_window_and_transients (MetaWindow *window,
                              gpointer   data)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+
   meta_window_lower (window);
 
   meta_window_foreach_transient (window, lower_window_and_transients, NULL);
@@ -87,22 +90,22 @@ lower_window_and_transients (MetaWindow *window,
        * Do extra sanity checks to avoid possible race conditions.
        * (Borrowed from window.c.)
        */
-      if (window->display->active_workspace &&
+      if (workspace_manager->active_workspace &&
           meta_window_located_on_workspace (window,
-                                            window->display->active_workspace))
+                                            workspace_manager->active_workspace))
         {
           GList* link;
-          link = g_list_find (window->display->active_workspace->mru_list,
+          link = g_list_find (workspace_manager->active_workspace->mru_list,
                               window);
           g_assert (link);
 
-          window->display->active_workspace->mru_list =
-            g_list_remove_link (window->display->active_workspace->mru_list,
+          workspace_manager->active_workspace->mru_list =
+            g_list_remove_link (workspace_manager->active_workspace->mru_list,
                                 link);
           g_list_free (link);
 
-          window->display->active_workspace->mru_list =
-            g_list_append (window->display->active_workspace->mru_list,
+          workspace_manager->active_workspace->mru_list =
+            g_list_append (workspace_manager->active_workspace->mru_list,
                            window);
         }
     }
@@ -116,6 +119,7 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
                                   guint32  timestamp)
 {
   MetaWindow *window = get_window (xdisplay, frame_xwindow);
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
 
   lower_window_and_transients (window, NULL);
 
@@ -123,7 +127,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->display->active_workspace,
+  meta_workspace_focus_default_window (workspace_manager->active_workspace,
                                        NULL,
                                        timestamp);
 }
diff --git a/src/core/display-private.h b/src/core/display-private.h
index dca2533..dcf7b5e 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -241,16 +241,6 @@ 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;
-
   MetaBell *bell;
   MetaWorkspaceManager *workspace_manager;
 };
@@ -441,46 +431,4 @@ 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,
-                                           MetaDisplayCorner starting_corner,
-                                           gboolean          vertical_layout,
-                                           int               n_rows,
-                                           int               n_columns);
-
-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);
-
-void meta_display_update_num_workspaces (MetaDisplay *display,
-                                         guint32      timestamp,
-                                         int          new_num);
-
 #endif
diff --git a/src/core/display.c b/src/core/display.c
index 3ebfab9..6db6884 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -154,8 +154,7 @@ enum
 enum {
   PROP_0,
 
-  PROP_FOCUS_WINDOW,
-  PROP_N_WORKSPACES
+  PROP_FOCUS_WINDOW
 };
 
 static guint display_signals [LAST_SIGNAL] = { 0 };
@@ -190,9 +189,6 @@ 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;
@@ -536,14 +532,6 @@ meta_display_class_init (MetaDisplayClass *klass)
                                                         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));
-
 }
 
 
@@ -688,18 +676,6 @@ 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:
  *
@@ -763,13 +739,6 @@ 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);
@@ -793,25 +762,6 @@ meta_display_open (void)
 
   display->workspace_manager = meta_workspace_manager_new (display);
 
-  /* This is the default layout extracted from default
-   * variable values in update_num_workspaces ()
-   * This can be overriden using _NET_DESKTOP_LAYOUT in
-   * meta_x11_display_new (), if it's specified */
-  meta_display_update_workspace_layout (display,
-                                        META_DISPLAY_TOPLEFT,
-                                        FALSE,
-                                        -1,
-                                         1);
-
-  /* There must be at least one workspace at all times,
-   * so create that required workspace.
-   */
-  meta_workspace_new (display);
-
-  meta_display_init_workspaces (display);
-
-  reload_logical_monitors (display);
-
   display->startup_notification = meta_startup_notification_get (display);
   g_signal_connect (display->startup_notification, "changed",
                     G_CALLBACK (on_startup_notification_changed), display);
@@ -2561,18 +2511,6 @@ 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);
-      int new_num = meta_prefs_get_num_workspaces ();
-      meta_display_update_num_workspaces (display, timestamp, new_num);
-    }
 }
 
 void
@@ -3079,8 +3017,6 @@ on_monitors_changed (MetaMonitorManager *manager,
   MetaBackend *backend;
   MetaCursorRenderer *cursor_renderer;
 
-  reload_logical_monitors (display);
-
   /* Fix up monitor for all windows on this display */
   meta_display_foreach_window (display, META_LIST_INCLUDE_OVERRIDE_REDIRECT,
                                (MetaDisplayWindowFunc)
@@ -3657,6 +3593,7 @@ MetaWindow *
 meta_display_get_pointer_window (MetaDisplay *display,
                                  MetaWindow  *not_this_one)
 {
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
   MetaBackend *backend = meta_get_backend ();
   MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
   MetaWindow *window;
@@ -3669,7 +3606,7 @@ 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->active_workspace,
+                                                         workspace_manager->active_workspace,
                                                          not_this_one,
                                                          x, y);
 
@@ -3677,709 +3614,16 @@ meta_display_get_pointer_window (MetaDisplay *display,
 }
 
 void
-meta_display_init_workspaces (MetaDisplay *display)
-{
-  int num;
-
-  g_return_if_fail (META_IS_DISPLAY (display));
-
-  if (meta_prefs_get_dynamic_workspaces ())
-    /* This will be properly updated using _NET_NUMBER_OF_DESKTOPS
-     * (if set) in meta_x11_display_new () */
-    num = 1;
-  else
-    num = meta_prefs_get_num_workspaces ();
-
-  meta_display_update_num_workspaces (display, META_CURRENT_TIME, num);
-
-  meta_workspace_activate (display->workspaces->data, META_CURRENT_TIME);
-}
-
-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);
-
-  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)
-    g_signal_emit (display, display_signals[ACTIVE_WORKSPACE_CHANGED], 0, NULL);
-
-  for (l = next; l != NULL; 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);
-
-  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;
-}
-
-void
-meta_display_update_num_workspaces (MetaDisplay *display,
-                                    guint32      timestamp,
-                                    int          new_num)
-{
-  int old_num;
-  GList *l;
-  int i = 0;
-  GList *extras = NULL;
-  MetaWorkspace *last_remaining = NULL;
-  gboolean need_change_space = FALSE;
-
-  g_assert (new_num > 0);
-
-  if (g_list_length (display->workspaces) == (guint) new_num)
-    return;
-
-  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 ;-)
-   */
-  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_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");
-}
-
-void
-meta_display_update_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);
-
-  if (display->workspace_layout_overridden)
-    return;
-
-  display->vertical_workspaces = vertical_layout != FALSE;
-  display->starting_corner = starting_corner;
-  display->rows_of_workspaces = n_rows;
-  display->columns_of_workspaces = n_columns;
-
-  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)
-{
-  meta_display_update_workspace_layout (display,
-                                        starting_corner,
-                                        vertical_layout,
-                                        n_rows,
-                                        n_columns);
-
-  display->workspace_layout_overridden = 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;
-        }
-    }
-
-  g_signal_emit (display, display_signals[SHOWING_DESKTOP_CHANGED], 0, NULL);
-}
-
-void
-meta_display_unshow_desktop (MetaDisplay *display)
-{
-  if (!display->active_workspace->showing_desktop)
-    return;
-
-  display->active_workspace->showing_desktop = FALSE;
-
-  queue_windows_showing (display);
-
-  g_signal_emit (display, display_signals[SHOWING_DESKTOP_CHANGED], 0, NULL);
-}
-
-/**
- * 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,
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
+
+  meta_workspace_focus_default_window (workspace_manager->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);
-}
-
 MetaWorkspaceManager *
 meta_display_get_workspace_manager (MetaDisplay *display)
 {
diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c
index 786cf9f..b11faba 100644
--- a/src/core/edge-resistance.c
+++ b/src/core/edge-resistance.c
@@ -23,6 +23,7 @@
 #include "edge-resistance.h"
 #include "boxes-private.h"
 #include "display-private.h"
+#include "meta-workspace-manager-private.h"
 #include "workspace-private.h"
 
 /* A simple macro for whether a given window's edges are potentially
@@ -955,6 +956,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
    * in the layer that we are working on
    */
   GSList *rem_windows, *rem_win_stacking;
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
 
   g_assert (display->grab_window != NULL);
   meta_topic (META_DEBUG_WINDOW_OPS,
@@ -966,7 +968,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
    */
   stacked_windows =
     meta_stack_list_windows (display->stack,
-                             display->active_workspace);
+                             workspace_manager->active_workspace);
 
   /*
    * 2nd: we need to separate that stacked list into a list of windows that
@@ -1127,8 +1129,8 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
    */
   cache_edges (display,
                edges,
-               display->active_workspace->monitor_edges,
-               display->active_workspace->screen_edges);
+               workspace_manager->active_workspace->monitor_edges,
+               workspace_manager->active_workspace->screen_edges);
   g_list_free (edges);
 
   /*
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 0f4e744..e3c2242 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -29,6 +29,7 @@
 
 #include <config.h>
 #include "keybindings-private.h"
+#include "meta-workspace-manager-private.h"
 #include "workspace-private.h"
 #include <meta/compositor.h>
 #include <meta/meta-x11-errors.h>
@@ -2540,8 +2541,9 @@ handle_switch_to_last_workspace (MetaDisplay     *display,
                                  MetaKeyBinding *binding,
                                  gpointer        dummy)
 {
-    gint target = meta_display_get_n_workspaces(display) - 1;
-    MetaWorkspace *workspace = meta_display_get_workspace_by_index (display, target);
+    MetaWorkspaceManager *workspace_manager = display->workspace_manager;
+    gint target = meta_workspace_manager_get_n_workspaces (workspace_manager) - 1;
+    MetaWorkspace *workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, target);
     meta_workspace_activate (workspace, event->time);
 }
 
@@ -2553,6 +2555,7 @@ handle_switch_to_workspace (MetaDisplay     *display,
                             gpointer         dummy)
 {
   gint which = binding->handler->data;
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
   MetaWorkspace *workspace;
 
   if (which < 0)
@@ -2561,12 +2564,12 @@ handle_switch_to_workspace (MetaDisplay     *display,
        * current workspace.
        */
 
-      workspace = meta_workspace_get_neighbor (display->active_workspace,
+      workspace = meta_workspace_get_neighbor (workspace_manager->active_workspace,
                                                which);
     }
   else
     {
-      workspace = meta_display_get_workspace_by_index (display, which);
+      workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which);
     }
 
   if (workspace)
@@ -2789,15 +2792,17 @@ handle_show_desktop (MetaDisplay     *display,
                      MetaKeyBinding  *binding,
                      gpointer         dummy)
 {
-  if (display->active_workspace->showing_desktop)
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
+
+  if (workspace_manager->active_workspace->showing_desktop)
     {
-      meta_display_unshow_desktop (display);
-      meta_workspace_focus_default_window (display->active_workspace,
+      meta_workspace_manager_unshow_desktop (workspace_manager);
+      meta_workspace_focus_default_window (workspace_manager->active_workspace,
                                            NULL,
                                            event->time);
     }
   else
-    meta_display_show_desktop (display, event->time);
+    meta_workspace_manager_show_desktop (workspace_manager, event->time);
 }
 
 static void
@@ -2884,6 +2889,7 @@ do_choose_window (MetaDisplay     *display,
                   MetaKeyBinding  *binding,
                   gboolean         backward)
 {
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
   MetaTabList type = binding->handler->data;
   MetaWindow *window;
 
@@ -2892,7 +2898,7 @@ do_choose_window (MetaDisplay     *display,
 
   window = meta_display_get_tab_next (display,
                                       type,
-                                      display->active_workspace,
+                                      workspace_manager->active_workspace,
                                       NULL,
                                       backward);
 
@@ -3107,14 +3113,15 @@ handle_move_to_workspace_last (MetaDisplay     *display,
                                MetaKeyBinding  *binding,
                                gpointer         dummy)
 {
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
   gint which;
   MetaWorkspace *workspace;
 
   if (window->always_sticky)
     return;
 
-  which = meta_display_get_n_workspaces (display) - 1;
-  workspace = meta_display_get_workspace_by_index (display, which);
+  which = meta_workspace_manager_get_n_workspaces (workspace_manager) - 1;
+  workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which);
   meta_window_change_workspace (window, workspace);
 }
 
@@ -3126,6 +3133,7 @@ handle_move_to_workspace  (MetaDisplay     *display,
                            MetaKeyBinding  *binding,
                            gpointer         dummy)
 {
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
   gint which = binding->handler->data;
   gboolean flip = (which < 0);
   MetaWorkspace *workspace;
@@ -3144,12 +3152,12 @@ handle_move_to_workspace  (MetaDisplay     *display,
   workspace = NULL;
   if (flip)
     {
-      workspace = meta_workspace_get_neighbor (display->active_workspace,
+      workspace = meta_workspace_get_neighbor (workspace_manager->active_workspace,
                                                which);
     }
   else
     {
-      workspace = meta_display_get_workspace_by_index (display, which);
+      workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which);
     }
 
   if (workspace)
diff --git a/src/core/meta-workspace-manager-private.h b/src/core/meta-workspace-manager-private.h
index 1dafa50..130fe9d 100644
--- a/src/core/meta-workspace-manager-private.h
+++ b/src/core/meta-workspace-manager-private.h
@@ -48,4 +48,47 @@ struct _MetaWorkspaceManager
 
 MetaWorkspaceManager *meta_workspace_manager_new (MetaDisplay *display);
 
+void meta_workspace_manager_init_workspaces         (MetaWorkspaceManager *workspace_manager);
+void meta_workspace_manager_update_workspace_layout (MetaWorkspaceManager *workspace_manager,
+                                                     MetaDisplayCorner     starting_corner,
+                                                     gboolean              vertical_layout,
+                                                     int                   n_rows,
+                                                     int                   n_columns);
+
+typedef struct MetaWorkspaceLayout MetaWorkspaceLayout;
+
+struct MetaWorkspaceLayout
+{
+  int rows;
+  int cols;
+  int *grid;
+  int grid_area;
+  int current_row;
+  int current_col;
+};
+
+void meta_workspace_manager_calc_workspace_layout (MetaWorkspaceManager *workspace_manager,
+                                                   int                   num_workspaces,
+                                                   int                   current_space,
+                                                   MetaWorkspaceLayout  *layout);
+
+void meta_workspace_manager_free_workspace_layout (MetaWorkspaceLayout *layout);
+
+void meta_workspace_manager_minimize_all_on_active_workspace_except (MetaWorkspaceManager *workspace_manager,
+                                                                     MetaWindow           *keep);
+
+/* Show/hide the desktop (temporarily hide all windows) */
+void meta_workspace_manager_show_desktop   (MetaWorkspaceManager *workspace_manager,
+                                            guint32               timestamp);
+void meta_workspace_manager_unshow_desktop (MetaWorkspaceManager *workspace_manager);
+
+void meta_workspace_manager_workspace_switched (MetaWorkspaceManager *workspace_manager,
+                                                int                   from,
+                                                int                   to,
+                                                MetaMotionDirection   direction);
+
+void meta_workspace_manager_update_num_workspaces (MetaWorkspaceManager *workspace_manager,
+                                                   guint32               timestamp,
+                                                   int                   new_num);
+
 #endif /* META_WORKSPACE_MANAGER_PRIVATE_H */
diff --git a/src/core/meta-workspace-manager.c b/src/core/meta-workspace-manager.c
index 0521337..7104554 100644
--- a/src/core/meta-workspace-manager.c
+++ b/src/core/meta-workspace-manager.c
@@ -28,7 +28,14 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "backends/meta-backend-private.h"
+
+#include "core/window-private.h"
+#include "core/workspace-private.h"
+
 #include "meta/meta-enum-types.h"
+#include "meta/prefs.h"
+#include "meta/util.h"
 
 G_DEFINE_TYPE (MetaWorkspaceManager, meta_workspace_manager, G_TYPE_OBJECT)
 
@@ -50,6 +57,9 @@ enum {
 
 static guint workspace_manager_signals [LAST_SIGNAL] = { 0 };
 
+static void prefs_changed_callback (MetaPreference pref,
+                                    void          *data);
+
 static void
 meta_workspace_manager_get_property (GObject    *object,
                                      guint       prop_id,
@@ -84,6 +94,16 @@ meta_workspace_manager_set_property (GObject      *object,
 }
 
 static void
+meta_workspace_manager_finalize (GObject *object)
+{
+  MetaWorkspaceManager *workspace_manager = META_WORKSPACE_MANAGER (object);
+
+  meta_prefs_remove_listener (prefs_changed_callback, workspace_manager);
+
+  G_OBJECT_CLASS (meta_workspace_manager_parent_class)->finalize (object);
+}
+
+static void
 meta_workspace_manager_class_init (MetaWorkspaceManagerClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -91,6 +111,8 @@ meta_workspace_manager_class_init (MetaWorkspaceManagerClass *klass)
   object_class->get_property = meta_workspace_manager_get_property;
   object_class->set_property = meta_workspace_manager_set_property;
 
+  object_class->finalize = meta_workspace_manager_finalize;
+
   workspace_manager_signals[WORKSPACE_ADDED] =
     g_signal_new ("workspace-added",
                   G_TYPE_FROM_CLASS (klass),
@@ -133,6 +155,14 @@ meta_workspace_manager_class_init (MetaWorkspaceManagerClass *klass)
                   G_SIGNAL_RUN_LAST,
                   0, NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
+
+  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));
 }
 
 static void
@@ -140,10 +170,25 @@ meta_workspace_manager_init (MetaWorkspaceManager *workspace_manager)
 {
 }
 
+static void
+reload_logical_monitors (MetaWorkspaceManager *workspace_manager)
+{
+  GList *l;
+
+  for (l = workspace_manager->workspaces; l != NULL; l = l->next)
+    {
+      MetaWorkspace *space = l->data;
+      meta_workspace_invalidate_work_area (space);
+    }
+}
+
 MetaWorkspaceManager *
 meta_workspace_manager_new (MetaDisplay *display)
 {
   MetaWorkspaceManager *workspace_manager;
+  MetaBackend *backend = meta_get_backend ();
+  MetaMonitorManager *monitor_manager
+    = meta_backend_get_monitor_manager (backend);
 
   workspace_manager = g_object_new (META_TYPE_WORKSPACE_MANAGER, NULL);
 
@@ -155,11 +200,747 @@ meta_workspace_manager_new (MetaDisplay *display)
   workspace_manager->vertical_workspaces = FALSE;
   workspace_manager->starting_corner = META_DISPLAY_TOPLEFT;
 
+  /* This is the default layout extracted from default
+   * variable values in update_num_workspaces ()
+   * This can be overriden using _NET_DESKTOP_LAYOUT in
+   * meta_x11_display_new (), if it's specified */
+  meta_workspace_manager_update_workspace_layout (workspace_manager,
+                                                  META_DISPLAY_TOPLEFT,
+                                                  FALSE,
+                                                  -1,
+                                                  1);
+
+  /* There must be at least one workspace at all times,
+   * so create that required workspace.
+   */
+  meta_workspace_new (workspace_manager);
+
+  meta_workspace_manager_init_workspaces (workspace_manager);
+
+  reload_logical_monitors (workspace_manager);
+
+  g_signal_connect_object (monitor_manager,
+                           "monitors-changed",
+                           G_CALLBACK (reload_logical_monitors),
+                           workspace_manager,
+                           G_CONNECT_SWAPPED);
+
+  meta_prefs_add_listener (prefs_changed_callback, workspace_manager);
+
   return workspace_manager;
 }
 
+void
+meta_workspace_manager_init_workspaces (MetaWorkspaceManager *workspace_manager)
+{
+  int num;
+
+  g_return_if_fail (META_IS_WORKSPACE_MANAGER (workspace_manager));
+
+  if (meta_prefs_get_dynamic_workspaces ())
+    /* This will be properly updated using _NET_NUMBER_OF_DESKTOPS
+     * (if set) in meta_x11_display_new () */
+    num = 1;
+  else
+    num = meta_prefs_get_num_workspaces ();
+
+  meta_workspace_manager_update_num_workspaces (workspace_manager, META_CURRENT_TIME, num);
+
+  meta_workspace_activate (workspace_manager->workspaces->data, META_CURRENT_TIME);
+}
+
 int
 meta_workspace_manager_get_n_workspaces (MetaWorkspaceManager *workspace_manager)
 {
   return g_list_length (workspace_manager->workspaces);
 }
+
+/**
+ * meta_workspace_manager_get_workspace_by_index:
+ * @workspace_manager: a #MetaWorkspaceManager
+ * @index: index of one of the display's workspaces
+ *
+ * Gets the workspace object for one of a workspace manager'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_workspace_manager_get_workspace_by_index (MetaWorkspaceManager *workspace_manager,
+                                               int                   idx)
+{
+  return g_list_nth_data (workspace_manager->workspaces, idx);
+}
+
+void
+meta_workspace_manager_remove_workspace (MetaWorkspaceManager *workspace_manager,
+                                         MetaWorkspace        *workspace,
+                                         guint32               timestamp)
+{
+  GList         *l;
+  GList         *next;
+  MetaWorkspace *neighbour = NULL;
+  int            index;
+  gboolean       active_index_changed;
+  int            new_num;
+
+  l = g_list_find (workspace_manager->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 == workspace_manager->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_workspace_manager_get_active_workspace_index (workspace_manager);
+
+  /* This also removes the workspace from the displays list */
+  meta_workspace_remove (workspace);
+
+  new_num = g_list_length (workspace_manager->workspaces);
+
+  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)
+    g_signal_emit (workspace_manager, workspace_manager_signals[ACTIVE_WORKSPACE_CHANGED], 0, NULL);
+
+  for (l = next; l != NULL; l = l->next)
+    {
+      MetaWorkspace *w = l->data;
+      meta_workspace_index_changed (w);
+    }
+
+  meta_display_queue_workarea_recalc (workspace_manager->display);
+
+  g_signal_emit (workspace_manager, workspace_manager_signals[WORKSPACE_REMOVED], 0, index);
+  g_object_notify (G_OBJECT (workspace_manager), "n-workspaces");
+}
+
+/**
+ * meta_workspace_manager_append_new_workspace:
+ * @workspace_manager: a #MetaWorkspaceManager
+ * @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 workspace manager and (optionally) switch to that
+ * display.
+ *
+ * Return value: (transfer none): the newly appended workspace.
+ */
+MetaWorkspace *
+meta_workspace_manager_append_new_workspace (MetaWorkspaceManager *workspace_manager,
+                                             gboolean              activate,
+                                             guint32               timestamp)
+{
+  MetaWorkspace *w;
+  int new_num;
+
+  /* This also adds the workspace to the workspace manager list */
+  w = meta_workspace_new (workspace_manager);
+
+  if (!w)
+    return NULL;
+
+  if (activate)
+    meta_workspace_activate (w, timestamp);
+
+  new_num = g_list_length (workspace_manager->workspaces);
+
+  if (!meta_prefs_get_dynamic_workspaces ())
+    meta_prefs_set_num_workspaces (new_num);
+
+  meta_display_queue_workarea_recalc (workspace_manager->display);
+
+  g_signal_emit (workspace_manager, workspace_manager_signals[WORKSPACE_ADDED],
+                 0, meta_workspace_index (w));
+  g_object_notify (G_OBJECT (workspace_manager), "n-workspaces");
+
+  return w;
+}
+
+void
+meta_workspace_manager_update_num_workspaces (MetaWorkspaceManager *workspace_manager,
+                                              guint32               timestamp,
+                                              int                   new_num)
+{
+  int old_num;
+  GList *l;
+  int i = 0;
+  GList *extras = NULL;
+  MetaWorkspace *last_remaining = NULL;
+  gboolean need_change_space = FALSE;
+
+  g_assert (new_num > 0);
+
+  if (g_list_length (workspace_manager->workspaces) == (guint) new_num)
+    return;
+
+  for (l = workspace_manager->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 ;-)
+   */
+  for (l = extras; l != NULL; l = l->next)
+    {
+      MetaWorkspace *w = l->data;
+
+      meta_workspace_relocate_windows (w, last_remaining);
+
+      if (w == workspace_manager->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 (workspace_manager);
+
+  meta_display_queue_workarea_recalc (workspace_manager->display);
+
+  for (i = old_num; i < new_num; i++)
+    g_signal_emit (workspace_manager, workspace_manager_signals[WORKSPACE_ADDED], 0, i);
+
+  g_object_notify (G_OBJECT (workspace_manager), "n-workspaces");
+}
+
+void
+meta_workspace_manager_update_workspace_layout (MetaWorkspaceManager *workspace_manager,
+                                                MetaDisplayCorner     starting_corner,
+                                                gboolean              vertical_layout,
+                                                int                   n_rows,
+                                                int                   n_columns)
+{
+  g_return_if_fail (META_IS_WORKSPACE_MANAGER (workspace_manager));
+  g_return_if_fail (n_rows > 0 || n_columns > 0);
+  g_return_if_fail (n_rows != 0 && n_columns != 0);
+
+  if (workspace_manager->workspace_layout_overridden)
+    return;
+
+  workspace_manager->vertical_workspaces = vertical_layout != FALSE;
+  workspace_manager->starting_corner = starting_corner;
+  workspace_manager->rows_of_workspaces = n_rows;
+  workspace_manager->columns_of_workspaces = n_columns;
+
+  meta_verbose ("Workspace layout rows = %d cols = %d orientation = %d starting corner = %u\n",
+                workspace_manager->rows_of_workspaces,
+                workspace_manager->columns_of_workspaces,
+                workspace_manager->vertical_workspaces,
+                workspace_manager->starting_corner);
+}
+
+/**
+ * meta_workspace_manager_override_workspace_layout:
+ * @workspace_manager: a #MetaWorkspaceManager
+ * @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_workspace_manager_override_workspace_layout (MetaWorkspaceManager *workspace_manager,
+                                                  MetaDisplayCorner     starting_corner,
+                                                  gboolean              vertical_layout,
+                                                  int                   n_rows,
+                                                  int                   n_columns)
+{
+  meta_workspace_manager_update_workspace_layout (workspace_manager,
+                                                  starting_corner,
+                                                  vertical_layout,
+                                                  n_rows,
+                                                  n_columns);
+
+  workspace_manager->workspace_layout_overridden = TRUE;
+}
+
+#ifdef WITH_VERBOSE_MODE
+static const char *
+meta_workspace_manager_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_workspace_manager_calc_workspace_layout (MetaWorkspaceManager *workspace_manager,
+                                              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 = workspace_manager->rows_of_workspaces;
+  cols = workspace_manager->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,
+                workspace_manager->vertical_workspaces ? "(true)" : "(false)",
+                meta_workspace_manager_corner_to_string (workspace_manager->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 (workspace_manager->starting_corner)
+    {
+    case META_DISPLAY_TOPLEFT:
+      if (workspace_manager->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 (workspace_manager->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 (workspace_manager->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 (workspace_manager->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_workspace_manager_free_workspace_layout (MetaWorkspaceLayout *layout)
+{
+  g_free (layout->grid);
+}
+
+static void
+queue_windows_showing (MetaWorkspaceManager *workspace_manager)
+{
+  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 (workspace_manager->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_workspace_manager_minimize_all_on_active_workspace_except (MetaWorkspaceManager *workspace_manager,
+                                                                MetaWindow           *keep)
+{
+  GList *l;
+
+  for (l = workspace_manager->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_workspace_manager_show_desktop (MetaWorkspaceManager *workspace_manager,
+                                     guint32               timestamp)
+{
+  GList *l;
+
+  if (workspace_manager->active_workspace->showing_desktop)
+    return;
+
+  workspace_manager->active_workspace->showing_desktop = TRUE;
+
+  queue_windows_showing (workspace_manager);
+
+  /* Focus the most recently used META_WINDOW_DESKTOP window, if there is one;
+   * see bug 159257.
+   */
+  for (l = workspace_manager->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;
+        }
+    }
+
+  g_signal_emit (workspace_manager, workspace_manager_signals[SHOWING_DESKTOP_CHANGED], 0, NULL);
+}
+
+void
+meta_workspace_manager_unshow_desktop (MetaWorkspaceManager *workspace_manager)
+{
+  if (!workspace_manager->active_workspace->showing_desktop)
+    return;
+
+  workspace_manager->active_workspace->showing_desktop = FALSE;
+
+  queue_windows_showing (workspace_manager);
+
+  g_signal_emit (workspace_manager, workspace_manager_signals[SHOWING_DESKTOP_CHANGED], 0, NULL);
+}
+
+/**
+ * meta_workspace_manager_get_workspaces: (skip)
+ * @workspace_manager: a #MetaWorkspaceManager
+ *
+ * Returns: (transfer none) (element-type Meta.Workspace): The workspaces for @display
+ */
+GList *
+meta_workspace_manager_get_workspaces (MetaWorkspaceManager *workspace_manager)
+{
+  return workspace_manager->workspaces;
+}
+
+int
+meta_workspace_manager_get_active_workspace_index (MetaWorkspaceManager *workspace_manager)
+{
+  MetaWorkspace *active = workspace_manager->active_workspace;
+
+  if (!active)
+    return -1;
+
+  return meta_workspace_index (active);
+}
+
+/**
+ * meta_workspace_manager_get_active_workspace:
+ * @workspace_manager: A #MetaWorkspaceManager
+ *
+ * Returns: (transfer none): The current workspace
+ */
+MetaWorkspace *
+meta_workspace_manager_get_active_workspace (MetaWorkspaceManager *workspace_manager)
+{
+  return workspace_manager->active_workspace;
+}
+
+void 
+meta_workspace_manager_workspace_switched (MetaWorkspaceManager *workspace_manager,
+                                           int                   from,
+                                           int                   to,
+                                           MetaMotionDirection   direction)
+{
+  g_signal_emit (workspace_manager, workspace_manager_signals[WORKSPACE_SWITCHED], 0,
+                 from, to, direction);
+}
+
+static void
+prefs_changed_callback (MetaPreference pref,
+                        void          *data)
+{
+  MetaWorkspaceManager *workspace_manager = 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 (workspace_manager->display);
+      int new_num = meta_prefs_get_num_workspaces ();
+      meta_workspace_manager_update_num_workspaces (workspace_manager, timestamp, new_num);
+    }
+}
diff --git a/src/core/stack.c b/src/core/stack.c
index dffce9a..1bc117b 100644
--- a/src/core/stack.c
+++ b/src/core/stack.c
@@ -27,6 +27,7 @@
 
 #include <config.h>
 #include "stack.h"
+#include "meta-workspace-manager-private.h"
 #include "window-private.h"
 #include <meta/meta-x11-errors.h>
 #include "frame.h"
@@ -103,6 +104,8 @@ void
 meta_stack_add (MetaStack  *stack,
                 MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+
   g_return_if_fail (!window->override_redirect);
 
   meta_topic (META_DEBUG_STACK, "Adding window %s to the stack\n", window->desc);
@@ -119,13 +122,15 @@ meta_stack_add (MetaStack  *stack,
               window->desc, window->stack_position);
 
   stack_sync_to_xserver (stack);
-  meta_stack_update_window_tile_matches (stack, window->display->active_workspace);
+  meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
 }
 
 void
 meta_stack_remove (MetaStack  *stack,
                    MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+
   meta_topic (META_DEBUG_STACK, "Removing window %s from the stack\n", window->desc);
 
   if (window->stack_position < 0)
@@ -159,27 +164,29 @@ meta_stack_remove (MetaStack  *stack,
     }
 
   stack_sync_to_xserver (stack);
-  meta_stack_update_window_tile_matches (stack, window->display->active_workspace);
+  meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
 }
 
 void
 meta_stack_update_layer (MetaStack  *stack,
                          MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   stack->need_relayer = TRUE;
 
   stack_sync_to_xserver (stack);
-  meta_stack_update_window_tile_matches (stack, window->display->active_workspace);
+  meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
 }
 
 void
 meta_stack_update_transient (MetaStack  *stack,
                              MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   stack->need_constrain = TRUE;
 
   stack_sync_to_xserver (stack);
-  meta_stack_update_window_tile_matches (stack, window->display->active_workspace);
+  meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
 }
 
 /* raise/lower within a layer */
@@ -187,6 +194,7 @@ void
 meta_stack_raise (MetaStack  *stack,
                   MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   GList *l;
   int max_stack_position = window->stack_position;
   MetaWorkspace *workspace;
@@ -208,13 +216,14 @@ 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->display->active_workspace);
+  meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
 }
 
 void
 meta_stack_lower (MetaStack  *stack,
                   MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   GList *l;
   int min_stack_position = window->stack_position;
   MetaWorkspace *workspace;
@@ -236,7 +245,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->display->active_workspace);
+  meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
 }
 
 void
@@ -1463,8 +1472,10 @@ void
 meta_window_set_stack_position (MetaWindow *window,
                                 int         position)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+
   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->display->active_workspace);
+                                         workspace_manager->active_workspace);
 }
diff --git a/src/core/window.c b/src/core/window.c
index 5662f66..863c170 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -33,6 +33,7 @@
 #include "util-private.h"
 #include "frame.h"
 #include <meta/meta-x11-errors.h>
+#include "meta-workspace-manager-private.h"
 #include "workspace-private.h"
 #include "stack.h"
 #include "keybindings-private.h"
@@ -680,9 +681,10 @@ is_desktop_or_dock_foreach (MetaWindow *window,
 static void
 maybe_leave_show_desktop_mode (MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   gboolean is_desktop_or_dock;
 
-  if (!window->display->active_workspace->showing_desktop)
+  if (!workspace_manager->active_workspace->showing_desktop)
     return;
 
   /* If the window is a transient for the dock or desktop, don't
@@ -699,9 +701,9 @@ maybe_leave_show_desktop_mode (MetaWindow *window)
 
   if (!is_desktop_or_dock)
     {
-      meta_display_minimize_all_on_active_workspace_except (window->display,
-                                                            window);
-      meta_display_unshow_desktop (window->display);
+      meta_workspace_manager_minimize_all_on_active_workspace_except (workspace_manager,
+                                                                      window);
+      meta_workspace_manager_unshow_desktop (workspace_manager);
     }
 }
 
@@ -853,6 +855,7 @@ _meta_window_shared_new (MetaDisplay         *display,
                          MetaCompEffect       effect,
                          XWindowAttributes   *attrs)
 {
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
   MetaWindow *window;
 
   g_assert (attrs != NULL);
@@ -1156,8 +1159,8 @@ _meta_window_shared_new (MetaDisplay         *display,
                       "Window %s is initially on space %d\n",
                       window->desc, window->initial_workspace);
 
-          workspace = meta_display_get_workspace_by_index (window->display,
-                                                           window->initial_workspace);
+          workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager,
+                                                                     window->initial_workspace);
         }
 
       set_workspace_state (window, on_all_workspaces, workspace);
@@ -1196,7 +1199,7 @@ _meta_window_shared_new (MetaDisplay         *display,
                       "Putting window %s on active workspace\n",
                       window->desc);
 
-          set_workspace_state (window, FALSE, window->display->active_workspace);
+          set_workspace_state (window, FALSE, workspace_manager->active_workspace);
         }
 
       meta_window_update_struts (window);
@@ -1296,6 +1299,7 @@ void
 meta_window_unmanage (MetaWindow  *window,
                       guint32      timestamp)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   GList *tmp;
 
   meta_verbose ("Unmanaging %s\n", window->desc);
@@ -1382,7 +1386,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->display->active_workspace, NULL, timestamp);
+      meta_workspace_focus_default_window (workspace_manager->active_workspace, NULL, timestamp);
     }
   else
     {
@@ -1428,7 +1432,7 @@ meta_window_unmanage (MetaWindow  *window,
   g_assert (window->workspace == NULL);
 
 #ifndef G_DISABLE_CHECKS
-  tmp = window->display->workspaces;
+  tmp = workspace_manager->workspaces;
   while (tmp != NULL)
     {
       MetaWorkspace *workspace = tmp->data;
@@ -1540,6 +1544,7 @@ ancestor_is_minimized (MetaWindow *window)
 gboolean
 meta_window_showing_on_its_workspace (MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   gboolean showing;
   gboolean is_desktop_or_dock;
   MetaWorkspace* workspace_of_window;
@@ -1559,7 +1564,7 @@ meta_window_showing_on_its_workspace (MetaWindow *window)
                                 &is_desktop_or_dock);
 
   if (window->on_all_workspaces)
-    workspace_of_window = window->display->active_workspace;
+    workspace_of_window = workspace_manager->active_workspace;
   else if (window->workspace)
     workspace_of_window = window->workspace;
   else /* This only seems to be needed for startup */
@@ -1591,6 +1596,8 @@ meta_window_showing_on_its_workspace (MetaWindow *window)
 gboolean
 meta_window_should_be_showing (MetaWindow  *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+
 #ifdef HAVE_WAYLAND
   if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
       !meta_wayland_surface_get_buffer (window->surface))
@@ -1599,7 +1606,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->display->active_workspace) &&
+  return (meta_window_located_on_workspace (window, workspace_manager->active_workspace) &&
           meta_window_showing_on_its_workspace (window));
 }
 
@@ -2451,6 +2458,7 @@ meta_window_show (MetaWindow *window)
 static void
 meta_window_hide (MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   gboolean did_hide;
 
   meta_topic (META_DEBUG_WINDOW_STATE,
@@ -2521,11 +2529,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->display->active_workspace &&
+      if (my_workspace == workspace_manager->active_workspace &&
           !my_workspace->showing_desktop)
         not_this_one = window;
 
-      meta_workspace_focus_default_window (window->display->active_workspace,
+      meta_workspace_focus_default_window (workspace_manager->active_workspace,
                                            not_this_one,
                                            timestamp);
     }
@@ -3364,6 +3372,7 @@ meta_window_activate_full (MetaWindow     *window,
                            MetaClientType  source_indication,
                            MetaWorkspace  *workspace)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   gboolean allow_workspace_switch;
   meta_topic (META_DEBUG_FOCUS,
               "_NET_ACTIVE_WINDOW message sent for %s at time %u "
@@ -3392,7 +3401,7 @@ meta_window_activate_full (MetaWindow     *window,
 
   /* Get window on current or given workspace */
   if (workspace == NULL)
-    workspace = window->display->active_workspace;
+    workspace = workspace_manager->active_workspace;
 
   /* For non-transient windows, we just set up a pulsing indicator,
      rather than move windows or workspaces.
@@ -3590,6 +3599,7 @@ void
 meta_window_update_monitor (MetaWindow *window,
                             gboolean    user_op)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   const MetaLogicalMonitor *old;
 
   old = window->monitor;
@@ -3609,8 +3619,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->display->active_workspace != window->workspace)
-        meta_window_change_workspace (window, window->display->active_workspace);
+          workspace_manager->active_workspace != window->workspace)
+        meta_window_change_workspace (window, workspace_manager->active_workspace);
 
       meta_window_main_monitor_changed (window, old);
 
@@ -3645,6 +3655,7 @@ meta_window_move_resize_internal (MetaWindow          *window,
    * to the client.
    */
 
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   gboolean did_placement;
   guint old_output_winsys_id;
   MetaRectangle unconstrained_rect;
@@ -3767,7 +3778,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->display->active_workspace);
+                                         workspace_manager->active_workspace);
 }
 
 /**
@@ -4309,6 +4320,7 @@ void
 meta_window_focus (MetaWindow  *window,
                    guint32      timestamp)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   MetaWindow *modal_transient;
 
   g_return_if_fail (!window->override_redirect);
@@ -4335,8 +4347,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->display->active_workspace))
-        meta_window_change_workspace (modal_transient, window->display->active_workspace);
+      if (!meta_window_located_on_workspace (modal_transient, workspace_manager->active_workspace))
+        meta_window_change_workspace (modal_transient, workspace_manager->active_workspace);
       window = modal_transient;
     }
 
@@ -4386,6 +4398,8 @@ set_workspace_state (MetaWindow    *window,
                      gboolean       on_all_workspaces,
                      MetaWorkspace *workspace)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+
   /* If we're on all workspaces, then our new workspace must be NULL. */
   if (on_all_workspaces)
     g_assert (workspace == NULL);
@@ -4407,7 +4421,7 @@ set_workspace_state (MetaWindow    *window,
   else if (window->on_all_workspaces)
     {
       GList *l;
-      for (l = window->display->workspaces; l != NULL; l = l->next)
+      for (l = workspace_manager->workspaces; l != NULL; l = l->next)
         {
           MetaWorkspace *ws = l->data;
           meta_workspace_remove_window (ws, window);
@@ -4422,7 +4436,7 @@ set_workspace_state (MetaWindow    *window,
   else if (window->on_all_workspaces)
     {
       GList *l;
-      for (l = window->display->workspaces; l != NULL; l = l->next)
+      for (l = workspace_manager->workspaces; l != NULL; l = l->next)
         {
           MetaWorkspace *ws = l->data;
           meta_workspace_add_window (ws, window);
@@ -4455,6 +4469,7 @@ should_be_on_all_workspaces (MetaWindow *window)
 void
 meta_window_on_all_workspaces_changed (MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   gboolean on_all_workspaces = should_be_on_all_workspaces (window);
 
   if (window->on_all_workspaces == on_all_workspaces)
@@ -4470,7 +4485,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->display->active_workspace;
+      workspace = workspace_manager->active_workspace;
     }
 
   set_workspace_state (window, on_all_workspaces, workspace);
@@ -4691,6 +4706,7 @@ meta_window_change_workspace_by_index (MetaWindow *window,
                                        gint        space_index,
                                        gboolean    append)
 {
+  MetaWorkspaceManager *workspace_manager;
   MetaWorkspace *workspace;
   MetaDisplay   *display;
 
@@ -4703,12 +4719,13 @@ meta_window_change_workspace_by_index (MetaWindow *window,
     }
 
   display = window->display;
+  workspace_manager = display->workspace_manager;
 
   workspace =
-    meta_display_get_workspace_by_index (display, space_index);
+    meta_workspace_manager_get_workspace_by_index (workspace_manager, space_index);
 
   if (!workspace && append)
-    workspace = meta_display_append_new_workspace (display, FALSE, META_CURRENT_TIME);
+    workspace = meta_workspace_manager_append_new_workspace (workspace_manager, FALSE, META_CURRENT_TIME);
 
   if (workspace)
     meta_window_change_workspace (window, workspace);
@@ -4808,6 +4825,8 @@ void
 meta_window_set_focused_internal (MetaWindow *window,
                                   gboolean    focused)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+
   if (focused)
     {
       window->has_focus = TRUE;
@@ -4822,22 +4841,22 @@ meta_window_set_focused_internal (MetaWindow *window,
        * list only if the window is actually on the active
        * workspace.
        */
-      if (window->display->active_workspace &&
+      if (workspace_manager->active_workspace &&
           meta_window_located_on_workspace (window,
-                                            window->display->active_workspace))
+                                            workspace_manager->active_workspace))
         {
           GList* link;
-          link = g_list_find (window->display->active_workspace->mru_list,
+          link = g_list_find (workspace_manager->active_workspace->mru_list,
                               window);
           g_assert (link);
 
-          window->display->active_workspace->mru_list =
-            g_list_remove_link (window->display->active_workspace->mru_list,
+          workspace_manager->active_workspace->mru_list =
+            g_list_remove_link (workspace_manager->active_workspace->mru_list,
                                 link);
           g_list_free (link);
 
-          window->display->active_workspace->mru_list =
-            g_list_prepend (window->display->active_workspace->mru_list,
+          workspace_manager->active_workspace->mru_list =
+            g_list_prepend (workspace_manager->active_workspace->mru_list,
                             window);
         }
 
@@ -5080,8 +5099,10 @@ idle_update_icon (gpointer data)
 GList*
 meta_window_get_workspaces (MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+
   if (window->on_all_workspaces)
-    return window->display->workspaces;
+    return workspace_manager->workspaces;
   else if (window->workspace != NULL)
     return window->workspace->list_containing_self;
   else if (window->constructing)
@@ -5438,6 +5459,7 @@ meta_window_show_menu_for_rect (MetaWindow         *window,
 void
 meta_window_shove_titlebar_onscreen (MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   MetaRectangle  frame_rect;
   GList         *onscreen_region;
   int            horiz_amount, vert_amount;
@@ -5450,7 +5472,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->display->active_workspace->screen_region;
+  onscreen_region = workspace_manager->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
@@ -5478,6 +5500,7 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window)
 gboolean
 meta_window_titlebar_is_onscreen (MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   MetaRectangle  titlebar_rect, frame_rect;
   GList         *onscreen_region;
   gboolean       is_onscreen;
@@ -5502,7 +5525,7 @@ meta_window_titlebar_is_onscreen (MetaWindow *window)
    * them overlaps with the titlebar sufficiently to consider it onscreen.
    */
   is_onscreen = FALSE;
-  onscreen_region = window->display->active_workspace->screen_region;
+  onscreen_region = workspace_manager->active_workspace->screen_region;
   while (onscreen_region)
     {
       MetaRectangle *spanning_rect = onscreen_region->data;
@@ -6574,11 +6597,12 @@ ensure_mru_position_after (MetaWindow *window,
    * map.
    */
 
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   GList* active_mru_list;
   GList* window_position;
   GList* after_this_one_position;
 
-  active_mru_list         = window->display->active_workspace->mru_list;
+  active_mru_list         = workspace_manager->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);
 
@@ -6591,12 +6615,12 @@ ensure_mru_position_after (MetaWindow *window,
 
   if (g_list_length (window_position) > g_list_length (after_this_one_position))
     {
-      window->display->active_workspace->mru_list =
-        g_list_delete_link (window->display->active_workspace->mru_list,
+      workspace_manager->active_workspace->mru_list =
+        g_list_delete_link (workspace_manager->active_workspace->mru_list,
                             window_position);
 
-      window->display->active_workspace->mru_list =
-        g_list_insert_before (window->display->active_workspace->mru_list,
+      workspace_manager->active_workspace->mru_list =
+        g_list_insert_before (workspace_manager->active_workspace->mru_list,
                               after_this_one_position->next,
                               window);
     }
@@ -6714,12 +6738,13 @@ meta_window_get_stable_sequence (MetaWindow *window)
 void
 meta_window_set_demands_attention (MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   MetaRectangle candidate_rect, other_rect;
   GList *stack = window->display->stack->sorted;
   MetaWindow *other_window;
   gboolean obscured = FALSE;
 
-  MetaWorkspace *workspace = window->display->active_workspace;
+  MetaWorkspace *workspace = workspace_manager->active_workspace;
 
   if (window->wm_state_demands_attention)
     return;
@@ -6905,8 +6930,10 @@ meta_window_get_window_type (MetaWindow *window)
 MetaWorkspace *
 meta_window_get_workspace (MetaWindow *window)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
+
   if (window->on_all_workspaces)
-    return window->display->active_workspace;
+    return workspace_manager->active_workspace;
   else
     return window->workspace;
 }
diff --git a/src/core/workspace-private.h b/src/core/workspace-private.h
index f63be95..35d0e70 100644
--- a/src/core/workspace-private.h
+++ b/src/core/workspace-private.h
@@ -38,6 +38,7 @@ struct _MetaWorkspace
 {
   GObject parent_instance;
   MetaDisplay *display;
+  MetaWorkspaceManager *manager;
 
   GList *windows;
 
@@ -72,7 +73,7 @@ struct _MetaWorkspaceClass
   GObjectClass parent_class;
 };
 
-MetaWorkspace* meta_workspace_new           (MetaDisplay   *display);
+MetaWorkspace* meta_workspace_new           (MetaWorkspaceManager *workspace_manager);
 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 390ae25..3819ca1 100644
--- a/src/core/workspace.c
+++ b/src/core/workspace.c
@@ -36,6 +36,7 @@
 #include "backends/meta-logical-monitor.h"
 #include "x11/meta-x11-display-private.h"
 #include <meta/workspace.h>
+#include "meta-workspace-manager-private.h"
 #include "workspace-private.h"
 #include "boxes-private.h"
 #include <meta/meta-x11-errors.h>
@@ -221,17 +222,20 @@ meta_workspace_init (MetaWorkspace *workspace)
 {
 }
 
-MetaWorkspace*
-meta_workspace_new (MetaDisplay *display)
+MetaWorkspace *
+meta_workspace_new (MetaWorkspaceManager *workspace_manager)
 {
+  MetaDisplay *display = workspace_manager->display;
   MetaWorkspace *workspace;
   GSList *windows, *l;
 
   workspace = g_object_new (META_TYPE_WORKSPACE, NULL);
 
   workspace->display = display;
-  workspace->display->workspaces =
-    g_list_append (workspace->display->workspaces, workspace);
+  workspace->manager = workspace_manager;
+
+  workspace_manager->workspaces =
+    g_list_append (workspace_manager->workspaces, workspace);
   workspace->windows = NULL;
   workspace->mru_list = NULL;
 
@@ -318,12 +322,14 @@ assert_workspace_empty (MetaWorkspace *workspace)
 void
 meta_workspace_remove (MetaWorkspace *workspace)
 {
-  g_return_if_fail (workspace != workspace->display->active_workspace);
+  MetaWorkspaceManager *manager = workspace->display->workspace_manager;
+
+  g_return_if_fail (workspace != manager->active_workspace);
 
   assert_workspace_empty (workspace);
 
-  workspace->display->workspaces =
-    g_list_remove (workspace->display->workspaces, workspace);
+  manager->workspaces =
+    g_list_remove (manager->workspaces, workspace);
 
   meta_workspace_clear_logical_monitor_data (workspace);
 
@@ -438,14 +444,14 @@ workspace_switch_sound(MetaWorkspace *from,
   int i, nw, x, y, fi, ti;
   const char *e;
 
-  nw = meta_display_get_n_workspaces(from->display);
+  nw = meta_workspace_manager_get_n_workspaces (from->manager);
   fi = meta_workspace_index(from);
   ti = meta_workspace_index(to);
 
-  meta_display_calc_workspace_layout(from->display,
-                                     nw,
-                                     fi,
-                                     &layout);
+  meta_workspace_manager_calc_workspace_layout (from->manager,
+                                                nw,
+                                                fi,
+                                                &layout);
 
   for (i = 0; i < nw; i++)
     if (layout.grid[i] == ti)
@@ -488,7 +494,7 @@ workspace_switch_sound(MetaWorkspace *from,
                   NULL);
 
  finish:
-  meta_display_free_workspace_layout (&layout);
+  meta_workspace_manager_free_workspace_layout (&layout);
 #endif /* HAVE_LIBCANBERRA */
 }
 
@@ -518,7 +524,6 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
 {
   MetaWorkspace  *old;
   MetaWindow     *move_window;
-  MetaDisplay    *display;
   MetaCompositor *comp;
   MetaWorkspaceLayout layout1, layout2;
   gint num_workspaces, current_space, new_space;
@@ -527,22 +532,22 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
   meta_verbose ("Activating workspace %d\n",
                 meta_workspace_index (workspace));
 
-  if (workspace->display->active_workspace == workspace)
+  if (workspace->manager->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->display);
 
-  if (workspace->display->active_workspace)
-    workspace_switch_sound (workspace->display->active_workspace, workspace);
+  if (workspace->manager->active_workspace)
+    workspace_switch_sound (workspace->manager->active_workspace, workspace);
 
   /* Note that old can be NULL; e.g. when starting up */
-  old = workspace->display->active_workspace;
+  old = workspace->manager->active_workspace;
 
-  workspace->display->active_workspace = workspace;
+  workspace->manager->active_workspace = workspace;
 
-  g_signal_emit_by_name (workspace->display, "active-workspace-changed");
+  g_signal_emit_by_name (workspace->manager, "active-workspace-changed");
 
   if (old == NULL)
     return;
@@ -552,7 +557,7 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
    * _net_showing_desktop hint
    */
   if (old->showing_desktop != workspace->showing_desktop)
-    g_signal_emit_by_name (workspace->display, "showing-desktop-changed");
+    g_signal_emit_by_name (workspace->manager, "showing-desktop-changed");
 
   move_window = NULL;
   if (meta_grab_op_is_moving (workspace->display->grab_op))
@@ -577,18 +582,17 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
    /*
     * Notify the compositor that the active workspace is changing.
     */
-   display = workspace->display;
-   comp = meta_display_get_compositor (display);
+   comp = meta_display_get_compositor (workspace->display);
    direction = 0;
 
    current_space = meta_workspace_index (old);
    new_space     = meta_workspace_index (workspace);
-   num_workspaces = meta_display_get_n_workspaces (workspace->display);
-   meta_display_calc_workspace_layout (workspace->display, num_workspaces,
-                                       current_space, &layout1);
+   num_workspaces = meta_workspace_manager_get_n_workspaces (workspace->manager);
+   meta_workspace_manager_calc_workspace_layout (workspace->manager, num_workspaces,
+                                                 current_space, &layout1);
 
-   meta_display_calc_workspace_layout (workspace->display, num_workspaces,
-                                       new_space, &layout2);
+   meta_workspace_manager_calc_workspace_layout (workspace->manager, num_workspaces,
+                                                 new_space, &layout2);
 
    if (meta_get_locale_direction () == META_LOCALE_DIRECTION_RTL)
      {
@@ -625,8 +629,8 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
          direction = META_MOTION_UP_LEFT;
      }
 
-   meta_display_free_workspace_layout (&layout1);
-   meta_display_free_workspace_layout (&layout2);
+   meta_workspace_manager_free_workspace_layout (&layout1);
+   meta_workspace_manager_free_workspace_layout (&layout2);
 
    meta_compositor_switch_workspace (comp, old, workspace, direction);
 
@@ -649,7 +653,8 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
       meta_workspace_focus_default_window (workspace, NULL, timestamp);
     }
 
-   meta_display_workspace_switched (display, current_space, new_space, direction);
+   meta_workspace_manager_workspace_switched (workspace->manager, current_space,
+                                              new_space, direction);
 }
 
 void
@@ -664,7 +669,7 @@ meta_workspace_index (MetaWorkspace *workspace)
 {
   int ret;
 
-  ret = g_list_index (workspace->display->workspaces, workspace);
+  ret = g_list_index (workspace->manager->workspaces, workspace);
 
   if (ret < 0)
     meta_bug ("Workspace does not exist to index!\n");
@@ -737,7 +742,7 @@ 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->display->active_workspace)
+  if (workspace == workspace->manager->active_workspace)
     meta_display_cleanup_edges (workspace->display);
 
   meta_workspace_clear_logical_monitor_data (workspace);
@@ -1198,9 +1203,9 @@ meta_workspace_get_neighbor (MetaWorkspace      *workspace,
   gboolean ltr;
 
   current_space = meta_workspace_index (workspace);
-  num_workspaces = meta_display_get_n_workspaces (workspace->display);
-  meta_display_calc_workspace_layout (workspace->display, num_workspaces,
-                                      current_space, &layout);
+  num_workspaces = meta_workspace_manager_get_n_workspaces (workspace->manager);
+  meta_workspace_manager_calc_workspace_layout (workspace->manager, num_workspaces,
+                                                current_space, &layout);
 
   meta_verbose ("Getting neighbor of %d in direction %s\n",
                 current_space, meta_motion_direction_to_string (direction));
@@ -1245,9 +1250,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_display_free_workspace_layout (&layout);
+  meta_workspace_manager_free_workspace_layout (&layout);
 
-  return meta_display_get_workspace_by_index (workspace->display, i);
+  return meta_workspace_manager_get_workspace_by_index (workspace->manager, i);
 }
 
 const char*
diff --git a/src/meta/display.h b/src/meta/display.h
index 6d446a6..a165421 100644
--- a/src/meta/display.h
+++ b/src/meta/display.h
@@ -203,24 +203,6 @@ 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);
 
@@ -239,12 +221,6 @@ typedef enum
   META_DISPLAY_BOTTOMRIGHT
 } MetaDisplayCorner;
 
-void meta_display_override_workspace_layout (MetaDisplay       *display,
-                                             MetaDisplayCorner starting_corner,
-                                             gboolean          vertical_layout,
-                                             int               n_rows,
-                                             int               n_columns);
-
 MetaWorkspaceManager *meta_display_get_workspace_manager (MetaDisplay *display);
 
 #endif
diff --git a/src/meta/meta-workspace-manager.h b/src/meta/meta-workspace-manager.h
index 29604f2..52b2f0e 100644
--- a/src/meta/meta-workspace-manager.h
+++ b/src/meta/meta-workspace-manager.h
@@ -32,6 +32,28 @@
 #define META_TYPE_WORKSPACE_MANAGER (meta_workspace_manager_get_type ())
 G_DECLARE_FINAL_TYPE (MetaWorkspaceManager, meta_workspace_manager, META, WORKSPACE_MANAGER, GObject)
 
+GList *meta_workspace_manager_get_workspaces (MetaWorkspaceManager *workspace_manager);
+
 int meta_workspace_manager_get_n_workspaces (MetaWorkspaceManager *workspace_manager);
 
+MetaWorkspace* meta_workspace_manager_get_workspace_by_index (MetaWorkspaceManager *workspace_manager,
+                                                              int                   index);
+
+void meta_workspace_manager_remove_workspace (MetaWorkspaceManager *workspace_manager,
+                                              MetaWorkspace        *workspace,
+                                              guint32               timestamp);
+
+MetaWorkspace *meta_workspace_manager_append_new_workspace (MetaWorkspaceManager *workspace_manager,
+                                                            gboolean              activate,
+                                                            guint32               timestamp);
+
+int meta_workspace_manager_get_active_workspace_index (MetaWorkspaceManager *workspace_manager);
+
+MetaWorkspace *meta_workspace_manager_get_active_workspace (MetaWorkspaceManager *workspace_manager);
+
+void meta_workspace_manager_override_workspace_layout (MetaWorkspaceManager *workspace_manager,
+                                                       MetaDisplayCorner     starting_corner,
+                                                       gboolean              vertical_layout,
+                                                       int                   n_rows,
+                                                       int                   n_columns);
 #endif /* META_WORKSPACE_MANAGER_H */
diff --git a/src/x11/events.c b/src/x11/events.c
index d45c4b3..e1e1a68 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -32,6 +32,7 @@
 #include "meta/meta-backend.h"
 #include "bell.h"
 #include "display-private.h"
+#include "meta-workspace-manager-private.h"
 #include "window-private.h"
 #include "workspace-private.h"
 #include "backends/meta-cursor-tracker-private.h"
@@ -844,6 +845,7 @@ handle_input_xevent (MetaX11Display *x11_display,
   Window modified;
   MetaWindow *window;
   MetaDisplay *display = x11_display->display;
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
 
   if (input_event == NULL)
     return FALSE;
@@ -912,7 +914,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 (display->active_workspace,
+              meta_workspace_focus_default_window (workspace_manager->active_workspace,
                                                    NULL,
                                                    meta_x11_display_get_current_time_roundtrip 
(x11_display));
             }
@@ -924,7 +926,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 (display->active_workspace,
+              meta_workspace_focus_default_window (workspace_manager->active_workspace,
                                                    NULL,
                                                    meta_x11_display_get_current_time_roundtrip 
(x11_display));
             }
@@ -1197,6 +1199,7 @@ handle_other_xevent (MetaX11Display *x11_display,
                      XEvent         *event)
 {
   MetaDisplay *display = x11_display->display;
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
   Window modified;
   MetaWindow *window;
   MetaWindow *property_for_window;
@@ -1398,12 +1401,12 @@ handle_other_xevent (MetaX11Display *x11_display,
       if (window->minimized)
         {
           meta_window_unminimize (window);
-          if (window->workspace != window->display->active_workspace)
+          if (window->workspace != workspace_manager->active_workspace)
             {
               meta_verbose ("Changing workspace due to MapRequest mapped = %d minimized = %d\n",
                             window->mapped, window->minimized);
               meta_window_change_workspace (window,
-                                            window->display->active_workspace);
+                                            workspace_manager->active_workspace);
             }
         }
       break;
@@ -1544,7 +1547,7 @@ handle_other_xevent (MetaX11Display *x11_display,
                                 "specified timestamp of %u\n",
                                 space, time);
 
-                  workspace = meta_display_get_workspace_by_index (display, space);
+                  workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, space);
 
                   /* Handle clients using the older version of the spec... */
                   if (time == 0 && workspace)
@@ -1585,11 +1588,11 @@ handle_other_xevent (MetaX11Display *x11_display,
                                 showing_desktop ? "show" : "hide");
 
                   if (showing_desktop)
-                    meta_display_show_desktop (display, timestamp);
+                    meta_workspace_manager_show_desktop (workspace_manager, timestamp);
                   else
                     {
-                      meta_display_unshow_desktop (display);
-                      meta_workspace_focus_default_window (display->active_workspace, NULL, timestamp);
+                      meta_workspace_manager_unshow_desktop (workspace_manager);
+                      meta_workspace_focus_default_window (workspace_manager->active_workspace, NULL, 
timestamp);
                     }
                 }
               else if (event->xclient.message_type ==
diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
index 6a3b792..3815a40 100644
--- a/src/x11/meta-x11-display.c
+++ b/src/x11/meta-x11-display.c
@@ -55,6 +55,7 @@
 #include "backends/meta-logical-monitor.h"
 #include "backends/x11/meta-backend-x11.h"
 #include "core/frame.h"
+#include "core/meta-workspace-manager-private.h"
 #include "core/util-private.h"
 #include "core/workspace-private.h"
 #include "meta/main.h"
@@ -787,8 +788,8 @@ init_event_masks (MetaX11Display *x11_display)
 }
 
 static void
-set_active_workspace_hint (MetaDisplay    *display,
-                           MetaX11Display *x11_display)
+set_active_workspace_hint (MetaWorkspaceManager *workspace_manager,
+                           MetaX11Display       *x11_display)
 {
   unsigned long data[1];
 
@@ -798,10 +799,10 @@ set_active_workspace_hint (MetaDisplay    *display,
    * on restart. By doing this we keep the current
    * desktop on restart.
    */
-  if (display->closing > 0)
+  if (x11_display->display->closing > 0)
     return;
 
-  data[0] = meta_workspace_index (display->active_workspace);
+  data[0] = meta_workspace_index (workspace_manager->active_workspace);
 
   meta_verbose ("Setting _NET_CURRENT_DESKTOP to %lu\n", data[0]);
 
@@ -815,17 +816,17 @@ set_active_workspace_hint (MetaDisplay    *display,
 }
 
 static void
-set_number_of_spaces_hint (MetaDisplay *display,
-                           GParamSpec  *pspec,
-                           gpointer     user_data)
+set_number_of_spaces_hint (MetaWorkspaceManager *workspace_manager,
+                           GParamSpec           *pspec,
+                           gpointer              user_data)
 {
   MetaX11Display *x11_display = user_data;
   unsigned long data[1];
 
-  if (display->closing > 0)
+  if (x11_display->display->closing > 0)
     return;
 
-  data[0] = meta_display_get_n_workspaces (display);
+  data[0] = meta_workspace_manager_get_n_workspaces (workspace_manager);
 
   meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %lu\n", data[0]);
 
@@ -839,12 +840,12 @@ set_number_of_spaces_hint (MetaDisplay *display,
 }
 
 static void
-set_showing_desktop_hint (MetaDisplay    *display,
-                          MetaX11Display *x11_display)
+set_showing_desktop_hint (MetaWorkspaceManager *workspace_manager,
+                          MetaX11Display       *x11_display)
 {
   unsigned long data[1];
 
-  data[0] = display->active_workspace->showing_desktop ? 1 : 0;
+  data[0] = workspace_manager->active_workspace->showing_desktop ? 1 : 0;
 
   meta_x11_error_trap_push (x11_display);
   XChangeProperty (x11_display->xdisplay,
@@ -858,12 +859,15 @@ set_showing_desktop_hint (MetaDisplay    *display,
 static void
 set_workspace_names (MetaX11Display *x11_display)
 {
+  MetaWorkspaceManager *workspace_manager;
   GString *flattened;
   int i;
   int n_spaces;
 
+  workspace_manager = x11_display->display->workspace_manager;
+
   /* flatten to nul-separated list */
-  n_spaces = meta_display_get_n_workspaces (x11_display->display);
+  n_spaces = meta_workspace_manager_get_n_workspaces (workspace_manager);
   flattened = g_string_new ("");
   i = 0;
   while (i < n_spaces)
@@ -897,16 +901,17 @@ static void
 set_work_area_hint (MetaDisplay    *display,
                     MetaX11Display *x11_display)
 {
+  MetaWorkspaceManager *workspace_manager = display->workspace_manager;
   int num_workspaces;
   GList *l;
   unsigned long *data, *tmp;
   MetaRectangle area;
 
-  num_workspaces = meta_display_get_n_workspaces (display);
+  num_workspaces = meta_workspace_manager_get_n_workspaces (workspace_manager);
   data = g_new (unsigned long, num_workspaces * 4);
   tmp = data;
 
-  for (l = display->workspaces; l != NULL; l = l->next)
+  for (l = workspace_manager->workspaces; l != NULL; l = l->next)
     {
       MetaWorkspace *workspace = l->data;
 
@@ -1246,8 +1251,8 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
                     (int) current_workspace_index);
 
       /* Switch to the _NET_CURRENT_DESKTOP workspace */
-      current_workspace = meta_display_get_workspace_by_index (display,
-                                                               current_workspace_index);
+      current_workspace = meta_workspace_manager_get_workspace_by_index (display->workspace_manager,
+                                                                         current_workspace_index);
 
       if (current_workspace != NULL)
         meta_workspace_activate (current_workspace, timestamp);
@@ -1272,25 +1277,25 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
           meta_XFree (list);
         }
 
-        if (num > meta_display_get_n_workspaces (display))
-          meta_display_update_num_workspaces (display, timestamp, num);
+        if (num > meta_workspace_manager_get_n_workspaces (display->workspace_manager))
+          meta_workspace_manager_update_num_workspaces (display->workspace_manager, timestamp, num);
     }
 
-  set_active_workspace_hint (display, x11_display);
+  set_active_workspace_hint (display->workspace_manager, x11_display);
 
-  g_signal_connect_object (display, "active-workspace-changed",
+  g_signal_connect_object (display->workspace_manager, "active-workspace-changed",
                            G_CALLBACK (set_active_workspace_hint),
                            x11_display, 0);
 
-  set_number_of_spaces_hint (display, NULL, x11_display);
+  set_number_of_spaces_hint (display->workspace_manager, NULL, x11_display);
 
-  g_signal_connect_object (display, "notify::n-workspaces",
+  g_signal_connect_object (display->workspace_manager, "notify::n-workspaces",
                            G_CALLBACK (set_number_of_spaces_hint),
                            x11_display, 0);
 
-  set_showing_desktop_hint (display, x11_display);
+  set_showing_desktop_hint (display->workspace_manager, x11_display);
 
-  g_signal_connect_object (display, "showing-desktop-changed",
+  g_signal_connect_object (display->workspace_manager, "showing-desktop-changed",
                            G_CALLBACK (set_showing_desktop_hint),
                            x11_display, 0);
 
@@ -2008,6 +2013,7 @@ meta_x11_display_update_workspace_names (MetaX11Display *x11_display)
 void
 meta_x11_display_update_workspace_layout (MetaX11Display *x11_display)
 {
+  MetaWorkspaceManager *workspace_manager = x11_display->display->workspace_manager;
   gboolean vertical_layout = FALSE;
   int n_rows = -1;
   int n_columns = 1;
@@ -2015,7 +2021,7 @@ meta_x11_display_update_workspace_layout (MetaX11Display *x11_display)
   uint32_t *list;
   int n_items;
 
-  if (x11_display->display->workspace_layout_overridden)
+  if (workspace_manager->workspace_layout_overridden)
     return;
 
   list = NULL;
@@ -2093,11 +2099,11 @@ meta_x11_display_update_workspace_layout (MetaX11Display *x11_display)
 
       meta_XFree (list);
 
-      meta_display_update_workspace_layout (x11_display->display,
-                                            starting_corner,
-                                            vertical_layout,
-                                            n_rows,
-                                            n_columns);
+      meta_workspace_manager_update_workspace_layout (workspace_manager,
+                                                      starting_corner,
+                                                      vertical_layout,
+                                                      n_rows,
+                                                      n_columns);
     }
 }
 
diff --git a/src/x11/window-props.c b/src/x11/window-props.c
index 946568c..d06a89a 100644
--- a/src/x11/window-props.c
+++ b/src/x11/window-props.c
@@ -49,6 +49,7 @@
 #include <unistd.h>
 #include <string.h>
 #include "util-private.h"
+#include "meta-workspace-manager-private.h"
 
 #ifndef HOST_NAME_MAX
 /* Solaris headers apparently don't define this so do so manually; #326745 */
@@ -1027,6 +1028,7 @@ reload_net_startup_id (MetaWindow    *window,
                        MetaPropValue *value,
                        gboolean       initial)
 {
+  MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
   guint32 timestamp = window->net_wm_user_time;
   MetaWorkspace *workspace = NULL;
 
@@ -1049,7 +1051,8 @@ reload_net_startup_id (MetaWindow    *window,
         if (window->initial_timestamp_set)
           timestamp = window->initial_timestamp;
         if (window->initial_workspace_set)
-          workspace = meta_display_get_workspace_by_index (window->display, window->initial_workspace);
+          workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager,
+                                                                     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 1062d94..47d5c3f 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -50,6 +50,7 @@
 #include "xprops.h"
 #include "session.h"
 #include "workspace-private.h"
+#include "meta-workspace-manager-private.h"
 
 #include "backends/meta-logical-monitor.h"
 #include "backends/x11/meta-backend-x11.h"
@@ -447,11 +448,12 @@ meta_window_apply_session_info (MetaWindow *window,
       tmp = info->workspace_indices;
       while (tmp != NULL)
         {
+          MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
           MetaWorkspace *space;
 
           space =
-            meta_display_get_workspace_by_index (window->display,
-                                                 GPOINTER_TO_INT (tmp->data));
+            meta_workspace_manager_get_workspace_by_index (workspace_manager,
+                                                           GPOINTER_TO_INT (tmp->data));
 
           if (space)
             spaces = g_slist_prepend (spaces, space);
@@ -2307,6 +2309,7 @@ meta_window_x11_client_message (MetaWindow *window,
            x11_display->atom__NET_WM_DESKTOP)
     {
       int space;
+      MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
       MetaWorkspace *workspace;
 
       space = event->xclient.data.l[0];
@@ -2315,8 +2318,8 @@ meta_window_x11_client_message (MetaWindow *window,
                     window->desc, space);
 
       workspace =
-        meta_display_get_workspace_by_index (window->display,
-                                             space);
+        meta_workspace_manager_get_workspace_by_index (workspace_manager,
+                                                       space);
 
       if (workspace)
         meta_window_change_workspace (window, workspace);


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