From 297ae747716debbed71df357c370decdaaf14648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 14 May 2024 17:19:59 +0200 Subject: [PATCH] window: Replace 'winsys_id' for monitor matching Instead use an abstract "logical monitor id" that is generated from the logical monitor. Instead of using low level numbers from the mode setting devices, use either data from the EDID, or the connector, if the EDID is not useful. This should help with windows remembering monitor positions when the same monitor reappears but with another mode setting device ID. Part-of: --- src/backends/meta-logical-monitor.c | 95 ++++++++++++++++++++++------- src/backends/meta-logical-monitor.h | 23 ++++--- src/backends/meta-monitor.c | 40 +++++------- src/core/window-private.h | 2 +- src/core/window.c | 50 ++++++++++----- 5 files changed, 138 insertions(+), 72 deletions(-) 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);