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 ec6790bd5e)
This commit is contained in:
Frank Praznik
2026-09-02 12:15:21 -04:00
parent e1bc7d6de9
commit b90ac95029

View File

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