From 68f3b5849a9fb438fbc92ab426b3555dc5deecf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 2 Dec 2016 17:39:01 +0800 Subject: [PATCH] workspace: Don't keep state given logical monitor indices Don't store logical monitor specific state in an array where the index from the monitor manager is used as index locally. Instead just use table associating a logical monitor with a monitor specific state holder, and store the state in there. This way we don't have the workspace implementation relying on implementation details of other units. https://bugzilla.gnome.org/show_bug.cgi?id=777732 --- src/core/constraints.c | 6 +- src/core/workspace-private.h | 10 +-- src/core/workspace.c | 145 ++++++++++++++++++++++------------- 3 files changed, 96 insertions(+), 65 deletions(-) diff --git a/src/core/constraints.c b/src/core/constraints.c index 7ccce5171..2aa27648f 100644 --- a/src/core/constraints.c +++ b/src/core/constraints.c @@ -410,8 +410,7 @@ setup_constraint_info (ConstraintInfo *info, info->usable_screen_region = meta_workspace_get_onscreen_region (cur_workspace); info->usable_monitor_region = - meta_workspace_get_onmonitor_region (cur_workspace, - logical_monitor->number); + meta_workspace_get_onmonitor_region (cur_workspace, logical_monitor); /* Log all this information for debugging */ meta_topic (META_DEBUG_GEOMETRY, @@ -496,8 +495,7 @@ place_window_if_needed(MetaWindow *window, &info->work_area_monitor); cur_workspace = window->screen->active_workspace; info->usable_monitor_region = - meta_workspace_get_onmonitor_region (cur_workspace, - logical_monitor->number); + meta_workspace_get_onmonitor_region (cur_workspace, logical_monitor); info->current.x = placed_rect.x; info->current.y = placed_rect.y; diff --git a/src/core/workspace-private.h b/src/core/workspace-private.h index 3b5e940fb..54d9db01f 100644 --- a/src/core/workspace-private.h +++ b/src/core/workspace-private.h @@ -54,12 +54,10 @@ struct _MetaWorkspace GList *list_containing_self; + GHashTable *logical_monitor_data; + MetaRectangle work_area_screen; - MetaRectangle *work_area_monitor; - gint n_work_area_monitor; GList *screen_region; - GList **monitor_region; - gint n_monitor_regions; GList *screen_edges; GList *monitor_edges; GSList *builtin_struts; @@ -90,8 +88,8 @@ void meta_workspace_get_work_area_for_logical_monitor (MetaWorkspace *works void meta_workspace_invalidate_work_area (MetaWorkspace *workspace); GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace); -GList* meta_workspace_get_onmonitor_region (MetaWorkspace *workspace, - int which_monitor); +GList * meta_workspace_get_onmonitor_region (MetaWorkspace *workspace, + MetaLogicalMonitor *logical_monitor); void meta_workspace_focus_default_window (MetaWorkspace *workspace, MetaWindow *not_this_one, diff --git a/src/core/workspace.c b/src/core/workspace.c index dd1538ce6..7f56b622e 100644 --- a/src/core/workspace.c +++ b/src/core/workspace.c @@ -78,6 +78,59 @@ enum static guint signals[LAST_SIGNAL] = { 0 }; +typedef struct _MetaWorkspaceLogicalMonitorData +{ + GList *logical_monitor_region; + MetaRectangle logical_monitor_work_area; +} MetaWorkspaceLogicalMonitorData; + +static MetaWorkspaceLogicalMonitorData * +meta_workspace_get_logical_monitor_data (MetaWorkspace *workspace, + MetaLogicalMonitor *logical_monitor) +{ + if (!workspace->logical_monitor_data) + return NULL; + return g_hash_table_lookup (workspace->logical_monitor_data, logical_monitor); +} + +static void +workspace_logical_monitor_data_free (MetaWorkspaceLogicalMonitorData *data) +{ + g_clear_pointer (&data->logical_monitor_region, + meta_rectangle_free_list_and_elements); +} + +static MetaWorkspaceLogicalMonitorData * +meta_workspace_ensure_logical_monitor_data (MetaWorkspace *workspace, + MetaLogicalMonitor *logical_monitor) +{ + MetaWorkspaceLogicalMonitorData *data; + + data = meta_workspace_get_logical_monitor_data (workspace, logical_monitor); + if (data) + return data; + + if (!workspace->logical_monitor_data) + { + workspace->logical_monitor_data = + g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, + (GDestroyNotify) workspace_logical_monitor_data_free); + } + + data = g_new0 (MetaWorkspaceLogicalMonitorData, 1); + g_hash_table_insert (workspace->logical_monitor_data, logical_monitor, data); + + return data; +} + +static void +meta_workspace_clear_logical_monitor_data (MetaWorkspace *workspace) +{ + g_clear_pointer (&workspace->logical_monitor_data, g_hash_table_destroy); +} + static void meta_workspace_finalize (GObject *object) { @@ -182,14 +235,12 @@ meta_workspace_new (MetaScreen *screen) workspace->mru_list = NULL; workspace->work_areas_invalid = TRUE; - workspace->work_area_monitor = NULL; workspace->work_area_screen.x = 0; workspace->work_area_screen.y = 0; workspace->work_area_screen.width = 0; workspace->work_area_screen.height = 0; workspace->screen_region = NULL; - workspace->monitor_region = NULL; workspace->screen_edges = NULL; workspace->monitor_edges = NULL; workspace->list_containing_self = g_list_prepend (NULL, workspace); @@ -273,7 +324,7 @@ meta_workspace_remove (MetaWorkspace *workspace) workspace->screen->workspaces = g_list_remove (workspace->screen->workspaces, workspace); - g_free (workspace->work_area_monitor); + meta_workspace_clear_logical_monitor_data (workspace); g_list_free (workspace->mru_list); g_list_free (workspace->list_containing_self); @@ -289,12 +340,7 @@ meta_workspace_remove (MetaWorkspace *workspace) if (!workspace->work_areas_invalid) { - int i; - workspace_free_all_struts (workspace); - for (i = 0; i < workspace->n_monitor_regions; i++) - meta_rectangle_free_list_and_elements (workspace->monitor_region[i]); - g_free (workspace->monitor_region); meta_rectangle_free_list_and_elements (workspace->screen_region); meta_rectangle_free_list_and_elements (workspace->screen_edges); meta_rectangle_free_list_and_elements (workspace->monitor_edges); @@ -677,7 +723,6 @@ meta_workspace_list_windows (MetaWorkspace *workspace) void meta_workspace_invalidate_work_area (MetaWorkspace *workspace) { - int i; GList *windows, *l; if (workspace->work_areas_invalid) @@ -697,18 +742,13 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace) if (workspace == workspace->screen->active_workspace) meta_display_cleanup_edges (workspace->screen->display); - g_free (workspace->work_area_monitor); - workspace->work_area_monitor = NULL; + meta_workspace_clear_logical_monitor_data (workspace); workspace_free_all_struts (workspace); - for (i = 0; i < workspace->n_monitor_regions; i++) - meta_rectangle_free_list_and_elements (workspace->monitor_region[i]); - g_free (workspace->monitor_region); meta_rectangle_free_list_and_elements (workspace->screen_region); meta_rectangle_free_list_and_elements (workspace->screen_edges); meta_rectangle_free_list_and_elements (workspace->monitor_edges); - workspace->monitor_region = NULL; workspace->screen_region = NULL; workspace->screen_edges = NULL; workspace->monitor_edges = NULL; @@ -755,14 +795,12 @@ ensure_work_areas_validated (MetaWorkspace *workspace) GList *windows; GList *tmp; GList *logical_monitors, *l; - int i; MetaRectangle work_area; if (!workspace->work_areas_invalid) return; g_assert (workspace->all_struts == NULL); - g_assert (workspace->monitor_region == NULL); g_assert (workspace->screen_region == NULL); g_assert (workspace->screen_edges == NULL); g_assert (workspace->monitor_edges == NULL); @@ -787,26 +825,24 @@ ensure_work_areas_validated (MetaWorkspace *workspace) /* STEP 2: Get the maximal/spanning rects for the onscreen and * on-single-monitor regions */ - g_assert (workspace->monitor_region == NULL); g_assert (workspace->screen_region == NULL); logical_monitors = meta_monitor_manager_get_logical_monitors (monitor_manager); - - workspace->n_monitor_regions = - (int) meta_monitor_manager_get_num_logical_monitors (monitor_manager); - workspace->monitor_region = g_new (GList*, workspace->n_monitor_regions); - i = 0; for (l = logical_monitors; l; l = l->next) { MetaLogicalMonitor *logical_monitor = l->data; + MetaWorkspaceLogicalMonitorData *data; - workspace->monitor_region[i] = + g_assert (!meta_workspace_get_logical_monitor_data (workspace, + logical_monitor)); + + data = meta_workspace_ensure_logical_monitor_data (workspace, + logical_monitor); + data->logical_monitor_region = meta_rectangle_get_minimal_spanning_set_for_region ( &logical_monitor->rect, workspace->all_struts); - - i++; } workspace->screen_region = @@ -871,41 +907,36 @@ ensure_work_areas_validated (MetaWorkspace *workspace) workspace->work_area_screen.height); /* Now find the work areas for each monitor */ - g_free (workspace->work_area_monitor); - workspace->n_work_area_monitor = - meta_monitor_manager_get_num_logical_monitors (monitor_manager); - workspace->work_area_monitor = g_new (MetaRectangle, - workspace->n_work_area_monitor); - - i = 0; for (l = logical_monitors; l; l = l->next) { MetaLogicalMonitor *logical_monitor = l->data; + MetaWorkspaceLogicalMonitorData *data; + data = meta_workspace_get_logical_monitor_data (workspace, + logical_monitor); work_area = logical_monitor->rect; - if (workspace->monitor_region[i] == NULL) + if (!data->logical_monitor_region) /* FIXME: constraints.c untested with this, but it might be nice for * a screen reader or magnifier. */ work_area = meta_rect (work_area.x, work_area.y, -1, -1); else - meta_rectangle_clip_to_region (workspace->monitor_region[i], + meta_rectangle_clip_to_region (data->logical_monitor_region, FIXED_DIRECTION_NONE, &work_area); - workspace->work_area_monitor[i] = work_area; + data->logical_monitor_work_area = work_area; + meta_topic (META_DEBUG_WORKAREA, "Computed work area for workspace %d " "monitor %d: %d,%d %d x %d\n", meta_workspace_index (workspace), - i, - workspace->work_area_monitor[i].x, - workspace->work_area_monitor[i].y, - workspace->work_area_monitor[i].width, - workspace->work_area_monitor[i].height); - - i++; + logical_monitor->number, + data->logical_monitor_work_area.x, + data->logical_monitor_work_area.y, + data->logical_monitor_work_area.width, + data->logical_monitor_work_area.height); } /* STEP 4: Make sure the screen_region is nonempty (separate from step 2 @@ -1061,20 +1092,20 @@ meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace, int which_monitor, MetaRectangle *area) { -#ifndef G_DISABLE_ASSERT MetaBackend *backend = meta_get_backend(); MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); - int n_logical_monitors = - meta_monitor_manager_get_num_logical_monitors (monitor_manager); -#endif - - g_assert (which_monitor >= 0); + MetaLogicalMonitor *logical_monitor; + MetaWorkspaceLogicalMonitorData *data; ensure_work_areas_validated (workspace); - g_assert (which_monitor < n_logical_monitors); - *area = workspace->work_area_monitor[which_monitor]; + logical_monitor = + meta_monitor_manager_get_logical_monitor_from_number (monitor_manager, + which_monitor); + data = meta_workspace_get_logical_monitor_data (workspace, logical_monitor); + + *area = data->logical_monitor_work_area; } /** @@ -1101,13 +1132,17 @@ meta_workspace_get_onscreen_region (MetaWorkspace *workspace) return workspace->screen_region; } -GList* -meta_workspace_get_onmonitor_region (MetaWorkspace *workspace, - int which_monitor) +GList * +meta_workspace_get_onmonitor_region (MetaWorkspace *workspace, + MetaLogicalMonitor *logical_monitor) { + MetaWorkspaceLogicalMonitorData *data; + ensure_work_areas_validated (workspace); - return workspace->monitor_region[which_monitor]; + data = meta_workspace_get_logical_monitor_data (workspace, logical_monitor); + + return data->logical_monitor_region; } #ifdef WITH_VERBOSE_MODE