wayland: Unset keyboard focus if surface is destroyed

Depending on the ordering of the surface-associated resources
being destroyed, we may fall into the following situation:

 - wl_surface is destroyed
 - destruction notifications for the surface runs
 - The MetaWaylandKeyboard attempts to synchronize the window
   focus
 - The MetaWindow is not destroyed yet, so the focused window
   remains the same, and the MetaWaylandKeyboard keeps the same
   focus MetaWaylandSurface.
 - wl_surface finalizes destruction, MetaWaylandSurface now has
   a NULL resource
 - xdg_toplevel destructor kicks in, it unmanages the window
 - The current focus window is again looked up, forced to look
   a different window
 - The MetaWaylandKeyboard focus now changes, tries to leave the
   old surface, but it has a NULL resource already, and raises
   a protocol error.

If the order is inverted, the window being unmanaged triggers a
focus change into a different window, the MetaWaylandKeyboard
triggers a focus change while the MetaWaylandSurface is still
intact, it succeeds, and the window gets properly destroyed.

In order to make this independent of the order, it makes sense
to make MetaWaylandKeyboard do like the other objects tracking
focus surfaces, and have it care of its own little parcel. The
surface destructor changed to simply unsetting the keyboard focus
to NULL (guaranteeing that the old focus is left while the surface
resource is still up), and leaving potential focus changes to
the xdg_toplevel_destructor->unmanage->update_focus paths.

Doing that alone is basically a revert of commit 228d681b, thus
is still subject to keyboard focus being lost after a popup is
destroyed. Change the approach to trigger the focus sync (and
new focus surface lookup) so it happens from xdg_popup_destructor
specifically to popups and alike xdg_toplevel.

Fixes: 228d681b ("wayland: Trigger full focus sync after keyboard focus surface is destroyed")

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2853
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3077>
This commit is contained in:
Carlos Garnacho 2023-06-14 21:15:36 +02:00 committed by Marge Bot
parent a95a3a0d30
commit c858ad7f91
2 changed files with 7 additions and 7 deletions

View File

@ -231,13 +231,8 @@ keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandKeyboard *keyboard =
wl_container_of (listener, keyboard, focus_surface_listener);
MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (keyboard);
MetaWaylandSeat *seat = meta_wayland_input_device_get_seat (input_device);
MetaWaylandCompositor *compositor = meta_wayland_seat_get_compositor (seat);
MetaContext *context = meta_wayland_compositor_get_context (compositor);
MetaDisplay *display = meta_context_get_display (context);
meta_display_sync_wayland_input_focus (display);
meta_wayland_keyboard_set_focus (keyboard, NULL);
}
static gboolean

View File

@ -590,10 +590,15 @@ xdg_popup_destructor (struct wl_resource *resource)
{
MetaWaylandXdgPopup *xdg_popup =
META_WAYLAND_XDG_POPUP (wl_resource_get_user_data (resource));
MetaWaylandSurfaceRole *surface_role =
META_WAYLAND_SURFACE_ROLE (xdg_popup);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
dismiss_popup (xdg_popup);
xdg_popup->resource = NULL;
meta_display_sync_wayland_input_focus (display_from_surface (surface));
}
static void