SDL: X11: allow using touchscreen, while pointer is grabbed (see bug #3978)

From 531d83bf6a140fcb5a858c9f23c76198016db869 Mon Sep 17 00:00:00 2001
From: Sylvain <[EMAIL REDACTED]>
Date: Wed, 12 May 2021 23:13:48 +0200
Subject: [PATCH] X11: allow using touchscreen, while pointer is grabbed (see
 bug #3978)

---
 src/video/x11/SDL_x11window.c  |  4 ++++
 src/video/x11/SDL_x11xinput2.c | 44 ++++++++++++++++++++++++++++++++++
 src/video/x11/SDL_x11xinput2.h |  2 ++
 3 files changed, 50 insertions(+)

diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index 19bae22b8..8ed2a4437 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -1623,6 +1623,8 @@ X11_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
             }
         }
 
+        X11_Xinput2GrabTouch(_this, window);
+
         /* Raise the window if we grab the mouse */
         X11_XRaiseWindow(display, data->xwindow);
 
@@ -1632,6 +1634,8 @@ X11_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
         }
     } else {
         X11_XUngrabPointer(display, CurrentTime);
+
+        X11_Xinput2UngrabTouch(_this, window);
     }
     X11_XSync(display, False);
 }
diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c
index 6634490e4..9f30da4b6 100644
--- a/src/video/x11/SDL_x11xinput2.c
+++ b/src/video/x11/SDL_x11xinput2.c
@@ -343,6 +343,50 @@ X11_Xinput2IsMultitouchSupported()
 #endif
 }
 
+void
+X11_Xinput2GrabTouch(_THIS, SDL_Window *window)
+{
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+    Display *display = data->videodata->display;
+
+    unsigned char mask[4] = { 0, 0, 0, 0 };
+    XIGrabModifiers mods;
+    XIEventMask eventmask;
+
+    mods.modifiers = XIAnyModifier;
+    mods.status = 0;
+
+    eventmask.deviceid = XIAllDevices;
+    eventmask.mask_len = sizeof(mask);
+    eventmask.mask = mask;
+
+    XISetMask(eventmask.mask, XI_TouchBegin);
+    XISetMask(eventmask.mask, XI_TouchUpdate);
+    XISetMask(eventmask.mask, XI_TouchEnd);
+    XISetMask(eventmask.mask, XI_Motion);
+
+    XIGrabTouchBegin(display, XIAllDevices, data->xwindow, True, &eventmask, 1, &mods);
+#endif
+}
+
+void
+X11_Xinput2UngrabTouch(_THIS, SDL_Window *window)
+{
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+    Display *display = data->videodata->display;
+
+    XIGrabModifiers mods;
+
+    mods.modifiers = XIAnyModifier;
+    mods.status = 0;
+
+    XIUngrabTouchBegin(display, XIAllDevices, data->xwindow, 1, &mods);
+#endif
+}
+
+
 #endif /* SDL_VIDEO_DRIVER_X11 */
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/x11/SDL_x11xinput2.h b/src/video/x11/SDL_x11xinput2.h
index 7fe4fb87a..5dd69266a 100644
--- a/src/video/x11/SDL_x11xinput2.h
+++ b/src/video/x11/SDL_x11xinput2.h
@@ -36,6 +36,8 @@ extern int X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *
 extern int X11_Xinput2IsInitialized(void);
 extern int X11_Xinput2IsMultitouchSupported(void);
 extern void X11_Xinput2SelectTouch(_THIS, SDL_Window *window);
+extern void X11_Xinput2GrabTouch(_THIS, SDL_Window *window);
+extern void X11_Xinput2UngrabTouch(_THIS, SDL_Window *window);
 
 #endif /* SDL_x11xinput2_h_ */