SDL: Use the specific pointer device ID for X11 button and motion events

From 20a860c87657a2c2f01441d9d395c479b718d909 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 21 Mar 2024 16:15:09 -0700
Subject: [PATCH] Use the specific pointer device ID for X11 button and motion
 events

---
 src/video/x11/SDL_x11events.c  | 14 +++++++-------
 src/video/x11/SDL_x11events.h  |  4 ++--
 src/video/x11/SDL_x11xinput2.c | 16 +++++++++++-----
 3 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 1a63f06f60704..3766515796e54 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -832,7 +832,7 @@ SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window)
     return NULL;
 }
 
-void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, int button, const float x, const float y, const unsigned long time)
+void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, const float x, const float y, const unsigned long time)
 {
     SDL_Window *window = windowdata->window;
     const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
@@ -842,7 +842,7 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, i
     printf("window %p: ButtonPress (X11 button = %d)\n", window, button);
 #endif
     if (X11_IsWheelEvent(display, button, &xticks, &yticks)) {
-        SDL_SendMouseWheel(0, window, videodata->mouseID, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL);
+        SDL_SendMouseWheel(0, window, mouseID, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL);
     } else {
         SDL_bool ignore_click = SDL_FALSE;
         if (button == Button1) {
@@ -863,13 +863,13 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, i
             windowdata->last_focus_event_time = 0;
         }
         if (!ignore_click) {
-            SDL_SendMouseButton(0, window, videodata->mouseID, SDL_PRESSED, button);
+            SDL_SendMouseButton(0, window, mouseID, SDL_PRESSED, button);
         }
     }
     X11_UpdateUserTime(windowdata, time);
 }
 
-void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, int button)
+void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button)
 {
     SDL_Window *window = windowdata->window;
     const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
@@ -884,7 +884,7 @@ void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata,
             /* see explanation at case ButtonPress */
             button -= (8 - SDL_BUTTON_X1);
         }
-        SDL_SendMouseButton(0, window, videodata->mouseID, SDL_RELEASED, button);
+        SDL_SendMouseButton(0, window, mouseID, SDL_RELEASED, button);
     }
 }
 
@@ -1531,13 +1531,13 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
 
     case ButtonPress:
     {
-        X11_HandleButtonPress(_this, data, xevent->xbutton.button,
+        X11_HandleButtonPress(_this, data, videodata->mouseID, xevent->xbutton.button,
                               xevent->xbutton.x, xevent->xbutton.y, xevent->xbutton.time);
     } break;
 
     case ButtonRelease:
     {
-        X11_HandleButtonRelease(_this, data, xevent->xbutton.button);
+        X11_HandleButtonRelease(_this, data, videodata->mouseID, xevent->xbutton.button);
     } break;
 #endif /* !SDL_VIDEO_DRIVER_X11_XINPUT2 */
 
diff --git a/src/video/x11/SDL_x11events.h b/src/video/x11/SDL_x11events.h
index 3e34064e05abc..911d9102e412b 100644
--- a/src/video/x11/SDL_x11events.h
+++ b/src/video/x11/SDL_x11events.h
@@ -29,8 +29,8 @@ extern void X11_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window);
 extern int X11_SuspendScreenSaver(SDL_VideoDevice *_this);
 extern void X11_ReconcileKeyboardState(SDL_VideoDevice *_this);
 extern void X11_GetBorderValues(SDL_WindowData *data);
-extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button, const float x, const float y, const unsigned long time);
-extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button);
+extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *wdata, SDL_MouseID mouseID, int button, const float x, const float y, const unsigned long time);
+extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *wdata, SDL_MouseID mouseID, int button);
 extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window);
 extern SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, SDL_bool force_new_result);
 extern SDL_bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y);
diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c
index d742ecd783216..38fb75ed353e6 100644
--- a/src/video/x11/SDL_x11xinput2.c
+++ b/src/video/x11/SDL_x11xinput2.c
@@ -108,11 +108,17 @@ static void xinput2_init_device_list(SDL_VideoData *videodata)
         switch (dev->use) {
         case XIMasterKeyboard:
             videodata->keyboardID = (SDL_KeyboardID)dev->deviceid;
-            SDL_AddKeyboard(videodata->keyboardID, SDL_FALSE);
+            SDL_AddKeyboard((SDL_KeyboardID)dev->deviceid, SDL_FALSE);
+            break;
+        case XISlaveKeyboard:
+            SDL_AddKeyboard((SDL_KeyboardID)dev->deviceid, SDL_FALSE);
             break;
         case XIMasterPointer:
             videodata->mouseID = (SDL_MouseID)dev->deviceid;
-            SDL_AddMouse(videodata->mouseID, SDL_FALSE);
+            SDL_AddMouse((SDL_MouseID)dev->deviceid, SDL_FALSE);
+            break;
+        case XISlavePointer:
+            SDL_AddMouse((SDL_MouseID)dev->deviceid, SDL_FALSE);
             break;
         default:
             break;
@@ -471,10 +477,10 @@ int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
             }
 
             if (pressed) {
-                X11_HandleButtonPress(_this, windowdata, button,
+                X11_HandleButtonPress(_this, windowdata, (SDL_MouseID)xev->sourceid, button,
                                       xev->event_x, xev->event_y, xev->time);
             } else {
-                X11_HandleButtonRelease(_this, windowdata, button);
+                X11_HandleButtonRelease(_this, windowdata, (SDL_MouseID)xev->sourceid, button);
             }
         }
     } break;
@@ -521,7 +527,7 @@ int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
                 SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
                 if (window) {
                     X11_ProcessHitTest(_this, window->driverdata, (float)xev->event_x, (float)xev->event_y, SDL_FALSE);
-                    SDL_SendMouseMotion(0, window, videodata->mouseID, SDL_FALSE, (float)xev->event_x, (float)xev->event_y);
+                    SDL_SendMouseMotion(0, window, (SDL_MouseID)xev->sourceid, SDL_FALSE, (float)xev->event_x, (float)xev->event_y);
                 }
             }
         }