backend: Dispatch initial burst of events synchronously on init

This will consist of device-added events, meaning before init finishes,
we can derive some state that depends on the set of input devices
available on startup, such as cursor visibility.

This avoids cursor visibility switching between hidden and visibility
during startup.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3070>
This commit is contained in:
Jonas Ådahl 2023-06-12 16:46:33 +02:00 committed by Marge Bot
parent 27606cf1fb
commit 49e6ce459c
3 changed files with 64 additions and 25 deletions

View File

@ -688,7 +688,7 @@ clutter_stage_compress_motion (ClutterStage *stage,
event->motion.dy_unaccel = dy_unaccel + dst_dy_unaccel;
}
void
CLUTTER_EXPORT void
_clutter_stage_process_queued_events (ClutterStage *stage)
{
ClutterStagePrivate *priv;

View File

@ -154,6 +154,8 @@ struct _MetaBackendPrivate
GList *gpus;
GList *hw_cursor_inhibitors;
gboolean in_init;
guint device_update_idle_id;
ClutterInputDevice *current_device;
@ -422,8 +424,9 @@ on_device_added (ClutterSeat *seat,
device_type = clutter_input_device_get_device_type (device);
if (device_type == CLUTTER_TOUCHSCREEN_DEVICE ||
device_type == CLUTTER_POINTER_DEVICE)
if (!priv->in_init &&
(device_type == CLUTTER_TOUCHSCREEN_DEVICE ||
device_type == CLUTTER_POINTER_DEVICE))
{
meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker,
determine_hotplug_pointer_visibility (seat));
@ -446,6 +449,8 @@ on_device_removed (ClutterSeat *seat,
MetaBackend *backend = META_BACKEND (user_data);
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
g_warn_if_fail (!priv->in_init);
if (clutter_input_device_get_device_mode (device) ==
CLUTTER_INPUT_MODE_LOGICAL)
return;
@ -1032,6 +1037,8 @@ update_pointer_visibility_from_event (MetaBackend *backend,
ClutterInputDeviceType device_type;
uint32_t time_ms;
g_warn_if_fail (!priv->in_init);
device = clutter_event_get_source_device (event);
device_type = clutter_input_device_get_device_type (device);
time_ms = clutter_event_get_time (event);
@ -1063,6 +1070,28 @@ update_pointer_visibility_from_event (MetaBackend *backend,
}
}
static gboolean
dispatch_clutter_event (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
ClutterEvent *event;
event = clutter_event_get ();
if (event)
{
g_warn_if_fail (!priv->in_init ||
event->type == CLUTTER_DEVICE_ADDED);
event->any.stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
clutter_do_event (event);
meta_backend_update_from_event (backend, event);
clutter_event_free (event);
return TRUE;
}
return FALSE;
}
/* Mutter is responsible for pulling events off the X queue, so Clutter
* doesn't need (and shouldn't) run its normal event source which polls
* the X fd, but we do have to deal with dispatching events that accumulate
@ -1095,16 +1124,8 @@ clutter_source_dispatch (GSource *source,
gpointer user_data)
{
MetaBackendSource *backend_source = (MetaBackendSource *) source;
ClutterEvent *event = clutter_event_get ();
if (event)
{
event->any.stage =
CLUTTER_STAGE (meta_backend_get_stage (backend_source->backend));
clutter_do_event (event);
meta_backend_update_from_event (backend_source->backend, event);
clutter_event_free (event);
}
dispatch_clutter_event (backend_source->backend);
return TRUE;
}
@ -1205,6 +1226,15 @@ meta_backend_initable_init (GInitable *initable,
meta_backend_post_init (backend);
while (TRUE)
{
if (!dispatch_clutter_event (backend))
break;
}
_clutter_stage_process_queued_events (CLUTTER_STAGE (priv->stage));
priv->in_init = FALSE;
return TRUE;
}
@ -1217,6 +1247,9 @@ initable_iface_init (GInitableIface *initable_iface)
static void
meta_backend_init (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
priv->in_init = TRUE;
}
/**
@ -1708,7 +1741,11 @@ void
meta_backend_update_from_event (MetaBackend *backend,
ClutterEvent *event)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
update_last_device_from_event (backend, event);
if (!priv->in_init)
update_pointer_visibility_from_event (backend, event);
}

View File

@ -2841,6 +2841,8 @@ init_libinput (MetaSeatImpl *seat_impl,
seat_impl->libinput = libinput;
process_events (seat_impl);
return TRUE;
}
@ -2877,18 +2879,6 @@ input_thread (MetaSeatImpl *seat_impl)
NULL,
(GDestroyNotify) meta_device_file_release);
if (!(seat_impl->flags & META_SEAT_NATIVE_FLAG_NO_LIBINPUT))
{
g_autoptr (GError) error = NULL;
if (!init_libinput (seat_impl, &error))
{
g_critical ("Failed to initialize seat: %s", error->message);
seat_impl->input_thread_initialized = TRUE;
return NULL;
}
}
seat_impl->input_settings = meta_input_settings_native_new_in_impl (seat_impl);
g_signal_connect_object (seat_impl->input_settings, "kbd-a11y-changed",
G_CALLBACK (kbd_a11y_changed_cb), seat_impl, 0);
@ -2912,6 +2902,18 @@ input_thread (MetaSeatImpl *seat_impl)
if (meta_input_settings_maybe_restore_numlock_state (seat_impl->input_settings))
meta_seat_impl_set_keyboard_numlock_in_impl (seat_impl, TRUE);
if (!(seat_impl->flags & META_SEAT_NATIVE_FLAG_NO_LIBINPUT))
{
g_autoptr (GError) error = NULL;
if (!init_libinput (seat_impl, &error))
{
g_critical ("Failed to initialize seat: %s", error->message);
seat_impl->input_thread_initialized = TRUE;
return NULL;
}
}
seat_impl->has_touchscreen = has_touchscreen (seat_impl);
seat_impl->has_tablet_switch = has_tablet_switch (seat_impl);
update_touch_mode (seat_impl);