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
This commit is contained in:
Jonas Ådahl 2016-12-02 17:39:01 +08:00
parent 6de3e4a07e
commit 68f3b5849a
3 changed files with 96 additions and 65 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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