SDL: Be explicit about the event mouse and keyboard ID

From d1eb4adb1618bb2685974eb720b10bc63b049b9f Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 21 Mar 2024 09:27:12 -0700
Subject: [PATCH] Be explicit about the event mouse and keyboard ID

---
 include/SDL3/SDL_pen.h                      |   2 +-
 src/core/haiku/SDL_BApp.h                   |  13 +-
 src/core/linux/SDL_evdev.c                  |  17 +
 src/core/openbsd/SDL_wscons_kbd.c           |  21 +-
 src/core/openbsd/SDL_wscons_mouse.c         |  53 +--
 src/core/winrt/SDL_winrtapp_direct3d.cpp    |   2 +-
 src/events/SDL_keyboard.c                   |  23 +-
 src/events/SDL_keyboard_c.h                 |   4 +-
 src/events/SDL_mouse.c                      |  34 +-
 src/events/SDL_mouse_c.h                    |   9 +-
 src/events/SDL_pen.c                        |  11 +-
 src/events/SDL_touch.c                      |   4 +-
 src/video/android/SDL_androidkeyboard.c     |   4 +-
 src/video/android/SDL_androidmouse.c        |  12 +-
 src/video/android/SDL_androidvideo.c        |   2 +
 src/video/android/SDL_androidvideo.h        |   2 +
 src/video/cocoa/SDL_cocoakeyboard.m         |   9 +-
 src/video/cocoa/SDL_cocoamouse.m            |  16 +-
 src/video/cocoa/SDL_cocoavideo.h            |   2 +
 src/video/cocoa/SDL_cocoavideo.m            |  10 +
 src/video/cocoa/SDL_cocoawindow.m           |  23 +-
 src/video/emscripten/SDL_emscriptenevents.c |  14 +-
 src/video/emscripten/SDL_emscriptenvideo.c  |   4 +
 src/video/emscripten/SDL_emscriptenvideo.h  |   3 +
 src/video/haiku/SDL_BApp.h                  | 425 --------------------
 src/video/haiku/SDL_bvideo.cc               |   6 +
 src/video/kmsdrm/SDL_kmsdrmmouse.c          |   2 +-
 src/video/ngage/SDL_ngageevents.cpp         |  24 +-
 src/video/ngage/SDL_ngagevideo.h            |   2 +
 src/video/qnx/SDL_qnx.h                     |   3 +
 src/video/qnx/SDL_qnxkeyboard.c             |   4 +-
 src/video/qnx/SDL_qnxvideo.c                |   7 +-
 src/video/raspberry/SDL_rpimouse.c          |   2 +-
 src/video/riscos/SDL_riscosevents.c         |   8 +-
 src/video/riscos/SDL_riscosvideo.c          |  18 +-
 src/video/riscos/SDL_riscosvideo.h          |   2 +
 src/video/uikit/SDL_uikitevents.m           |   8 +-
 src/video/vita/SDL_vitakeyboard.c           |  61 +--
 src/video/vita/SDL_vitamouse.c              |  19 +-
 src/video/wayland/SDL_waylandevents.c       |  14 +-
 src/video/windows/SDL_windowsevents.c       |  79 ++--
 src/video/windows/SDL_windowsevents.h       |   2 +-
 src/video/windows/SDL_windowsmouse.c        |   2 +-
 src/video/windows/SDL_windowsvideo.c        |   2 +-
 src/video/windows/SDL_windowsvideo.h        |   3 +
 src/video/winrt/SDL_winrtevents_c.h         |   3 +
 src/video/winrt/SDL_winrtkeyboard.cpp       |   2 +-
 src/video/winrt/SDL_winrtpointerinput.cpp   |  17 +-
 src/video/winrt/SDL_winrtvideo.cpp          |   5 +
 src/video/x11/SDL_x11events.c               |  52 +--
 src/video/x11/SDL_x11video.h                |   3 +
 src/video/x11/SDL_x11xinput2.c              |   4 +-
 test/testautomation_pen.c                   |  13 +-
 53 files changed, 383 insertions(+), 703 deletions(-)
 delete mode 100644 src/video/haiku/SDL_BApp.h

diff --git a/include/SDL3/SDL_pen.h b/include/SDL3/SDL_pen.h
index 57744599f4635..9eab3c0ad2554 100644
--- a/include/SDL3/SDL_pen.h
+++ b/include/SDL3/SDL_pen.h
@@ -58,7 +58,7 @@ typedef Uint32 SDL_PenID; /**< SDL_PenIDs identify pens uniquely within a sessio
 
 #define SDL_PEN_INVALID ((SDL_PenID)0) /**< Reserved invalid ::SDL_PenID is valid */
 
-#define SDL_PEN_MOUSEID ((SDL_PenID)-2) /**< Device ID for mouse events triggered by pen events */
+#define SDL_PEN_MOUSEID ((SDL_MouseID)-2) /**< Device ID for mouse events triggered by pen events */
 
 #define SDL_PEN_INFO_UNKNOWN (-1) /**< Marks unknown information when querying the pen */
 
diff --git a/src/core/haiku/SDL_BApp.h b/src/core/haiku/SDL_BApp.h
index 2d5be1e2b493c..54f98b267f561 100644
--- a/src/core/haiku/SDL_BApp.h
+++ b/src/core/haiku/SDL_BApp.h
@@ -46,6 +46,9 @@ extern "C" {
 
 #include <vector>
 
+#define BAPP_KEYBOARD_ID    1
+#define BAPP_MOUSE_ID       1
+
 /* Forward declarations */
 class SDL_BLooper;
 class SDL_BWin;
@@ -248,12 +251,12 @@ class SDL_BLooper : public BLooper
             SDL_GetWindowPosition(win, &winPosX, &winPosY);
             int dx = x - (winWidth / 2);
             int dy = y - (winHeight / 2);
-            SDL_SendMouseMotion(0, win, 0, SDL_GetMouse()->relative_mode, (float)dx, (float)dy);
+            SDL_SendMouseMotion(0, win, BAPP_MOUSE_ID, SDL_GetMouse()->relative_mode, (float)dx, (float)dy);
             set_mouse_position((winPosX + winWidth / 2), (winPosY + winHeight / 2));
             if (!be_app->IsCursorHidden())
                 be_app->HideCursor();
         } else {
-            SDL_SendMouseMotion(0, win, 0, 0, (float)x, (float)y);
+            SDL_SendMouseMotion(0, win, BAPP_MOUSE_ID, SDL_FALSE, (float)x, (float)y);
             if (SDL_CursorVisible() && be_app->IsCursorHidden())
                 be_app->ShowCursor();
         }
@@ -271,7 +274,7 @@ class SDL_BLooper : public BLooper
             return;
         }
         win = GetSDLWindow(winID);
-        SDL_SendMouseButton(0, win, 0, state, button);
+        SDL_SendMouseButton(0, win, BAPP_MOUSE_ID, state, button);
     }
 
     void _HandleMouseWheel(BMessage *msg)
@@ -286,7 +289,7 @@ class SDL_BLooper : public BLooper
             return;
         }
         win = GetSDLWindow(winID);
-        SDL_SendMouseWheel(0, win, 0, xTicks, -yTicks, SDL_MOUSEWHEEL_NORMAL);
+        SDL_SendMouseWheel(0, win, BAPP_MOUSE_ID, xTicks, -yTicks, SDL_MOUSEWHEEL_NORMAL);
     }
 
     void _HandleKey(BMessage *msg)
@@ -303,7 +306,7 @@ class SDL_BLooper : public BLooper
             return;
         }
         HAIKU_SetKeyState(scancode, state);
-        SDL_SendKeyboardKey(0, 0, state, HAIKU_GetScancodeFromBeKey(scancode));
+        SDL_SendKeyboardKey(0, BAPP_KEYBOARD_ID, state, HAIKU_GetScancodeFromBeKey(scancode));
 
         if (state == SDL_PRESSED && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) {
             const int8 *keyUtf8;
diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c
index 5a8c6e5e5e4b1..fa9b141315150 100644
--- a/src/core/linux/SDL_evdev.c
+++ b/src/core/linux/SDL_evdev.c
@@ -605,11 +605,20 @@ static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode)
     return scancode;
 }
 
+static int SDL_EVDEV_init_keyboard(SDL_evdevlist_item *item, int udev_class)
+{
+    SDL_AddKeyboard((SDL_KeyboardID)item->fd, SDL_TRUE);
+
+    return 0;
+}
+
 static int SDL_EVDEV_init_mouse(SDL_evdevlist_item *item, int udev_class)
 {
     int ret;
     struct input_absinfo abs_info;
 
+    SDL_AddMouse((SDL_MouseID)item->fd, SDL_TRUE);
+
     ret = ioctl(item->fd, EVIOCGABS(ABS_X), &abs_info);
     if (ret < 0) {
         // no absolute mode info, continue
@@ -922,6 +931,14 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class)
             SDL_free(item);
             return ret;
         }
+    } else if (udev_class & SDL_UDEV_DEVICE_KEYBOARD) {
+        int ret = SDL_EVDEV_init_keyboard(item, udev_class);
+        if (ret < 0) {
+            close(item->fd);
+            SDL_free(item->path);
+            SDL_free(item);
+            return ret;
+        }
     }
 
     if (!_this->last) {
diff --git a/src/core/openbsd/SDL_wscons_kbd.c b/src/core/openbsd/SDL_wscons_kbd.c
index 1cc361b7697bd..541ad2cbef34d 100644
--- a/src/core/openbsd/SDL_wscons_kbd.c
+++ b/src/core/openbsd/SDL_wscons_kbd.c
@@ -33,6 +33,7 @@
 #include <unistd.h>
 
 #include "../../events/SDL_events_c.h"
+#include "../../events/SDL_keyboard_c.h"
 
 #ifdef SDL_PLATFORM_NETBSD
 #define KS_GROUP_Ascii    KS_GROUP_Plain
@@ -388,6 +389,7 @@ static struct wscons_keycode_to_SDL
 typedef struct
 {
     int fd;
+    SDL_KeyboardID keyboardID;
     struct wskbd_map_data keymap;
     int ledstate;
     int origledstate;
@@ -420,14 +422,19 @@ static SDL_WSCONS_input_data *SDL_WSCONS_Init_Keyboard(const char *dev)
     SDL_WSCONS_input_data *input = (SDL_WSCONS_input_data *)SDL_calloc(1, sizeof(SDL_WSCONS_input_data));
 
     if (!input) {
-        return input;
+        return NULL;
     }
+
     input->fd = open(dev, O_RDWR | O_NONBLOCK | O_CLOEXEC);
     if (input->fd == -1) {
         SDL_free(input);
         input = NULL;
         return NULL;
     }
+
+    input->keyboardID = SDL_GetNextObjectID();
+    SDL_AddKeyboard(input->keyboardID, SDL_FALSE);
+
     input->keymap.map = SDL_calloc(sizeof(struct wscons_keymap), KS_NUMKEYCODES);
     if (!input->keymap.map) {
         SDL_free(input);
@@ -553,22 +560,22 @@ static void Translate_to_keycode(SDL_WSCONS_input_data *input, int type, keysym_
     switch (keyDesc.command) {
     case KS_Cmd_ScrollBack:
     {
-        SDL_SendKeyboardKey(0, 0, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEUP);
+        SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEUP);
         return;
     }
     case KS_Cmd_ScrollFwd:
     {
-        SDL_SendKeyboardKey(0, 0, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEDOWN);
+        SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEDOWN);
         return;
     }
     }
     for (i = 0; i < sizeof(conversion_table) / sizeof(struct wscons_keycode_to_SDL); i++) {
         if (conversion_table[i].sourcekey == group[0]) {
-            SDL_SendKeyboardKey(0, 0, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, conversion_table[i].targetKey);
+            SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, conversion_table[i].targetKey);
             return;
         }
     }
-    SDL_SendKeyboardKey(0, 0, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_UNKNOWN);
+    SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_UNKNOWN);
 }
 
 static void updateKeyboard(SDL_WSCONS_input_data *input)
@@ -802,13 +809,13 @@ static void updateKeyboard(SDL_WSCONS_input_data *input)
             } break;
             case WSCONS_EVENT_ALL_KEYS_UP:
                 for (i = 0; i < SDL_NUM_SCANCODES; i++) {
-                    SDL_SendKeyboardKey(0, 0, SDL_RELEASED, i);
+                    SDL_SendKeyboardKey(0, input->keyboardID, SDL_RELEASED, i);
                 }
                 break;
             }
 
             if (input->type == WSKBD_TYPE_USB && events[i].value <= 0xE7)
-                SDL_SendKeyboardKey(0, 0, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, (SDL_Scancode)events[i].value);
+                SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, (SDL_Scancode)events[i].value);
             else
                 Translate_to_keycode(input, type, events[i].value);
 
diff --git a/src/core/openbsd/SDL_wscons_mouse.c b/src/core/openbsd/SDL_wscons_mouse.c
index 3d3de9557977a..435de1e099b3d 100644
--- a/src/core/openbsd/SDL_wscons_mouse.c
+++ b/src/core/openbsd/SDL_wscons_mouse.c
@@ -32,6 +32,7 @@
 typedef struct SDL_WSCONS_mouse_input_data
 {
     int fd;
+    SDL_MouseID mouseID;
 } SDL_WSCONS_mouse_input_data;
 
 SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse()
@@ -39,32 +40,36 @@ SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse()
 #ifdef WSMOUSEIO_SETVERSION
     int version = WSMOUSE_EVENT_VERSION;
 #endif
-    SDL_WSCONS_mouse_input_data *mouseInputData = SDL_calloc(1, sizeof(SDL_WSCONS_mouse_input_data));
+    SDL_WSCONS_mouse_input_data *input = SDL_calloc(1, sizeof(SDL_WSCONS_mouse_input_data));
 
-    if (!mouseInputData) {
+    if (!input) {
         return NULL;
     }
-    mouseInputData->fd = open("/dev/wsmouse", O_RDWR | O_NONBLOCK | O_CLOEXEC);
-    if (mouseInputData->fd == -1) {
-        SDL_free(mouseInputData);
+    input->fd = open("/dev/wsmouse", O_RDWR | O_NONBLOCK | O_CLOEXEC);
+    if (input->fd == -1) {
+        SDL_free(input);
         return NULL;
     }
+
+    input->mouseID = SDL_GetNextObjectID();
+    SDL_AddMouse(input->mouseID, SDL_FALSE);
+
 #ifdef WSMOUSEIO_SETMODE
-    ioctl(mouseInputData->fd, WSMOUSEIO_SETMODE, WSMOUSE_COMPAT);
+    ioctl(input->fd, WSMOUSEIO_SETMODE, WSMOUSE_COMPAT);
 #endif
 #ifdef WSMOUSEIO_SETVERSION
-    ioctl(mouseInputData->fd, WSMOUSEIO_SETVERSION, &version);
+    ioctl(input->fd, WSMOUSEIO_SETVERSION, &version);
 #endif
-    return mouseInputData;
+    return input;
 }
 
-void updateMouse(SDL_WSCONS_mouse_input_data *inputData)
+void updateMouse(SDL_WSCONS_mouse_input_data *input)
 {
     struct wscons_event events[64];
     int n;
     SDL_Mouse *mouse = SDL_GetMouse();
 
-    if ((n = read(inputData->fd, events, sizeof(events))) > 0) {
+    if ((n = read(input->fd, events, sizeof(events))) > 0) {
         int i;
         n /= sizeof(struct wscons_event);
         for (i = 0; i < n; i++) {
@@ -74,13 +79,13 @@ void updateMouse(SDL_WSCONS_mouse_input_data *inputData)
             {
                 switch (events[i].value) {
                 case 0: /* Left Mouse Button. */
-                    SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_PRESSED, SDL_BUTTON_LEFT);
+                    SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_PRESSED, SDL_BUTTON_LEFT);
                     break;
                 case 1: /* Middle Mouse Button. */
-                    SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_PRESSED, SDL_BUTTON_MIDDLE);
+                    SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_PRESSED, SDL_BUTTON_MIDDLE);
                     break;
                 case 2: /* Right Mouse Button. */
-                    SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_PRESSED, SDL_BUTTON_RIGHT);
+                    SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_PRESSED, SDL_BUTTON_RIGHT);
                     break;
                 }
             } break;
@@ -88,34 +93,34 @@ void updateMouse(SDL_WSCONS_mouse_input_data *inputData)
             {
                 switch (events[i].value) {
                 case 0: /* Left Mouse Button. */
-                    SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_RELEASED, SDL_BUTTON_LEFT);
+                    SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_RELEASED, SDL_BUTTON_LEFT);
                     break;
                 case 1: /* Middle Mouse Button. */
-                    SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_RELEASED, SDL_BUTTON_MIDDLE);
+                    SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_RELEASED, SDL_BUTTON_MIDDLE);
                     break;
                 case 2: /* Right Mouse Button. */
-                    SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_RELEASED, SDL_BUTTON_RIGHT);
+                    SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_RELEASED, SDL_BUTTON_RIGHT);
                     break;
                 }
             } break;
             case WSCONS_EVENT_MOUSE_DELTA_X:
             {
-                SDL_SendMouseMotion(0, mouse->focus, mouse->mouseID, 1, (float)events[i].value, 0.0f);
+                SDL_SendMouseMotion(0, mouse->focus, input->mouseID, 1, (float)events[i].value, 0.0f);
                 break;
             }
             case WSCONS_EVENT_MOUSE_DELTA_Y:
             {
-                SDL_SendMouseMotion(0, mouse->focus, mouse->mouseID, 1, 0.0f, -(float)events[i].value);
+                SDL_SendMouseMotion(0, mouse->focus, input->mouseID, 1, 0.0f, -(float)events[i].value);
                 break;
             }
             case WSCONS_EVENT_MOUSE_DELTA_W:
             {
-                SDL_SendMouseWheel(0, mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
+                SDL_SendMouseWheel(0, mouse->focus, input->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
                 break;
             }
             case WSCONS_EVENT_MOUSE_DELTA_Z:
             {
-                SDL_SendMouseWheel(0, mouse->focus, mouse->mouseID, 0, -events[i].value, SDL_MOUSEWHEEL_NORMAL);
+                SDL_SendMouseWheel(0, mouse->focus, input->mouseID, 0, -events[i].value, SDL_MOUSEWHEEL_NORMAL);
                 break;
             }
             }
@@ -123,11 +128,11 @@ void updateMouse(SDL_WSCONS_mouse_input_data *inputData)
     }
 }
 
-void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data *inputData)
+void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data *input)
 {
-    if (!inputData) {
+    if (!input) {
         return;
     }
-    close(inputData->fd);
-    SDL_free(inputData);
+    close(input->fd);
+    SDL_free(input);
 }
diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp
index 9fddd3d106c30..0565d4f85542a 100644
--- a/src/core/winrt/SDL_winrtapp_direct3d.cpp
+++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp
@@ -538,7 +538,7 @@ void SDL_WinRTApp::OnWindowActivated(CoreWindow ^ sender, WindowActivatedEventAr
              */
 #if !SDL_WINAPI_FAMILY_PHONE || NTDDI_VERSION >= NTDDI_WINBLUE
             Point cursorPos = WINRT_TransformCursorPosition(window, sender->PointerPosition, TransformToSDLWindowSize);
-            SDL_SendMouseMotion(0, window, 0, 0, cursorPos.X, cursorPos.Y);
+            SDL_SendMouseMotion(0, window, 0, SDL_FALSE, cursorPos.X, cursorPos.Y);
 #endif
 
             /* TODO, WinRT: see if the Win32 bugfix from https://hg.libsdl.org/SDL/rev/d278747da408 needs to be applied (on window activation) */
diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c
index 63bd9842ec45c..1e5eb02a09cf4 100644
--- a/src/events/SDL_keyboard.c
+++ b/src/events/SDL_keyboard.c
@@ -691,7 +691,7 @@ SDL_bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys)
     return SDL_TRUE;
 }
 
-void SDL_PrivateKeyboardAdded(SDL_KeyboardID keyboardID)
+void SDL_AddKeyboard(SDL_KeyboardID keyboardID, SDL_bool send_event)
 {
     int keyboard_index = -1;
 
@@ -717,14 +717,16 @@ void SDL_PrivateKeyboardAdded(SDL_KeyboardID keyboardID)
     SDL_keyboards = keyboards;
     ++SDL_keyboard_count;
 
-    SDL_Event event;
-    SDL_zero(event);
-    event.type = SDL_EVENT_KEYBOARD_ADDED;
-    event.kdevice.which = keyboardID;
-    SDL_PushEvent(&event);
+    if (send_event) {
+        SDL_Event event;
+        SDL_zero(event);
+        event.type = SDL_EVENT_KEYBOARD_ADDED;
+        event.kdevice.which = keyboardID;
+        SDL_PushEvent(&event);
+    }
 }
 
-void SDL_PrivateKeyboardRemoved(SDL_KeyboardID keyboardID)
+void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID)
 {
     int keyboard_index = -1;
 
@@ -936,13 +938,6 @@ static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_Keybo
     Uint8 repeat = SDL_FALSE;
     const Uint8 source = flags & KEYBOARD_SOURCE_MASK;
 
-    if (keyboardID == 0) {
-        if (source == KEYBOARD_HARDWARE && SDL_keyboard_count > 0) {
-            /* Assume it's from the first keyboard */
-            keyboardID = SDL_keyboards[0];
-        }
-    }
-
     if (scancode == SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) {
         return 0;
     }
diff --git a/src/events/SDL_keyboard_c.h b/src/events/SDL_keyboard_c.h
index f32566df7b298..584951a947579 100644
--- a/src/events/SDL_keyboard_c.h
+++ b/src/events/SDL_keyboard_c.h
@@ -30,10 +30,10 @@ extern int SDL_InitKeyboard(void);
 extern SDL_bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys);
 
 /* A keyboard has been added to the system */
-extern void SDL_PrivateKeyboardAdded(SDL_KeyboardID keyboardID);
+extern void SDL_AddKeyboard(SDL_KeyboardID keyboardID, SDL_bool send_event);
 
 /* A keyboard has been removed from the system */
-extern void SDL_PrivateKeyboardRemoved(SDL_KeyboardID keyboardID);
+extern void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID);
 
 /* Get the default keymap */
 extern void SDL_GetDefaultKeymap(SDL_Keycode *keymap);
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 347227020d577..616115bf7a369 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -41,7 +41,7 @@ static SDL_MouseID *SDL_mice;
 /* for mapping mouse events to touch */
 static SDL_bool track_mouse_down = SDL_FALSE;
 
-static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y);
+static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_bool relative, float x, float y);
 
 static void SDLCALL SDL_MouseDoubleClickTimeChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
 {
@@ -235,7 +235,7 @@ SDL_bool SDL_IsMouse(Uint16 vendor, Uint16 product)
     return SDL_TRUE;
 }
 
-void SDL_PrivateMouseAdded(SDL_MouseID mouseID)
+void SDL_AddMouse(SDL_MouseID mouseID, SDL_bool send_event)
 {
     int mouse_index = -1;
 
@@ -261,14 +261,16 @@ void SDL_PrivateMouseAdded(SDL_MouseID mouseID)
     SDL_mice = mice;
     ++SDL_mouse_count;
 
-    SDL_Event event;
-    SDL_zero(event);
-    event.type = SDL_EVENT_MOUSE_ADDED;
-    event.mdevice.which = mouseID;
-    SDL_PushEvent(&event);
+    if (send_event) {
+        SDL_Event event;
+        SDL_zero(event);
+        event.type = SDL_EVENT_MOUSE_ADDED;
+        event.mdevice.which = mouseID;
+        SDL_PushEvent(&event);
+    }
 }
 
-void SDL_PrivateMouseRemoved(SDL_MouseID mouseID)
+void SDL_RemoveMouse(SDL_MouseID mouseID)
 {
     int mouse_index = -1;
 
@@ -469,7 +471,7 @@ void SDL_SetMouseFocus(SDL_Window *window)
     SDL_SetCursor(NULL);
 }
 
-SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, float x, float y)
+SDL_bool SDL_MousePositionInWindow(SDL_Window *window, float x, float y)
 {
     if (!window) {
         return SDL_FALSE;
@@ -487,7 +489,7 @@ SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, floa
 static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint32 buttonstate, SDL_bool send_mouse_motion)
 {
     SDL_Mouse *mouse = SDL_GetMouse();
-    SDL_bool inWindow = SDL_MousePositionInWindow(window, mouse->mouseID, x, y);
+    SDL_bool inWindow = SDL_MousePositionInWindow(window, x, y);
 
     if (!inWindow) {
         if (window == mouse->focus) {
@@ -495,7 +497,7 @@ static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint3
             SDL_Log("Mouse left window, synthesizing move & focus lost event\n");
 #endif
             if (send_mouse_motion) {
-                SDL_PrivateSendMouseMotion(0, window, mouse->mouseID, 0, x, y);
+                SDL_PrivateSendMouseMotion(0, window, 0, SDL_FALSE, x, y);
             }
             SDL_SetMouseFocus(NULL);
         }
@@ -508,13 +510,13 @@ static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint3
 #endif
         SDL_SetMouseFocus(window);
         if (send_mouse_motion) {
-            SDL_PrivateSendMouseMotion(0, window, mouse->mouseID, 0, x, y);
+            SDL_PrivateSendMouseMotion(0, window, 0, SDL_FALSE, x, y);
         }
     }
     return SDL_TRUE;
 }
 
-int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y)
+int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_bool relative, float x, float y)
 {
     if (window && !relative) {
         SDL_Mouse *mouse = SDL_GetMouse();
@@ -672,7 +674,7 @@ static void ConstrainMousePosition(SDL_Mouse *mouse, SDL_Window *window, float *
     }
 }
 
-static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y)
+static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_bool relative, float x, float y)
 {
     SDL_Mouse *mouse = SDL_GetMouse();
     int posted;
@@ -713,7 +715,7 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_
                 if (mouse->WarpMouse) {
                     mouse->WarpMouse(window, center_x, center_y);
                 } else {
-                    SDL_PrivateSendMouseMotion(timestamp, window, mouseID, 0, center_x, center_y);
+                    SDL_PrivateSendMouseMotion(timestamp, window, mouseID, SDL_FALSE, center_x, center_y);
                 }
             }
         }
@@ -1186,7 +1188,7 @@ void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, SDL_bool
         (!mouse->relative_mode || mouse->relative_mode_warp)) {
         mouse->WarpMouse(window, x, y);
     } else {
-        SDL_PrivateSendMouseMotion(0, window, mouse->mouseID, 0, x, y);
+        SDL_PrivateSendMouseMotion(0, window, 0, SDL_FALSE, x, y);
     }
 }
 
diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h
index 1b2ccbeacd013..ea700a30b3ac8 100644
--- a/src/events/SDL_mouse_c.h
+++ b/src/events/SDL_mouse_c.h
@@ -75,7 +75,6 @@ typedef struct
     Uint32 (*GetGlobalMouseState)(float *x, float *y);
 
     /* Data common to all mice */
-    SDL_MouseID mouseID;
     SDL_Window *focus;
     float x;
     float y;
@@ -132,10 +131,10 @@ extern void SDL_PostInitMouse(void);
 extern SDL_bool SDL_IsMouse(Uint16 vendor, Uint16 product);
 
 /* A mouse has been added to the system */
-extern void SDL_PrivateMouseAdded(SDL_MouseID mouseID);
+extern void SDL_AddMouse(SDL_MouseID mouseID, SDL_bool send_event);
 
 /* A mouse has been removed from the system */
-extern void SDL_PrivateMouseRemoved(SDL_MouseID mouseID);
+extern void SDL_RemoveMouse(SDL_MouseID mouseID);
 
 /* Get the mouse state structure */
 extern SDL_Mouse *SDL_GetMouse(void);
@@ -153,7 +152,7 @@ extern int SDL_UpdateMouseCapture(SDL_bool force_release);
 extern int SDL_SetMouseSystemScale(int num_values, const float *values);
 
 /* Send a mouse motion event */
-extern int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y);
+extern int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_bool relative, float x, float y);
 
 /* Send a mouse button event */
 extern int SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button);
@@ -173,7 +172,7 @@ extern void SDL_ResetMouse(void);
 #endif /* 0 */
 
 /* Check if mouse position is within window or captured by window */
-extern SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, float x, float y);
+extern SDL_bool SDL_MousePositionInWindow(SDL_Window *window, float x, float y);
 
 /* Shutdown the mouse subsystem */
 extern void SDL_QuitMouse(void);
diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c
index 43ec94921e275..e2eb4e10cf973 100644
--- a/src/events/SDL_pen.c
+++ b/src/events/SDL_pen.c
@@ -496,7 +496,6 @@ int SDL_SendPenMotion(Uint64 timestamp,
                       SDL_bool window_relative,
                       const SDL_PenStatusInfo *status)
 {
-    const SDL_Mouse *mouse = SDL_GetMouse();
     int i;
     SDL_Pen *pen = SDL_GetPenPtr(instance_id);
     SDL_Event event;
@@ -539,7 +538,7 @@ int SDL_SendPenMotion(Uint64 timestamp,
 
     send_mouse_update = (x != last_x) || (y != last_y);
 
-    if (!(SDL_MousePositionInWindow(window, mouse->mouseID, x, y))) {
+    if (!(SDL_MousePositionInWindow(window, x, y))) {
         return SDL_FALSE;
     }
 
@@ -557,7 +556,7 @@ int SDL_SendPenMotion(Uint64 timestamp,
     if (send_mouse_update) {
         switch (pen_mouse_emulation_mode) {
         case PEN_MOUSE_EMULATE:
-            return (SDL_SendMouseMotion(0, window, SDL_PEN_MOUSEID, 0, x, y)) || posted;
+            return (SDL_SendMouseMotion(0, window, SDL_PEN_MOUSEID, SDL_FALSE, x, y)) || posted;
 
         case PEN_MOUSE_STATELESS:
             /* Report mouse event but don't update mouse state */
@@ -584,7 +583,6 @@ int SDL_SendPenMotion(Uint64 timestamp,
 
 int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state)
 {
-    SDL_Mouse *mouse = SDL_GetMouse();
     SDL_Pen *pen = SDL_GetPenPtr(instance_id);
     SDL_Event event;
     SDL_bool posted = SDL_FALSE;
@@ -597,7 +595,7 @@ int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state)
     }
     window = pen->header.window;
 
-    if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, mouse->mouseID, last->x, last->y))) {
+    if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, last->x, last->y))) {
         return SDL_FALSE;
     }
 
@@ -663,7 +661,6 @@ int SDL_SendPenButton(Uint64 timestamp,
                       SDL_PenID instance_id,
                       Uint8 state, Uint8 button)
 {
-    SDL_Mouse *mouse = SDL_GetMouse();
     SDL_Pen *pen = SDL_GetPenPtr(instance_id);
     SDL_Event event;
     SDL_bool posted = SDL_FALSE;
@@ -676,7 +673,7 @@ int SDL_SendPenButton(Uint64 timestamp,
     }
     window = pen->header.window;
 
-    if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, mouse->mouseID, last->x, last->y))) {
+    if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, last->x, last->y))) {
         return SDL_FALSE;
     }
 
diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c
index dcd855771c13e..98975e9ca028f 100644
--- a/src/events/SDL_touch.c
+++ b/src/events/SDL_touch.c
@@ -279,7 +279,7 @@ int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_W
                             if (pos_y > (float)(window->h - 1)) {
                                 pos_y = (float)(window->h - 1);
                             }
-                            SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
+                            SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, SDL_FALSE, pos_x, pos_y);
                             SDL_SendMouseButton(timestamp, window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
                         }
                     } else {
@@ -403,7 +403,7 @@ int SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid,
                         if (pos_y > (float)(window->h - 1)) {
                             pos_y = (float)(window->h - 1);
                         }
-                        SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
+                        SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, SDL_FALSE, pos_x, pos_y);
                     }
                 }
             }
diff --git a/src/video/android/SDL_androidkeyboard.c b/src/video/android/SDL_androidkeyboard.c
index 3c5063bd31adb..cff44ed6139ae 100644
--- a/src/video/android/SDL_androidkeyboard.c
+++ b/src/video/android/SDL_androidkeyboard.c
@@ -330,12 +330,12 @@ static SDL_Scancode TranslateKeycode(int keycode)
 
 int Android_OnKeyDown(int keycode)
 {
-    return SDL_SendKeyboardKey(0, 0, SDL_PRESSED, TranslateKeycode(keycode));
+    return SDL_SendKeyboardKey(0, Android_KeyboardID, SDL_PRESSED, TranslateKeycode(keycode));
 }
 
 int Android_OnKeyUp(int keycode)
 {
-    return SDL_SendKeyboardKey(0, 0, SDL_RELEASED, TranslateKeycode(keycode));
+    return SDL_SendKeyboardKey(0, Android_KeyboardID, SDL_RELEASED, TranslateKeycode(keycode));
 }
 
 SDL_bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this)
diff --git a/src/video/android/SDL_androidmouse.c b/src/video/android/SDL_androidmouse.c
index 39dee434fef8a..122fece95fedb 100644
--- a/src/video/android/SDL_androidmouse.c
+++ b/src/video/android/SDL_androidmouse.c
@@ -221,25 +221,25 @@ void Android_OnMouse(SDL_Window *window, int state, i

(Patch may be truncated, please check the link at the top of this post.)