1
0
Fork 0

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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3753>
This commit is contained in:
Jonas Ådahl 2024-05-14 17:19:59 +02:00 committed by Marge Bot
parent ad60d7123b
commit 297ae74771
5 changed files with 138 additions and 72 deletions

View file

@ -44,21 +44,14 @@
#include "backends/meta-crtc.h" #include "backends/meta-crtc.h"
#include "backends/meta-output.h" #include "backends/meta-output.h"
G_DEFINE_TYPE (MetaLogicalMonitor, meta_logical_monitor, G_TYPE_OBJECT) typedef struct _MetaLogicalMonitorPrivate
static MetaMonitor *
get_first_monitor (MetaMonitorManager *monitor_manager,
GList *monitor_configs)
{ {
MetaMonitorConfig *first_monitor_config; MetaLogicalMonitorId *id;
MetaMonitorSpec *first_monitor_spec; } MetaLogicalMonitorPrivate;
first_monitor_config = g_list_first (monitor_configs)->data; G_DEFINE_TYPE_WITH_PRIVATE (MetaLogicalMonitor,
first_monitor_spec = first_monitor_config->monitor_spec; meta_logical_monitor,
G_TYPE_OBJECT)
return meta_monitor_manager_get_monitor_from_spec (monitor_manager,
first_monitor_spec);
}
typedef struct typedef struct
{ {
@ -87,17 +80,12 @@ meta_logical_monitor_new (MetaMonitorManager *monitor_manager,
{ {
MetaLogicalMonitor *logical_monitor; MetaLogicalMonitor *logical_monitor;
GList *monitor_configs; GList *monitor_configs;
MetaMonitor *first_monitor;
MetaOutput *main_output;
logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL); logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL);
monitor_configs = logical_monitor_config->monitor_configs; 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->number = monitor_number;
logical_monitor->winsys_id = meta_output_get_id (main_output);
logical_monitor->scale = logical_monitor_config->scale; logical_monitor->scale = logical_monitor_config->scale;
logical_monitor->transform = logical_monitor_config->transform; logical_monitor->transform = logical_monitor_config->transform;
logical_monitor->in_fullscreen = -1; logical_monitor->in_fullscreen = -1;
@ -137,16 +125,13 @@ meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager,
int monitor_number) int monitor_number)
{ {
MetaLogicalMonitor *logical_monitor; MetaLogicalMonitor *logical_monitor;
MetaOutput *main_output;
MetaMonitorTransform transform; MetaMonitorTransform transform;
logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL); logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL);
transform = derive_monitor_transform (monitor); transform = derive_monitor_transform (monitor);
main_output = meta_monitor_get_main_output (monitor);
logical_monitor->number = monitor_number; logical_monitor->number = monitor_number;
logical_monitor->winsys_id = meta_output_get_id (main_output);
logical_monitor->scale = scale; logical_monitor->scale = scale;
logical_monitor->transform = transform; logical_monitor->transform = transform;
logical_monitor->in_fullscreen = -1; logical_monitor->in_fullscreen = -1;
@ -158,10 +143,34 @@ meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager,
return logical_monitor; 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 void
meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor, meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
MetaMonitor *monitor) MetaMonitor *monitor)
{ {
MetaLogicalMonitorPrivate *priv =
meta_logical_monitor_get_instance_private (logical_monitor);
GList *l; GList *l;
gboolean is_presentation; gboolean is_presentation;
@ -187,6 +196,9 @@ meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
logical_monitor->is_presentation = is_presentation; logical_monitor->is_presentation = is_presentation;
if (!priv->id)
priv->id = generate_id (logical_monitor);
meta_monitor_set_logical_monitor (monitor, logical_monitor); meta_monitor_set_logical_monitor (monitor, logical_monitor);
} }
@ -282,6 +294,8 @@ static void
meta_logical_monitor_dispose (GObject *object) meta_logical_monitor_dispose (GObject *object)
{ {
MetaLogicalMonitor *logical_monitor = META_LOGICAL_MONITOR (object); MetaLogicalMonitor *logical_monitor = META_LOGICAL_MONITOR (object);
MetaLogicalMonitorPrivate *priv =
meta_logical_monitor_get_instance_private (logical_monitor);
if (logical_monitor->monitors) if (logical_monitor->monitors)
{ {
@ -289,6 +303,8 @@ meta_logical_monitor_dispose (GObject *object)
logical_monitor->monitors = NULL; logical_monitor->monitors = NULL;
} }
g_clear_pointer (&priv->id, meta_logical_monitor_id_free);
G_OBJECT_CLASS (meta_logical_monitor_parent_class)->dispose (object); G_OBJECT_CLASS (meta_logical_monitor_parent_class)->dispose (object);
} }
@ -339,3 +355,40 @@ meta_logical_monitor_has_neighbor (MetaLogicalMonitor *logical_monitor,
return FALSE; 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);
}

View file

@ -41,19 +41,11 @@ struct _MetaLogicalMonitor
float scale; float scale;
MetaMonitorTransform transform; 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; GList *monitors;
}; };
typedef struct _MetaLogicalMonitorId MetaLogicalMonitorId;
#define META_TYPE_LOGICAL_MONITOR (meta_logical_monitor_get_type ()) #define META_TYPE_LOGICAL_MONITOR (meta_logical_monitor_get_type ())
G_DECLARE_FINAL_TYPE (MetaLogicalMonitor, meta_logical_monitor, G_DECLARE_FINAL_TYPE (MetaLogicalMonitor, meta_logical_monitor,
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, void meta_logical_monitor_foreach_crtc (MetaLogicalMonitor *logical_monitor,
MetaLogicalMonitorCrtcFunc func, MetaLogicalMonitorCrtcFunc func,
gpointer user_data); 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);

View file

@ -66,17 +66,6 @@ typedef struct _MetaMonitorPrivate
MetaLogicalMonitor *logical_monitor; 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; char *display_name;
} MetaMonitorPrivate; } MetaMonitorPrivate;
@ -424,20 +413,23 @@ meta_monitor_is_same_as (MetaMonitor *monitor,
{ {
const MetaMonitorSpec *spec = meta_monitor_get_spec (monitor); const MetaMonitorSpec *spec = meta_monitor_get_spec (monitor);
const MetaMonitorSpec *other_spec = meta_monitor_get_spec (other_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 || spec_is_unknown =
g_strcmp0 (spec->product, "unknown") == 0 || g_strcmp0 (spec->vendor, "unknown") == 0 ||
g_strcmp0 (spec->serial, "unknown") == 0) && g_strcmp0 (spec->product, "unknown") == 0 ||
(g_strcmp0 (other_spec->vendor, "unknown") == 0 || g_strcmp0 (spec->serial, "unknown") == 0;
g_strcmp0 (other_spec->product, "unknown") == 0 || other_spec_is_unknown =
g_strcmp0 (other_spec->serial, "unknown") == 0)) g_strcmp0 (other_spec->vendor, "unknown") == 0 ||
{ g_strcmp0 (other_spec->product, "unknown") == 0 ||
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); g_strcmp0 (other_spec->serial, "unknown") == 0;
MetaMonitorPrivate *other_priv =
meta_monitor_get_instance_private (other_monitor);
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) if (g_strcmp0 (spec->vendor, other_spec->vendor) != 0)
return FALSE; return FALSE;
@ -840,7 +832,6 @@ meta_monitor_normal_new (MetaMonitorManager *monitor_manager,
monitor_priv->outputs = g_list_append (NULL, g_object_ref (output)); monitor_priv->outputs = g_list_append (NULL, g_object_ref (output));
meta_output_set_monitor (output, monitor); meta_output_set_monitor (output, monitor);
monitor_priv->winsys_id = meta_output_get_id (output);
meta_monitor_generate_spec (monitor); meta_monitor_generate_spec (monitor);
meta_monitor_normal_generate_modes (monitor_normal); 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_priv->backend = meta_monitor_manager_get_backend (monitor_manager);
monitor_tiled->tile_group_id = output_info->tile_info.group_id; 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; monitor_tiled->origin_output = output;
add_tiled_monitor_outputs (meta_output_get_gpu (output), monitor_tiled); add_tiled_monitor_outputs (meta_output_get_gpu (output), monitor_tiled);

View file

@ -262,7 +262,7 @@ struct _MetaWindow
double tile_hfraction; 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 /* 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 * been overridden (via a client message), the window will cover the union of

View file

@ -325,6 +325,9 @@ meta_window_finalize (GObject *object)
if (window->cgroup_path) if (window->cgroup_path)
g_object_unref (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->startup_id);
g_free (window->role); g_free (window->role);
g_free (window->res_class); g_free (window->res_class);
@ -1129,9 +1132,10 @@ meta_window_constructed (GObject *object)
} }
if (window->monitor) if (window->monitor)
window->preferred_output_winsys_id = window->monitor->winsys_id; {
else window->preferred_logical_monitor =
window->preferred_output_winsys_id = UINT_MAX; meta_logical_monitor_dup_id (window->monitor);
}
window->tile_match = NULL; window->tile_match = NULL;
@ -3662,22 +3666,27 @@ meta_window_get_highest_scale_monitor (MetaWindow *window)
} }
static MetaLogicalMonitor * static MetaLogicalMonitor *
find_monitor_by_winsys_id (MetaWindow *window, find_monitor_by_id (MetaWindow *window,
uint64_t winsys_id) const MetaLogicalMonitorId *id)
{ {
MetaBackend *backend = backend_from_window (window); MetaBackend *backend = backend_from_window (window);
MetaMonitorManager *monitor_manager = MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend); meta_backend_get_monitor_manager (backend);
GList *logical_monitors, *l; GList *logical_monitors, *l;
if (!id)
return NULL;
logical_monitors = logical_monitors =
meta_monitor_manager_get_logical_monitors (monitor_manager); meta_monitor_manager_get_logical_monitors (monitor_manager);
for (l = logical_monitors; l; l = l->next) for (l = logical_monitors; l; l = l->next)
{ {
MetaLogicalMonitor *logical_monitor = l->data; 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; return logical_monitor;
} }
@ -3694,11 +3703,13 @@ meta_window_find_monitor_from_id (MetaWindow *window)
MetaLogicalMonitor *old_monitor = window->monitor; MetaLogicalMonitor *old_monitor = window->monitor;
MetaLogicalMonitor *new_monitor; MetaLogicalMonitor *new_monitor;
new_monitor = find_monitor_by_winsys_id (window, new_monitor = find_monitor_by_id (window, window->preferred_logical_monitor);
window->preferred_output_winsys_id);
if (old_monitor && !new_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) if (!new_monitor)
{ {
@ -3979,15 +3990,21 @@ meta_window_move_resize_internal (MetaWindow *window,
if (window->monitor) if (window->monitor)
{ {
uint64_t old_output_winsys_id; const MetaLogicalMonitorId *old_id;
const MetaLogicalMonitorId *new_id;
old_output_winsys_id = window->monitor->winsys_id;
old_id = meta_logical_monitor_get_id (window->monitor);
meta_window_update_monitor (window, update_monitor_flags); 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) 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 else
{ {
@ -4179,7 +4196,10 @@ meta_window_move_to_monitor (MetaWindow *window,
meta_window_move_between_rects (window, 0, &old_area, &new_area); 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) if (window->fullscreen || window->override_redirect)
meta_display_queue_check_fullscreen (window->display); meta_display_queue_check_fullscreen (window->display);