SDL: Improved XInput controller detection (364ab)

From 364abb87020aeffd506c830f3d46250cafe92b8c 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.

(cherry picked from commit 55a75875f0ef74799d2993ef835481ea6a409342)
---
 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 a7e42e7c77557..9299ac528a35e 100644
--- a/src/joystick/windows/SDL_windows_gaming_input.c
+++ b/src/joystick/windows/SDL_windows_gaming_input.c
@@ -110,7 +110,7 @@ extern SDL_bool SDL_XINPUT_Enabled(void);
 extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version);
 
 
-static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
+static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product, const char* name)
 {
 #if defined(SDL_JOYSTICK_XINPUT) || defined(SDL_JOYSTICK_RAWINPUT)
     PRAWINPUTDEVICELIST raw_devices = NULL;
@@ -126,6 +126,13 @@ static SDL_bool SDL_IsXInputDevice(Uint16 vendor, Uint16 product)
         return SDL_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 SDL_TRUE;
+    }
+
     /* Go through RAWINPUT (WinXP and later) to find HID devices. */
     if ((GetRawInputDeviceList(NULL, &raw_device_count, sizeof(RAWINPUTDEVICELIST)) == -1) || (!raw_device_count)) {
         return SDL_FALSE; /* oh well. */
@@ -508,7 +515,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
             ignore_joystick = SDL_TRUE;
         }
 
-        if (!ignore_joystick && SDL_IsXInputDevice(vendor, product)) {
+        if (!ignore_joystick && SDL_IsXInputDevice(vendor, product, name)) {
             ignore_joystick = SDL_TRUE;
         }