wayland: Make the pointer leave non-alive surfaces

Listen to changes in MetaWindow::is-alive, so that the pointer
can logically leave the surface as soon as that happens. This
helps prevent flooding the client socket while it is stalled.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2122>
This commit is contained in:
Carlos Garnacho 2021-09-03 23:49:46 +02:00 committed by Marge Bot
parent 26676a829e
commit c07c50d189
2 changed files with 51 additions and 0 deletions

View File

@ -248,6 +248,18 @@ meta_wayland_pointer_unbind_pointer_client_resource (struct wl_resource *resourc
client);
}
static MetaWindow *
surface_get_effective_window (MetaWaylandSurface *surface)
{
MetaWaylandSurface *toplevel;
toplevel = meta_wayland_surface_get_toplevel (surface);
if (!toplevel)
return NULL;
return meta_wayland_surface_get_window (toplevel);
}
static void
sync_focus_surface (MetaWaylandPointer *pointer)
{
@ -453,6 +465,17 @@ default_grab_focus (MetaWaylandPointerGrab *grab,
break;
}
if (surface)
{
MetaWindow *window = NULL;
window = surface_get_effective_window (surface);
/* Avoid focusing a non-alive surface */
if (!window || !meta_window_get_alive (window))
surface = NULL;
}
meta_wayland_pointer_set_focus (pointer, surface);
}
@ -901,6 +924,16 @@ focus_surface_destroyed (MetaWaylandSurface *surface,
meta_wayland_pointer_set_focus (pointer, NULL);
}
static void
focus_surface_alive_notify (MetaWindow *window,
GParamSpec *pspec,
MetaWaylandPointer *pointer)
{
if (!meta_window_get_alive (window))
meta_wayland_pointer_set_focus (pointer, NULL);
sync_focus_surface (pointer);
}
void
meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface)
@ -910,6 +943,7 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
ClutterBackend *clutter_backend = clutter_get_default_backend ();
ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend);
MetaWindow *toplevel_window;
g_return_if_fail (meta_cursor_tracker_get_pointer_visible (cursor_tracker) ||
clutter_seat_is_unfocus_inhibited (clutter_seat) ||
@ -932,6 +966,13 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
pointer->focus_client = NULL;
}
toplevel_window = surface_get_effective_window (pointer->focus_surface);
if (toplevel_window)
{
g_clear_signal_handler (&pointer->focus_surface_alive_notify_id,
toplevel_window);
}
g_clear_signal_handler (&pointer->focus_surface_destroyed_handler_id,
pointer->focus_surface);
pointer->focus_surface = NULL;
@ -960,6 +1001,15 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
clutter_get_current_event_time (),
pos.x, pos.y);
toplevel_window = surface_get_effective_window (pointer->focus_surface);
if (toplevel_window)
{
pointer->focus_surface_alive_notify_id =
g_signal_connect (toplevel_window, "notify::is-alive",
G_CALLBACK (focus_surface_alive_notify),
pointer);
}
pointer->focus_client =
meta_wayland_pointer_get_pointer_client (pointer, client);
if (pointer->focus_client)

View File

@ -72,6 +72,7 @@ struct _MetaWaylandPointer
MetaWaylandSurface *focus_surface;
gulong focus_surface_destroyed_handler_id;
gulong focus_surface_alive_notify_id;
guint32 focus_serial;
guint32 click_serial;