Make workspace management work without X11

https://bugzilla.gnome.org/show_bug.cgi?id=759538
This commit is contained in:
Armin Krezović 2017-08-26 22:29:10 +02:00 committed by Jonas Ådahl
parent 14d8aec4b8
commit 8adab02757
6 changed files with 375 additions and 306 deletions

View File

@ -444,7 +444,11 @@ MetaWindow *meta_display_get_pointer_window (MetaDisplay *display,
MetaWindow *not_this_one); MetaWindow *not_this_one);
void meta_display_init_workspaces (MetaDisplay *display); 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; typedef struct MetaWorkspaceLayout MetaWorkspaceLayout;
@ -477,4 +481,8 @@ void meta_display_workspace_switched (MetaDisplay *display,
int to, int to,
MetaMotionDirection direction); MetaMotionDirection direction);
void meta_display_update_num_workspaces (MetaDisplay *display,
guint32 timestamp,
int new_num);
#endif #endif

View File

@ -140,7 +140,9 @@ enum
WORKSPACE_ADDED, WORKSPACE_ADDED,
WORKSPACE_REMOVED, WORKSPACE_REMOVED,
WORKSPACE_SWITCHED, WORKSPACE_SWITCHED,
ACTIVE_WORKSPACE_CHANGED,
IN_FULLSCREEN_CHANGED, IN_FULLSCREEN_CHANGED,
SHOWING_DESKTOP_CHANGED,
STARTUP_SEQUENCE_CHANGED, STARTUP_SEQUENCE_CHANGED,
MONITORS_CHANGED, MONITORS_CHANGED,
RESTACKED, RESTACKED,
@ -174,10 +176,6 @@ static void on_monitors_changed (MetaMonitorManager *monitor_manager,
static void prefs_changed_callback (MetaPreference pref, static void prefs_changed_callback (MetaPreference pref,
void *data); void *data);
static void set_workspace_names (MetaDisplay *display);
static void update_num_workspaces (MetaDisplay *display,
guint32 timestamp);
static int mru_cmp (gconstpointer a, static int mru_cmp (gconstpointer a,
gconstpointer b); gconstpointer b);
@ -488,6 +486,14 @@ meta_display_class_init (MetaDisplayClass *klass)
G_TYPE_INT, G_TYPE_INT,
META_TYPE_MOTION_DIRECTION); 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] = display_signals[IN_FULLSCREEN_CHANGED] =
g_signal_new ("in-fullscreen-changed", g_signal_new ("in-fullscreen-changed",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
@ -495,6 +501,14 @@ meta_display_class_init (MetaDisplayClass *klass)
0, NULL, NULL, NULL, 0, NULL, NULL, NULL,
G_TYPE_NONE, 0); 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] = display_signals[STARTUP_SEQUENCE_CHANGED] =
g_signal_new ("startup-sequence-changed", g_signal_new ("startup-sequence-changed",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
@ -790,6 +804,26 @@ meta_display_open (void)
meta_display_set_cursor (display, META_CURSOR_DEFAULT); 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); x11_display = meta_x11_display_new (display, &error);
g_assert (x11_display != NULL); /* Required, for now */ g_assert (x11_display != NULL); /* Required, for now */
display->x11_display = x11_display; display->x11_display = x11_display;
@ -800,15 +834,6 @@ meta_display_open (void)
display->stack = meta_stack_new (display); display->stack = meta_stack_new (display);
display->stack_tracker = meta_stack_tracker_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); meta_bell_init (display);
display->last_focus_time = timestamp; display->last_focus_time = timestamp;
@ -825,8 +850,6 @@ meta_display_open (void)
g_signal_connect (display->startup_notification, "changed", g_signal_connect (display->startup_notification, "changed",
G_CALLBACK (on_startup_notification_changed), display); G_CALLBACK (on_startup_notification_changed), display);
meta_display_init_workspaces (display);
enable_compositor (display); enable_compositor (display);
if (display->x11_display) if (display->x11_display)
@ -2559,11 +2582,8 @@ prefs_changed_callback (MetaPreference pref,
*/ */
guint32 timestamp = guint32 timestamp =
meta_display_get_current_time_roundtrip (display); meta_display_get_current_time_roundtrip (display);
update_num_workspaces (display, timestamp); int new_num = meta_prefs_get_num_workspaces ();
} meta_display_update_num_workspaces (display, timestamp, new_num);
else if (pref == META_PREF_WORKSPACE_NAMES)
{
set_workspace_names (display);
} }
} }
@ -3717,36 +3737,20 @@ meta_display_get_pointer_window (MetaDisplay *display,
void void
meta_display_init_workspaces (MetaDisplay *display) meta_display_init_workspaces (MetaDisplay *display)
{ {
MetaWorkspace *current_workspace; int num;
uint32_t current_workspace_index = 0;
guint32 timestamp;
g_return_if_fail (META_IS_DISPLAY (display)); g_return_if_fail (META_IS_DISPLAY (display));
timestamp = display->x11_display->wm_sn_timestamp; if (meta_prefs_get_dynamic_workspaces ())
/* This will be properly updated using _NET_NUMBER_OF_DESKTOPS
/* Get current workspace */ * (if set) in meta_x11_display_new () */
if (meta_prop_get_cardinal (display->x11_display, num = 1;
display->x11_display->xroot,
display->x11_display->atom__NET_CURRENT_DESKTOP,
&current_workspace_index))
meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
(int) current_workspace_index);
else else
meta_verbose ("No _NET_CURRENT_DESKTOP present\n"); num = meta_prefs_get_num_workspaces ();
update_num_workspaces (display, timestamp); meta_display_update_num_workspaces (display, META_CURRENT_TIME, num);
set_workspace_names (display); meta_workspace_activate (display->workspaces->data, META_CURRENT_TIME);
/* Switch to the _NET_CURRENT_DESKTOP workspace */
current_workspace = meta_display_get_workspace_by_index (display,
current_workspace_index);
if (current_workspace != NULL)
meta_workspace_activate (current_workspace, timestamp);
else
meta_workspace_activate (display->workspaces->data, timestamp);
} }
int int
@ -3816,15 +3820,13 @@ meta_display_remove_workspace (MetaDisplay *display,
new_num = g_list_length (display->workspaces); 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 ()) if (!meta_prefs_get_dynamic_workspaces ())
meta_prefs_set_num_workspaces (new_num); meta_prefs_set_num_workspaces (new_num);
/* If deleting a workspace before the current workspace, the active /* If deleting a workspace before the current workspace, the active
* workspace index changes, so we need to update that hint */ * workspace index changes, so we need to update that hint */
if (active_index_changed) 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; l = l->next) for (l = next; l; l = l->next)
{ {
@ -3871,8 +3873,6 @@ meta_display_append_new_workspace (MetaDisplay *display,
new_num = g_list_length (display->workspaces); 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 ()) if (!meta_prefs_get_dynamic_workspaces ())
meta_prefs_set_num_workspaces (new_num); meta_prefs_set_num_workspaces (new_num);
@ -3885,51 +3885,23 @@ meta_display_append_new_workspace (MetaDisplay *display,
return w; return w;
} }
static void void
update_num_workspaces (MetaDisplay *display, meta_display_update_num_workspaces (MetaDisplay *display,
guint32 timestamp) guint32 timestamp,
int new_num)
{ {
int new_num, old_num; int old_num;
GList *l; GList *l;
int i; int i = 0;
GList *extras; GList *extras = NULL;
MetaWorkspace *last_remaining; MetaWorkspace *last_remaining = NULL;
gboolean need_change_space; gboolean need_change_space = FALSE;
if (meta_prefs_get_dynamic_workspaces ())
{
int n_items;
uint32_t *list;
n_items = 0;
list = NULL;
if (meta_prop_get_cardinal_list (display->x11_display,
display->x11_display->xroot,
display->x11_display->atom__NET_NUMBER_OF_DESKTOPS,
&list, &n_items))
{
new_num = list[0];
meta_XFree (list);
}
else
{
new_num = 1;
}
}
else
{
new_num = meta_prefs_get_num_workspaces ();
}
g_assert (new_num > 0); g_assert (new_num > 0);
if (g_list_length (display->workspaces) == (guint) new_num) if (g_list_length (display->workspaces) == (guint) new_num)
return; return;
last_remaining = NULL;
extras = NULL;
i = 0;
for (l = display->workspaces; l != NULL; l = l->next) for (l = display->workspaces; l != NULL; l = l->next)
{ {
MetaWorkspace *w = l->data; MetaWorkspace *w = l->data;
@ -3951,7 +3923,6 @@ update_num_workspaces (MetaDisplay *display,
* wacky if the config tool for changing number of workspaces * wacky if the config tool for changing number of workspaces
* is on a removed workspace ;-) * is on a removed workspace ;-)
*/ */
need_change_space = FALSE;
for (l = extras; l != NULL; l = l->next) for (l = extras; l != NULL; l = l->next)
{ {
MetaWorkspace *w = l->data; MetaWorkspace *w = l->data;
@ -3978,8 +3949,6 @@ update_num_workspaces (MetaDisplay *display,
for (i = old_num; i < new_num; i++) for (i = old_num; i < new_num; i++)
meta_workspace_new (display); meta_workspace_new (display);
meta_x11_display_set_number_of_spaces_hint (display->x11_display, new_num);
meta_display_queue_workarea_recalc (display); meta_display_queue_workarea_recalc (display);
for (i = old_num; i < new_num; i++) for (i = old_num; i < new_num; i++)
@ -3988,100 +3957,24 @@ update_num_workspaces (MetaDisplay *display,
g_object_notify (G_OBJECT (display), "n-workspaces"); 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 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; g_return_if_fail (META_IS_DISPLAY (display));
int n_items; 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) if (display->workspace_layout_overridden)
return; return;
list = NULL; display->vertical_workspaces = vertical_layout != FALSE;
n_items = 0; display->starting_corner = starting_corner;
display->rows_of_workspaces = n_rows;
if (meta_prop_get_cardinal_list (display->x11_display, display->columns_of_workspaces = n_columns;
display->x11_display->xroot,
display->x11_display->atom__NET_DESKTOP_LAYOUT,
&list, &n_items))
{
if (n_items == 3 || n_items == 4)
{
int cols, rows;
switch (list[0])
{
case _NET_WM_ORIENTATION_HORZ:
display->vertical_workspaces = FALSE;
break;
case _NET_WM_ORIENTATION_VERT:
display->vertical_workspaces = TRUE;
break;
default:
meta_warning ("Someone set a weird orientation in _NET_DESKTOP_LAYOUT\n");
break;
}
cols = list[1];
rows = list[2];
if (rows <= 0 && cols <= 0)
{
meta_warning ("Columns = %d rows = %d in _NET_DESKTOP_LAYOUT makes no sense\n", rows, cols);
}
else
{
if (rows > 0)
display->rows_of_workspaces = rows;
else
display->rows_of_workspaces = -1;
if (cols > 0)
display->columns_of_workspaces = cols;
else
display->columns_of_workspaces = -1;
}
if (n_items == 4)
{
switch (list[3])
{
case _NET_WM_TOPLEFT:
display->starting_corner = META_DISPLAY_TOPLEFT;
break;
case _NET_WM_TOPRIGHT:
display->starting_corner = META_DISPLAY_TOPRIGHT;
break;
case _NET_WM_BOTTOMRIGHT:
display->starting_corner = META_DISPLAY_BOTTOMRIGHT;
break;
case _NET_WM_BOTTOMLEFT:
display->starting_corner = META_DISPLAY_BOTTOMLEFT;
break;
default:
meta_warning ("Someone set a weird starting corner in _NET_DESKTOP_LAYOUT\n");
break;
}
}
else
display->starting_corner = META_DISPLAY_TOPLEFT;
}
else
{
meta_warning ("Someone set _NET_DESKTOP_LAYOUT to %d integers instead of 4 "
"(3 is accepted for backwards compat)\n", n_items);
}
meta_XFree (list);
}
meta_verbose ("Workspace layout rows = %d cols = %d orientation = %d starting corner = %u\n", meta_verbose ("Workspace layout rows = %d cols = %d orientation = %d starting corner = %u\n",
display->rows_of_workspaces, display->rows_of_workspaces,
@ -4110,64 +4003,13 @@ meta_display_override_workspace_layout (MetaDisplay *display,
int n_rows, int n_rows,
int n_columns) int n_columns)
{ {
g_return_if_fail (META_IS_DISPLAY (display)); meta_display_update_workspace_layout (display,
g_return_if_fail (n_rows > 0 || n_columns > 0); starting_corner,
g_return_if_fail (n_rows != 0 && n_columns != 0); vertical_layout,
n_rows,
n_columns);
display->workspace_layout_overridden = TRUE; 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 #ifdef WITH_VERBOSE_MODE
@ -4527,7 +4369,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 void
@ -4540,7 +4382,7 @@ meta_display_unshow_desktop (MetaDisplay *display)
queue_windows_showing (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);
} }
/** /**

View File

@ -543,17 +543,17 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
workspace->display->active_workspace = 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 /* If the "show desktop" mode is active for either the old workspace
* or the new one *but not both*, then update the * or the new one *but not both*, then update the
* _net_showing_desktop hint * _net_showing_desktop hint
*/ */
if (old && (old->showing_desktop != workspace->showing_desktop)) if (old->showing_desktop != workspace->showing_desktop)
meta_x11_display_update_showing_desktop_hint (workspace->display->x11_display); g_signal_emit_by_name (workspace->display, "showing-desktop-changed");
if (old == NULL)
return;
move_window = NULL; move_window = NULL;
if (meta_grab_op_is_moving (workspace->display->grab_op)) if (meta_grab_op_is_moving (workspace->display->grab_op))
@ -650,7 +650,6 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
meta_workspace_focus_default_window (workspace, NULL, timestamp); meta_workspace_focus_default_window (workspace, NULL, timestamp);
} }
/* Emit switched signal from screen.c */
meta_display_workspace_switched (display, current_space, new_space, direction); meta_display_workspace_switched (display, current_space, new_space, direction);
} }

View File

@ -1486,7 +1486,7 @@ handle_other_xevent (MetaX11Display *x11_display,
{ {
if (event->xproperty.atom == if (event->xproperty.atom ==
x11_display->atom__NET_DESKTOP_LAYOUT) 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 == else if (event->xproperty.atom ==
x11_display->atom__NET_DESKTOP_NAMES) x11_display->atom__NET_DESKTOP_NAMES)
meta_x11_display_update_workspace_names (x11_display); meta_x11_display_update_workspace_names (x11_display);

View File

@ -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, MetaLogicalMonitor *meta_x11_display_xinerama_index_to_logical_monitor (MetaX11Display *x11_display,
int xinerama_index); int xinerama_index);
/* Update whether the destkop is being shown for the current active_workspace */ void meta_x11_display_update_workspace_layout (MetaX11Display *x11_display);
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_update_workspace_names (MetaX11Display *x11_display);
void meta_x11_display_set_active_workspace_hint (MetaX11Display *x11_display);
void meta_x11_display_set_number_of_spaces_hint (MetaX11Display *x11_display,
int n_spaces);
#endif /* META_X11_DISPLAY_PRIVATE_H */ #endif /* META_X11_DISPLAY_PRIVATE_H */

View File

@ -87,11 +87,16 @@ static void on_monitors_changed (MetaDisplay *display,
static void update_cursor_theme (MetaX11Display *x11_display); static void update_cursor_theme (MetaX11Display *x11_display);
static void unset_wm_check_hint (MetaX11Display *x11_display); static void unset_wm_check_hint (MetaX11Display *x11_display);
static void prefs_changed_callback (MetaPreference pref,
void *data);
static void static void
meta_x11_display_dispose (GObject *object) meta_x11_display_dispose (GObject *object)
{ {
MetaX11Display *x11_display = META_X11_DISPLAY (object); MetaX11Display *x11_display = META_X11_DISPLAY (object);
meta_prefs_remove_listener (prefs_changed_callback, x11_display);
meta_x11_display_ungrab_keys (x11_display); meta_x11_display_ungrab_keys (x11_display);
if (x11_display->ui) if (x11_display->ui)
@ -683,6 +688,113 @@ init_event_masks (MetaX11Display *x11_display)
XSelectInput (x11_display->xdisplay, x11_display->xroot, event_mask); 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) * meta_set_wm_name: (skip)
* @wm_name: value for _NET_WM_NAME * @wm_name: value for _NET_WM_NAME
@ -736,6 +848,8 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
Atom wm_sn_atom; Atom wm_sn_atom;
char buf[128]; char buf[128];
guint32 timestamp; 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. */ /* A list of all atom names, so that we can intern them in one go. */
const char *atom_names[] = { const char *atom_names[] = {
@ -927,6 +1041,70 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
x11_display->keys_grabbed = FALSE; x11_display->keys_grabbed = FALSE;
meta_x11_display_grab_keys (x11_display); 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; return x11_display;
} }
@ -1564,23 +1742,6 @@ meta_x11_display_xinerama_index_to_logical_monitor (MetaX11Display *x11_display,
return NULL; return NULL;
} }
void
meta_x11_display_update_showing_desktop_hint (MetaX11Display *x11_display)
{
MetaDisplay *display = x11_display->display;
unsigned long data[1];
data[0] = display->active_workspace->showing_desktop ? 1 : 0;
meta_error_trap_push (x11_display);
XChangeProperty (x11_display->xdisplay,
x11_display->xroot,
x11_display->atom__NET_SHOWING_DESKTOP,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
meta_error_trap_pop (x11_display);
}
void void
meta_x11_display_update_workspace_names (MetaX11Display *x11_display) meta_x11_display_update_workspace_names (MetaX11Display *x11_display)
{ {
@ -1617,54 +1778,118 @@ meta_x11_display_update_workspace_names (MetaX11Display *x11_display)
g_strfreev (names); 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 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]; if (x11_display->display->workspace_layout_overridden)
/* 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; 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,
meta_error_trap_push (x11_display);
XChangeProperty (x11_display->xdisplay,
x11_display->xroot, x11_display->xroot,
x11_display->atom__NET_CURRENT_DESKTOP, x11_display->atom__NET_DESKTOP_LAYOUT,
XA_CARDINAL, &list, &n_items))
32, PropModeReplace, (guchar*) data, 1);
meta_error_trap_pop (x11_display);
}
void
meta_x11_display_set_number_of_spaces_hint (MetaX11Display *x11_display,
int n_spaces)
{ {
unsigned long data[1]; if (n_items == 3 || n_items == 4)
{
int cols, rows;
if (x11_display->display->closing > 0) switch (list[0])
return; {
case _NET_WM_ORIENTATION_HORZ:
data[0] = n_spaces; vertical_layout = FALSE;
break;
meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %lu\n", data[0]); case _NET_WM_ORIENTATION_VERT:
vertical_layout = TRUE;
meta_error_trap_push (x11_display); break;
XChangeProperty (x11_display->xdisplay, default:
x11_display->xroot, meta_warning ("Someone set a weird orientation in _NET_DESKTOP_LAYOUT\n");
x11_display->atom__NET_NUMBER_OF_DESKTOPS, break;
XA_CARDINAL, }
32, PropModeReplace, (guchar*) data, 1);
meta_error_trap_pop (x11_display); 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)
n_rows = rows;
else
n_rows = -1;
if (cols > 0)
n_columns = cols;
else
n_columns = -1;
}
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_XFree (list);
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);
}
} }