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