From cf077a55b77e5802475a5fe4f1314aa7c29ee593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Wed, 12 Feb 2025 18:33:35 +0100 Subject: [PATCH] Backport DRM lease configuration Backport DRM lease configuration via monitors.xml and D-Bus: - https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4112 - https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4121 Resolves: RHEL-62220 --- ...-Add-forlease-config-to-monitors.xml.patch | 338 +++++++++++++ ...Return-for-lease-status-in-GetCurren.patch | 201 ++++++++ ...r-Keep-track-of-the-for-lease-status.patch | 462 ++++++++++++++++++ ...Allow-to-check-if-config-has-a-visib.patch | 80 +++ ...Configure-for-lease-monitors-in-Appl.patch | 224 +++++++++ ...d-meta_output_kms_from_kms_connector.patch | 74 +++ ...name-meta_kms_connector_is_for_lease.patch | 78 +++ ...-Handle-monitors-configured-for-leas.patch | 130 +++++ mutter.spec | 13 + 9 files changed, 1600 insertions(+) create mode 100644 0001-monitor-manager-Add-forlease-config-to-monitors.xml.patch create mode 100644 0001-monitor-manager-Return-for-lease-status-in-GetCurren.patch create mode 100644 0002-monitor-Keep-track-of-the-for-lease-status.patch create mode 100644 0002-monitor-manager-Allow-to-check-if-config-has-a-visib.patch create mode 100644 0003-monitor-manager-Configure-for-lease-monitors-in-Appl.patch create mode 100644 0003-output-kms-Add-meta_output_kms_from_kms_connector.patch create mode 100644 0004-kms-connector-Rename-meta_kms_connector_is_for_lease.patch create mode 100644 0005-native-drm-lease-Handle-monitors-configured-for-leas.patch diff --git a/0001-monitor-manager-Add-forlease-config-to-monitors.xml.patch b/0001-monitor-manager-Add-forlease-config-to-monitors.xml.patch new file mode 100644 index 0000000..c5f1e40 --- /dev/null +++ b/0001-monitor-manager-Add-forlease-config-to-monitors.xml.patch @@ -0,0 +1,338 @@ +From 406de0d6d72bcd68ccc71880e618d933537d755c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= +Date: Mon, 28 Oct 2024 08:37:12 +0100 +Subject: [PATCH 1/5] monitor-manager: Add forlease config to monitors.xml + +Allow to configure a list of monitors as available for lease in +monitors.xml. + +The monitors available for lease, must be disabled as well. + +Part-of: +--- + src/backends/meta-monitor-config-manager.c | 23 +++++++ + src/backends/meta-monitor-config-manager.h | 2 + + src/backends/meta-monitor-config-store.c | 79 +++++++++++++++++++++- + 3 files changed, 103 insertions(+), 1 deletion(-) + +diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c +index 279169ace9..ecf4ee8202 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -1495,6 +1495,8 @@ meta_monitors_config_key_new (GList *logical_monitor_conf + } + } + ++ /* Monitors for lease must be disabled (see meta_verify_monitors_config ()). ++ Therefore, there is no need to include them here. */ + for (l = disabled_monitor_specs; l; l = l->next) + { + MetaMonitorSpec *monitor_spec = l->data; +@@ -1598,6 +1600,7 @@ meta_monitors_config_set_parent_config (MetaMonitorsConfig *config, + MetaMonitorsConfig * + meta_monitors_config_new_full (GList *logical_monitor_configs, + GList *disabled_monitor_specs, ++ GList *for_lease_monitor_specs, + MetaLogicalMonitorLayoutMode layout_mode, + MetaMonitorsConfigFlag flags) + { +@@ -1606,6 +1609,7 @@ meta_monitors_config_new_full (GList *logical_monitor_con + config = g_object_new (META_TYPE_MONITORS_CONFIG, NULL); + config->logical_monitor_configs = logical_monitor_configs; + config->disabled_monitor_specs = disabled_monitor_specs; ++ config->for_lease_monitor_specs = for_lease_monitor_specs; + config->layout_mode = layout_mode; + config->key = meta_monitors_config_key_new (logical_monitor_configs, + disabled_monitor_specs, +@@ -1649,6 +1653,7 @@ meta_monitors_config_new (MetaMonitorManager *monitor_manager, + + return meta_monitors_config_new_full (logical_monitor_configs, + disabled_monitor_specs, ++ NULL, + layout_mode, + flags); + } +@@ -1664,6 +1669,8 @@ meta_monitors_config_finalize (GObject *object) + (GDestroyNotify) meta_logical_monitor_config_free); + g_list_free_full (config->disabled_monitor_specs, + (GDestroyNotify) meta_monitor_spec_free); ++ g_list_free_full (config->for_lease_monitor_specs, ++ (GDestroyNotify) meta_monitor_spec_free); + + G_OBJECT_CLASS (meta_monitors_config_parent_class)->finalize (object); + } +@@ -1907,5 +1914,21 @@ meta_verify_monitors_config (MetaMonitorsConfig *config, + } + } + ++ for (l = config->for_lease_monitor_specs; l; l = l->next) ++ { ++ MetaMonitorSpec *monitor_spec = l->data; ++ gpointer disabled = NULL; ++ ++ disabled = g_list_find_custom (config->disabled_monitor_specs, ++ monitor_spec, ++ (GCompareFunc) meta_monitor_spec_compare); ++ if (!disabled) ++ { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, ++ "For lease monitor must be explicitly disabled"); ++ return FALSE; ++ } ++ } ++ + return TRUE; + } +diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h +index 8d21c8694c..87a29bc2dd 100644 +--- a/src/backends/meta-monitor-config-manager.h ++++ b/src/backends/meta-monitor-config-manager.h +@@ -67,6 +67,7 @@ struct _MetaMonitorsConfig + GList *logical_monitor_configs; + + GList *disabled_monitor_specs; ++ GList *for_lease_monitor_specs; + + MetaMonitorsConfigFlag flags; + +@@ -142,6 +143,7 @@ void meta_monitor_config_manager_save_current (MetaMonitorConfigManager *config_ + META_EXPORT_TEST + MetaMonitorsConfig * meta_monitors_config_new_full (GList *logical_monitor_configs, + GList *disabled_monitors, ++ GList *for_lease_monitors, + MetaLogicalMonitorLayoutMode layout_mode, + MetaMonitorsConfigFlag flags); + +diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c +index 6e8aed1f9e..eb22dc3f36 100644 +--- a/src/backends/meta-monitor-config-store.c ++++ b/src/backends/meta-monitor-config-store.c +@@ -89,6 +89,14 @@ + * Serial C + * + * ++ * ++ * ++ * LVDS3 ++ * Vendor C ++ * Product C ++ * Serial C ++ * ++ * + * + * + * +@@ -158,6 +166,7 @@ typedef enum + STATE_MONITOR_MAXBPC, + STATE_MONITOR_RGB_RANGE, + STATE_DISABLED, ++ STATE_FOR_LEASE, + STATE_POLICY, + STATE_STORES, + STATE_STORE, +@@ -184,6 +193,7 @@ typedef struct + MetaMonitorConfig *current_monitor_config; + MetaLogicalMonitorConfig *current_logical_monitor_config; + GList *current_disabled_monitor_specs; ++ GList *current_for_lease_monitor_specs; + gboolean seen_policy; + gboolean seen_stores; + gboolean seen_dbus; +@@ -333,6 +343,10 @@ handle_start_element (GMarkupParseContext *context, + { + parser->state = STATE_DISABLED; + } ++ else if (g_str_equal (element_name, "forlease")) ++ { ++ parser->state = STATE_FOR_LEASE; ++ } + else + { + enter_unknown_element (parser, element_name, +@@ -578,6 +592,22 @@ handle_start_element (GMarkupParseContext *context, + return; + } + ++ case STATE_FOR_LEASE: ++ { ++ if (!g_str_equal (element_name, "monitorspec")) ++ { ++ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, ++ "Invalid element '%s' under forlease", element_name); ++ return; ++ } ++ ++ parser->current_monitor_spec = g_new0 (MetaMonitorSpec, 1); ++ parser->monitor_spec_parent_state = STATE_FOR_LEASE; ++ parser->state = STATE_MONITOR_SPEC; ++ ++ return; ++ } ++ + case STATE_POLICY: + { + if (!(parser->extra_config_flags & +@@ -673,6 +703,15 @@ finish_monitor_spec (ConfigParser *parser) + parser->current_monitor_spec); + parser->current_monitor_spec = NULL; + ++ return; ++ } ++ case STATE_FOR_LEASE: ++ { ++ parser->current_for_lease_monitor_specs = ++ g_list_prepend (parser->current_for_lease_monitor_specs, ++ parser->current_monitor_spec); ++ parser->current_monitor_spec = NULL; ++ + return; + } + +@@ -729,12 +768,15 @@ static gboolean + detect_layout_mode_configs (MetaMonitorManager *monitor_manager, + GList *logical_monitor_configs, + GList *disabled_monitor_specs, ++ GList *for_lease_monitor_specs, + MetaMonitorsConfigFlag config_flags, + MetaMonitorsConfig **physical_layout_mode_config, + MetaMonitorsConfig **logical_layout_mode_config, + GError **error) + { +- GList *logical_monitor_configs_copy, *disabled_monitor_specs_copy; ++ GList *logical_monitor_configs_copy; ++ GList *disabled_monitor_specs_copy; ++ GList *for_lease_monitor_specs_copy; + MetaMonitorsConfig *physical_config, *logical_config; + g_autoptr (GError) local_error_physical = NULL; + g_autoptr (GError) local_error_logical = NULL; +@@ -743,12 +785,15 @@ detect_layout_mode_configs (MetaMonitorManager *monitor_manager, + meta_clone_logical_monitor_config_list (logical_monitor_configs); + disabled_monitor_specs_copy = + g_list_copy_deep (disabled_monitor_specs, (GCopyFunc) meta_monitor_spec_clone, NULL); ++ for_lease_monitor_specs_copy = ++ g_list_copy_deep (for_lease_monitor_specs, (GCopyFunc) meta_monitor_spec_clone, NULL); + + derive_logical_monitor_layouts (logical_monitor_configs, + META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL); + physical_config = + meta_monitors_config_new_full (g_steal_pointer (&logical_monitor_configs), + g_steal_pointer (&disabled_monitor_specs), ++ g_steal_pointer (&for_lease_monitor_specs), + META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL, + config_flags); + +@@ -761,6 +806,7 @@ detect_layout_mode_configs (MetaMonitorManager *monitor_manager, + logical_config = + meta_monitors_config_new_full (g_steal_pointer (&logical_monitor_configs_copy), + g_steal_pointer (&disabled_monitor_specs_copy), ++ g_steal_pointer (&for_lease_monitor_specs_copy), + META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL, + config_flags); + +@@ -1207,6 +1253,7 @@ static MetaMonitorsConfig * + attempt_layout_mode_conversion (MetaMonitorManager *monitor_manager, + GList *logical_monitor_configs, + GList *disabled_monitor_specs, ++ GList *for_lease_monitor_specs, + MetaMonitorsConfigFlag config_flags) + { + GList *logical_monitor_configs_copy; +@@ -1251,6 +1298,9 @@ create_full_config: + g_list_copy_deep (disabled_monitor_specs, + (GCopyFunc) meta_monitor_spec_clone, + NULL), ++ g_list_copy_deep (for_lease_monitor_specs, ++ (GCopyFunc) meta_monitor_spec_clone, ++ NULL), + META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL, + config_flags); + +@@ -1438,6 +1488,14 @@ handle_end_element (GMarkupParseContext *context, + return; + } + ++ case STATE_FOR_LEASE: ++ { ++ g_assert (g_str_equal (element_name, "forlease")); ++ ++ parser->state = STATE_CONFIGURATION; ++ return; ++ } ++ + case STATE_CONFIGURATION: + { + MetaMonitorConfigStore *store = parser->config_store; +@@ -1458,6 +1516,7 @@ handle_end_element (GMarkupParseContext *context, + if (!detect_layout_mode_configs (store->monitor_manager, + parser->current_logical_monitor_configs, + parser->current_disabled_monitor_specs, ++ parser->current_for_lease_monitor_specs, + config_flags, + &physical_layout_mode_config, + &logical_layout_mode_config, +@@ -1465,11 +1524,13 @@ handle_end_element (GMarkupParseContext *context, + { + parser->current_logical_monitor_configs = NULL; + parser->current_disabled_monitor_specs = NULL; ++ parser->current_for_lease_monitor_specs = NULL; + return; + } + + parser->current_logical_monitor_configs = NULL; + parser->current_disabled_monitor_specs = NULL; ++ parser->current_for_lease_monitor_specs = NULL; + + if (physical_layout_mode_config) + { +@@ -1487,6 +1548,7 @@ handle_end_element (GMarkupParseContext *context, + attempt_layout_mode_conversion (store->monitor_manager, + physical_layout_mode_config->logical_monitor_configs, + physical_layout_mode_config->disabled_monitor_specs, ++ physical_layout_mode_config->for_lease_monitor_specs, + config_flags); + } + } +@@ -1508,11 +1570,13 @@ handle_end_element (GMarkupParseContext *context, + config = + meta_monitors_config_new_full (parser->current_logical_monitor_configs, + parser->current_disabled_monitor_specs, ++ parser->current_for_lease_monitor_specs, + layout_mode, + config_flags); + + parser->current_logical_monitor_configs = NULL; + parser->current_disabled_monitor_specs = NULL; ++ parser->current_for_lease_monitor_specs = NULL; + + if (!meta_verify_monitors_config (config, store->monitor_manager, + error)) +@@ -1747,6 +1811,7 @@ handle_text (GMarkupParseContext *context, + case STATE_MONITOR_MODE: + case STATE_TRANSFORM: + case STATE_DISABLED: ++ case STATE_FOR_LEASE: + case STATE_POLICY: + case STATE_STORES: + { +@@ -2323,6 +2388,18 @@ generate_config_xml (MetaMonitorConfigStore *config_store) + g_string_append (buffer, " \n"); + } + ++ if (config->for_lease_monitor_specs) ++ { ++ g_string_append (buffer, " \n"); ++ for (l = config->for_lease_monitor_specs; l; l = l->next) ++ { ++ MetaMonitorSpec *monitor_spec = l->data; ++ ++ append_monitor_spec (buffer, monitor_spec, " "); ++ } ++ g_string_append (buffer, " \n"); ++ } ++ + g_string_append (buffer, " \n"); + } + +-- +2.48.1 + diff --git a/0001-monitor-manager-Return-for-lease-status-in-GetCurren.patch b/0001-monitor-manager-Return-for-lease-status-in-GetCurren.patch new file mode 100644 index 0000000..20fe083 --- /dev/null +++ b/0001-monitor-manager-Return-for-lease-status-in-GetCurren.patch @@ -0,0 +1,201 @@ +From c93e06696fea37303e4d9143ed62a31a97532c51 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= +Date: Mon, 4 Nov 2024 19:12:19 +0100 +Subject: [PATCH 1/3] monitor-manager: Return for lease status in + GetCurrentState + +Add a new property to the list of monitors returned by the +GetCurrentState D-Bus API indicating whether the monitor is available +for lease or not. + +Part-of: +--- + .../org.gnome.Mutter.DisplayConfig.xml | 1 + + src/backends/meta-monitor-manager.c | 6 + + src/tests/monitor-unit-tests.c | 127 ++++++++++++++++++ + 3 files changed, 134 insertions(+) + +diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +index 3c28814b16..192c08a796 100644 +--- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml ++++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +@@ -392,6 +392,7 @@ + - "min-refresh-rate" (i): minimum refresh rate of monitor when + Variable Refresh Rate is active (absence + of this means unknown) ++ - "is-for-lease" (b): whether the monitor is for lease or not + + Possible mode flags: + 1 : preferred mode +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 55816ed7bb..127181df60 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -2032,6 +2032,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, + GVariantBuilder monitor_properties_builder; + GList *k; + gboolean is_builtin; ++ gboolean is_for_lease; + const char *display_name; + + current_mode = meta_monitor_get_current_mode (monitor); +@@ -2153,6 +2154,11 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, + g_variant_new_int32 (min_refresh_rate)); + } + ++ is_for_lease = meta_monitor_is_for_lease (monitor); ++ g_variant_builder_add (&monitor_properties_builder, "{sv}", ++ "is-for-lease", ++ g_variant_new_boolean (is_for_lease)); ++ + g_variant_builder_add (&monitors_builder, MONITOR_FORMAT, + monitor_spec->connector, + monitor_spec->vendor, +diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c +index 0d5d1511ea..1f87c36528 100644 +--- a/src/tests/monitor-unit-tests.c ++++ b/src/tests/monitor-unit-tests.c +@@ -9474,6 +9474,131 @@ meta_test_monitor_custom_for_lease_invalid_config (void) + g_test_assert_expected_messages (); + } + ++static void ++on_proxy_call_cb (GObject *object, ++ GAsyncResult *res, ++ gpointer user_data) ++{ ++ g_autoptr (GError) error = NULL; ++ GVariant **ret = user_data; ++ ++ *ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), res, &error); ++ g_assert_no_error (error); ++ g_assert_nonnull (ret); ++} ++ ++static void ++assert_monitor_state (GVariant *state, ++ guint monitor_index, ++ const char *connector, ++ gboolean is_for_lease) ++{ ++ g_autoptr (GVariant) monitors = NULL; ++ g_autoptr (GVariant) monitor = NULL; ++ g_autoptr (GVariant) monitor_spec = NULL; ++ g_autoptr (GVariant) spec_connector = NULL; ++ g_autoptr (GVariant) monitor_properties = NULL; ++ g_autoptr (GVariant) for_lease_property = NULL; ++ ++ monitors = g_variant_get_child_value (state, 1); ++ monitor = g_variant_get_child_value (monitors, monitor_index); ++ ++ monitor_spec = g_variant_get_child_value (monitor, 0); ++ spec_connector = g_variant_get_child_value (monitor_spec, 0); ++ g_assert_cmpstr (g_variant_get_string (spec_connector, NULL), ==, connector); ++ ++ monitor_properties = g_variant_get_child_value (monitor, 2); ++ for_lease_property = g_variant_lookup_value (monitor_properties, ++ "is-for-lease", ++ G_VARIANT_TYPE_BOOLEAN); ++ g_assert (g_variant_get_boolean (for_lease_property) == is_for_lease); ++} ++ ++static void ++meta_test_monitor_custom_for_lease_config_dbus (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, 1 }, ++ .n_possible_crtcs = 2, ++ .width_mm = 222, ++ .height_mm = 125, ++ .serial = "0x123456", ++ }, ++ { ++ .crtc = -1, ++ .modes = { 0 }, ++ .n_modes = 1, ++ .preferred_mode = 0, ++ .possible_crtcs = { 0, 1 }, ++ .n_possible_crtcs = 2, ++ .width_mm = 222, ++ .height_mm = 125, ++ .serial = "0x654321" ++ } ++ }, ++ .n_outputs = 2, ++ .crtcs = { ++ { ++ .current_mode = -1 ++ }, ++ { ++ .current_mode = -1 ++ } ++ }, ++ .n_crtcs = 2 ++ }; ++ MetaMonitorTestSetup *test_setup; ++ g_autoptr (GDBusProxy) display_config_proxy = NULL; ++ g_autoptr (GVariant) state = NULL; ++ ++ test_setup = meta_create_monitor_test_setup (test_backend, ++ &test_case_setup, ++ MONITOR_TEST_FLAG_NONE); ++ meta_set_custom_monitor_config (test_context, "forlease.xml"); ++ emulate_hotplug (test_setup); ++ check_monitor_test_clients_state (); ++ ++ 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_dbus_proxy_call (display_config_proxy, ++ "GetCurrentState", ++ NULL, ++ G_DBUS_CALL_FLAGS_NO_AUTO_START, ++ -1, ++ NULL, ++ on_proxy_call_cb, ++ &state); ++ while (!state) ++ g_main_context_iteration (NULL, TRUE); ++ ++ assert_monitor_state (state, 0, "DP-1", FALSE); ++ assert_monitor_state (state, 1, "DP-2", TRUE); ++} ++ + static gboolean + quit_main_loop (gpointer data) + { +@@ -10704,6 +10829,8 @@ init_monitor_tests (void) + meta_test_monitor_custom_for_lease_config); + add_monitor_test ("/backends/monitor/custom/for-lease-invalid-config", + meta_test_monitor_custom_for_lease_invalid_config); ++ add_monitor_test ("/backends/monitor/custom/for-lease-config-dbus", ++ meta_test_monitor_custom_for_lease_config_dbus); + + add_monitor_test ("/backends/monitor/migrated/rotated", + meta_test_monitor_migrated_rotated); +-- +2.48.1 + diff --git a/0002-monitor-Keep-track-of-the-for-lease-status.patch b/0002-monitor-Keep-track-of-the-for-lease-status.patch new file mode 100644 index 0000000..e187874 --- /dev/null +++ b/0002-monitor-Keep-track-of-the-for-lease-status.patch @@ -0,0 +1,462 @@ +From f93e85f69b9d63d4bedeaf778d5f620ad64ddab4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= +Date: Mon, 28 Oct 2024 08:44:35 +0100 +Subject: [PATCH 2/5] monitor: Keep track of the for lease status + +Add a flag to MetaMonitor indicating if the monitor is available for +lease and store/update it from the monitor configuration. + +Also, add unit tests validating that the configuration is applied and +that invalid configurations fail. + +Part-of: +--- + src/backends/meta-monitor-config-manager.c | 10 +- + src/backends/meta-monitor-manager-private.h | 3 + + src/backends/meta-monitor-manager.c | 41 +++++ + src/backends/meta-monitor.c | 19 ++ + src/backends/meta-monitor.h | 6 + + .../native/meta-monitor-manager-native.c | 1 + + .../monitor-configs/forlease-invalid.xml | 32 ++++ + src/tests/monitor-configs/forlease.xml | 40 +++++ + src/tests/monitor-unit-tests.c | 165 ++++++++++++++++++ + 9 files changed, 316 insertions(+), 1 deletion(-) + create mode 100644 src/tests/monitor-configs/forlease-invalid.xml + create mode 100644 src/tests/monitor-configs/forlease.xml + +diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c +index ecf4ee8202..0df193f0a4 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -1628,6 +1628,7 @@ meta_monitors_config_new (MetaMonitorManager *monitor_manager, + MetaMonitorsConfigFlag flags) + { + GList *disabled_monitor_specs = NULL; ++ GList *for_lease_monitor_specs = NULL; + GList *monitors; + GList *l; + +@@ -1649,11 +1650,18 @@ meta_monitors_config_new (MetaMonitorManager *monitor_manager, + disabled_monitor_specs = + g_list_prepend (disabled_monitor_specs, + meta_monitor_spec_clone (monitor_spec)); ++ ++ if (meta_monitor_is_for_lease (monitor)) ++ { ++ for_lease_monitor_specs = ++ g_list_prepend (for_lease_monitor_specs, ++ meta_monitor_spec_clone (monitor_spec)); ++ } + } + + return meta_monitors_config_new_full (logical_monitor_configs, + disabled_monitor_specs, +- NULL, ++ for_lease_monitor_specs, + layout_mode, + flags); + } +diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h +index 977ce417cc..66492c2a5f 100644 +--- a/src/backends/meta-monitor-manager-private.h ++++ b/src/backends/meta-monitor-manager-private.h +@@ -345,6 +345,9 @@ META_EXPORT_TEST + void meta_monitor_manager_update_logical_state (MetaMonitorManager *manager, + MetaMonitorsConfig *config); + ++void meta_monitor_manager_update_for_lease_state (MetaMonitorManager *manager, ++ MetaMonitorsConfig *config); ++ + META_EXPORT_TEST + void meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager, + MetaMonitorsConfig *config); +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 4fcc8a696c..55816ed7bb 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -3824,6 +3824,46 @@ meta_monitor_manager_update_logical_state (MetaMonitorManager *manager, + meta_monitor_manager_rebuild_logical_monitors (manager, config); + } + ++static gboolean ++is_monitor_configured_for_lease (MetaMonitor *monitor, ++ MetaMonitorsConfig *config) ++{ ++ MetaMonitorSpec *monitor_spec; ++ GList *l; ++ ++ monitor_spec = meta_monitor_get_spec (monitor); ++ ++ for (l = config->for_lease_monitor_specs; l; l = l->next) ++ { ++ MetaMonitorSpec *spec = l->data; ++ ++ if (meta_monitor_spec_equals (monitor_spec, spec)) ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++void ++meta_monitor_manager_update_for_lease_state (MetaMonitorManager *manager, ++ MetaMonitorsConfig *config) ++{ ++ GList *l; ++ ++ for (l = manager->monitors; l; l = l->next) ++ { ++ MetaMonitor *monitor = l->data; ++ gboolean is_for_lease; ++ ++ if (config) ++ is_for_lease = is_monitor_configured_for_lease (monitor, config); ++ else ++ is_for_lease = FALSE; ++ ++ meta_monitor_set_for_lease (monitor, is_for_lease); ++ } ++} ++ + void + meta_monitor_manager_rebuild (MetaMonitorManager *manager, + MetaMonitorsConfig *config) +@@ -3838,6 +3878,7 @@ meta_monitor_manager_rebuild (MetaMonitorManager *manager, + old_logical_monitors = manager->logical_monitors; + + meta_monitor_manager_update_logical_state (manager, config); ++ meta_monitor_manager_update_for_lease_state (manager, config); + + ensure_privacy_screen_settings (manager); + +diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c +index b7efabda2c..badde7cea2 100644 +--- a/src/backends/meta-monitor.c ++++ b/src/backends/meta-monitor.c +@@ -67,6 +67,8 @@ typedef struct _MetaMonitorPrivate + MetaLogicalMonitor *logical_monitor; + + char *display_name; ++ ++ gboolean is_for_lease; + } MetaMonitorPrivate; + + G_DEFINE_TYPE_WITH_PRIVATE (MetaMonitor, meta_monitor, G_TYPE_OBJECT) +@@ -2459,3 +2461,20 @@ meta_monitor_get_backlight (MetaMonitor *monitor, + return FALSE; + } + } ++ ++void ++meta_monitor_set_for_lease (MetaMonitor *monitor, ++ gboolean for_lease) ++{ ++ MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); ++ ++ priv->is_for_lease = for_lease; ++} ++ ++gboolean ++meta_monitor_is_for_lease (MetaMonitor *monitor) ++{ ++ MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); ++ ++ return priv->is_for_lease; ++} +diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h +index 01836dc0e7..cc11348b35 100644 +--- a/src/backends/meta-monitor.h ++++ b/src/backends/meta-monitor.h +@@ -349,4 +349,10 @@ META_EXPORT_TEST + gboolean meta_monitor_get_backlight (MetaMonitor *monitor, + int *value); + ++void meta_monitor_set_for_lease (MetaMonitor *monitor, ++ gboolean for_lease); ++ ++META_EXPORT_TEST ++gboolean meta_monitor_is_for_lease (MetaMonitor *monitor); ++ + G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaMonitorSpec, meta_monitor_spec_free) +diff --git a/src/backends/native/meta-monitor-manager-native.c b/src/backends/native/meta-monitor-manager-native.c +index 668f4e0eb4..21cc1b95be 100644 +--- a/src/backends/native/meta-monitor-manager-native.c ++++ b/src/backends/native/meta-monitor-manager-native.c +@@ -156,6 +156,7 @@ meta_monitor_manager_native_ensure_initial_config (MetaMonitorManager *manager) + config = meta_monitor_manager_ensure_configured (manager); + + meta_monitor_manager_update_logical_state (manager, config); ++ meta_monitor_manager_update_for_lease_state (manager, config); + } + + static void +diff --git a/src/tests/monitor-configs/forlease-invalid.xml b/src/tests/monitor-configs/forlease-invalid.xml +new file mode 100644 +index 0000000000..4a7ff9d5da +--- /dev/null ++++ b/src/tests/monitor-configs/forlease-invalid.xml +@@ -0,0 +1,32 @@ ++ ++ ++ logical ++ ++ 0 ++ 0 ++ 1 ++ yes ++ ++ ++ DP-1 ++ MetaProduct's Inc. ++ MetaMonitor ++ 0x123456 ++ ++ ++ 800 ++ 600 ++ 60 ++ ++ ++ ++ ++ ++ DP-1 ++ MetaProduct's Inc. ++ MetaMonitor ++ 0x123456 ++ ++ ++ ++ +diff --git a/src/tests/monitor-configs/forlease.xml b/src/tests/monitor-configs/forlease.xml +new file mode 100644 +index 0000000000..482f095a6d +--- /dev/null ++++ b/src/tests/monitor-configs/forlease.xml +@@ -0,0 +1,40 @@ ++ ++ ++ logical ++ ++ 0 ++ 0 ++ 1 ++ yes ++ ++ ++ DP-1 ++ MetaProduct's Inc. ++ MetaMonitor ++ 0x123456 ++ ++ ++ 800 ++ 600 ++ 60 ++ ++ ++ ++ ++ ++ DP-2 ++ MetaProduct's Inc. ++ MetaMonitor ++ 0x654321 ++ ++ ++ ++ ++ DP-2 ++ MetaProduct's Inc. ++ MetaMonitor ++ 0x654321 ++ ++ ++ ++ +diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c +index 2414789bab..326dd83855 100644 +--- a/src/tests/monitor-unit-tests.c ++++ b/src/tests/monitor-unit-tests.c +@@ -9176,6 +9176,167 @@ meta_test_monitor_custom_detached_groups (void) + g_assert_cmpstr (error->message, ==, "Logical monitors not adjacent"); + } + ++static void ++meta_test_monitor_custom_for_lease_config (void) ++{ ++ MonitorTestCase 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, 1 }, ++ .n_possible_crtcs = 2, ++ .width_mm = 222, ++ .height_mm = 125, ++ .serial = "0x123456", ++ }, ++ { ++ .crtc = -1, ++ .modes = { 0 }, ++ .n_modes = 1, ++ .preferred_mode = 0, ++ .possible_crtcs = { 0, 1 }, ++ .n_possible_crtcs = 2, ++ .width_mm = 222, ++ .height_mm = 125, ++ .serial = "0x654321" ++ } ++ }, ++ .n_outputs = 2, ++ .crtcs = { ++ { ++ .current_mode = -1 ++ }, ++ { ++ .current_mode = -1 ++ } ++ }, ++ .n_crtcs = 2 ++ }, ++ ++ .expect = { ++ .monitors = { ++ { ++ .outputs = { 0 }, ++ .n_outputs = 1, ++ .modes = { ++ { ++ .width = 800, ++ .height = 600, ++ .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 = 800, ++ .height = 600, ++ .refresh_rate = 60.0, ++ .crtc_modes = { ++ { ++ .output = 1, ++ .crtc_mode = 0 ++ } ++ } ++ } ++ }, ++ .n_modes = 1, ++ .current_mode = -1, ++ .width_mm = 222, ++ .height_mm = 125 ++ } ++ }, ++ .n_monitors = 2, ++ .logical_monitors = { ++ { ++ .monitors = { 0 }, ++ .n_monitors = 1, ++ .layout = { .x = 0, .y = 0, .width = 800, .height = 600 }, ++ .scale = 1, ++ .transform = MTK_MONITOR_TRANSFORM_NORMAL ++ }, ++ }, ++ .n_logical_monitors = 1, ++ .primary_logical_monitor = 0, ++ .n_outputs = 2, ++ .crtcs = { ++ { ++ .current_mode = 0, ++ }, ++ { ++ .current_mode = -1, ++ } ++ }, ++ .n_crtcs = 2, ++ .screen_width = 800, ++ .screen_height = 600, ++ } ++ }; ++ MetaMonitorTestSetup *test_setup; ++ MetaBackend *backend = meta_context_get_backend (test_context); ++ MetaMonitorManager *monitor_manager = ++ meta_backend_get_monitor_manager (backend); ++ GList *monitors; ++ MetaMonitor *first_monitor; ++ MetaMonitor *second_monitor; ++ ++ test_setup = meta_create_monitor_test_setup (test_backend, ++ &test_case.setup, ++ MONITOR_TEST_FLAG_NONE); ++ meta_set_custom_monitor_config (test_context, "forlease.xml"); ++ emulate_hotplug (test_setup); ++ ++ META_TEST_LOG_CALL ("Checking monitor configuration", ++ meta_check_monitor_configuration (test_context, ++ &test_case.expect)); ++ check_monitor_test_clients_state (); ++ ++ 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_active (first_monitor)); ++ g_assert_false (meta_monitor_is_for_lease (first_monitor)); ++ ++ g_assert_false (meta_monitor_is_active (second_monitor)); ++ g_assert_true (meta_monitor_is_for_lease (second_monitor)); ++} ++ ++static void ++meta_test_monitor_custom_for_lease_invalid_config (void) ++{ ++ g_test_expect_message ("libmutter-test", G_LOG_LEVEL_WARNING, ++ "*For lease monitor must be explicitly disabled"); ++ meta_set_custom_monitor_config (test_context, "forlease-invalid.xml"); ++ g_test_assert_expected_messages (); ++} ++ + static gboolean + quit_main_loop (gpointer data) + { +@@ -10400,6 +10561,10 @@ init_monitor_tests (void) + meta_test_monitor_custom_lid_switch_config); + add_monitor_test ("/backends/monitor/custom/detached-groups", + meta_test_monitor_custom_detached_groups); ++ add_monitor_test ("/backends/monitor/custom/for-lease-config", ++ meta_test_monitor_custom_for_lease_config); ++ add_monitor_test ("/backends/monitor/custom/for-lease-invalid-config", ++ meta_test_monitor_custom_for_lease_invalid_config); + + add_monitor_test ("/backends/monitor/migrated/rotated", + meta_test_monitor_migrated_rotated); +-- +2.48.1 + diff --git a/0002-monitor-manager-Allow-to-check-if-config-has-a-visib.patch b/0002-monitor-manager-Allow-to-check-if-config-has-a-visib.patch new file mode 100644 index 0000000..60ff034 --- /dev/null +++ b/0002-monitor-manager-Allow-to-check-if-config-has-a-visib.patch @@ -0,0 +1,80 @@ +From 80a19134ffb5ddd6577f00986aafcaf9db6505b9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= +Date: Tue, 5 Nov 2024 12:03:49 +0100 +Subject: [PATCH 2/3] monitor-manager: Allow to check if config has a visible + monitor + +Add a new function, similar to meta_logical_monitor_configs_have_monitor() +that, in addition, checks if the monitor is visible. + +Refactor, no functional change. + +Part-of: +--- + src/backends/meta-monitor-config-manager.c | 24 +++++++++++++++++----- + src/backends/meta-monitor-config-manager.h | 4 ++++ + 2 files changed, 23 insertions(+), 5 deletions(-) + +diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c +index 0df193f0a4..74aa2df4b1 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -1638,14 +1638,12 @@ meta_monitors_config_new (MetaMonitorManager *monitor_manager, + MetaMonitor *monitor = l->data; + MetaMonitorSpec *monitor_spec; + +- if (!monitor_matches_rule (monitor, monitor_manager, +- MONITOR_MATCH_VISIBLE)) ++ if (meta_logical_monitor_configs_have_visible_monitor (monitor_manager, ++ logical_monitor_configs, ++ monitor)) + continue; + + monitor_spec = meta_monitor_get_spec (monitor); +- if (meta_logical_monitor_configs_have_monitor (logical_monitor_configs, +- monitor_spec)) +- continue; + + disabled_monitor_specs = + g_list_prepend (disabled_monitor_specs, +@@ -1889,6 +1887,22 @@ meta_logical_monitor_configs_have_monitor (GList *logical_monitor_conf + return FALSE; + } + ++gboolean ++meta_logical_monitor_configs_have_visible_monitor (MetaMonitorManager *monitor_manager, ++ GList *logical_monitor_configs, ++ MetaMonitor *monitor) ++{ ++ MetaMonitorSpec *monitor_spec; ++ ++ if (!monitor_matches_rule (monitor, monitor_manager, MONITOR_MATCH_VISIBLE)) ++ return TRUE; ++ ++ monitor_spec = meta_monitor_get_spec (monitor); ++ ++ return meta_logical_monitor_configs_have_monitor (logical_monitor_configs, ++ monitor_spec); ++} ++ + static gboolean + meta_monitors_config_is_monitor_enabled (MetaMonitorsConfig *config, + MetaMonitorSpec *monitor_spec) +diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h +index 87a29bc2dd..f033ac6555 100644 +--- a/src/backends/meta-monitor-config-manager.h ++++ b/src/backends/meta-monitor-config-manager.h +@@ -187,6 +187,10 @@ META_EXPORT_TEST + gboolean meta_logical_monitor_configs_have_monitor (GList *logical_monitor_configs, + MetaMonitorSpec *monitor_spec); + ++gboolean meta_logical_monitor_configs_have_visible_monitor (MetaMonitorManager *monitor_manager, ++ GList *logical_monitor_configs, ++ MetaMonitor *monitor); ++ + META_EXPORT_TEST + gboolean meta_verify_monitor_mode_spec (MetaMonitorModeSpec *monitor_mode_spec, + GError **error); +-- +2.48.1 + diff --git a/0003-monitor-manager-Configure-for-lease-monitors-in-Appl.patch b/0003-monitor-manager-Configure-for-lease-monitors-in-Appl.patch new file mode 100644 index 0000000..ff64e66 --- /dev/null +++ b/0003-monitor-manager-Configure-for-lease-monitors-in-Appl.patch @@ -0,0 +1,224 @@ +From 479bb6921da3d7004a74c4c7db999534b32ff214 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= +Date: Tue, 5 Nov 2024 12:26:42 +0100 +Subject: [PATCH 3/3] monitor-manager: Configure for lease monitors in + ApplyMonitorsConfig + +Add a new property to the ApplyMonitorsConfig D-Bus API allowing to set +a list of monitors for lease. + +Part-of: +--- + .../org.gnome.Mutter.DisplayConfig.xml | 6 ++ + src/backends/meta-monitor-manager.c | 85 ++++++++++++++++++- + src/tests/monitor-unit-tests.c | 60 +++++++++++++ + 3 files changed, 147 insertions(+), 4 deletions(-) + +diff --git a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +index 192c08a796..fec38a34a8 100644 +--- a/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml ++++ b/data/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml +@@ -501,6 +501,12 @@ + * "layout-mode" (u): layout mode the passed configuration is in; may + only be set when changing the layout mode is + supported (see GetCurrentState). ++ * "monitors-for-lease" (a(ssss)): a list of monitors to be made available for ++ lease. Monitors listed here must not be listed in @logical_monitors: ++ * s connector: connector name (e.g. HDMI-1, DP-1, etc) ++ * s vendor: vendor name ++ * s product: product name ++ * s serial: product serial + --> + + +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 127181df60..abe1db6649 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -2713,6 +2713,74 @@ is_valid_layout_mode (MetaLogicalMonitorLayoutMode layout_mode) + return FALSE; + } + ++static GList * ++create_disabled_monitor_specs_for_config (MetaMonitorManager *monitor_manager, ++ GList *logical_monitor_configs) ++{ ++ GList *disabled_monitor_specs = NULL; ++ GList *monitors; ++ GList *l; ++ ++ monitors = meta_monitor_manager_get_monitors (monitor_manager); ++ for (l = monitors; l; l = l->next) ++ { ++ MetaMonitor *monitor = l->data; ++ ++ if (!meta_logical_monitor_configs_have_visible_monitor (monitor_manager, ++ logical_monitor_configs, ++ monitor)) ++ { ++ MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor); ++ ++ disabled_monitor_specs = ++ g_list_prepend (disabled_monitor_specs, ++ meta_monitor_spec_clone (monitor_spec)); ++ } ++ } ++ ++ return disabled_monitor_specs; ++} ++ ++static GList * ++create_for_lease_monitor_specs_from_variant (GVariant *properties_variant) ++{ ++ GList *for_lease_monitor_specs = NULL; ++ g_autoptr (GVariant) for_lease_variant = NULL; ++ GVariantIter iter; ++ char *connector = NULL; ++ char *vendor = NULL; ++ char *product = NULL; ++ char *serial = NULL; ++ ++ if (!properties_variant) ++ return NULL; ++ ++ for_lease_variant = g_variant_lookup_value (properties_variant, ++ "monitors-for-lease", ++ G_VARIANT_TYPE ("a(ssss)")); ++ if (!for_lease_variant) ++ return NULL; ++ ++ g_variant_iter_init (&iter, for_lease_variant); ++ while (g_variant_iter_next (&iter, "(ssss)", &connector, &vendor, &product, &serial)) ++ { ++ MetaMonitorSpec *monitor_spec; ++ ++ monitor_spec = g_new0 (MetaMonitorSpec, 1); ++ *monitor_spec = (MetaMonitorSpec) { ++ .connector = connector, ++ .vendor = vendor, ++ .product = product, ++ .serial = serial ++ }; ++ ++ for_lease_monitor_specs = ++ g_list_append (for_lease_monitor_specs, monitor_spec); ++ } ++ ++ return for_lease_monitor_specs; ++} ++ + static gboolean + meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skeleton, + GDBusMethodInvocation *invocation, +@@ -2730,6 +2798,8 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet + GVariantIter logical_monitor_configs_iter; + MetaMonitorsConfig *config; + GList *logical_monitor_configs = NULL; ++ GList *disabled_monitor_specs = NULL; ++ GList *for_lease_monitor_specs = NULL; + GError *error = NULL; + + if (serial != manager->serial) +@@ -2818,10 +2888,17 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet + logical_monitor_config); + } + +- config = meta_monitors_config_new (manager, +- logical_monitor_configs, +- layout_mode, +- META_MONITORS_CONFIG_FLAG_NONE); ++ disabled_monitor_specs = ++ create_disabled_monitor_specs_for_config (manager, ++ logical_monitor_configs); ++ for_lease_monitor_specs = ++ create_for_lease_monitor_specs_from_variant (properties_variant); ++ ++ config = meta_monitors_config_new_full (logical_monitor_configs, ++ disabled_monitor_specs, ++ for_lease_monitor_specs, ++ layout_mode, ++ META_MONITORS_CONFIG_FLAG_NONE); + if (!meta_verify_monitors_config (config, manager, &error)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, +diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c +index 1f87c36528..380f55cc75 100644 +--- a/src/tests/monitor-unit-tests.c ++++ b/src/tests/monitor-unit-tests.c +@@ -9564,6 +9564,10 @@ meta_test_monitor_custom_for_lease_config_dbus (void) + MetaMonitorTestSetup *test_setup; + g_autoptr (GDBusProxy) display_config_proxy = NULL; + g_autoptr (GVariant) state = NULL; ++ uint32_t serial; ++ GVariantBuilder b; ++ g_autoptr (GVariant) apply_config_ret = NULL; ++ g_autoptr (GVariant) new_state = NULL; + + test_setup = meta_create_monitor_test_setup (test_backend, + &test_case_setup, +@@ -9597,6 +9601,62 @@ meta_test_monitor_custom_for_lease_config_dbus (void) + + assert_monitor_state (state, 0, "DP-1", FALSE); + assert_monitor_state (state, 1, "DP-2", TRUE); ++ ++ /* Swap monitor for lease */ ++ serial = g_variant_get_uint32 (g_variant_get_child_value (state, 0)); ++ ++ g_variant_builder_init (&b, G_VARIANT_TYPE ("(uua(iiduba(ssa{sv}))a{sv})")); ++ g_variant_builder_add (&b, "u", serial); /* Serial from GetCurrentState */ ++ g_variant_builder_add (&b, "u", 1); /* Method: Temporary */ ++ ++ /* Logical monitors */ ++ g_variant_builder_open (&b, G_VARIANT_TYPE ("a(iiduba(ssa{sv}))")); ++ g_variant_builder_open (&b, G_VARIANT_TYPE ("(iiduba(ssa{sv}))")); ++ g_variant_builder_add (&b, "i", 0); /* x */ ++ g_variant_builder_add (&b, "i", 0); /* y */ ++ g_variant_builder_add (&b, "d", 1.0); /* Scale */ ++ g_variant_builder_add (&b, "u", 0); /* Transform */ ++ g_variant_builder_add (&b, "b", TRUE); /* Primary */ ++ g_variant_builder_add_parsed (&b, "[(%s, %s, @a{sv} {})]", /* Monitors */ ++ "DP-2", ++ "800x600@60.000"); ++ g_variant_builder_close (&b); ++ g_variant_builder_close (&b); ++ ++ /* Properties */ ++ g_variant_builder_open (&b, G_VARIANT_TYPE ("a{sv}")); ++ g_variant_builder_add_parsed (&b, "{'monitors-for-lease', <[(%s, %s, %s, %s)]>}", ++ "DP-1", ++ "MetaProduct\'s Inc.", ++ "MetaMonitor", ++ "0x123456"); ++ g_variant_builder_close (&b); ++ ++ g_dbus_proxy_call (display_config_proxy, ++ "ApplyMonitorsConfig", ++ g_variant_builder_end (&b), ++ G_DBUS_CALL_FLAGS_NO_AUTO_START, ++ -1, ++ NULL, ++ on_proxy_call_cb, ++ &apply_config_ret); ++ while (!apply_config_ret) ++ g_main_context_iteration (NULL, TRUE); ++ ++ /* Check that monitors changed */ ++ g_dbus_proxy_call (display_config_proxy, ++ "GetCurrentState", ++ NULL, ++ G_DBUS_CALL_FLAGS_NO_AUTO_START, ++ -1, ++ NULL, ++ on_proxy_call_cb, ++ &new_state); ++ while (!new_state) ++ g_main_context_iteration (NULL, TRUE); ++ ++ assert_monitor_state (new_state, 0, "DP-1", TRUE); ++ assert_monitor_state (new_state, 1, "DP-2", FALSE); + } + + static gboolean +-- +2.48.1 + diff --git a/0003-output-kms-Add-meta_output_kms_from_kms_connector.patch b/0003-output-kms-Add-meta_output_kms_from_kms_connector.patch new file mode 100644 index 0000000..359d27a --- /dev/null +++ b/0003-output-kms-Add-meta_output_kms_from_kms_connector.patch @@ -0,0 +1,74 @@ +From 863b31cae9be5e8e0467f1a9f93e7348d41f7e88 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= +Date: Tue, 29 Oct 2024 11:35:17 +0100 +Subject: [PATCH 3/5] output/kms: Add meta_output_kms_from_kms_connector() + +Add a function that returns a MetaOutputKms (if any) from a +MetaKmsConnector. + +Part-of: +--- + src/backends/native/meta-output-kms.c | 19 +++++++++++++++++++ + src/backends/native/meta-output-kms.h | 2 ++ + 2 files changed, 21 insertions(+) + +diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c +index 684cf0e094..27b7533a5e 100644 +--- a/src/backends/native/meta-output-kms.c ++++ b/src/backends/native/meta-output-kms.c +@@ -47,6 +47,8 @@ struct _MetaOutputKms + + G_DEFINE_TYPE (MetaOutputKms, meta_output_kms, META_TYPE_OUTPUT_NATIVE) + ++static GQuark kms_connector_output_kms_quark; ++ + MetaKmsConnector * + meta_output_kms_get_kms_connector (MetaOutputKms *output_kms) + { +@@ -90,6 +92,13 @@ meta_output_kms_can_clone (MetaOutputKms *output_kms, + return TRUE; + } + ++MetaOutputKms * ++meta_output_kms_from_kms_connector (MetaKmsConnector *connector) ++{ ++ return g_object_get_qdata (G_OBJECT (connector), ++ kms_connector_output_kms_quark); ++} ++ + static GBytes * + meta_output_kms_read_edid (MetaOutputNative *output_native) + { +@@ -534,6 +543,16 @@ meta_output_kms_new (MetaGpuKms *gpu_kms, + meta_output_unassign_crtc (output); + } + ++ if (!kms_connector_output_kms_quark) ++ { ++ kms_connector_output_kms_quark = ++ g_quark_from_static_string ("kms-connector-output-kms-quark"); ++ } ++ ++ g_object_set_qdata (G_OBJECT (kms_connector), ++ kms_connector_output_kms_quark, ++ output_kms); ++ + return output_kms; + } + +diff --git a/src/backends/native/meta-output-kms.h b/src/backends/native/meta-output-kms.h +index e0eb60eb4d..4391dc1899 100644 +--- a/src/backends/native/meta-output-kms.h ++++ b/src/backends/native/meta-output-kms.h +@@ -39,6 +39,8 @@ MetaKmsConnector * meta_output_kms_get_kms_connector (MetaOutputKms *output_kms) + + uint32_t meta_output_kms_get_connector_id (MetaOutputKms *output_kms); + ++MetaOutputKms * meta_output_kms_from_kms_connector (MetaKmsConnector *connector); ++ + MetaOutputKms * meta_output_kms_new (MetaGpuKms *gpu_kms, + MetaKmsConnector *kms_connector, + MetaOutput *old_output, +-- +2.48.1 + diff --git a/0004-kms-connector-Rename-meta_kms_connector_is_for_lease.patch b/0004-kms-connector-Rename-meta_kms_connector_is_for_lease.patch new file mode 100644 index 0000000..100ab70 --- /dev/null +++ b/0004-kms-connector-Rename-meta_kms_connector_is_for_lease.patch @@ -0,0 +1,78 @@ +From 63b7d958f226b05694eeeed7d1a7bc77d84464ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= +Date: Tue, 29 Oct 2024 12:09:21 +0100 +Subject: [PATCH 4/5] kms/connector: Rename meta_kms_connector_is_for_lease() + +Now that connectors can be configured as for lease, rename the function +to meta_kms_connector_is_non_desktop() to make clear that it returns +the hardware configuration rather than the user configuration. + +Part-of: +--- + src/backends/native/meta-drm-lease.c | 4 ++-- + src/backends/native/meta-gpu-kms.c | 2 +- + src/backends/native/meta-kms-connector.c | 2 +- + src/backends/native/meta-kms-connector.h | 2 +- + 4 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/backends/native/meta-drm-lease.c b/src/backends/native/meta-drm-lease.c +index 7cddb6c8ed..302147e9bb 100644 +--- a/src/backends/native/meta-drm-lease.c ++++ b/src/backends/native/meta-drm-lease.c +@@ -227,7 +227,7 @@ find_resources_to_lease (MetaDrmLeaseManager *lease_manager, + MetaKmsDevice *connector_device; + + if (!g_list_find (available_connectors, connector) || +- !meta_kms_connector_is_for_lease (connector)) ++ !meta_kms_connector_is_non_desktop (connector)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Failed to find connector %u (%s)", +@@ -645,7 +645,7 @@ update_connectors (MetaDrmLeaseManager *lease_manager, + kms_connector = o->data; + lease = NULL; + +- if (!meta_kms_connector_is_for_lease (kms_connector)) ++ if (!meta_kms_connector_is_non_desktop (kms_connector)) + continue; + + if (g_list_find (lease_manager->connectors, kms_connector)) +diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c +index 3b4356ca6b..c633d6d68e 100644 +--- a/src/backends/native/meta-gpu-kms.c ++++ b/src/backends/native/meta-gpu-kms.c +@@ -355,7 +355,7 @@ init_outputs (MetaGpuKms *gpu_kms) + if (!meta_kms_connector_get_current_state (kms_connector)) + continue; + +- if (meta_kms_connector_is_for_lease (kms_connector)) ++ if (meta_kms_connector_is_non_desktop (kms_connector)) + continue; + + old_output = +diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c +index cc6cd89f56..7723416aa3 100644 +--- a/src/backends/native/meta-kms-connector.c ++++ b/src/backends/native/meta-kms-connector.c +@@ -165,7 +165,7 @@ meta_kms_connector_get_current_state (MetaKmsConnector *connector) + } + + gboolean +-meta_kms_connector_is_for_lease (MetaKmsConnector *connector) ++meta_kms_connector_is_non_desktop (MetaKmsConnector *connector) + { + const char *lease_connectors_str; + +diff --git a/src/backends/native/meta-kms-connector.h b/src/backends/native/meta-kms-connector.h +index 84ee7f5c26..328465d0fa 100644 +--- a/src/backends/native/meta-kms-connector.h ++++ b/src/backends/native/meta-kms-connector.h +@@ -102,4 +102,4 @@ MetaKmsMode * meta_kms_connector_get_preferred_mode (MetaKmsConnector *connector + META_EXPORT_TEST + const MetaKmsConnectorState * meta_kms_connector_get_current_state (MetaKmsConnector *connector); + +-gboolean meta_kms_connector_is_for_lease (MetaKmsConnector *connector); ++gboolean meta_kms_connector_is_non_desktop (MetaKmsConnector *connector); +-- +2.48.1 + diff --git a/0005-native-drm-lease-Handle-monitors-configured-for-leas.patch b/0005-native-drm-lease-Handle-monitors-configured-for-leas.patch new file mode 100644 index 0000000..4c5482c --- /dev/null +++ b/0005-native-drm-lease-Handle-monitors-configured-for-leas.patch @@ -0,0 +1,130 @@ +From 55910e467f42ce9d6e761afd8f50110cb1cc3164 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= +Date: Mon, 28 Oct 2024 08:54:45 +0100 +Subject: [PATCH 5/5] native/drm-lease: Handle monitors configured for lease + +Follow the configuration stored in MetaMonitor and make connectors +configured as for lease available to Wayland clients. + +Part-of: +--- + src/backends/native/meta-drm-lease.c | 45 ++++++++++++++++++++++++++-- + 1 file changed, 43 insertions(+), 2 deletions(-) + +diff --git a/src/backends/native/meta-drm-lease.c b/src/backends/native/meta-drm-lease.c +index 302147e9bb..582f869b3b 100644 +--- a/src/backends/native/meta-drm-lease.c ++++ b/src/backends/native/meta-drm-lease.c +@@ -21,12 +21,14 @@ + + #include + ++#include "backends/meta-logical-monitor.h" + #include "backends/native/meta-crtc-kms.h" + #include "backends/native/meta-kms.h" + #include "backends/native/meta-kms-connector.h" + #include "backends/native/meta-kms-crtc-private.h" + #include "backends/native/meta-kms-device.h" + #include "backends/native/meta-kms-plane.h" ++#include "backends/native/meta-output-kms.h" + + enum + { +@@ -68,6 +70,7 @@ struct _MetaDrmLeaseManager + + gulong resources_changed_handler_id; + gulong lease_changed_handler_id; ++ gulong monitors_changed_handler_id; + + /* MetaKmsDevice *kms_device */ + GList *devices; +@@ -179,6 +182,32 @@ find_plane_to_lease (MetaKmsCrtc *kms_crtc, + return NULL; + } + ++static gboolean ++is_connector_configured_for_lease (MetaKmsConnector *connector) ++{ ++ const MetaKmsConnectorState *connector_state; ++ MetaOutputKms *output_kms; ++ MetaMonitor *monitor; ++ ++ connector_state = meta_kms_connector_get_current_state (connector); ++ if (!connector_state) ++ return FALSE; ++ ++ output_kms = meta_output_kms_from_kms_connector (connector); ++ if (!output_kms) ++ return FALSE; ++ ++ monitor = meta_output_get_monitor (META_OUTPUT (output_kms)); ++ return meta_monitor_is_for_lease (monitor); ++} ++ ++static gboolean ++is_connector_for_lease (MetaKmsConnector *connector) ++{ ++ return meta_kms_connector_is_non_desktop (connector) || ++ is_connector_configured_for_lease (connector); ++} ++ + static gboolean + find_resources_to_lease (MetaDrmLeaseManager *lease_manager, + MetaKmsDevice *kms_device, +@@ -227,7 +256,7 @@ find_resources_to_lease (MetaDrmLeaseManager *lease_manager, + MetaKmsDevice *connector_device; + + if (!g_list_find (available_connectors, connector) || +- !meta_kms_connector_is_non_desktop (connector)) ++ !is_connector_for_lease (connector)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Failed to find connector %u (%s)", +@@ -645,7 +674,7 @@ update_connectors (MetaDrmLeaseManager *lease_manager, + kms_connector = o->data; + lease = NULL; + +- if (!meta_kms_connector_is_non_desktop (kms_connector)) ++ if (!is_connector_for_lease (kms_connector)) + continue; + + if (g_list_find (lease_manager->connectors, kms_connector)) +@@ -845,6 +874,9 @@ meta_drm_lease_manager_constructed (GObject *object) + { + MetaDrmLeaseManager *lease_manager = META_DRM_LEASE_MANAGER (object); + MetaKms *kms = lease_manager->kms; ++ MetaBackend *backend = meta_kms_get_backend (kms); ++ MetaMonitorManager *monitor_manager = ++ meta_backend_get_monitor_manager (backend); + + lease_manager->resources_changed_handler_id = + g_signal_connect (kms, "resources-changed", +@@ -854,6 +886,10 @@ meta_drm_lease_manager_constructed (GObject *object) + g_signal_connect (kms, "lease-changed", + G_CALLBACK (on_lease_changed), + lease_manager); ++ lease_manager->monitors_changed_handler_id = ++ g_signal_connect_swapped (monitor_manager, "monitors-changed-internal", ++ G_CALLBACK (update_resources), ++ lease_manager); + + lease_manager->leases = + g_hash_table_new_full (NULL, NULL, +@@ -905,9 +941,14 @@ meta_drm_lease_manager_dispose (GObject *object) + { + MetaDrmLeaseManager *lease_manager = META_DRM_LEASE_MANAGER (object); + MetaKms *kms = lease_manager->kms; ++ MetaBackend *backend = meta_kms_get_backend (kms); ++ MetaMonitorManager *monitor_manager = ++ meta_backend_get_monitor_manager (backend); + + g_clear_signal_handler (&lease_manager->resources_changed_handler_id, kms); + g_clear_signal_handler (&lease_manager->lease_changed_handler_id, kms); ++ g_clear_signal_handler (&lease_manager->monitors_changed_handler_id, ++ monitor_manager); + + g_list_free_full (g_steal_pointer (&lease_manager->devices), g_object_unref); + g_list_free_full (g_steal_pointer (&lease_manager->connectors), +-- +2.48.1 + diff --git a/mutter.spec b/mutter.spec index 0ab5506..b970478 100644 --- a/mutter.spec +++ b/mutter.spec @@ -46,6 +46,19 @@ Patch: 0002-cursor-renderer-native-Store-formats-in-MetaCursorRe.patch Patch: 0003-cursor-renderer-native-Probe-formats-supported-by-cu.patch Patch: 0001-cursor-renderer-native-Skip-init_hw_cursor_support_f.patch +# RHEL-62220 +# DRM lease configuration via monitors.xml and D-Bus: +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4112 +Patch: 0001-monitor-manager-Add-forlease-config-to-monitors.xml.patch +Patch: 0002-monitor-Keep-track-of-the-for-lease-status.patch +Patch: 0003-output-kms-Add-meta_output_kms_from_kms_connector.patch +Patch: 0004-kms-connector-Rename-meta_kms_connector_is_for_lease.patch +Patch: 0005-native-drm-lease-Handle-monitors-configured-for-leas.patch +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4121 +Patch: 0001-monitor-manager-Return-for-lease-status-in-GetCurren.patch +Patch: 0002-monitor-manager-Allow-to-check-if-config-has-a-visib.patch +Patch: 0003-monitor-manager-Configure-for-lease-monitors-in-Appl.patch + # Backports from gnome-47 branch between 47.5 and 47.6 Patch: 0001-wayland-Fix-refresh-interval-reporting-in-presentati.patch Patch: 0002-input-capture-session-Disconnect-on_keymap_changed-o.patch