From b90ac95029d801c5abc59472ba8e2200dff31e1e Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Wed, 2 Sep 2026 12:15:21 -0400 Subject: [PATCH] x11: Ignore BadWindow errors when handling a SelectionRequest When handing a SelectionRequest event, XChangeProperty can generate a BadWindow error if the requesting window was already destroyed. Register an error handler to catch this, and prevent it from being fatal. (cherry picked from commit ec6790bd5e10aa25c1743eb96e48b6ffb2c18267) --- src/video/x11/SDL_x11events.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 6435c920d6..db08c229d0 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -614,6 +614,17 @@ static void X11_UpdateUserTime(SDL_WindowData *data, const unsigned long latest) } } +static int SelectionRequestErrorHandler(Display *d, XErrorEvent *e) +{ + // Ignore BadWindow, as it can happen during XChangeProperty if the target window was already destroyed. + if (e->error_code != BadWindow) { + char err_msg[128]; + X11_XGetErrorText(d, e->error_code, err_msg, sizeof(err_msg)); + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Failed to handle SelectionRequest: %hhu (%s)", e->error_code, err_msg); + } + return 0; +} + static void X11_HandleClipboardEvent(_THIS, const XEvent *xevent) { int i; @@ -627,6 +638,7 @@ static void X11_HandleClipboardEvent(_THIS, const XEvent *xevent) /* Copy the selection from our own CUTBUFFER to the requested property */ case SelectionRequest: { + int (*prev_handler)(Display *, XErrorEvent *); const XSelectionRequestEvent *req = &xevent->xselectionrequest; XEvent sevent; int seln_format, mime_formats; @@ -641,6 +653,11 @@ static void X11_HandleClipboardEvent(_THIS, const XEvent *xevent) req->requestor, req->target); #endif + /* If the requesting window was already destroyed, XChangeProperty can generate a BadWindow + * error. Register an error handler to catch this, and prevent it from being fatal. + */ + prev_handler = X11_XSetErrorHandler(SelectionRequestErrorHandler); + SDL_zero(sevent); sevent.xany.type = SelectionNotify; sevent.xselection.selection = req->selection; @@ -690,6 +707,8 @@ static void X11_HandleClipboardEvent(_THIS, const XEvent *xevent) } X11_XSendEvent(display, req->requestor, False, 0, &sevent); X11_XSync(display, False); + + X11_XSetErrorHandler(prev_handler); } break; case SelectionNotify: