diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml
index 8c1b951a7..cf9db4fd4 100644
--- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml
+++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml
@@ -521,5 +521,12 @@
+
+
+
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index 921d1dcbb..eb5907469 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -1205,11 +1205,36 @@ update_night_light_supported (MetaMonitorManager *manager)
night_light_supported);
}
+static void
+update_has_external_monitor (MetaMonitorManager *monitor_manager)
+{
+ GList *l;
+ gboolean has_external_monitor = FALSE;
+
+ for (l = meta_monitor_manager_get_monitors (monitor_manager); l; l = l->next)
+ {
+ MetaMonitor *monitor = l->data;
+
+ if (meta_monitor_is_laptop_panel (monitor))
+ continue;
+
+ if (!meta_monitor_is_active (monitor))
+ continue;
+
+ has_external_monitor = TRUE;
+ break;
+ }
+
+ meta_dbus_display_config_set_has_external_monitor (monitor_manager->display_config,
+ has_external_monitor);
+}
+
static void
meta_monitor_manager_notify_monitors_changed (MetaMonitorManager *manager)
{
meta_backend_monitors_changed (manager->backend);
+ update_has_external_monitor (manager);
update_backlight (manager, TRUE);
g_signal_emit (manager, signals[MONITORS_CHANGED_INTERNAL], 0);
@@ -1247,6 +1272,7 @@ meta_monitor_manager_setup (MetaMonitorManager *manager)
meta_monitor_manager_notify_monitors_changed (manager);
+ update_has_external_monitor (manager);
update_backlight (manager, TRUE);
manager->in_init = FALSE;
diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h
index bd23d8f97..01836dc0e 100644
--- a/src/backends/meta-monitor.h
+++ b/src/backends/meta-monitor.h
@@ -124,6 +124,7 @@ gboolean meta_monitor_get_max_bpc (MetaMonitor *monitor,
MetaOutputRGBRange meta_monitor_get_rgb_range (MetaMonitor *monitor);
+META_EXPORT_TEST
gboolean meta_monitor_is_laptop_panel (MetaMonitor *monitor);
gboolean meta_monitor_is_virtual (MetaMonitor *monitor);
diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c
index 2e0539fc1..a55e06055 100644
--- a/src/tests/monitor-unit-tests.c
+++ b/src/tests/monitor-unit-tests.c
@@ -4113,6 +4113,191 @@ meta_test_monitor_switch_config_remember_scale (void)
check_monitor_test_clients_state ();
}
+static void
+wait_for_boolean_property (GDBusProxy *proxy,
+ const char *property_name,
+ gboolean expected_value)
+{
+ g_debug ("Waiting for property '%s' to become %s on '%s'",
+ property_name,
+ expected_value ? "TRUE" : "FALSE",
+ g_dbus_proxy_get_interface_name (proxy));
+
+ while (TRUE)
+ {
+ g_autoptr (GVariant) value_variant = NULL;
+
+ value_variant = g_dbus_proxy_get_cached_property (proxy, property_name);
+ g_assert_nonnull (value_variant);
+
+ if (g_variant_get_boolean (value_variant) == expected_value)
+ break;
+
+ g_main_context_iteration (NULL, TRUE);
+ }
+}
+
+static void
+proxy_ready_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GDBusProxy *proxy;
+ GDBusProxy **display_config_proxy_ptr = user_data;
+ g_autoptr (GError) error = NULL;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ g_assert_nonnull (proxy);
+ g_assert_no_error (error);
+
+ *display_config_proxy_ptr = proxy;
+}
+
+static void
+meta_test_monitor_has_external_monitor (void)
+{
+ MonitorTestCaseSetup test_case_setup = {
+ .modes = {
+ {
+ .width = 800,
+ .height = 600,
+ .refresh_rate = 60.0
+ },
+ },
+ .n_modes = 1,
+ .outputs = {
+ {
+ .crtc = -1,
+ .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 = FALSE,
+ }
+ },
+ .n_outputs = 2,
+ .crtcs = {
+ {
+ .current_mode = -1
+ }
+ },
+ .n_crtcs = 2
+ };
+ MetaBackend *backend = meta_context_get_backend (test_context);
+ MetaMonitorManager *monitor_manager =
+ meta_backend_get_monitor_manager (backend);
+ MetaMonitorTestSetup *test_setup;
+ GList *monitors;
+ MetaMonitor *first_monitor;
+ MetaMonitor *second_monitor;
+ g_autoptr (GDBusProxy) display_config_proxy = NULL;
+ g_autoptr (GError) error = NULL;
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ NULL,
+ "org.gnome.Mutter.DisplayConfig",
+ "/org/gnome/Mutter/DisplayConfig",
+ "org.gnome.Mutter.DisplayConfig",
+ NULL,
+ proxy_ready_cb,
+ &display_config_proxy);
+ while (!display_config_proxy)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_debug ("Connecting one builtin and one external monitor");
+
+ test_setup = meta_create_monitor_test_setup (test_backend,
+ &test_case_setup,
+ MONITOR_TEST_FLAG_NO_STORED);
+ emulate_hotplug (test_setup);
+
+ monitors = meta_monitor_manager_get_monitors (monitor_manager);
+ g_assert_cmpuint (g_list_length (monitors), ==, 2);
+ first_monitor = g_list_nth_data (monitors, 0);
+ second_monitor = g_list_nth_data (monitors, 1);
+ g_assert_true (meta_monitor_is_laptop_panel (first_monitor));
+ g_assert_true (meta_monitor_is_active (first_monitor));
+ g_assert_false (meta_monitor_is_laptop_panel (second_monitor));
+ g_assert_true (meta_monitor_is_active (second_monitor));
+
+ wait_for_boolean_property (G_DBUS_PROXY (display_config_proxy),
+ "HasExternalMonitor",
+ TRUE);
+
+ g_debug ("Disconnecting external monitor");
+
+ test_case_setup.n_outputs = 1;
+ test_setup = meta_create_monitor_test_setup (test_backend,
+ &test_case_setup,
+ MONITOR_TEST_FLAG_NO_STORED);
+ emulate_hotplug (test_setup);
+
+ monitors = meta_monitor_manager_get_monitors (monitor_manager);
+ g_assert_cmpuint (g_list_length (monitors), ==, 1);
+ first_monitor = g_list_nth_data (monitors, 0);
+ g_assert_true (meta_monitor_is_laptop_panel (first_monitor));
+ g_assert_true (meta_monitor_is_active (first_monitor));
+
+ wait_for_boolean_property (G_DBUS_PROXY (display_config_proxy),
+ "HasExternalMonitor",
+ FALSE);
+
+ g_debug ("Reconnect external monitor.");
+
+ test_case_setup.n_outputs = 2;
+ test_setup = meta_create_monitor_test_setup (test_backend,
+ &test_case_setup,
+ MONITOR_TEST_FLAG_NO_STORED);
+ emulate_hotplug (test_setup);
+
+ monitors = meta_monitor_manager_get_monitors (monitor_manager);
+ g_assert_cmpuint (g_list_length (monitors), ==, 2);
+ first_monitor = g_list_nth_data (monitors, 0);
+ second_monitor = g_list_nth_data (monitors, 1);
+ g_assert_true (meta_monitor_is_laptop_panel (first_monitor));
+ g_assert_true (meta_monitor_is_active (first_monitor));
+ g_assert_false (meta_monitor_is_laptop_panel (second_monitor));
+ g_assert_true (meta_monitor_is_active (second_monitor));
+
+ wait_for_boolean_property (G_DBUS_PROXY (display_config_proxy),
+ "HasExternalMonitor",
+ TRUE);
+
+ g_debug ("Disable external monitor.");
+
+ meta_monitor_manager_switch_config (monitor_manager,
+ META_MONITOR_SWITCH_CONFIG_BUILTIN);
+ while (g_main_context_iteration (NULL, FALSE));
+
+ monitors = meta_monitor_manager_get_monitors (monitor_manager);
+ g_assert_cmpuint (g_list_length (monitors), ==, 2);
+ first_monitor = g_list_nth_data (monitors, 0);
+ second_monitor = g_list_nth_data (monitors, 1);
+ g_assert_true (meta_monitor_is_laptop_panel (first_monitor));
+ g_assert_true (meta_monitor_is_active (first_monitor));
+ g_assert_false (meta_monitor_is_laptop_panel (second_monitor));
+ g_assert_false (meta_monitor_is_active (second_monitor));
+
+ wait_for_boolean_property (G_DBUS_PROXY (display_config_proxy),
+ "HasExternalMonitor",
+ FALSE);
+}
+
static void
check_monitor_configuration_per_orientation (MonitorTestCase *test_case,
unsigned int monitor_index,
@@ -10153,6 +10338,9 @@ init_monitor_tests (void)
add_monitor_test ("/backends/monitor/switch-config-remember-scale",
meta_test_monitor_switch_config_remember_scale);
+ add_monitor_test ("/backends/monitor/has-external-monitor",
+ meta_test_monitor_has_external_monitor);
+
add_monitor_test ("/backends/monitor/orientation/is-managed",
meta_test_monitor_orientation_is_managed);
add_monitor_test ("/backends/monitor/orientation/initial-rotated",