summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ã…dahl <jadahl@gmail.com>2023-03-14 17:28:24 +0100
committerMarge Bot <marge-bot@gnome.org>2023-03-18 16:20:49 +0000
commit214a7d393b014cb12c1b7986e99e92d1eb324ff2 (patch)
treefcace47bb8bf36bbf1423dc148afebe4129871e0
parent5daddf0bc733c4d935767d1598610837347606e1 (diff)
downloadmutter-214a7d393b014cb12c1b7986e99e92d1eb324ff2.tar.gz
monitor-manager: Apply switch-config in idle callback
Just as with restoring the previous monitor configuration in case the user clicked "revert" in GNOME Shell's monitor configuration confirmation dialog, we need to do switch configs in an idle callback as well. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2694 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2912>
-rw-r--r--src/backends/meta-monitor-manager.c60
-rw-r--r--src/tests/monitor-unit-tests.c5
-rw-r--r--src/tests/native-kms-hotplug.c119
3 files changed, 172 insertions, 12 deletions
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index e6df87630..28cc457e7 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -116,6 +116,8 @@ typedef struct _MetaMonitorManagerPrivate
gboolean has_builtin_panel;
gboolean night_light_supported;
const char *experimental_hdr;
+
+ guint switch_config_handle_id;
} MetaMonitorManagerPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaMonitorManager, meta_monitor_manager,
@@ -1356,6 +1358,8 @@ static void
meta_monitor_manager_dispose (GObject *object)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
+ MetaMonitorManagerPrivate *priv =
+ meta_monitor_manager_get_instance_private (manager);
g_clear_handle_id (&manager->dbus_name_id, g_bus_unown_name);
@@ -1364,6 +1368,7 @@ meta_monitor_manager_dispose (GObject *object)
g_clear_handle_id (&manager->persistent_timeout_id, g_source_remove);
g_clear_handle_id (&manager->restore_config_id, g_source_remove);
+ g_clear_handle_id (&priv->switch_config_handle_id, g_source_remove);
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object);
}
@@ -3863,35 +3868,66 @@ meta_monitor_manager_rotate_monitor (MetaMonitorManager *manager)
g_object_unref (config);
}
-void
-meta_monitor_manager_switch_config (MetaMonitorManager *manager,
- MetaMonitorSwitchConfigType config_type)
+typedef struct
{
- GError *error = NULL;
+ MetaMonitorManager *monitor_manager;
+ MetaMonitorSwitchConfigType config_type;
+} SwitchConfigData;
+
+static gboolean
+switch_config_idle_cb (gpointer user_data)
+{
+ SwitchConfigData *data = user_data;
+ MetaMonitorManager *monitor_manager = data->monitor_manager;
+ MetaMonitorManagerPrivate *priv =
+ meta_monitor_manager_get_instance_private (monitor_manager);
+ MetaMonitorConfigManager *config_manager = monitor_manager->config_manager;
MetaMonitorsConfig *config;
+ g_autoptr (GError) error = NULL;
- g_return_if_fail (config_type != META_MONITOR_SWITCH_CONFIG_UNKNOWN);
+ priv->switch_config_handle_id = 0;
config =
- meta_monitor_config_manager_create_for_switch_config (manager->config_manager,
- config_type);
+ meta_monitor_config_manager_create_for_switch_config (config_manager,
+ data->config_type);
if (!config)
- return;
+ return G_SOURCE_REMOVE;
- if (!meta_monitor_manager_apply_monitors_config (manager,
+ if (!meta_monitor_manager_apply_monitors_config (monitor_manager,
config,
META_MONITORS_CONFIG_METHOD_TEMPORARY,
&error))
{
g_warning ("Failed to use switch monitor configuration: %s",
error->message);
- g_error_free (error);
}
else
{
- manager->current_switch_config = config_type;
+ monitor_manager->current_switch_config = data->config_type;
}
- g_object_unref (config);
+
+ return G_SOURCE_REMOVE;
+}
+
+void
+meta_monitor_manager_switch_config (MetaMonitorManager *manager,
+ MetaMonitorSwitchConfigType config_type)
+{
+ MetaMonitorManagerPrivate *priv =
+ meta_monitor_manager_get_instance_private (manager);
+ SwitchConfigData *data;
+
+ g_return_if_fail (config_type != META_MONITOR_SWITCH_CONFIG_UNKNOWN);
+
+ data = g_new0 (SwitchConfigData, 1);
+ data->monitor_manager = manager;
+ data->config_type = config_type;
+
+ g_clear_handle_id (&priv->switch_config_handle_id, g_source_remove);
+ priv->switch_config_handle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+ switch_config_idle_cb,
+ data,
+ g_free);
}
gboolean
diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c
index 5aedb7844..99355f6fe 100644
--- a/src/tests/monitor-unit-tests.c
+++ b/src/tests/monitor-unit-tests.c
@@ -3626,6 +3626,7 @@ meta_test_monitor_switch_external_without_external (void)
meta_monitor_manager_switch_config (monitor_manager,
META_MONITOR_SWITCH_CONFIG_EXTERNAL);
+ while (g_main_context_iteration (NULL, FALSE));
META_TEST_LOG_CALL ("Checking monitor configuration",
meta_check_monitor_configuration (test_context,
&test_case.expect));
@@ -3817,6 +3818,7 @@ meta_test_monitor_switch_config_remember_scale (void)
meta_monitor_manager_switch_config (monitor_manager,
META_MONITOR_SWITCH_CONFIG_BUILTIN);
+ while (g_main_context_iteration (NULL, FALSE));
META_TEST_LOG_CALL ("Checking monitor configuration",
meta_check_monitor_configuration (test_context,
&test_case.expect));
@@ -3837,6 +3839,7 @@ meta_test_monitor_switch_config_remember_scale (void)
meta_monitor_manager_switch_config (monitor_manager,
META_MONITOR_SWITCH_CONFIG_EXTERNAL);
+ while (g_main_context_iteration (NULL, FALSE));
META_TEST_LOG_CALL ("Checking monitor configuration",
meta_check_monitor_configuration (test_context,
&test_case.expect));
@@ -3856,6 +3859,7 @@ meta_test_monitor_switch_config_remember_scale (void)
meta_monitor_manager_switch_config (monitor_manager,
META_MONITOR_SWITCH_CONFIG_ALL_LINEAR);
+ while (g_main_context_iteration (NULL, FALSE));
META_TEST_LOG_CALL ("Checking monitor configuration",
meta_check_monitor_configuration (test_context,
&test_case.expect));
@@ -3874,6 +3878,7 @@ meta_test_monitor_switch_config_remember_scale (void)
meta_monitor_manager_switch_config (monitor_manager,
META_MONITOR_SWITCH_CONFIG_ALL_MIRROR);
+ while (g_main_context_iteration (NULL, FALSE));
META_TEST_LOG_CALL ("Checking monitor configuration",
meta_check_monitor_configuration (test_context,
&test_case.expect));
diff --git a/src/tests/native-kms-hotplug.c b/src/tests/native-kms-hotplug.c
index 4a6f2e0aa..3c60aa10a 100644
--- a/src/tests/native-kms-hotplug.c
+++ b/src/tests/native-kms-hotplug.c
@@ -17,11 +17,16 @@
#include "config.h"
+#include <linux/input-event-codes.h>
+
+#include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor-manager-private.h"
+#include "backends/meta-virtual-monitor.h"
#include "backends/native/meta-backend-native.h"
#include "backends/native/meta-udev.h"
#include "meta-test/meta-context-test.h"
#include "tests/drm-mock/drm-mock.h"
+#include "tests/meta-test-utils.h"
typedef enum _State
{
@@ -207,6 +212,118 @@ meta_test_disconnect_connect (void)
g_signal_handler_disconnect (stage, presented_handler_id);
}
+static gboolean
+on_key_release (ClutterActor *actor,
+ const ClutterEvent *event,
+ MetaMonitorManager *monitor_manager)
+{
+ if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_a)
+ {
+ g_debug ("Switching config");
+ meta_monitor_manager_switch_config (monitor_manager,
+ META_MONITOR_SWITCH_CONFIG_ALL_MIRROR);
+ }
+
+ return TRUE;
+}
+
+static void
+on_monitors_changed (MetaMonitorManager *monitor_manager,
+ gboolean *monitors_changed)
+{
+ *monitors_changed = TRUE;
+}
+
+static void
+meta_test_switch_config (void)
+{
+ MetaBackend *backend = meta_context_get_backend (test_context);
+ MetaMonitorManager *monitor_manager =
+ meta_backend_get_monitor_manager (backend);
+ ClutterActor *stage = meta_backend_get_stage (backend);
+ ClutterSeat *seat = meta_backend_get_default_seat (backend);
+ g_autoptr (ClutterVirtualInputDevice) virtual_keyboard = NULL;
+ g_autoptr (MetaVirtualMonitor) virtual_monitor = NULL;
+ GList *logical_monitors;
+ MetaRectangle logical_monitor_layout;
+ gulong after_paint_handler_id;
+ gulong presented_handler_id;
+ gboolean monitors_changed;
+ g_autoptr (GError) error = NULL;
+ ClutterActor *actor;
+ State state;
+
+ after_paint_handler_id = g_signal_connect (stage, "after-paint",
+ G_CALLBACK (on_after_paint),
+ &state);
+ presented_handler_id = g_signal_connect (stage, "presented",
+ G_CALLBACK (on_presented),
+ &state);
+ g_signal_connect (monitor_manager, "monitors-changed",
+ G_CALLBACK (on_monitors_changed),
+ &monitors_changed);
+
+ logical_monitors =
+ meta_monitor_manager_get_logical_monitors (monitor_manager);
+ g_assert_cmpuint (g_list_length (logical_monitors), ==, 1);
+ logical_monitor_layout =
+ meta_logical_monitor_get_layout (logical_monitors->data);
+
+ virtual_monitor = meta_create_test_monitor (test_context,
+ logical_monitor_layout.width,
+ logical_monitor_layout.height,
+ 60.0);
+
+ actor = clutter_actor_new ();
+ g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
+ clutter_actor_insert_child_above (stage,
+ actor,
+ clutter_actor_get_first_child (stage));
+ clutter_actor_set_size (actor,
+ logical_monitor_layout.width,
+ logical_monitor_layout.height);
+ clutter_actor_set_position (actor, 0, 0);
+ clutter_actor_set_reactive (actor, TRUE);
+ clutter_actor_show (actor);
+ clutter_actor_grab_key_focus (actor);
+ g_signal_connect (actor, "key-press-event",
+ G_CALLBACK (on_key_release),
+ monitor_manager);
+
+ monitors_changed = FALSE;
+ g_signal_connect (monitor_manager, "monitors-changed",
+ G_CALLBACK (on_monitors_changed),
+ &monitors_changed);
+
+ g_debug ("Sending virtual keyboard event");
+ virtual_keyboard =
+ clutter_seat_create_virtual_device (seat, CLUTTER_KEYBOARD_DEVICE);
+ clutter_virtual_input_device_notify_key (virtual_keyboard,
+ CLUTTER_CURRENT_TIME,
+ KEY_A,
+ CLUTTER_KEY_STATE_PRESSED);
+ clutter_virtual_input_device_notify_key (virtual_keyboard,
+ CLUTTER_CURRENT_TIME,
+ KEY_A,
+ CLUTTER_KEY_STATE_RELEASED);
+
+ g_debug ("Waiting for monitors changed");
+ while (!monitors_changed)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_debug ("Waiting for being repainted");
+ state = INIT;
+ clutter_actor_queue_redraw (stage);
+ while (state != PRESENTED)
+ g_main_context_iteration (NULL, TRUE);
+
+ clutter_actor_destroy (actor);
+ g_assert_null (actor);
+
+ g_signal_handler_disconnect (stage, after_paint_handler_id);
+ g_signal_handler_disconnect (stage, presented_handler_id);
+}
+
static void
init_tests (void)
{
@@ -214,6 +331,8 @@ init_tests (void)
meta_test_reload);
g_test_add_func ("/hotplug/disconnect-connect",
meta_test_disconnect_connect);
+ g_test_add_func ("/hotplug/switch-config",
+ meta_test_switch_config);
}
int