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

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