mirror of
https://github.com/brl/mutter.git
synced 2024-12-26 21:02:14 +00:00
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>
This commit is contained in:
parent
5daddf0bc7
commit
214a7d393b
@ -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;
|
||||
MetaMonitorsConfig *config;
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaMonitorSwitchConfigType config_type;
|
||||
} SwitchConfigData;
|
||||
|
||||
g_return_if_fail (config_type != META_MONITOR_SWITCH_CONFIG_UNKNOWN);
|
||||
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;
|
||||
|
||||
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
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user