summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2020-11-27 08:03:38 +0000
committerJonas Ådahl <jadahl@gmail.com>2020-11-27 13:30:00 +0000
commitf6a13ef7a9ff764a8b90745abd6e898580976aa3 (patch)
treeafcc713b6b7a9d74d05322562ea1f51af7c7ffb7
parenta54d38e03e1d2c50668464ef1d5fabeee849456d (diff)
downloadmutter-cherry-pick-f6db6cd2.tar.gz
monitor-config-manager: Handle multiple builtin panels gracefullycherry-pick-f6db6cd2
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 (cherry picked from commit f6db6cd2032a1c85c137935907fd9e5c756a5f06) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1608>
-rw-r--r--src/backends/meta-monitor-config-manager.c3
-rw-r--r--src/tests/monitor-unit-tests.c146
2 files changed, 149 insertions, 0 deletions
diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
index b317aca0e..1ef92c2d4 100644
--- a/src/backends/meta-monitor-config-manager.c
+++ b/src/backends/meta-monitor-config-manager.c
@@ -1225,6 +1225,9 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager)
x += logical_monitor_config->layout.width;
}
+ if (!logical_monitor_configs)
+ return NULL;
+
monitors_config = 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 6cce73997..f2a3da6a9 100644
--- a/src/tests/monitor-unit-tests.c
+++ b/src/tests/monitor-unit-tests.c
@@ -2507,6 +2507,150 @@ meta_test_monitor_non_upright_panel (void)
}
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,
+ .x = 1024,
+ },
+ },
+ .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.expect);
+
+ meta_monitor_manager_switch_config (monitor_manager,
+ META_MONITOR_SWITCH_CONFIG_EXTERNAL);
+ check_monitor_configuration (&test_case.expect);
+
+ check_monitor_test_clients_state ();
+}
+
+static void
meta_test_monitor_custom_vertical_config (void)
{
MonitorTestCase test_case = {
@@ -5656,6 +5800,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);