wayland: Remove all window references from seats when destroying a window

Compositors typically send keyboard, pointer, touch, and tablet leave events when a window is destroyed, however, this is not guaranteed behavior, and at least one compositor in widespread use doesn't always send pointer leave events immediately upon destroying a window. Ensure that all references held by seats to a focused window are removed before the underlying window surface and structs are destroyed to prevent potential segfaults if the seats are immediately destroyed after the window.
This commit is contained in:
Frank Praznik
2025-05-13 11:32:02 -04:00
parent 0a34279578
commit 83d4dce697
4 changed files with 84 additions and 61 deletions
File diff suppressed because it is too large Load Diff
+1
View File
@@ -205,6 +205,7 @@ extern bool Wayland_SeatHasRelativePointerFocus(SDL_WaylandSeat *seat);
extern void Wayland_SeatUpdatePointerGrab(SDL_WaylandSeat *seat);
extern void Wayland_DisplayUpdatePointerGrabs(SDL_VideoData *display, SDL_WindowData *window);
extern void Wayland_DisplayUpdateKeyboardGrabs(SDL_VideoData *display, SDL_WindowData *window);
extern void Wayland_DisplayRemoveWindowReferencesFromSeats(SDL_VideoData *display, SDL_WindowData *window);
/* The implicit grab serial needs to be updated on:
* - Keyboard key down/up
+6
View File
@@ -3093,6 +3093,12 @@ void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
WAYLAND_wl_display_roundtrip(data->display);
}
/* The compositor should have relinquished keyboard, pointer, touch, and tablet tool focus when the toplevel
* window was destroyed upon being hidden, but there is no guarantee of this, so ensure that all references
* to the window held by seats are released before destroying the underlying surface and struct.
*/
Wayland_DisplayRemoveWindowReferencesFromSeats(data, wind);
#ifdef SDL_VIDEO_OPENGL_EGL
if (wind->egl_surface) {
SDL_EGL_DestroySurface(_this, wind->egl_surface);
+2 -1
View File
@@ -132,9 +132,10 @@ struct SDL_WindowData
struct Wayland_SHMBuffer *icon_buffers;
int icon_buffer_count;
// Keyboard and pointer focus refcount.
// Keyboard, pointer, and touch focus refcount.
int keyboard_focus_count;
int pointer_focus_count;
int active_touch_count;
struct
{