Blame SOURCES/0001-monitor-config-manager-Handle-multiple-builtin-panel.patch

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