orientation-manager: Use an idle to apply monitor orientation changes

In X11 when we switch to another tty all the the signals are blocked (as
the display fd is not replying back to polling, causing the main loop to
stop), and they are all handled once we switch back to the tty.

This is not a problem for most of external events, but in case of
accelerometer changes, once we reactivate a mutter session we'll get
them all together, causing lots of monitor reconfigurations leading to
black screen for some seconds and most of the times to a wrong
configuration being applied.

To avoid this, batch all these events using an idle to only apply the
last one we got in a loop.

Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1217
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1233>
This commit is contained in:
Marco Trevisan (Treviño) 2020-05-01 16:32:46 +02:00 committed by Jonas Ådahl
parent d5f397977e
commit 4fe7569567
4 changed files with 102 additions and 2 deletions

View File

@ -52,6 +52,7 @@ struct _MetaOrientationManager
GCancellable *cancellable; GCancellable *cancellable;
guint iio_watch_id; guint iio_watch_id;
guint sync_idle_id;
GDBusProxy *iio_proxy; GDBusProxy *iio_proxy;
MetaOrientation prev_orientation; MetaOrientation prev_orientation;
MetaOrientation curr_orientation; MetaOrientation curr_orientation;
@ -135,13 +136,39 @@ sync_state (MetaOrientationManager *self)
g_signal_emit (self, signals[ORIENTATION_CHANGED], 0); g_signal_emit (self, signals[ORIENTATION_CHANGED], 0);
} }
static gboolean
changed_idle (gpointer user_data)
{
MetaOrientationManager *self = user_data;
self->sync_idle_id = 0;
sync_state (self);
return G_SOURCE_REMOVE;
}
static void
queue_sync_state (MetaOrientationManager *self)
{
/* We need this idle to avoid triggering events happening while the session
* is not active (under X11), ideally this should be handled by stopping
* events if the session is not active, but we'll need a MetaLogind available
* in all the backends for having this working.
*/
if (self->sync_idle_id)
return;
self->sync_idle_id = g_idle_add (changed_idle, self);
}
static void static void
orientation_lock_changed (GSettings *settings, orientation_lock_changed (GSettings *settings,
gchar *key, gchar *key,
gpointer user_data) gpointer user_data)
{ {
MetaOrientationManager *self = user_data; MetaOrientationManager *self = user_data;
sync_state (self); queue_sync_state (self);
} }
static void static void
@ -151,7 +178,7 @@ iio_properties_changed (GDBusProxy *proxy,
gpointer user_data) gpointer user_data)
{ {
MetaOrientationManager *self = user_data; MetaOrientationManager *self = user_data;
sync_state (self); queue_sync_state (self);
} }
static void static void
@ -288,6 +315,7 @@ meta_orientation_manager_finalize (GObject *object)
g_clear_object (&self->cancellable); g_clear_object (&self->cancellable);
g_bus_unwatch_name (self->iio_watch_id); g_bus_unwatch_name (self->iio_watch_id);
g_clear_handle_id (&self->sync_idle_id, g_source_remove);
g_clear_object (&self->iio_proxy); g_clear_object (&self->iio_proxy);
g_clear_object (&self->settings); g_clear_object (&self->settings);

View File

@ -36,6 +36,7 @@
#include "tests/monitor-test-utils.h" #include "tests/monitor-test-utils.h"
#include "tests/meta-test-utils.h" #include "tests/meta-test-utils.h"
#include "tests/unit-tests.h" #include "tests/unit-tests.h"
#include "tests/orientation-manager-unit-tests.h"
#include "x11/meta-x11-display-private.h" #include "x11/meta-x11-display-private.h"
static MonitorTestCase initial_test_case = { static MonitorTestCase initial_test_case = {
@ -3551,8 +3552,13 @@ typedef MetaSensorsProxyMock MetaSensorsProxyAutoResetMock;
static void static void
meta_sensors_proxy_reset (MetaSensorsProxyMock *proxy) meta_sensors_proxy_reset (MetaSensorsProxyMock *proxy)
{ {
MetaBackend *backend = meta_get_backend ();
MetaOrientationManager *orientation_manager =
meta_backend_get_orientation_manager (backend);
meta_sensors_proxy_mock_set_orientation (proxy, meta_sensors_proxy_mock_set_orientation (proxy,
META_ORIENTATION_NORMAL); META_ORIENTATION_NORMAL);
wait_for_orientation_changes (orientation_manager);
g_object_unref (proxy); g_object_unref (proxy);
} }
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaSensorsProxyAutoResetMock, G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaSensorsProxyAutoResetMock,
@ -3875,6 +3881,7 @@ meta_test_monitor_orientation_initial_rotated (void)
touch_device = meta_test_add_touch_device (backend); touch_device = meta_test_add_touch_device (backend);
orientation = META_ORIENTATION_LEFT_UP; orientation = META_ORIENTATION_LEFT_UP;
meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation); meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation);
wait_for_orientation_changes (orientation_manager);
g_assert_cmpuint ( g_assert_cmpuint (
meta_orientation_manager_get_orientation (orientation_manager), meta_orientation_manager_get_orientation (orientation_manager),
==, ==,
@ -3981,6 +3988,7 @@ meta_test_monitor_orientation_initial_rotated_no_touch_mode (void)
orientation_mock = meta_sensors_proxy_mock_get (); orientation_mock = meta_sensors_proxy_mock_get ();
orientation = META_ORIENTATION_LEFT_UP; orientation = META_ORIENTATION_LEFT_UP;
meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation); meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation);
wait_for_orientation_changes (orientation_manager);
g_assert_cmpuint ( g_assert_cmpuint (
meta_orientation_manager_get_orientation (orientation_manager), meta_orientation_manager_get_orientation (orientation_manager),
==, ==,
@ -4097,6 +4105,7 @@ meta_test_monitor_orientation_initial_stored_rotated (void)
touch_device = meta_test_add_touch_device (backend); touch_device = meta_test_add_touch_device (backend);
orientation = META_ORIENTATION_RIGHT_UP; orientation = META_ORIENTATION_RIGHT_UP;
meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation); meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation);
wait_for_orientation_changes (orientation_manager);
g_assert_cmpuint ( g_assert_cmpuint (
meta_orientation_manager_get_orientation (orientation_manager), meta_orientation_manager_get_orientation (orientation_manager),
==, ==,
@ -4122,6 +4131,11 @@ meta_test_monitor_orientation_initial_stored_rotated (void)
orientation = META_ORIENTATION_LEFT_UP; orientation = META_ORIENTATION_LEFT_UP;
meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation); meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation);
wait_for_orientation_changes (orientation_manager);
g_assert_cmpuint (
meta_orientation_manager_get_orientation (orientation_manager),
==,
orientation);
meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE); meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE);
meta_monitor_manager_lid_is_closed_changed (monitor_manager); meta_monitor_manager_lid_is_closed_changed (monitor_manager);
@ -4136,6 +4150,7 @@ meta_test_monitor_orientation_initial_stored_rotated (void)
orientation = META_ORIENTATION_RIGHT_UP; orientation = META_ORIENTATION_RIGHT_UP;
meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation); meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation);
wait_for_orientation_changes (orientation_manager);
g_assert_cmpuint ( g_assert_cmpuint (
meta_orientation_manager_get_orientation (orientation_manager), meta_orientation_manager_get_orientation (orientation_manager),
==, ==,
@ -4247,6 +4262,7 @@ meta_test_monitor_orientation_initial_stored_rotated_no_touch (void)
orientation_mock = meta_sensors_proxy_mock_get (); orientation_mock = meta_sensors_proxy_mock_get ();
orientation = META_ORIENTATION_RIGHT_UP; orientation = META_ORIENTATION_RIGHT_UP;
meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation); meta_sensors_proxy_mock_set_orientation (orientation_mock, orientation);
wait_for_orientation_changes (orientation_manager);
g_assert_cmpuint ( g_assert_cmpuint (
meta_orientation_manager_get_orientation (orientation_manager), meta_orientation_manager_get_orientation (orientation_manager),
==, ==,
@ -4390,6 +4406,7 @@ meta_test_monitor_orientation_changes (void)
MetaMonitorsConfig *previous; MetaMonitorsConfig *previous;
meta_sensors_proxy_mock_set_orientation (orientation_mock, i); meta_sensors_proxy_mock_set_orientation (orientation_mock, i);
wait_for_orientation_changes (orientation_manager);
g_assert_cmpuint ( g_assert_cmpuint (
meta_orientation_manager_get_orientation (orientation_manager), meta_orientation_manager_get_orientation (orientation_manager),
==, i); ==, i);
@ -4418,6 +4435,7 @@ meta_test_monitor_orientation_changes (void)
meta_sensors_proxy_mock_set_orientation (orientation_mock, meta_sensors_proxy_mock_set_orientation (orientation_mock,
META_ORIENTATION_NORMAL); META_ORIENTATION_NORMAL);
wait_for_orientation_changes (orientation_manager);
META_TEST_LOG_CALL ("Checking configuration per orientation", META_TEST_LOG_CALL ("Checking configuration per orientation",
check_monitor_configuration_per_orientation ( check_monitor_configuration_per_orientation (
&test_case.expect, 0, META_ORIENTATION_NORMAL, &test_case.expect, 0, META_ORIENTATION_NORMAL,
@ -4435,6 +4453,7 @@ meta_test_monitor_orientation_changes (void)
MetaMonitorsConfig *previous; MetaMonitorsConfig *previous;
meta_sensors_proxy_mock_set_orientation (orientation_mock, i); meta_sensors_proxy_mock_set_orientation (orientation_mock, i);
wait_for_orientation_changes (orientation_manager);
g_assert_cmpuint ( g_assert_cmpuint (
meta_orientation_manager_get_orientation (orientation_manager), meta_orientation_manager_get_orientation (orientation_manager),
==, i); ==, i);
@ -4611,6 +4630,7 @@ meta_test_monitor_orientation_changes_with_hotplugging (void)
for (i = META_N_ORIENTATIONS - 1; i > META_ORIENTATION_UNDEFINED; i--) for (i = META_N_ORIENTATIONS - 1; i > META_ORIENTATION_UNDEFINED; i--)
{ {
meta_sensors_proxy_mock_set_orientation (orientation_mock, i); meta_sensors_proxy_mock_set_orientation (orientation_mock, i);
wait_for_orientation_changes (orientation_manager);
g_assert_cmpuint ( g_assert_cmpuint (
meta_orientation_manager_get_orientation (orientation_manager), meta_orientation_manager_get_orientation (orientation_manager),
==, i); ==, i);
@ -4622,6 +4642,7 @@ meta_test_monitor_orientation_changes_with_hotplugging (void)
meta_sensors_proxy_mock_set_orientation (orientation_mock, meta_sensors_proxy_mock_set_orientation (orientation_mock,
META_ORIENTATION_NORMAL); META_ORIENTATION_NORMAL);
wait_for_orientation_changes (orientation_manager);
check_monitor_configuration (&test_case.expect); check_monitor_configuration (&test_case.expect);
/* External monitor connected */ /* External monitor connected */
@ -4642,6 +4663,7 @@ meta_test_monitor_orientation_changes_with_hotplugging (void)
for (i = META_N_ORIENTATIONS - 1; i > META_ORIENTATION_UNDEFINED; i--) for (i = META_N_ORIENTATIONS - 1; i > META_ORIENTATION_UNDEFINED; i--)
{ {
meta_sensors_proxy_mock_set_orientation (orientation_mock, i); meta_sensors_proxy_mock_set_orientation (orientation_mock, i);
wait_for_orientation_changes (orientation_manager);
g_assert_cmpuint ( g_assert_cmpuint (
meta_orientation_manager_get_orientation (orientation_manager), meta_orientation_manager_get_orientation (orientation_manager),
==, i); ==, i);
@ -4653,6 +4675,7 @@ meta_test_monitor_orientation_changes_with_hotplugging (void)
meta_sensors_proxy_mock_set_orientation (orientation_mock, meta_sensors_proxy_mock_set_orientation (orientation_mock,
META_ORIENTATION_NORMAL); META_ORIENTATION_NORMAL);
wait_for_orientation_changes (orientation_manager);
check_monitor_configuration (&test_case.expect); check_monitor_configuration (&test_case.expect);
/* Lid closed */ /* Lid closed */
@ -4672,11 +4695,13 @@ meta_test_monitor_orientation_changes_with_hotplugging (void)
for (i = META_N_ORIENTATIONS - 1; i > META_ORIENTATION_UNDEFINED; i--) for (i = META_N_ORIENTATIONS - 1; i > META_ORIENTATION_UNDEFINED; i--)
{ {
meta_sensors_proxy_mock_set_orientation (orientation_mock, i); meta_sensors_proxy_mock_set_orientation (orientation_mock, i);
wait_for_orientation_changes (orientation_manager);
check_monitor_configuration (&test_case.expect); check_monitor_configuration (&test_case.expect);
} }
meta_sensors_proxy_mock_set_orientation (orientation_mock, meta_sensors_proxy_mock_set_orientation (orientation_mock,
META_ORIENTATION_NORMAL); META_ORIENTATION_NORMAL);
wait_for_orientation_changes (orientation_manager);
/* /*
* The second part of this test emulate the following at each device rotation: * The second part of this test emulate the following at each device rotation:
@ -4719,6 +4744,7 @@ meta_test_monitor_orientation_changes_with_hotplugging (void)
/* Change orientation */ /* Change orientation */
meta_sensors_proxy_mock_set_orientation (orientation_mock, i); meta_sensors_proxy_mock_set_orientation (orientation_mock, i);
wait_for_orientation_changes (orientation_manager);
check_monitor_configuration (&test_case.expect); check_monitor_configuration (&test_case.expect);
/* Open the lid */ /* Open the lid */
@ -4734,6 +4760,7 @@ meta_test_monitor_orientation_changes_with_hotplugging (void)
meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE); meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE);
emulate_hotplug (test_setup); emulate_hotplug (test_setup);
wait_for_orientation_changes (orientation_manager);
META_TEST_LOG_CALL ("Checking configuration per orientation", META_TEST_LOG_CALL ("Checking configuration per orientation",
check_monitor_configuration_per_orientation ( check_monitor_configuration_per_orientation (
&test_case.expect, 0, i, 1024, 768)); &test_case.expect, 0, i, 1024, 768));
@ -4770,6 +4797,7 @@ meta_test_monitor_orientation_changes_with_hotplugging (void)
meta_sensors_proxy_mock_set_orientation (orientation_mock, meta_sensors_proxy_mock_set_orientation (orientation_mock,
META_ORIENTATION_NORMAL); META_ORIENTATION_NORMAL);
wait_for_orientation_changes (orientation_manager);
} }
static void static void

View File

@ -24,6 +24,44 @@
#include "tests/meta-sensors-proxy-mock.h" #include "tests/meta-sensors-proxy-mock.h"
static void
on_orientation_changed (gpointer data)
{
gboolean *changed = data;
*changed = TRUE;
}
static gboolean
on_max_wait_timeout (gpointer data)
{
guint *timeout_id = data;
*timeout_id = 0;
return G_SOURCE_REMOVE;
}
void
wait_for_orientation_changes (MetaOrientationManager *orientation_manager)
{
gboolean changed = FALSE;
gulong connection_id;
guint timeout_id;
timeout_id = g_timeout_add (300, on_max_wait_timeout, &timeout_id);
connection_id = g_signal_connect_swapped (orientation_manager,
"orientation-changed",
G_CALLBACK (on_orientation_changed),
&changed);
while (!changed && timeout_id)
g_main_context_iteration (NULL, TRUE);
g_clear_handle_id (&timeout_id, g_source_remove);
g_signal_handler_disconnect (orientation_manager, connection_id);
}
static void static void
meta_test_orientation_manager_no_daemon (void) meta_test_orientation_manager_no_daemon (void)
{ {
@ -64,6 +102,7 @@ meta_test_orientation_manager_has_accelerometer (void)
meta_sensors_proxy_mock_set_property (orientation_mock, meta_sensors_proxy_mock_set_property (orientation_mock,
"HasAccelerometer", "HasAccelerometer",
g_variant_new_boolean (TRUE)); g_variant_new_boolean (TRUE));
wait_for_orientation_changes (manager);
g_debug ("Checking whether accelerometer is present"); g_debug ("Checking whether accelerometer is present");
g_assert_true (meta_orientation_manager_has_accelerometer (manager)); g_assert_true (meta_orientation_manager_has_accelerometer (manager));
@ -104,6 +143,7 @@ meta_test_orientation_manager_accelerometer_orientations (void)
{ {
changed_called = FALSE; changed_called = FALSE;
meta_sensors_proxy_mock_set_orientation (orientation_mock, i); meta_sensors_proxy_mock_set_orientation (orientation_mock, i);
wait_for_orientation_changes (manager);
g_debug ("Checking orientation %d", i); g_debug ("Checking orientation %d", i);
g_assert_cmpuint (meta_orientation_manager_get_orientation (manager), g_assert_cmpuint (meta_orientation_manager_get_orientation (manager),

View File

@ -21,6 +21,10 @@
#ifndef ORIENTATION_MANAGER_UNIT_TESTS_H #ifndef ORIENTATION_MANAGER_UNIT_TESTS_H
#define ORIENTATION_MANAGER_UNIT_TESTS_H #define ORIENTATION_MANAGER_UNIT_TESTS_H
#include "backends/meta-orientation-manager.h"
void init_orientation_manager_tests (void); void init_orientation_manager_tests (void);
void wait_for_orientation_changes (MetaOrientationManager *orientation_manager);
#endif /* ORIENTATION_MANAGER_UNIT_TESTS_H */ #endif /* ORIENTATION_MANAGER_UNIT_TESTS_H */