Commit 4727f7941663b8659a8965cee5cbef53354051df

Sam Lantinga 2020-04-23T10:13:17

Don't use the WGI driver if another driver is already handling the joystick

diff --git a/src/joystick/windows/SDL_dinputjoystick.c b/src/joystick/windows/SDL_dinputjoystick.c
index 13e549e..cbb5bd9 100644
--- a/src/joystick/windows/SDL_dinputjoystick.c
+++ b/src/joystick/windows/SDL_dinputjoystick.c
@@ -698,6 +698,47 @@ SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
     SDL_RawDevListCount = 0;
 }
 
+typedef struct
+{
+    Uint16 vendor;
+    Uint16 product;
+    Uint16 version;
+    SDL_bool present;
+} EnumJoystickPresentData;
+
+static BOOL CALLBACK
+EnumJoystickPresentCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
+{
+    EnumJoystickPresentData *data = (EnumJoystickPresentData *)pContext;
+    Uint16 vendor = 0;
+    Uint16 product = 0;
+    Uint16 version = 0;
+
+    if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
+        vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1);
+        product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1);
+        if (data->vendor == vendor && data->product == product && data->version == version) {
+            data->present = SDL_TRUE;
+            return DIENUM_STOP;
+        }
+    }
+    return DIENUM_CONTINUE;
+}
+
+SDL_bool
+SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version)
+{
+    EnumJoystickPresentData data;
+
+    data.vendor = vendor;
+    data.product = product;
+    data.version = version;
+    data.present = SDL_FALSE;
+    IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoystickPresentCallback, &data, DIEDFL_ATTACHEDONLY);
+
+    return data.present;
+}
+
 static BOOL CALLBACK
 EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
 {
@@ -1261,6 +1302,12 @@ SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
 {
 }
 
+SDL_bool
+SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version)
+{
+    return SDL_FALSE;
+}
+
 int
 SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
 {
diff --git a/src/joystick/windows/SDL_dinputjoystick_c.h b/src/joystick/windows/SDL_dinputjoystick_c.h
index f647e7a..2e7e7db 100644
--- a/src/joystick/windows/SDL_dinputjoystick_c.h
+++ b/src/joystick/windows/SDL_dinputjoystick_c.h
@@ -22,6 +22,7 @@
 
 extern int SDL_DINPUT_JoystickInit(void);
 extern void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext);
+extern SDL_bool SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version);
 extern int SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice);
 extern int SDL_DINPUT_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
 extern void SDL_DINPUT_JoystickUpdate(SDL_Joystick * joystick);
diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c
index df33ead..cbfce0e 100644
--- a/src/joystick/windows/SDL_windows_gaming_input.c
+++ b/src/joystick/windows/SDL_windows_gaming_input.c
@@ -25,6 +25,7 @@
 #include "SDL_endian.h"
 #include "SDL_events.h"
 #include "../SDL_sysjoystick.h"
+#include "../hidapi/SDL_hidapijoystick_c.h"
 
 #include "../../core/windows/SDL_windows.h"
 #define COBJMACROS
@@ -173,16 +174,11 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
         Uint16 *guid16 = (Uint16 *)guid.data;
         __x_ABI_CWindows_CGaming_CInput_CIRawGameController2 *controller2 = NULL;
         __x_ABI_CWindows_CGaming_CInput_CIGameController *gamecontroller = NULL;
+        SDL_bool ignore_joystick = SDL_FALSE;
 
         __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareVendorId(controller, &vendor);
         __x_ABI_CWindows_CGaming_CInput_CIRawGameController_get_HardwareProductId(controller, &product);
 
-        if (SDL_IsXInputDevice(vendor, product)) {
-            /* This will be handled by the XInput driver */
-            __x_ABI_CWindows_CGaming_CInput_CIRawGameController_Release(controller);
-            return S_OK;
-        }
-
         hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IRawGameController2, (void **)&controller2);
         if (SUCCEEDED(hr)) {
             HSTRING hString;
@@ -243,7 +239,25 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
         guid.data[14] = 'w';
         guid.data[15] = (Uint8)type;
 
-        if (SDL_ShouldIgnoreJoystick(name, guid)) {
+#ifdef SDL_JOYSTICK_HIDAPI
+        if (!ignore_joystick && HIDAPI_IsDevicePresent(vendor, product, version, name)) {
+            ignore_joystick = SDL_TRUE;
+        }
+#endif
+
+        if (!ignore_joystick && SDL_DINPUT_JoystickPresent(vendor, product, version)) {
+            ignore_joystick = SDL_TRUE;
+        }
+
+        if (!ignore_joystick && SDL_IsXInputDevice(vendor, product)) {
+            ignore_joystick = SDL_TRUE;
+        }
+
+        if (!ignore_joystick && SDL_ShouldIgnoreJoystick(name, guid)) {
+            ignore_joystick = SDL_TRUE;
+        }
+
+        if (ignore_joystick) {
             SDL_free(name);
         } else {
             /* New device, add it */