[mutter/wip/xwayland-on-demand: 20/32] Make workspace management work without X11



commit c0e61281821894547f288fef50ea8396d41b0b47
Author: Armin Krezović <krezovic armin gmail com>
Date:   Sat Aug 26 22:29:10 2017 +0200

    Make workspace management work without X11

 src/core/display-private.h         |   10 +-
 src/core/display.c                 |  312 +++++++++-------------------------
 src/core/workspace.c               |   13 +-
 src/x11/events.c                   |    2 +-
 src/x11/meta-x11-display-private.h |    9 +-
 src/x11/meta-x11-display.c         |  333 ++++++++++++++++++++++++++++++------
 6 files changed, 374 insertions(+), 305 deletions(-)
---
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 25c341d..31a6965 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -443,7 +443,11 @@ 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);
+void meta_display_update_workspace_layout (MetaDisplay      *display,
+                                           MetaDisplayCorner starting_corner,
+                                           gboolean          vertical_layout,
+                                           int               n_rows,
+                                           int               n_columns);
 
 typedef struct MetaWorkspaceLayout MetaWorkspaceLayout;
 
@@ -476,4 +480,8 @@ void     meta_display_workspace_switched (MetaDisplay        *display,
                                           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 0f25e93..2547c4b 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -140,7 +140,9 @@ enum
   WORKSPACE_ADDED,
   WORKSPACE_REMOVED,
   WORKSPACE_SWITCHED,
+  ACTIVE_WORKSPACE_CHANGED,
   IN_FULLSCREEN_CHANGED,
+  SHOWING_DESKTOP_CHANGED,
   STARTUP_SEQUENCE_CHANGED,
   MONITORS_CHANGED,
   RESTACKED,
@@ -171,10 +173,6 @@ static void    on_monitors_changed       (MetaMonitorManager *manager,
 static void    prefs_changed_callback    (MetaPreference pref,
                                           void          *data);
 
-static void set_workspace_names   (MetaDisplay *display);
-static void update_num_workspaces (MetaDisplay *display,
-                                   guint32     timestamp);
-
 static int mru_cmp (gconstpointer a,
                     gconstpointer b);
 
@@ -485,6 +483,14 @@ meta_display_class_init (MetaDisplayClass *klass)
                   G_TYPE_INT,
                   META_TYPE_MOTION_DIRECTION);
 
+  display_signals[ACTIVE_WORKSPACE_CHANGED] =
+    g_signal_new ("active-workspace-changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
   display_signals[IN_FULLSCREEN_CHANGED] =
     g_signal_new ("in-fullscreen-changed",
                   G_TYPE_FROM_CLASS (klass),
@@ -492,6 +498,14 @@ meta_display_class_init (MetaDisplayClass *klass)
                   0, NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
 
+  display_signals[SHOWING_DESKTOP_CHANGED] =
+    g_signal_new ("showing-desktop-changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
   display_signals[STARTUP_SEQUENCE_CHANGED] =
     g_signal_new ("startup-sequence-changed",
                   G_TYPE_FROM_CLASS (klass),
@@ -784,6 +798,26 @@ meta_display_open (void)
 
   meta_display_set_cursor (display, META_CURSOR_DEFAULT);
 
+
+  /* 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);
+
   x11_display = meta_x11_display_new (display, &error);
   g_assert (x11_display != NULL); /* Required, for now */
   display->x11_display = x11_display;
@@ -794,15 +828,6 @@ meta_display_open (void)
   display->stack = meta_stack_new (display);
   display->stack_tracker = meta_stack_tracker_new (display);
 
-  reload_logical_monitors (display);
-
-  meta_display_update_workspace_layout (display);
-
-  /* There must be at least one workspace at all times,
-   * so create that required workspace.
-   */
-  meta_workspace_new (display);
-
   meta_bell_init (display);
 
   display->last_focus_time = timestamp;
@@ -819,8 +844,6 @@ meta_display_open (void)
   g_signal_connect (display->startup_notification, "changed",
                     G_CALLBACK (on_startup_notification_changed), display);
 
-  meta_display_init_workspaces (display);
-
   enable_compositor (display);
 
   if (display->x11_display)
@@ -2549,11 +2572,8 @@ prefs_changed_callback (MetaPreference pref,
        */
       guint32 timestamp =
         meta_display_get_current_time_roundtrip (display);
-      update_num_workspaces (display, timestamp);
-    }
-  else if (pref == META_PREF_WORKSPACE_NAMES)
-    {
-      set_workspace_names (display);
+      int new_num = meta_prefs_get_num_workspaces ();
+      meta_display_update_num_workspaces (display, timestamp, new_num);
     }
 }
 
@@ -3697,36 +3717,20 @@ meta_display_get_pointer_window (MetaDisplay *display,
 void
 meta_display_init_workspaces (MetaDisplay *display)
 {
-  MetaWorkspace *current_workspace;
-  uint32_t current_workspace_index = 0;
-  guint32 timestamp;
+  int num;
 
   g_return_if_fail (META_IS_DISPLAY (display));
 
-  timestamp = display->x11_display->wm_sn_timestamp;
-
-  /* Get current workspace */
-  if (meta_prop_get_cardinal (display->x11_display,
-                              display->x11_display->xroot,
-                              display->x11_display->atom__NET_CURRENT_DESKTOP,
-                              &current_workspace_index))
-    meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
-                  (int) current_workspace_index);
+  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
-    meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
-
-  update_num_workspaces (display, timestamp);
+    num = meta_prefs_get_num_workspaces ();
 
-  set_workspace_names (display);
+  meta_display_update_num_workspaces (display, META_CURRENT_TIME, num);
 
-  /* Switch to the _NET_CURRENT_DESKTOP workspace */
-  current_workspace = meta_display_get_workspace_by_index (display,
-                                                           current_workspace_index);
-
-  if (current_workspace != NULL)
-    meta_workspace_activate (current_workspace, timestamp);
-  else
-    meta_workspace_activate (display->workspaces->data, timestamp);
+  meta_workspace_activate (display->workspaces->data, META_CURRENT_TIME);
 }
 
 int
@@ -3796,15 +3800,13 @@ meta_display_remove_workspace (MetaDisplay   *display,
 
   new_num = g_list_length (display->workspaces);
 
-  meta_x11_display_set_number_of_spaces_hint (display->x11_display, new_num);
-
   if (!meta_prefs_get_dynamic_workspaces ())
     meta_prefs_set_num_workspaces (new_num);
 
   /* If deleting a workspace before the current workspace, the active
    * workspace index changes, so we need to update that hint */
   if (active_index_changed)
-      meta_x11_display_set_active_workspace_hint (display->x11_display);
+    g_signal_emit (display, display_signals[ACTIVE_WORKSPACE_CHANGED], 0, NULL);
 
   for (l = next; l != NULL; l = l->next)
     {
@@ -3850,8 +3852,6 @@ meta_display_append_new_workspace (MetaDisplay *display,
 
   new_num = g_list_length (display->workspaces);
 
-  meta_x11_display_set_number_of_spaces_hint (display->x11_display, new_num);
-
   if (!meta_prefs_get_dynamic_workspaces ())
     meta_prefs_set_num_workspaces (new_num);
 
@@ -3864,51 +3864,23 @@ meta_display_append_new_workspace (MetaDisplay *display,
   return w;
 }
 
-static void
-update_num_workspaces (MetaDisplay *display,
-                       guint32     timestamp)
+void
+meta_display_update_num_workspaces (MetaDisplay *display,
+                                    guint32      timestamp,
+                                    int          new_num)
 {
-  int new_num, old_num;
+  int old_num;
   GList *l;
-  int i;
-  GList *extras;
-  MetaWorkspace *last_remaining;
-  gboolean need_change_space;
-
-  if (meta_prefs_get_dynamic_workspaces ())
-    {
-      int n_items;
-      uint32_t *list;
-
-      n_items = 0;
-      list = NULL;
-
-      if (meta_prop_get_cardinal_list (display->x11_display,
-                                       display->x11_display->xroot,
-                                       display->x11_display->atom__NET_NUMBER_OF_DESKTOPS,
-                                       &list, &n_items))
-        {
-          new_num = list[0];
-          meta_XFree (list);
-        }
-      else
-        {
-          new_num = 1;
-        }
-    }
-  else
-    {
-      new_num = meta_prefs_get_num_workspaces ();
-    }
+  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;
 
-  last_remaining = NULL;
-  extras = NULL;
-  i = 0;
   for (l = display->workspaces; l != NULL; l = l->next)
     {
       MetaWorkspace *w = l->data;
@@ -3930,7 +3902,6 @@ update_num_workspaces (MetaDisplay *display,
    * wacky if the config tool for changing number of workspaces
    * is on a removed workspace ;-)
    */
-  need_change_space = FALSE;
   for (l = extras; l != NULL; l = l->next)
     {
       MetaWorkspace *w = l->data;
@@ -3957,8 +3928,6 @@ update_num_workspaces (MetaDisplay *display,
   for (i = old_num; i < new_num; i++)
     meta_workspace_new (display);
 
-  meta_x11_display_set_number_of_spaces_hint (display->x11_display, new_num);
-
   meta_display_queue_workarea_recalc (display);
 
   for (i = old_num; i < new_num; i++)
@@ -3967,100 +3936,24 @@ update_num_workspaces (MetaDisplay *display,
   g_object_notify (G_OBJECT (display), "n-workspaces");
 }
 
-#define _NET_WM_ORIENTATION_HORZ 0
-#define _NET_WM_ORIENTATION_VERT 1
-
-#define _NET_WM_TOPLEFT     0
-#define _NET_WM_TOPRIGHT    1
-#define _NET_WM_BOTTOMRIGHT 2
-#define _NET_WM_BOTTOMLEFT  3
-
 void
-meta_display_update_workspace_layout (MetaDisplay *display)
+meta_display_update_workspace_layout (MetaDisplay      *display,
+                                      MetaDisplayCorner starting_corner,
+                                      gboolean          vertical_layout,
+                                      int               n_rows,
+                                      int               n_columns)
 {
-  uint32_t *list;
-  int n_items;
+  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;
 
-  list = NULL;
-  n_items = 0;
-
-  if (meta_prop_get_cardinal_list (display->x11_display,
-                                   display->x11_display->xroot,
-                                   display->x11_display->atom__NET_DESKTOP_LAYOUT,
-                                   &list, &n_items))
-    {
-      if (n_items == 3 || n_items == 4)
-        {
-          int cols, rows;
-
-          switch (list[0])
-            {
-            case _NET_WM_ORIENTATION_HORZ:
-              display->vertical_workspaces = FALSE;
-              break;
-            case _NET_WM_ORIENTATION_VERT:
-              display->vertical_workspaces = TRUE;
-              break;
-            default:
-              meta_warning ("Someone set a weird orientation in _NET_DESKTOP_LAYOUT\n");
-              break;
-            }
-
-          cols = list[1];
-          rows = list[2];
-
-          if (rows <= 0 && cols <= 0)
-            {
-              meta_warning ("Columns = %d rows = %d in _NET_DESKTOP_LAYOUT makes no sense\n", rows, cols);
-            }
-          else
-            {
-              if (rows > 0)
-                display->rows_of_workspaces = rows;
-              else
-                display->rows_of_workspaces = -1;
-
-              if (cols > 0)
-                display->columns_of_workspaces = cols;
-              else
-                display->columns_of_workspaces = -1;
-            }
-
-          if (n_items == 4)
-            {
-              switch (list[3])
-                {
-                  case _NET_WM_TOPLEFT:
-                    display->starting_corner = META_DISPLAY_TOPLEFT;
-                    break;
-                  case _NET_WM_TOPRIGHT:
-                    display->starting_corner = META_DISPLAY_TOPRIGHT;
-                    break;
-                  case _NET_WM_BOTTOMRIGHT:
-                    display->starting_corner = META_DISPLAY_BOTTOMRIGHT;
-                    break;
-                  case _NET_WM_BOTTOMLEFT:
-                    display->starting_corner = META_DISPLAY_BOTTOMLEFT;
-                    break;
-                  default:
-                    meta_warning ("Someone set a weird starting corner in _NET_DESKTOP_LAYOUT\n");
-                    break;
-                }
-            }
-          else
-            display->starting_corner = META_DISPLAY_TOPLEFT;
-        }
-      else
-        {
-          meta_warning ("Someone set _NET_DESKTOP_LAYOUT to %d integers instead of 4 "
-                        "(3 is accepted for backwards compat)\n", n_items);
-        }
-
-      meta_XFree (list);
-    }
+  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,
@@ -4089,64 +3982,13 @@ meta_display_override_workspace_layout (MetaDisplay      *display,
                                         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);
+  meta_display_update_workspace_layout (display,
+                                        starting_corner,
+                                        vertical_layout,
+                                        n_rows,
+                                        n_columns);
 
   display->workspace_layout_overridden = TRUE;
-  display->vertical_workspaces = vertical_layout != FALSE;
-  display->starting_corner = starting_corner;
-  display->rows_of_workspaces = n_rows;
-  display->columns_of_workspaces = n_columns;
-
-  /* In theory we should remove _NET_DESKTOP_LAYOUT from _NET_SUPPORTED at this
-   * point, but it's unlikely that anybody checks that, and it's unlikely that
-   * anybody who checks that handles changes, so we'd probably just create
-   * a race condition. And it's hard to implement with the code in set_supported_hint()
-   */
-}
-
-static void
-set_workspace_names (MetaDisplay *display)
-{
-  /* This updates names on root window when the pref changes,
-   * note we only get prefs change notify if things have
-   * really changed.
-   */
-  MetaX11Display *x11_display = display->x11_display;
-  GString *flattened;
-  int i;
-  int n_spaces;
-
-  /* flatten to nul-separated list */
-  n_spaces = meta_display_get_n_workspaces (display);
-  flattened = g_string_new ("");
-  i = 0;
-  while (i < n_spaces)
-    {
-      const char *name;
-
-      name = meta_prefs_get_workspace_name (i);
-
-      if (name)
-        g_string_append_len (flattened, name,
-                             strlen (name) + 1);
-      else
-        g_string_append_len (flattened, "", 1);
-
-      ++i;
-    }
-
-  meta_error_trap_push (x11_display);
-  XChangeProperty (x11_display->xdisplay,
-                   x11_display->xroot,
-                   x11_display->atom__NET_DESKTOP_NAMES,
-                  x11_display->atom_UTF8_STRING,
-                   8, PropModeReplace,
-                  (unsigned char *)flattened->str, flattened->len);
-  meta_error_trap_pop (x11_display);
-
-  g_string_free (flattened, TRUE);
 }
 
 #ifdef WITH_VERBOSE_MODE
@@ -4506,7 +4348,7 @@ meta_display_show_desktop (MetaDisplay *display,
         }
     }
 
-  meta_x11_display_update_showing_desktop_hint (display->x11_display);
+  g_signal_emit (display, display_signals[SHOWING_DESKTOP_CHANGED], 0, NULL);
 }
 
 void
@@ -4519,7 +4361,7 @@ meta_display_unshow_desktop (MetaDisplay *display)
 
   queue_windows_showing (display);
 
-  meta_x11_display_update_showing_desktop_hint (display->x11_display);
+  g_signal_emit (display, display_signals[SHOWING_DESKTOP_CHANGED], 0, NULL);
 }
 
 /**
diff --git a/src/core/workspace.c b/src/core/workspace.c
index d0380e1..2984a2f 100644
--- a/src/core/workspace.c
+++ b/src/core/workspace.c
@@ -542,17 +542,17 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
 
   workspace->display->active_workspace = workspace;
 
-  meta_x11_display_set_active_workspace_hint (workspace->display->x11_display);
+  g_signal_emit_by_name (workspace->display, "active-workspace-changed");
+
+  if (old == NULL)
+    return;
 
   /* If the "show desktop" mode is active for either the old workspace
    * or the new one *but not both*, then update the
    * _net_showing_desktop hint
    */
-  if (old && (old->showing_desktop != workspace->showing_desktop))
-    meta_x11_display_update_showing_desktop_hint (workspace->display->x11_display);
-
-  if (old == NULL)
-    return;
+  if (old->showing_desktop != workspace->showing_desktop)
+    g_signal_emit_by_name (workspace->display, "showing-desktop-changed");
 
   move_window = NULL;
   if (meta_grab_op_is_moving (workspace->display->grab_op))
@@ -649,7 +649,6 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
       meta_workspace_focus_default_window (workspace, NULL, timestamp);
     }
 
-   /* Emit switched signal from screen.c */
    meta_display_workspace_switched (display, current_space, new_space, direction);
 }
 
diff --git a/src/x11/events.c b/src/x11/events.c
index 0cf03c4..249edd7 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -1486,7 +1486,7 @@ handle_other_xevent (MetaX11Display *x11_display,
           {
             if (event->xproperty.atom ==
                 x11_display->atom__NET_DESKTOP_LAYOUT)
-              meta_display_update_workspace_layout (display);
+              meta_x11_display_update_workspace_layout (x11_display);
             else if (event->xproperty.atom ==
                      x11_display->atom__NET_DESKTOP_NAMES)
               meta_x11_display_update_workspace_names (x11_display);
diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h
index 09bf2a0..a4af63e 100644
--- a/src/x11/meta-x11-display-private.h
+++ b/src/x11/meta-x11-display-private.h
@@ -202,12 +202,7 @@ int meta_x11_display_logical_monitor_to_xinerama_index (MetaX11Display     *x11_
 MetaLogicalMonitor *meta_x11_display_xinerama_index_to_logical_monitor (MetaX11Display *x11_display,
                                                                         int             xinerama_index);
 
-/* Update whether the destkop is being shown for the current active_workspace */
-void meta_x11_display_update_showing_desktop_hint (MetaX11Display *x11_display);
-void meta_x11_display_update_workspace_names      (MetaX11Display *x11_display);
-
-void meta_x11_display_set_active_workspace_hint   (MetaX11Display *x11_display);
-void meta_x11_display_set_number_of_spaces_hint   (MetaX11Display *x11_display,
-                                                   int             n_spaces);
+void meta_x11_display_update_workspace_layout (MetaX11Display *x11_display);
+void meta_x11_display_update_workspace_names  (MetaX11Display *x11_display);
 
 #endif /* META_X11_DISPLAY_PRIVATE_H */
diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
index 1357981..8f193d3 100644
--- a/src/x11/meta-x11-display.c
+++ b/src/x11/meta-x11-display.c
@@ -87,11 +87,16 @@ static void on_monitors_changed (MetaDisplay    *display,
 static void update_cursor_theme (MetaX11Display *x11_display);
 static void unset_wm_check_hint (MetaX11Display *x11_display);
 
+static void prefs_changed_callback (MetaPreference pref,
+                                    void          *data);
+
 static void
 meta_x11_display_dispose (GObject *object)
 {
   MetaX11Display *x11_display = META_X11_DISPLAY (object);
 
+  meta_prefs_remove_listener (prefs_changed_callback, x11_display);
+
   meta_x11_display_ungrab_keys (x11_display);
 
   if (x11_display->ui)
@@ -677,6 +682,113 @@ init_event_masks (MetaX11Display *x11_display)
   XSelectInput (x11_display->xdisplay, x11_display->xroot, event_mask);
 }
 
+static void
+set_active_workspace_hint (MetaDisplay    *display,
+                           MetaX11Display *x11_display)
+{
+  unsigned long data[1];
+
+  /* this is because we destroy the spaces in order,
+   * so we always end up setting a current desktop of
+   * 0 when closing a screen, so lose the current desktop
+   * on restart. By doing this we keep the current
+   * desktop on restart.
+   */
+  if (display->closing > 0)
+    return;
+
+  data[0] = meta_workspace_index (display->active_workspace);
+
+  meta_verbose ("Setting _NET_CURRENT_DESKTOP to %lu\n", data[0]);
+
+  meta_error_trap_push (x11_display);
+  XChangeProperty (x11_display->xdisplay,
+                   x11_display->xroot,
+                   x11_display->atom__NET_CURRENT_DESKTOP,
+                   XA_CARDINAL,
+                   32, PropModeReplace, (guchar*) data, 1);
+  meta_error_trap_pop (x11_display);
+}
+
+static void
+set_number_of_spaces_hint (MetaDisplay *display,
+                           GParamSpec  *pspec,
+                           gpointer     user_data)
+{
+  MetaX11Display *x11_display = user_data;
+  unsigned long data[1];
+
+  if (display->closing > 0)
+    return;
+
+  data[0] = meta_display_get_n_workspaces (display);
+
+  meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %lu\n", data[0]);
+
+  meta_error_trap_push (x11_display);
+  XChangeProperty (x11_display->xdisplay,
+                   x11_display->xroot,
+                   x11_display->atom__NET_NUMBER_OF_DESKTOPS,
+                   XA_CARDINAL,
+                   32, PropModeReplace, (guchar*) data, 1);
+  meta_error_trap_pop (x11_display);
+}
+
+static void
+set_showing_desktop_hint (MetaDisplay    *display,
+                          MetaX11Display *x11_display)
+{
+  unsigned long data[1];
+
+  data[0] = display->active_workspace->showing_desktop ? 1 : 0;
+
+  meta_error_trap_push (x11_display);
+  XChangeProperty (x11_display->xdisplay,
+                   x11_display->xroot,
+                   x11_display->atom__NET_SHOWING_DESKTOP,
+                   XA_CARDINAL,
+                   32, PropModeReplace, (guchar*) data, 1);
+  meta_error_trap_pop (x11_display);
+}
+
+static void
+set_workspace_names (MetaX11Display *x11_display)
+{
+  GString *flattened;
+  int i;
+  int n_spaces;
+
+  /* flatten to nul-separated list */
+  n_spaces = meta_display_get_n_workspaces (x11_display->display);
+  flattened = g_string_new ("");
+  i = 0;
+  while (i < n_spaces)
+    {
+      const char *name;
+
+      name = meta_prefs_get_workspace_name (i);
+
+      if (name)
+        g_string_append_len (flattened, name,
+                             strlen (name) + 1);
+      else
+        g_string_append_len (flattened, "", 1);
+
+      ++i;
+    }
+
+  meta_error_trap_push (x11_display);
+  XChangeProperty (x11_display->xdisplay,
+                   x11_display->xroot,
+                   x11_display->atom__NET_DESKTOP_NAMES,
+                  x11_display->atom_UTF8_STRING,
+                   8, PropModeReplace,
+                  (unsigned char *)flattened->str, flattened->len);
+  meta_error_trap_pop (x11_display);
+
+  g_string_free (flattened, TRUE);
+}
+
 /**
  * meta_set_wm_name: (skip)
  * @wm_name: value for _NET_WM_NAME
@@ -730,6 +842,8 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
   Atom wm_sn_atom;
   char buf[128];
   guint32 timestamp;
+  MetaWorkspace *current_workspace;
+  uint32_t current_workspace_index = 0;
 
   /* A list of all atom names, so that we can intern them in one go. */
   const char *atom_names[] = {
@@ -921,6 +1035,70 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
   x11_display->keys_grabbed = FALSE;
   meta_x11_display_grab_keys (x11_display);
 
+  meta_x11_display_update_workspace_layout (x11_display);
+
+  /* Get current workspace */
+  if (meta_prop_get_cardinal (x11_display,
+                              x11_display->xroot,
+                              x11_display->atom__NET_CURRENT_DESKTOP,
+                              &current_workspace_index))
+    {
+      meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
+                    (int) current_workspace_index);
+
+      /* Switch to the _NET_CURRENT_DESKTOP workspace */
+      current_workspace = meta_display_get_workspace_by_index (display,
+                                                               current_workspace_index);
+
+      if (current_workspace != NULL)
+        meta_workspace_activate (current_workspace, timestamp);
+    }
+  else
+    {
+      meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
+    }
+
+  if (meta_prefs_get_dynamic_workspaces ())
+    {
+      int num = 0;
+      int n_items = 0;
+      uint32_t *list = NULL;
+
+      if (meta_prop_get_cardinal_list (x11_display,
+                                       x11_display->xroot,
+                                       x11_display->atom__NET_NUMBER_OF_DESKTOPS,
+                                       &list, &n_items))
+        {
+          num = list[0];
+          meta_XFree (list);
+        }
+
+        if (num > meta_display_get_n_workspaces (display))
+          meta_display_update_num_workspaces (display, timestamp, num);
+    }
+
+  set_active_workspace_hint (display, x11_display);
+
+  g_signal_connect_object (display, "active-workspace-changed",
+                           G_CALLBACK (set_active_workspace_hint),
+                           x11_display, 0);
+
+  set_number_of_spaces_hint (display, NULL, x11_display);
+
+  g_signal_connect_object (display, "notify::n-workspaces",
+                           G_CALLBACK (set_number_of_spaces_hint),
+                           x11_display, 0);
+
+  set_showing_desktop_hint (display, x11_display);
+
+  g_signal_connect_object (display, "showing-desktop-changed",
+                           G_CALLBACK (set_showing_desktop_hint),
+                           x11_display, 0);
+
+  set_workspace_names (x11_display);
+
+  meta_prefs_add_listener (prefs_changed_callback, x11_display);
+
   return x11_display;
 }
 
@@ -1560,23 +1738,6 @@ meta_x11_display_xinerama_index_to_logical_monitor (MetaX11Display *x11_display,
 }
 
 void
-meta_x11_display_update_showing_desktop_hint (MetaX11Display *x11_display)
-{
-  MetaDisplay *display = x11_display->display;
-  unsigned long data[1];
-
-  data[0] = display->active_workspace->showing_desktop ? 1 : 0;
-
-  meta_error_trap_push (x11_display);
-  XChangeProperty (x11_display->xdisplay,
-                   x11_display->xroot,
-                   x11_display->atom__NET_SHOWING_DESKTOP,
-                   XA_CARDINAL,
-                   32, PropModeReplace, (guchar*) data, 1);
-  meta_error_trap_pop (x11_display);
-}
-
-void
 meta_x11_display_update_workspace_names (MetaX11Display *x11_display)
 {
   char **names;
@@ -1612,54 +1773,118 @@ meta_x11_display_update_workspace_names (MetaX11Display *x11_display)
   g_strfreev (names);
 }
 
+#define _NET_WM_ORIENTATION_HORZ 0
+#define _NET_WM_ORIENTATION_VERT 1
+
+#define _NET_WM_TOPLEFT     0
+#define _NET_WM_TOPRIGHT    1
+#define _NET_WM_BOTTOMRIGHT 2
+#define _NET_WM_BOTTOMLEFT  3
 
 void
-meta_x11_display_set_active_workspace_hint (MetaX11Display *x11_display)
+meta_x11_display_update_workspace_layout (MetaX11Display *x11_display)
 {
-  MetaDisplay *display = x11_display->display;
+  gboolean vertical_layout = FALSE;
+  int n_rows = -1;
+  int n_columns = 1;
+  MetaDisplayCorner starting_corner = META_DISPLAY_TOPLEFT;
+  uint32_t *list;
+  int n_items;
 
-  unsigned long data[1];
-
-  /* this is because we destroy the spaces in order,
-   * so we always end up setting a current desktop of
-   * 0 when closing a screen, so lose the current desktop
-   * on restart. By doing this we keep the current
-   * desktop on restart.
-   */
-  if (display->closing > 0)
+  if (x11_display->display->workspace_layout_overridden)
     return;
 
-  data[0] = meta_workspace_index (display->active_workspace);
+  list = NULL;
+  n_items = 0;
 
-  meta_verbose ("Setting _NET_CURRENT_DESKTOP to %lu\n", data[0]);
+  if (meta_prop_get_cardinal_list (x11_display,
+                                   x11_display->xroot,
+                                   x11_display->atom__NET_DESKTOP_LAYOUT,
+                                   &list, &n_items))
+    {
+      if (n_items == 3 || n_items == 4)
+        {
+          int cols, rows;
 
-  meta_error_trap_push (x11_display);
-  XChangeProperty (x11_display->xdisplay,
-                   x11_display->xroot,
-                   x11_display->atom__NET_CURRENT_DESKTOP,
-                   XA_CARDINAL,
-                   32, PropModeReplace, (guchar*) data, 1);
-  meta_error_trap_pop (x11_display);
-}
+          switch (list[0])
+            {
+            case _NET_WM_ORIENTATION_HORZ:
+              vertical_layout = FALSE;
+              break;
+            case _NET_WM_ORIENTATION_VERT:
+              vertical_layout = TRUE;
+              break;
+            default:
+              meta_warning ("Someone set a weird orientation in _NET_DESKTOP_LAYOUT\n");
+              break;
+            }
 
-void
-meta_x11_display_set_number_of_spaces_hint (MetaX11Display *x11_display,
-                                            int             n_spaces)
-{
-  unsigned long data[1];
+          cols = list[1];
+          rows = list[2];
 
-  if (x11_display->display->closing > 0)
-    return;
+          if (rows <= 0 && cols <= 0)
+            {
+              meta_warning ("Columns = %d rows = %d in _NET_DESKTOP_LAYOUT makes no sense\n", rows, cols);
+            }
+          else
+            {
+              if (rows > 0)
+                n_rows = rows;
+              else
+                n_rows = -1;
+
+              if (cols > 0)
+                n_columns = cols;
+              else
+                n_columns = -1;
+            }
 
-  data[0] = n_spaces;
+          if (n_items == 4)
+            {
+              switch (list[3])
+                {
+                  case _NET_WM_TOPLEFT:
+                    starting_corner = META_DISPLAY_TOPLEFT;
+                    break;
+                  case _NET_WM_TOPRIGHT:
+                    starting_corner = META_DISPLAY_TOPRIGHT;
+                    break;
+                  case _NET_WM_BOTTOMRIGHT:
+                    starting_corner = META_DISPLAY_BOTTOMRIGHT;
+                    break;
+                  case _NET_WM_BOTTOMLEFT:
+                    starting_corner = META_DISPLAY_BOTTOMLEFT;
+                    break;
+                  default:
+                    meta_warning ("Someone set a weird starting corner in _NET_DESKTOP_LAYOUT\n");
+                    break;
+                }
+            }
+        }
+      else
+        {
+          meta_warning ("Someone set _NET_DESKTOP_LAYOUT to %d integers instead of 4 "
+                        "(3 is accepted for backwards compat)\n", n_items);
+        }
 
-  meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %lu\n", data[0]);
+      meta_XFree (list);
 
-  meta_error_trap_push (x11_display);
-  XChangeProperty (x11_display->xdisplay,
-                   x11_display->xroot,
-                   x11_display->atom__NET_NUMBER_OF_DESKTOPS,
-                   XA_CARDINAL,
-                   32, PropModeReplace, (guchar*) data, 1);
-  meta_error_trap_pop (x11_display);
+      meta_display_update_workspace_layout (x11_display->display,
+                                            starting_corner,
+                                            vertical_layout,
+                                            n_rows,
+                                            n_columns);
+    }
+}
+
+static void
+prefs_changed_callback (MetaPreference pref,
+                        void          *data)
+{
+  MetaX11Display *x11_display = data;
+
+  if (pref == META_PREF_WORKSPACE_NAMES)
+    {
+      set_workspace_names (x11_display);
+    }
 }


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