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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3618>
This commit is contained in:
Carlos Garnacho 2024-02-26 15:30:36 +01:00 committed by Marge Bot
parent 7fc49f742b
commit 1d5676bc9a

View File

@ -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))