Commit 8dea23c705dce35e949208aa0e44618e628a5cf5

Sam Lantinga 2019-05-19T10:44:14

Fixed bug 3911 - SYSWM generic X11 events missing event data Andrei Drexler For X11 GenericEvents, the associated data is only available between a call to XGetEventData and the matching XFreeEventData, i.e. in X11_HandleGenericEvent. Trying to call XGetEventData a second time on the same event will fail, so an application that wants to inspect XInput2 events (e.g. for stylus pressure) has no way of retrieving its data from queued SYSWM events. The attached patch (based on SDL-2.0.7-11629) sends SYSWM messages from X11_HandleGenericEvent while the data is still available, allowing client code to register an event filter/watcher and process the event inside the callback.

diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 2c903f7..cd46eff 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -309,6 +309,20 @@ static void X11_HandleGenericEvent(SDL_VideoData *videodata, XEvent *xev)
     XGenericEventCookie *cookie = &xev->xcookie;
     if (X11_XGetEventData(videodata->display, cookie)) {
         X11_HandleXinput2Event(videodata, cookie);
+
+        /* Send a SDL_SYSWMEVENT if the application wants them.
+         * Since event data is only available until XFreeEventData is called,
+         * the *only* way for an application to access it is to register an event filter/watcher
+         * and do all the processing on the SDL_SYSWMEVENT inside the callback. */
+        if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
+            SDL_SysWMmsg wmmsg;
+
+            SDL_VERSION(&wmmsg.version);
+            wmmsg.subsystem = SDL_SYSWM_X11;
+            wmmsg.msg.x11.event = *xev;
+            SDL_SendSysWMEvent(&wmmsg);
+        }
+
         X11_XFreeEventData(videodata->display, cookie);
     }
 }
@@ -684,6 +698,13 @@ X11_DispatchEvent(_THIS)
         return;
     }
 
+#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
+    if(xevent.type == GenericEvent) {
+        X11_HandleGenericEvent(videodata, &xevent);
+        return;
+    }
+#endif
+
     /* Send a SDL_SYSWMEVENT if the application wants them */
     if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
         SDL_SysWMmsg wmmsg;
@@ -694,13 +715,6 @@ X11_DispatchEvent(_THIS)
         SDL_SendSysWMEvent(&wmmsg);
     }
 
-#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
-    if(xevent.type == GenericEvent) {
-        X11_HandleGenericEvent(videodata, &xevent);
-        return;
-    }
-#endif
-
 #if 0
     printf("type = %d display = %d window = %d\n",
            xevent.type, xevent.xany.display, xevent.xany.window);