You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mutter/SOURCES/0001-monitor-config-manager...

212 lines
6.3 KiB

From 19024a5b2eff02b22cdb3fc90142f522dd361996 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 27 Nov 2020 09:03:38 +0100
Subject: [PATCH] monitor-config-manager: Handle multiple builtin panels
gracefully
While multiple built-in panels isn't actually supported in any
meaningful manner, if we would ever end up with such a situation, e.g.
due to kernel bugs[0], we shouldn't crash when trying to set an
'external only' without any external monitors.
While we could handle this with more degraded functionality (e.g. don't
support the 'switch' method of monitor configuration at all), handle it
by simply not trying to switch to external-only when there are no,
according to the kernel, external monitors available. This would e.g.
still allow betwene 'mirror-all', and 'linear' switches.
The crash itself was disguised as an arbitrary X11 BadValue error, due
to mutter trying to resize the root window to 0x0, as the monitor
configuration that was applied consisted of zero logical monitors, thus
was effectively empty.
[0] https://bugzilla.redhat.com/show_bug.cgi?id=1896904
Related: https://bugzilla.redhat.com/show_bug.cgi?id=1899260
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1607>
---
src/backends/meta-monitor-config-manager.c | 3 +
src/tests/monitor-unit-tests.c | 145 +++++++++++++++++++++
2 files changed, 148 insertions(+)
diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
index bc1a39db8..d62bad52d 100644
--- a/src/backends/meta-monitor-config-manager.c
+++ b/src/backends/meta-monitor-config-manager.c
@@ -1157,6 +1157,9 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager)
x += logical_monitor_config->layout.width;
}
+ if (!logical_monitor_configs)
+ return NULL;
+
return meta_monitors_config_new (monitor_manager,
logical_monitor_configs,
layout_mode,
diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c
index f47544b03..725f84173 100644
--- a/src/tests/monitor-unit-tests.c
+++ b/src/tests/monitor-unit-tests.c
@@ -3175,6 +3175,149 @@ meta_test_monitor_non_upright_panel (void)
check_monitor_configuration (&test_case);
}
+static void
+meta_test_monitor_switch_external_without_external (void)
+{
+ MonitorTestCase test_case = {
+ .setup = {
+ .modes = {
+ {
+ .width = 1024,
+ .height = 768,
+ .refresh_rate = 60.0
+ }
+ },
+ .n_modes = 1,
+ .outputs = {
+ {
+ .crtc = 0,
+ .modes = { 0 },
+ .n_modes = 1,
+ .preferred_mode = 0,
+ .possible_crtcs = { 0 },
+ .n_possible_crtcs = 1,
+ .width_mm = 222,
+ .height_mm = 125,
+ .is_laptop_panel = TRUE
+ },
+ {
+ .crtc = 1,
+ .modes = { 0 },
+ .n_modes = 1,
+ .preferred_mode = 0,
+ .possible_crtcs = { 1 },
+ .n_possible_crtcs = 1,
+ .width_mm = 222,
+ .height_mm = 125,
+ .is_laptop_panel = TRUE
+ }
+ },
+ .n_outputs = 2,
+ .crtcs = {
+ {
+ .current_mode = 0
+ },
+ {
+ .current_mode = 0
+ }
+ },
+ .n_crtcs = 2
+ },
+
+ .expect = {
+ .monitors = {
+ {
+ .outputs = { 0 },
+ .n_outputs = 1,
+ .modes = {
+ {
+ .width = 1024,
+ .height = 768,
+ .refresh_rate = 60.0,
+ .crtc_modes = {
+ {
+ .output = 0,
+ .crtc_mode = 0
+ }
+ }
+ }
+ },
+ .n_modes = 1,
+ .current_mode = 0,
+ .width_mm = 222,
+ .height_mm = 125
+ },
+ {
+ .outputs = { 1 },
+ .n_outputs = 1,
+ .modes = {
+ {
+ .width = 1024,
+ .height = 768,
+ .refresh_rate = 60.0,
+ .crtc_modes = {
+ {
+ .output = 1,
+ .crtc_mode = 0
+ }
+ }
+ }
+ },
+ .n_modes = 1,
+ .current_mode = 0,
+ .width_mm = 222,
+ .height_mm = 125
+ }
+ },
+ .n_monitors = 2,
+ .logical_monitors = {
+ {
+ .monitors = { 0 },
+ .n_monitors = 1,
+ .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 },
+ .scale = 1
+ },
+ {
+ .monitors = { 1 },
+ .n_monitors = 1,
+ .layout = { .x = 1024, .y = 0, .width = 1024, .height = 768 },
+ .scale = 1
+ }
+ },
+ .n_logical_monitors = 2,
+ .primary_logical_monitor = 0,
+ .n_outputs = 2,
+ .crtcs = {
+ {
+ .current_mode = 0,
+ },
+ {
+ .current_mode = 0,
+ },
+ },
+ .n_crtcs = 2,
+ .n_tiled_monitors = 0,
+ .screen_width = 2048,
+ .screen_height = 768
+ }
+ };
+ MetaMonitorTestSetup *test_setup;
+ MetaBackend *backend = meta_get_backend ();
+ MetaMonitorManager *monitor_manager =
+ meta_backend_get_monitor_manager (backend);
+
+ test_setup = create_monitor_test_setup (&test_case.setup,
+ MONITOR_TEST_FLAG_NO_STORED);
+ emulate_hotplug (test_setup);
+ check_monitor_configuration (&test_case);
+
+ meta_monitor_manager_switch_config (monitor_manager,
+ META_MONITOR_SWITCH_CONFIG_EXTERNAL);
+ check_monitor_configuration (&test_case);
+
+ check_monitor_test_clients_state ();
+}
+
static void
meta_test_monitor_custom_vertical_config (void)
{
@@ -5969,6 +6112,8 @@ init_monitor_tests (void)
meta_test_monitor_preferred_non_first_mode);
add_monitor_test ("/backends/monitor/non-upright-panel",
meta_test_monitor_non_upright_panel);
+ add_monitor_test ("/backends/monitor/switch-external-without-external",
+ meta_test_monitor_switch_external_without_external);
add_monitor_test ("/backends/monitor/custom/vertical-config",
meta_test_monitor_custom_vertical_config);
--
2.29.2