From 1d5676bc9aca5832a6522d4964bd57768d158b3b Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Mon, 26 Feb 2024 15:30:36 +0100 Subject: [PATCH] wayland: Handle event interface changes during focus synchronization Currently, we don't handle too well the removal of a MetaWaylandEventInterface during meta_wayland_event_interface_invalidate_all_focus(), since the MetaWaylandEventInterface may be freed at an intermediate point in that function while handling the focus change for all input devices. Turn this invalidate_all_focus() function into a MetaWaylandInput method, and always ensure to use the currently effective MetaWaylandEventInterface when resetting the focus for each device. This fixes the situation through handling reentrancy naturally, a focus sync (say, triggered by a grab) would reset a device focus (say, pointer), which would remove an event interface (say, a pointer constraint), which would invalidate_all_focus() again underneath using the new effective MetaWaylandEventInterface. When that is done, the initial invalidate_all_focus() call would re-apply the same focus to the same currently effective MetaWaylandEventInterface, resulting in a no-op for the remainder of the function. Part-of: --- src/wayland/meta-wayland-input.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/wayland/meta-wayland-input.c b/src/wayland/meta-wayland-input.c index a0caa7253..346dfe348 100644 --- a/src/wayland/meta-wayland-input.c +++ b/src/wayland/meta-wayland-input.c @@ -137,9 +137,10 @@ meta_wayland_event_handler_invalidate_focus (MetaWaylandEventHandler *handler, } static void -meta_wayland_event_handler_invalidate_all_focus (MetaWaylandEventHandler *handler) +meta_wayland_input_invalidate_all_focus (MetaWaylandInput *input) { - MetaWaylandSeat *seat = handler->input->seat; + MetaWaylandEventHandler *handler; + MetaWaylandSeat *seat = input->seat; ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); ClutterInputDevice *device; @@ -149,12 +150,14 @@ meta_wayland_event_handler_invalidate_all_focus (MetaWaylandEventHandler *handle if (meta_wayland_seat_has_pointer (seat)) { device = clutter_seat_get_pointer (clutter_seat); + handler = wl_container_of (input->event_handler_list.next, handler, link); meta_wayland_event_handler_invalidate_focus (handler, device, NULL); } if (meta_wayland_seat_has_keyboard (seat)) { device = clutter_seat_get_keyboard (clutter_seat); + handler = wl_container_of (input->event_handler_list.next, handler, link); meta_wayland_event_handler_invalidate_focus (handler, device, NULL); } @@ -163,11 +166,17 @@ meta_wayland_event_handler_invalidate_all_focus (MetaWaylandEventHandler *handle g_hash_table_iter_init (&iter, seat->tablet_seat->tablets); while (g_hash_table_iter_next (&iter, (gpointer*) &device, NULL)) - meta_wayland_event_handler_invalidate_focus (handler, device, NULL); + { + handler = wl_container_of (input->event_handler_list.next, handler, link); + meta_wayland_event_handler_invalidate_focus (handler, device, NULL); + } g_hash_table_iter_init (&iter, seat->tablet_seat->pads); while (g_hash_table_iter_next (&iter, (gpointer*) &device, NULL)) - meta_wayland_event_handler_invalidate_focus (handler, device, NULL); + { + handler = wl_container_of (input->event_handler_list.next, handler, link); + meta_wayland_event_handler_invalidate_focus (handler, device, NULL); + } } static gboolean @@ -248,7 +257,7 @@ meta_wayland_input_sync_focus (MetaWaylandInput *input) g_assert (!wl_list_empty (&input->event_handler_list)); handler = wl_container_of (input->event_handler_list.next, handler, link); - meta_wayland_event_handler_invalidate_all_focus (handler); + meta_wayland_input_invalidate_all_focus (input); } static void @@ -299,7 +308,7 @@ meta_wayland_input_attach_event_handler (MetaWaylandInput *input, input); } - meta_wayland_event_handler_invalidate_all_focus (handler); + meta_wayland_input_invalidate_all_focus (input); return handler; } @@ -331,7 +340,7 @@ meta_wayland_input_detach_event_handler (MetaWaylandInput *input, wl_container_of (input->event_handler_list.next, head, link); - meta_wayland_event_handler_invalidate_all_focus (head); + meta_wayland_input_invalidate_all_focus (input); } if (input->grab && !should_be_grabbed (input))