From 25f4af8fcf7d1a9a06be8d89694b1c612158f41f Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Mon, 7 Sep 2026 10:51:38 -0400
Subject: [PATCH] x11: Handle XTranslateCoordinates failing during a
reparenting operation
XTranslateCoordinates can generate a BadWindow error if called during a racy reparenting operation, so a non-fatal error handler is required.
---
src/video/x11/SDL_x11events.c | 31 +++++++++++++++++++++++++------
1 file changed, 25 insertions(+), 6 deletions(-)
diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 40cad72eb6bfd..5a2ae42795ae2 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -792,13 +792,16 @@ static void X11_UpdateUserTime(SDL_WindowData *data, const unsigned long latest)
}
}
-static int SelectionRequestErrorHandler(Display *d, XErrorEvent *e)
+static unsigned char x11_last_error;
+static int BadWindowErrorHandler(Display *d, XErrorEvent *e)
{
- // Ignore BadWindow, as it can happen during XChangeProperty if the target window was already destroyed.
+ x11_last_error = e->error_code;
+
+ // Ignore BadWindow in cases where it's not fatal.
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);
+ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "X failed request: %hhu (%s), major opcode: %hhu", e->error_code, err_msg, e->request_code);
}
return 0;
}
@@ -816,7 +819,6 @@ static void X11_HandleClipboardEvent(SDL_VideoDevice *_this, const XEvent *xeven
// 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 mime_formats;
@@ -838,7 +840,8 @@ static void X11_HandleClipboardEvent(SDL_VideoDevice *_this, const XEvent *xeven
/* 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);
+ x11_last_error = 0;
+ XErrorHandler prev_handler = X11_XSetErrorHandler(BadWindowErrorHandler);
if (req->selection == XA_PRIMARY) {
clipboard = &videodata->primary_selection;
@@ -1686,13 +1689,29 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
unsigned int NumChildren;
Window ChildReturn, Root, Parent;
Window *Children;
- // Translate these coordinates back to relative to root
+ /* Translate these coordinates back to relative to root.
+ *
+ * XTranslateCoordinates can generate a BadWindow error if called during a racy
+ * reparenting operation, so a non-fatal error handler is required.
+ */
+ x11_last_error = 0;
+ XErrorHandler prev_handler = X11_XSetErrorHandler(BadWindowErrorHandler);
+
X11_XQueryTree(data->videodata->display, xevent->xconfigure.window, &Root, &Parent, &Children, &NumChildren);
X11_XTranslateCoordinates(xevent->xconfigure.display,
Parent, DefaultRootWindow(xevent->xconfigure.display),
xevent->xconfigure.x, xevent->xconfigure.y,
&xevent->xconfigure.x, &xevent->xconfigure.y,
&ChildReturn);
+
+ // Make sure the error callback was called if XTranslateCoordinates() failed.
+ X11_XSync(display, False);
+ X11_XSetErrorHandler(prev_handler);
+
+ // If XTranslateCoordinates failed due to a BadWindow error, nothing more to do here.
+ if (x11_last_error == BadWindow) {
+ break;
+ }
}
/* Some window managers send ConfigureNotify before PropertyNotify when changing state (Xfce and