monitor-manager: Don't apply configurations with unsupported color modes

The set of supported color modes of a monitor might change for the same
monitor, for example by the monitor providing different EDID blobs
depending on configuration done on the monitor itself.

When we have a color mode configured that is not actually supported by
the monitor at the moment, amend the configuration and fall back on the
default color mode.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3911
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4364>
This commit is contained in:
Jonas Ådahl 2025-03-26 00:01:04 +01:00 committed by Bruce Leidl
parent cb5d43b39a
commit e5ff0dbc81
2 changed files with 107 additions and 5 deletions

View File

@ -923,7 +923,12 @@ get_last_color_mode_for_monitor (MetaMonitorConfigManager *config_manager,
monitor_config = find_monitor_config (config, monitor); monitor_config = find_monitor_config (config, monitor);
if (monitor_config) if (monitor_config)
{ {
*out_color_mode = monitor_config->color_mode; MetaColorMode color_mode = monitor_config->color_mode;
if (!meta_monitor_is_color_mode_supported (monitor, color_mode))
continue;
*out_color_mode = color_mode;
return TRUE; return TRUE;
} }
} }

View File

@ -52,6 +52,7 @@
#include "backends/meta-monitor.h" #include "backends/meta-monitor.h"
#include "backends/meta-monitor-config-manager.h" #include "backends/meta-monitor-config-manager.h"
#include "backends/meta-monitor-config-store.h" #include "backends/meta-monitor-config-store.h"
#include "backends/meta-monitor-config-utils.h"
#include "backends/meta-output.h" #include "backends/meta-output.h"
#include "backends/meta-virtual-monitor.h" #include "backends/meta-virtual-monitor.h"
#include "clutter/clutter.h" #include "clutter/clutter.h"
@ -130,6 +131,8 @@ G_DEFINE_TYPE_WITH_PRIVATE (MetaMonitorManager, meta_monitor_manager,
static void initialize_dbus_interface (MetaMonitorManager *manager); static void initialize_dbus_interface (MetaMonitorManager *manager);
static void monitor_manager_setup_dbus_config_handlers (MetaMonitorManager *manager); static void monitor_manager_setup_dbus_config_handlers (MetaMonitorManager *manager);
static gboolean meta_monitors_config_has_monitors_connected (MetaMonitorsConfig *config,
MetaMonitorManager *manager);
static gboolean static gboolean
meta_monitor_manager_is_config_complete (MetaMonitorManager *manager, meta_monitor_manager_is_config_complete (MetaMonitorManager *manager,
MetaMonitorsConfig *config); MetaMonitorsConfig *config);
@ -692,6 +695,82 @@ should_use_stored_config (MetaMonitorManager *manager)
!meta_monitor_manager_has_hotplug_mode_update (manager)); !meta_monitor_manager_has_hotplug_mode_update (manager));
} }
static gboolean
is_logical_monitor_config_amend_needed (MetaMonitorManager *manager,
MetaLogicalMonitorConfig *logical_monitor_config)
{
GList *l;
for (l = logical_monitor_config->monitor_configs; l; l = l->next)
{
MetaMonitorConfig *monitor_config = l->data;
MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec;
MetaMonitor *monitor;
monitor = meta_monitor_manager_get_monitor_from_spec (manager,
monitor_spec);
if (!meta_monitor_is_color_mode_supported (monitor,
monitor_config->color_mode))
return TRUE;
}
return FALSE;
}
static gboolean
is_monitors_config_amend_needed (MetaMonitorManager *manager,
MetaMonitorsConfig *config)
{
GList *l;
g_assert (meta_monitors_config_has_monitors_connected (config, manager));
for (l = config->logical_monitor_configs; l; l = l->next)
{
MetaLogicalMonitorConfig *logical_monitor_config = l->data;
if (is_logical_monitor_config_amend_needed (manager,
logical_monitor_config))
return TRUE;
}
return FALSE;
}
static void
amend_monitor_config (MetaMonitorConfig *monitor_config,
MetaMonitorManager *manager)
{
MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec;
MetaMonitor *monitor;
monitor = meta_monitor_manager_get_monitor_from_spec (manager,
monitor_spec);
if (!meta_monitor_is_color_mode_supported (monitor,
monitor_config->color_mode))
monitor_config->color_mode = META_COLOR_MODE_DEFAULT;
}
static void
amend_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config,
MetaMonitorManager *manager)
{
g_list_foreach (logical_monitor_config->monitor_configs,
(GFunc) amend_monitor_config,
manager);
}
static void
amend_monitors_config (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
MetaMonitorsConfig *base_config)
{
g_list_foreach (config->logical_monitor_configs,
(GFunc) amend_logical_monitor_config,
manager);
meta_monitors_config_set_parent_config (config, base_config);
}
MetaMonitorsConfig * MetaMonitorsConfig *
meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
{ {
@ -714,6 +793,7 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
if (config) if (config)
{ {
g_autoptr (MetaMonitorsConfig) oriented_config = NULL; g_autoptr (MetaMonitorsConfig) oriented_config = NULL;
g_autoptr (MetaMonitorsConfig) amended_config = NULL;
if (manager->panel_orientation_managed) if (manager->panel_orientation_managed)
{ {
@ -724,6 +804,13 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
config = oriented_config; config = oriented_config;
} }
if (is_monitors_config_amend_needed (manager, config))
{
amended_config = meta_monitors_config_copy (config);
amend_monitors_config (manager, amended_config, config);
config = amended_config;
}
if (!meta_monitor_manager_apply_monitors_config (manager, if (!meta_monitor_manager_apply_monitors_config (manager,
config, config,
method, method,
@ -798,6 +885,7 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
if (config) if (config)
{ {
g_autoptr (MetaMonitorsConfig) oriented_config = NULL; g_autoptr (MetaMonitorsConfig) oriented_config = NULL;
g_autoptr (MetaMonitorsConfig) amended_config = NULL;
if (manager->panel_orientation_managed) if (manager->panel_orientation_managed)
{ {
@ -809,26 +897,35 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
config = oriented_config; config = oriented_config;
} }
config = g_object_ref (config);
if (meta_monitor_manager_is_config_complete (manager, config)) if (meta_monitor_manager_is_config_complete (manager, config))
{ {
if (is_monitors_config_amend_needed (manager, config))
{
amended_config = meta_monitors_config_copy (config);
amend_monitors_config (manager, amended_config, config);
config = amended_config;
}
if (!meta_monitor_manager_apply_monitors_config (manager, if (!meta_monitor_manager_apply_monitors_config (manager,
config, config,
method, method,
&error)) &error))
{ {
config = NULL;
g_warning ("Failed to use suggested monitor configuration: %s", g_warning ("Failed to use suggested monitor configuration: %s",
error->message); error->message);
g_clear_error (&error); g_clear_error (&error);
} }
else else
{ {
config = g_object_ref (config);
goto done; goto done;
} }
} }
else
g_clear_object (&config); {
config = NULL;
}
} }
config = meta_monitor_config_manager_create_linear (manager->config_manager); config = meta_monitor_config_manager_create_linear (manager->config_manager);