SDL: Improved XInput controller detection

From 6b4b9b5f2bc690faf35d6baf527a3a3c2f471eef Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 2 Jan 2025 10:01:29 -0800
Subject: [PATCH] Improved XInput controller detection

Sometimes we'll get a Windows.Gaming.Input callback before the raw input device is even in the list, so try some other methods to better detect XInput devices.
---
 src/joystick/windows/SDL_windows_gaming_input.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c
index fae93f52565bb..dbc5658ef5424 100644
--- a/src/joystick/windows/SDL_windows_gaming_input.c
+++ b/src/joystick/windows/SDL_windows_gaming_input.c
@@ -107,7 +107,7 @@ DEFINE_GUID(IID___x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics, 0xeb
 extern bool SDL_XINPUT_Enabled(void);
 
 
-static bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
+static bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product, const char *name)
 {
 #if defined(SDL_JOYSTICK_XINPUT) || defined(SDL_JOYSTICK_RAWINPUT)
     PRAWINPUTDEVICELIST raw_devices = NULL;
@@ -123,6 +123,13 @@ static bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
         return false;
     }
 
+    // Sometimes we'll get a Windows.Gaming.Input callback before the raw input device is even in the list,
+    // so try to do some checks up front to catch these cases.
+    if (SDL_IsJoystickXboxOne(vendor, product) ||
+        (name && SDL_strncmp(name, "Xbox ", 5) == 0)) {
+        return true;
+    }
+
     // Go through RAWINPUT (WinXP and later) to find HID devices.
     if ((GetRawInputDeviceList(NULL, &raw_device_count, sizeof(RAWINPUTDEVICELIST)) == -1) || (!raw_device_count)) {
         return false; // oh well.
@@ -453,7 +460,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
             ignore_joystick = true;
         }
 
-        if (!ignore_joystick && SDL_IsXInputDevice(vendor, product)) {
+        if (!ignore_joystick && SDL_IsXInputDevice(vendor, product, name)) {
             // This hasn't been detected by the RAWINPUT driver yet, but it will be picked up later.
             ignore_joystick = true;
         }