diff --git a/src/backends/meta-logical-monitor.c b/src/backends/meta-logical-monitor.c index c6946e953..75b72212b 100644 --- a/src/backends/meta-logical-monitor.c +++ b/src/backends/meta-logical-monitor.c @@ -44,21 +44,14 @@ #include "backends/meta-crtc.h" #include "backends/meta-output.h" -G_DEFINE_TYPE (MetaLogicalMonitor, meta_logical_monitor, G_TYPE_OBJECT) - -static MetaMonitor * -get_first_monitor (MetaMonitorManager *monitor_manager, - GList *monitor_configs) +typedef struct _MetaLogicalMonitorPrivate { - MetaMonitorConfig *first_monitor_config; - MetaMonitorSpec *first_monitor_spec; + MetaLogicalMonitorId *id; +} MetaLogicalMonitorPrivate; - first_monitor_config = g_list_first (monitor_configs)->data; - first_monitor_spec = first_monitor_config->monitor_spec; - - return meta_monitor_manager_get_monitor_from_spec (monitor_manager, - first_monitor_spec); -} +G_DEFINE_TYPE_WITH_PRIVATE (MetaLogicalMonitor, + meta_logical_monitor, + G_TYPE_OBJECT) typedef struct { @@ -87,17 +80,12 @@ meta_logical_monitor_new (MetaMonitorManager *monitor_manager, { MetaLogicalMonitor *logical_monitor; GList *monitor_configs; - MetaMonitor *first_monitor; - MetaOutput *main_output; logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL); monitor_configs = logical_monitor_config->monitor_configs; - first_monitor = get_first_monitor (monitor_manager, monitor_configs); - main_output = meta_monitor_get_main_output (first_monitor); logical_monitor->number = monitor_number; - logical_monitor->winsys_id = meta_output_get_id (main_output); logical_monitor->scale = logical_monitor_config->scale; logical_monitor->transform = logical_monitor_config->transform; logical_monitor->in_fullscreen = -1; @@ -137,16 +125,13 @@ meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager, int monitor_number) { MetaLogicalMonitor *logical_monitor; - MetaOutput *main_output; MetaMonitorTransform transform; logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL); transform = derive_monitor_transform (monitor); - main_output = meta_monitor_get_main_output (monitor); logical_monitor->number = monitor_number; - logical_monitor->winsys_id = meta_output_get_id (main_output); logical_monitor->scale = scale; logical_monitor->transform = transform; logical_monitor->in_fullscreen = -1; @@ -158,10 +143,34 @@ meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager, return logical_monitor; } +static MetaLogicalMonitorId * +generate_id (MetaLogicalMonitor *logical_monitor) +{ + MetaMonitor *monitor = g_list_first (logical_monitor->monitors)->data; + MetaMonitorSpec *spec = meta_monitor_get_spec (monitor); + + if (g_strcmp0 (spec->vendor, "unknown") == 0 || + g_strcmp0 (spec->product, "unknown") == 0 || + g_strcmp0 (spec->serial, "unknown") == 0) + { + return (MetaLogicalMonitorId *) g_strdup_printf ("CONNECTOR:%s", + spec->connector); + } + else + { + return (MetaLogicalMonitorId *) g_strdup_printf ("EDID:%s:%s:%s", + spec->vendor, + spec->product, + spec->serial); + } +} + void meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor, MetaMonitor *monitor) { + MetaLogicalMonitorPrivate *priv = + meta_logical_monitor_get_instance_private (logical_monitor); GList *l; gboolean is_presentation; @@ -187,6 +196,9 @@ meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor, logical_monitor->is_presentation = is_presentation; + if (!priv->id) + priv->id = generate_id (logical_monitor); + meta_monitor_set_logical_monitor (monitor, logical_monitor); } @@ -282,6 +294,8 @@ static void meta_logical_monitor_dispose (GObject *object) { MetaLogicalMonitor *logical_monitor = META_LOGICAL_MONITOR (object); + MetaLogicalMonitorPrivate *priv = + meta_logical_monitor_get_instance_private (logical_monitor); if (logical_monitor->monitors) { @@ -289,6 +303,8 @@ meta_logical_monitor_dispose (GObject *object) logical_monitor->monitors = NULL; } + g_clear_pointer (&priv->id, meta_logical_monitor_id_free); + G_OBJECT_CLASS (meta_logical_monitor_parent_class)->dispose (object); } @@ -339,3 +355,40 @@ meta_logical_monitor_has_neighbor (MetaLogicalMonitor *logical_monitor, return FALSE; } + +void +meta_logical_monitor_id_free (MetaLogicalMonitorId *id) +{ + g_free (id); +} + +MetaLogicalMonitorId * +meta_logical_monitor_id_dup (const MetaLogicalMonitorId *id) +{ + return (MetaLogicalMonitorId *) g_strdup ((char *) id); +} + +gboolean +meta_logical_monitor_id_equal (const MetaLogicalMonitorId *id, + const MetaLogicalMonitorId *other_id) +{ + return g_str_equal ((const char *) id, (const char *) other_id); +} + +const MetaLogicalMonitorId * +meta_logical_monitor_get_id (MetaLogicalMonitor *logical_monitor) +{ + MetaLogicalMonitorPrivate *priv = + meta_logical_monitor_get_instance_private (logical_monitor); + + return priv->id; +} + +MetaLogicalMonitorId * +meta_logical_monitor_dup_id (MetaLogicalMonitor *logical_monitor) +{ + MetaLogicalMonitorPrivate *priv = + meta_logical_monitor_get_instance_private (logical_monitor); + + return meta_logical_monitor_id_dup (priv->id); +} diff --git a/src/backends/meta-logical-monitor.h b/src/backends/meta-logical-monitor.h index 824d804f2..3a261aa94 100644 --- a/src/backends/meta-logical-monitor.h +++ b/src/backends/meta-logical-monitor.h @@ -41,19 +41,11 @@ struct _MetaLogicalMonitor float scale; MetaMonitorTransform transform; - /* The primary or first output for this monitor, 0 if we can't figure out. - It can be matched to a winsys_id of a MetaOutput. - - This is used as an opaque token on reconfiguration when switching from - clone to extended, to decide on what output the windows should go next - (it's an attempt to keep windows on the same monitor, and preferably on - the primary one). - */ - uint64_t winsys_id; - GList *monitors; }; +typedef struct _MetaLogicalMonitorId MetaLogicalMonitorId; + #define META_TYPE_LOGICAL_MONITOR (meta_logical_monitor_get_type ()) G_DECLARE_FINAL_TYPE (MetaLogicalMonitor, meta_logical_monitor, META, LOGICAL_MONITOR, @@ -100,3 +92,14 @@ gboolean meta_logical_monitor_has_neighbor (MetaLogicalMonitor *logical_monito void meta_logical_monitor_foreach_crtc (MetaLogicalMonitor *logical_monitor, MetaLogicalMonitorCrtcFunc func, gpointer user_data); + +void meta_logical_monitor_id_free (MetaLogicalMonitorId *id); + +MetaLogicalMonitorId * meta_logical_monitor_id_dup (const MetaLogicalMonitorId *id); + +gboolean meta_logical_monitor_id_equal (const MetaLogicalMonitorId *id, + const MetaLogicalMonitorId *other_id); + +const MetaLogicalMonitorId * meta_logical_monitor_get_id (MetaLogicalMonitor *logical_monitor); + +MetaLogicalMonitorId * meta_logical_monitor_dup_id (MetaLogicalMonitor *logical_monitor); diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c index 0fad87c73..9cbd7cbb8 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -66,17 +66,6 @@ typedef struct _MetaMonitorPrivate MetaLogicalMonitor *logical_monitor; - /* - * The primary or first output for this monitor, 0 if we can't figure out. - * It can be matched to a winsys_id of a MetaOutput. - * - * This is used as an opaque token on reconfiguration when switching from - * clone to extended, to decide on what output the windows should go next - * (it's an attempt to keep windows on the same monitor, and preferably on - * the primary one). - */ - uint64_t winsys_id; - char *display_name; } MetaMonitorPrivate; @@ -424,20 +413,23 @@ meta_monitor_is_same_as (MetaMonitor *monitor, { const MetaMonitorSpec *spec = meta_monitor_get_spec (monitor); const MetaMonitorSpec *other_spec = meta_monitor_get_spec (other_monitor); + gboolean spec_is_unknown; + gboolean other_spec_is_unknown; - if ((g_strcmp0 (spec->vendor, "unknown") == 0 || - g_strcmp0 (spec->product, "unknown") == 0 || - g_strcmp0 (spec->serial, "unknown") == 0) && - (g_strcmp0 (other_spec->vendor, "unknown") == 0 || - g_strcmp0 (other_spec->product, "unknown") == 0 || - g_strcmp0 (other_spec->serial, "unknown") == 0)) - { - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - MetaMonitorPrivate *other_priv = - meta_monitor_get_instance_private (other_monitor); + spec_is_unknown = + g_strcmp0 (spec->vendor, "unknown") == 0 || + g_strcmp0 (spec->product, "unknown") == 0 || + g_strcmp0 (spec->serial, "unknown") == 0; + other_spec_is_unknown = + g_strcmp0 (other_spec->vendor, "unknown") == 0 || + g_strcmp0 (other_spec->product, "unknown") == 0 || + g_strcmp0 (other_spec->serial, "unknown") == 0; - return priv->winsys_id == other_priv->winsys_id; - } + if (spec_is_unknown && other_spec_is_unknown) + return g_strcmp0 (spec->connector, other_spec->connector) == 0; + + if (spec_is_unknown || other_spec_is_unknown) + return FALSE; if (g_strcmp0 (spec->vendor, other_spec->vendor) != 0) return FALSE; @@ -840,7 +832,6 @@ meta_monitor_normal_new (MetaMonitorManager *monitor_manager, monitor_priv->outputs = g_list_append (NULL, g_object_ref (output)); meta_output_set_monitor (output, monitor); - monitor_priv->winsys_id = meta_output_get_id (output); meta_monitor_generate_spec (monitor); meta_monitor_normal_generate_modes (monitor_normal); @@ -1553,7 +1544,6 @@ meta_monitor_tiled_new (MetaMonitorManager *monitor_manager, monitor_priv->backend = meta_monitor_manager_get_backend (monitor_manager); monitor_tiled->tile_group_id = output_info->tile_info.group_id; - monitor_priv->winsys_id = meta_output_get_id (output); monitor_tiled->origin_output = output; add_tiled_monitor_outputs (meta_output_get_gpu (output), monitor_tiled); diff --git a/src/core/window-private.h b/src/core/window-private.h index 57d8be670..492d247a5 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -262,7 +262,7 @@ struct _MetaWindow double tile_hfraction; - uint64_t preferred_output_winsys_id; + MetaLogicalMonitorId *preferred_logical_monitor; /* Area to cover when in fullscreen mode. If _NET_WM_FULLSCREEN_MONITORS has * been overridden (via a client message), the window will cover the union of diff --git a/src/core/window.c b/src/core/window.c index d90859e49..395bbea1c 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -325,6 +325,9 @@ meta_window_finalize (GObject *object) if (window->cgroup_path) g_object_unref (window->cgroup_path); + g_clear_pointer (&window->preferred_logical_monitor, + meta_logical_monitor_id_free); + g_free (window->startup_id); g_free (window->role); g_free (window->res_class); @@ -1129,9 +1132,10 @@ meta_window_constructed (GObject *object) } if (window->monitor) - window->preferred_output_winsys_id = window->monitor->winsys_id; - else - window->preferred_output_winsys_id = UINT_MAX; + { + window->preferred_logical_monitor = + meta_logical_monitor_dup_id (window->monitor); + } window->tile_match = NULL; @@ -3662,22 +3666,27 @@ meta_window_get_highest_scale_monitor (MetaWindow *window) } static MetaLogicalMonitor * -find_monitor_by_winsys_id (MetaWindow *window, - uint64_t winsys_id) +find_monitor_by_id (MetaWindow *window, + const MetaLogicalMonitorId *id) { MetaBackend *backend = backend_from_window (window); MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); GList *logical_monitors, *l; + if (!id) + return NULL; + logical_monitors = meta_monitor_manager_get_logical_monitors (monitor_manager); for (l = logical_monitors; l; l = l->next) { MetaLogicalMonitor *logical_monitor = l->data; + const MetaLogicalMonitorId *other_id = + meta_logical_monitor_get_id (logical_monitor); - if (logical_monitor->winsys_id == winsys_id) + if (meta_logical_monitor_id_equal (id, other_id)) return logical_monitor; } @@ -3694,11 +3703,13 @@ meta_window_find_monitor_from_id (MetaWindow *window) MetaLogicalMonitor *old_monitor = window->monitor; MetaLogicalMonitor *new_monitor; - new_monitor = find_monitor_by_winsys_id (window, - window->preferred_output_winsys_id); + new_monitor = find_monitor_by_id (window, window->preferred_logical_monitor); if (old_monitor && !new_monitor) - new_monitor = find_monitor_by_winsys_id (window, old_monitor->winsys_id); + { + new_monitor = find_monitor_by_id (window, + meta_logical_monitor_get_id (old_monitor)); + } if (!new_monitor) { @@ -3979,15 +3990,21 @@ meta_window_move_resize_internal (MetaWindow *window, if (window->monitor) { - uint64_t old_output_winsys_id; - - old_output_winsys_id = window->monitor->winsys_id; + const MetaLogicalMonitorId *old_id; + const MetaLogicalMonitorId *new_id; + old_id = meta_logical_monitor_get_id (window->monitor); meta_window_update_monitor (window, update_monitor_flags); + new_id = meta_logical_monitor_get_id (window->monitor); - if (old_output_winsys_id != window->monitor->winsys_id && + if (!meta_logical_monitor_id_equal (old_id, new_id) && flags & META_MOVE_RESIZE_MOVE_ACTION && flags & META_MOVE_RESIZE_USER_ACTION) - window->preferred_output_winsys_id = window->monitor->winsys_id; + { + g_clear_pointer (&window->preferred_logical_monitor, + meta_logical_monitor_id_free); + window->preferred_logical_monitor = + meta_logical_monitor_id_dup (new_id); + } } else { @@ -4179,7 +4196,10 @@ meta_window_move_to_monitor (MetaWindow *window, meta_window_move_between_rects (window, 0, &old_area, &new_area); } - window->preferred_output_winsys_id = window->monitor->winsys_id; + g_clear_pointer (&window->preferred_logical_monitor, + meta_logical_monitor_id_free); + window->preferred_logical_monitor = + meta_logical_monitor_dup_id (window->monitor); if (window->fullscreen || window->override_redirect) meta_display_queue_check_fullscreen (window->display);