From f803c0ee0a4a8148e1ac352f5d0b3050d042febf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 1 May 2020 15:53:55 +0200 Subject: [PATCH] monitor-manager: Add config relationships and use it for orientation events When we get an orientation event we don't care about keeping track of the configuration changes, but actually we can consider the new configuration just a variant of the previous one, adapted to floating device hardware events, so we only want to apply it if possible, but we don't want to keep a record of it for reverting capabilities. Doing that would in fact, break the ability of reverting back to an actual temporary or persistent configuration. For example when device orientation events happen while we're waiting for an user resolution change confirmation, we would save our new rotated configuration in the history, making then impossible to revert back to the original persistent one. So in such case, don't keep track of those configurations in the history, but only keep track of the last one as current, checking whether the new current is child or sibling of the previously one. Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1221 Related to: https://gitlab.gnome.org/GNOME/mutter/-/issues/646 Part-of: --- src/backends/meta-monitor-config-manager.c | 54 +++++- src/backends/meta-monitor-config-manager.h | 5 + src/backends/meta-monitor-manager.c | 15 ++ src/tests/monitor-unit-tests.c | 187 +++++++++++++++++++++ 4 files changed, 256 insertions(+), 5 deletions(-) diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c index 5f8324338..0a895c0a5 100644 --- a/src/backends/meta-monitor-config-manager.c +++ b/src/backends/meta-monitor-config-manager.c @@ -1038,6 +1038,7 @@ create_for_builtin_display_rotation (MetaMonitorConfigManager *config_manager, MetaMonitorManager *monitor_manager = config_manager->monitor_manager; MetaLogicalMonitorConfig *logical_monitor_config; MetaLogicalMonitorConfig *current_logical_monitor_config; + MetaMonitorsConfig *config; GList *logical_monitor_configs, *current_configs; MetaLogicalMonitorLayoutMode layout_mode; @@ -1085,10 +1086,13 @@ create_for_builtin_display_rotation (MetaMonitorConfigManager *config_manager, } layout_mode = base_config->layout_mode; - return meta_monitors_config_new (monitor_manager, - logical_monitor_configs, - layout_mode, - META_MONITORS_CONFIG_FLAG_NONE); + config = meta_monitors_config_new (monitor_manager, + logical_monitor_configs, + layout_mode, + META_MONITORS_CONFIG_FLAG_NONE); + meta_monitors_config_set_parent_config (config, base_config); + + return config; } MetaMonitorsConfig * @@ -1121,6 +1125,9 @@ meta_monitor_config_manager_create_for_builtin_orientation (MetaMonitorConfigMan MetaMonitorsConfig * meta_monitor_config_manager_create_for_rotate_monitor (MetaMonitorConfigManager *config_manager) { + if (!config_manager->current_config) + return NULL; + return create_for_builtin_display_rotation (config_manager, config_manager->current_config, TRUE, @@ -1319,11 +1326,37 @@ meta_monitor_config_manager_create_for_switch_config (MetaMonitorConfigManager return config; } +static MetaMonitorsConfig * +get_root_config (MetaMonitorsConfig *config) +{ + if (!config->parent_config) + return config; + + return get_root_config (config->parent_config); +} + +static gboolean +has_same_root_config (MetaMonitorsConfig *config_a, + MetaMonitorsConfig *config_b) +{ + return get_root_config (config_a) == get_root_config (config_b); +} + void meta_monitor_config_manager_set_current (MetaMonitorConfigManager *config_manager, MetaMonitorsConfig *config) { - if (config_manager->current_config) + MetaMonitorsConfig *current_config = config_manager->current_config; + gboolean overrides_current = FALSE; + + if (config && current_config && + has_same_root_config (config, current_config)) + { + overrides_current = meta_monitors_config_key_equal (config->key, + current_config->key); + } + + if (current_config && !overrides_current) { g_queue_push_head (&config_manager->config_history, g_object_ref (config_manager->current_config)); @@ -1522,6 +1555,16 @@ meta_monitors_config_set_switch_config (MetaMonitorsConfig *config, config->switch_config = switch_config; } +void +meta_monitors_config_set_parent_config (MetaMonitorsConfig *config, + MetaMonitorsConfig *parent_config) +{ + g_assert (config != parent_config); + g_assert (!parent_config || parent_config->parent_config != config); + + g_set_object (&config->parent_config, parent_config); +} + MetaMonitorsConfig * meta_monitors_config_new_full (GList *logical_monitor_configs, GList *disabled_monitor_specs, @@ -1583,6 +1626,7 @@ meta_monitors_config_finalize (GObject *object) { MetaMonitorsConfig *config = META_MONITORS_CONFIG (object); + g_clear_object (&config->parent_config); meta_monitors_config_key_free (config->key); g_list_free_full (config->logical_monitor_configs, (GDestroyNotify) meta_logical_monitor_config_free); diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h index 0b37665bc..025bafb8f 100644 --- a/src/backends/meta-monitor-config-manager.h +++ b/src/backends/meta-monitor-config-manager.h @@ -62,6 +62,7 @@ struct _MetaMonitorsConfig { GObject parent; + MetaMonitorsConfig *parent_config; MetaMonitorsConfigKey *key; GList *logical_monitor_configs; @@ -157,6 +158,10 @@ META_EXPORT_TEST void meta_monitors_config_set_switch_config (MetaMonitorsConfig *config, MetaMonitorSwitchConfigType switch_config); +META_EXPORT_TEST +void meta_monitors_config_set_parent_config (MetaMonitorsConfig *config, + MetaMonitorsConfig *parent_config); + META_EXPORT_TEST unsigned int meta_monitors_config_key_hash (gconstpointer config_key); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index 30fcee971..1e34f17da 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -773,6 +773,18 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) config = meta_monitor_config_manager_get_previous (manager->config_manager); if (config) { + g_autoptr (MetaMonitorsConfig) oriented_config = NULL; + + if (manager->panel_orientation_managed) + { + oriented_config = + meta_monitor_config_manager_create_for_builtin_orientation ( + manager->config_manager, config); + + if (oriented_config) + config = oriented_config; + } + config = g_object_ref (config); if (meta_monitor_manager_is_config_complete (manager, config)) @@ -891,6 +903,9 @@ handle_orientation_change (MetaOrientationManager *orientation_manager, current_config = meta_monitor_config_manager_get_current (manager->config_manager); + if (!current_config) + return; + config = meta_monitor_config_manager_create_for_orientation (manager->config_manager, current_config, diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c index d79d4f37c..dff80cbc9 100644 --- a/src/tests/monitor-unit-tests.c +++ b/src/tests/monitor-unit-tests.c @@ -302,6 +302,107 @@ meta_test_monitor_config_store_set_current_on_empty (void) g_assert_null (meta_monitor_config_manager_pop_previous (config_manager)); } +static void +meta_test_monitor_config_store_set_current_with_parent_on_empty (void) +{ + g_autoptr (MetaMonitorsConfig) parent_config = NULL; + g_autoptr (MetaMonitorsConfig) child_config1 = NULL; + g_autoptr (MetaMonitorsConfig) child_config2 = NULL; + g_autoptr (MetaMonitorsConfig) child_config3 = NULL; + g_autoptr (MetaMonitorsConfig) linear_config = NULL; + g_autoptr (MetaMonitorsConfig) fallback_config = NULL; + MetaBackend *backend = meta_get_backend (); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; + MetaMonitorsConfig *old_current; + + parent_config = meta_monitor_config_manager_create_linear (config_manager); + + child_config1 = meta_monitor_config_manager_create_linear (config_manager); + meta_monitors_config_set_parent_config (child_config1, parent_config); + old_current = meta_monitor_config_manager_get_current (config_manager); + + g_assert_null (old_current); + g_assert_nonnull (child_config1); + + meta_monitor_config_manager_set_current (config_manager, child_config1); + + g_assert (meta_monitor_config_manager_get_current (config_manager) == + child_config1); + g_assert (meta_monitor_config_manager_get_current (config_manager) != + old_current); + g_assert_null (meta_monitor_config_manager_get_previous (config_manager)); + g_assert_null (meta_monitor_config_manager_pop_previous (config_manager)); + + child_config2 = meta_monitor_config_manager_create_linear (config_manager); + meta_monitors_config_set_parent_config (child_config2, parent_config); + g_assert (child_config2->parent_config == parent_config); + + old_current = meta_monitor_config_manager_get_current (config_manager); + g_assert_nonnull (old_current->parent_config); + meta_monitor_config_manager_set_current (config_manager, child_config2); + + g_assert (meta_monitor_config_manager_get_current (config_manager) == + child_config2); + g_assert (meta_monitor_config_manager_get_current (config_manager) != + old_current); + g_assert_null (meta_monitor_config_manager_get_previous (config_manager)); + g_assert_null (meta_monitor_config_manager_pop_previous (config_manager)); + + child_config3 = meta_monitor_config_manager_create_linear (config_manager); + meta_monitors_config_set_parent_config (child_config3, child_config2); + + old_current = meta_monitor_config_manager_get_current (config_manager); + g_assert_nonnull (old_current->parent_config); + meta_monitor_config_manager_set_current (config_manager, child_config3); + + g_assert (meta_monitor_config_manager_get_current (config_manager) == + child_config3); + g_assert (meta_monitor_config_manager_get_current (config_manager) != + old_current); + g_assert_null (meta_monitor_config_manager_get_previous (config_manager)); + g_assert_null (meta_monitor_config_manager_pop_previous (config_manager)); + + linear_config = meta_monitor_config_manager_create_linear (config_manager); + g_assert_null (linear_config->parent_config); + + old_current = meta_monitor_config_manager_get_current (config_manager); + g_assert_nonnull (old_current->parent_config); + meta_monitor_config_manager_set_current (config_manager, linear_config); + + g_assert (meta_monitor_config_manager_get_current (config_manager) == + linear_config); + g_assert (meta_monitor_config_manager_get_current (config_manager) != + old_current); + g_assert (meta_monitor_config_manager_get_previous (config_manager) == + child_config3); + + fallback_config = + meta_monitor_config_manager_create_fallback (config_manager); + g_assert_null (fallback_config->parent_config); + + old_current = meta_monitor_config_manager_get_current (config_manager); + g_assert_null (old_current->parent_config); + meta_monitor_config_manager_set_current (config_manager, fallback_config); + + g_assert (meta_monitor_config_manager_get_current (config_manager) == + fallback_config); + g_assert (meta_monitor_config_manager_get_current (config_manager) != + old_current); + + g_assert (meta_monitor_config_manager_get_previous (config_manager) == + linear_config); + g_assert (meta_monitor_config_manager_pop_previous (config_manager) == + linear_config); + g_assert (meta_monitor_config_manager_get_previous (config_manager) == + child_config3); + g_assert (meta_monitor_config_manager_pop_previous (config_manager) == + child_config3); + g_assert_null (meta_monitor_config_manager_get_previous (config_manager)); + g_assert_null (meta_monitor_config_manager_pop_previous (config_manager)); +} + static void meta_test_monitor_config_store_set_current (void) { @@ -340,6 +441,88 @@ meta_test_monitor_config_store_set_current (void) g_assert_null (meta_monitor_config_manager_pop_previous (config_manager)); } +static void +meta_test_monitor_config_store_set_current_with_parent (void) +{ + g_autoptr (MetaMonitorsConfig) child_config = NULL; + g_autoptr (MetaMonitorsConfig) other_child = NULL; + g_autoptr (MetaMonitorsConfig) linear_config = NULL; + g_autoptr (MetaMonitorsConfig) fallback_config = NULL; + MetaBackend *backend = meta_get_backend (); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; + MetaMonitorsConfig *old_current; + + linear_config = meta_monitor_config_manager_create_linear (config_manager); + g_assert_null (linear_config->parent_config); + + old_current = meta_monitor_config_manager_get_current (config_manager); + g_assert_null (old_current); + meta_monitor_config_manager_set_current (config_manager, linear_config); + + g_assert (meta_monitor_config_manager_get_current (config_manager) == + linear_config); + g_assert (meta_monitor_config_manager_get_current (config_manager) != + old_current); + g_assert_null (meta_monitor_config_manager_get_previous (config_manager)); + g_assert_null (meta_monitor_config_manager_pop_previous (config_manager)); + + fallback_config = meta_monitor_config_manager_create_fallback (config_manager); + g_assert_nonnull (fallback_config); + g_assert_null (fallback_config->parent_config); + + old_current = meta_monitor_config_manager_get_current (config_manager); + g_assert_nonnull (old_current); + g_assert_null (old_current->parent_config); + meta_monitor_config_manager_set_current (config_manager, fallback_config); + + g_assert (meta_monitor_config_manager_get_current (config_manager) == + fallback_config); + g_assert (meta_monitor_config_manager_get_current (config_manager) != + old_current); + g_assert (meta_monitor_config_manager_get_previous (config_manager) == + old_current); + + child_config = meta_monitor_config_manager_create_linear (config_manager); + old_current = meta_monitor_config_manager_get_current (config_manager); + meta_monitors_config_set_parent_config (child_config, old_current); + + g_assert_nonnull (child_config); + g_assert_nonnull (old_current); + g_assert (old_current == fallback_config); + g_assert_null (old_current->parent_config); + + meta_monitor_config_manager_set_current (config_manager, child_config); + + g_assert (meta_monitor_config_manager_get_current (config_manager) == + child_config); + g_assert (meta_monitor_config_manager_get_current (config_manager) != + old_current); + g_assert (meta_monitor_config_manager_get_previous (config_manager) == + linear_config); + + other_child = meta_monitor_config_manager_create_linear (config_manager); + meta_monitors_config_set_parent_config (other_child, old_current); + + old_current = meta_monitor_config_manager_get_current (config_manager); + g_assert_nonnull (old_current->parent_config); + g_assert (old_current == child_config); + meta_monitor_config_manager_set_current (config_manager, other_child); + + g_assert (meta_monitor_config_manager_get_current (config_manager) == + other_child); + g_assert (meta_monitor_config_manager_get_current (config_manager) != + old_current); + g_assert (meta_monitor_config_manager_get_previous (config_manager) == + linear_config); + g_assert (meta_monitor_config_manager_pop_previous (config_manager) == + linear_config); + + g_assert_null (meta_monitor_config_manager_get_previous (config_manager)); + g_assert_null (meta_monitor_config_manager_pop_previous (config_manager)); +} + static void meta_test_monitor_config_store_set_current_max_size (void) { @@ -7044,8 +7227,12 @@ init_monitor_tests (void) add_monitor_test ("/backends/monitor/config-store/set_current-on-empty", meta_test_monitor_config_store_set_current_on_empty); + add_monitor_test ("/backends/monitor/config-store/set_current-with-parent-on-empty", + meta_test_monitor_config_store_set_current_with_parent_on_empty); add_monitor_test ("/backends/monitor/config-store/set_current", meta_test_monitor_config_store_set_current); + add_monitor_test ("/backends/monitor/config-store/set_current-with-parent", + meta_test_monitor_config_store_set_current_with_parent); add_monitor_test ("/backends/monitor/config-store/set_current-max-size", meta_test_monitor_config_store_set_current_max_size); add_monitor_test ("/backends/monitor/config-store/set_current-null",