Просмотр исходного кода

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)
Frank Praznik 2 недель назад
Родитель
Сommit
b90ac95029
1 измененных файлов с 19 добавлено и 0 удалено
  1. 19 0
      src/video/x11/SDL_x11events.c

+ 19 - 0
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)
 static void X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
 {
 {
     int i;
     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 */
         /* Copy the selection from our own CUTBUFFER to the requested property */
     case SelectionRequest:
     case SelectionRequest:
     {
     {
+        int (*prev_handler)(Display *, XErrorEvent *);
         const XSelectionRequestEvent *req = &xevent->xselectionrequest;
         const XSelectionRequestEvent *req = &xevent->xselectionrequest;
         XEvent sevent;
         XEvent sevent;
         int seln_format, mime_formats;
         int seln_format, mime_formats;
@@ -641,6 +653,11 @@ static void X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
                req->requestor, req->target);
                req->requestor, req->target);
 #endif
 #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);
         SDL_zero(sevent);
         sevent.xany.type = SelectionNotify;
         sevent.xany.type = SelectionNotify;
         sevent.xselection.selection = req->selection;
         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_XSendEvent(display, req->requestor, False, 0, &sevent);
         X11_XSync(display, False);
         X11_XSync(display, False);
+
+        X11_XSetErrorHandler(prev_handler);
     } break;
     } break;
 
 
     case SelectionNotify:
     case SelectionNotify: