From 715e7bda225226847565ae47a34e9144b8b2d76b Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 9 Nov 2021 01:43:44 -0600 Subject: [PATCH] haptic: Don't enumerate joysticks if the joystick subsystem is active The joystick subsystem has complex precedence logic to deal multiple competing backends like XInput, RawInput, and WGI. Let it fire the MaybeAdd callbacks for joystick devices, since it knows which backend will end up managing them. This resolves a situation where the RawInput joystick backend would take control of an XInput device but the XInput haptic backend would still create a haptic device. Since the XInput joystick backend didn't own the underlying joystick device, we'd end up with an orphaned haptic device that didn't work with SDL_HapticOpenFromJoystick() on the associated joystick device. --- src/haptic/windows/SDL_dinputhaptic.c | 28 ++++++++++++++++++--------- src/haptic/windows/SDL_xinputhaptic.c | 4 +++- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/haptic/windows/SDL_dinputhaptic.c b/src/haptic/windows/SDL_dinputhaptic.c index 523793ebe..4b41e2752 100644 --- a/src/haptic/windows/SDL_dinputhaptic.c +++ b/src/haptic/windows/SDL_dinputhaptic.c @@ -20,6 +20,7 @@ */ #include "../../SDL_internal.h" +#include "SDL.h" #include "SDL_error.h" #include "SDL_haptic.h" #include "../SDL_syshaptic.h" @@ -70,6 +71,7 @@ SDL_DINPUT_HapticInit(void) { HRESULT ret; HINSTANCE instance; + DWORD devClass; if (dinput != NULL) { /* Already open. */ return SDL_SetError("Haptic: SubSystem already open."); @@ -103,16 +105,24 @@ SDL_DINPUT_HapticInit(void) } /* Look for haptic devices. */ - ret = IDirectInput8_EnumDevices(dinput, - 0, - EnumHapticsCallback, - NULL, - DIEDFL_FORCEFEEDBACK | - DIEDFL_ATTACHEDONLY); - if (FAILED(ret)) { - SDL_SYS_HapticQuit(); - return DI_SetError("Enumerating DirectInput devices", ret); + for (devClass = DI8DEVCLASS_DEVICE; devClass <= DI8DEVCLASS_GAMECTRL; devClass++) { + if (devClass == DI8DEVCLASS_GAMECTRL && SDL_WasInit(SDL_INIT_JOYSTICK)) { + /* The joystick subsystem will manage adding DInput joystick haptic devices */ + continue; + } + + ret = IDirectInput8_EnumDevices(dinput, + devClass, + EnumHapticsCallback, + NULL, + DIEDFL_FORCEFEEDBACK | + DIEDFL_ATTACHEDONLY); + if (FAILED(ret)) { + SDL_SYS_HapticQuit(); + return DI_SetError("Enumerating DirectInput devices", ret); + } } + return 0; } diff --git a/src/haptic/windows/SDL_xinputhaptic.c b/src/haptic/windows/SDL_xinputhaptic.c index 9ee2d82d6..5ed3f0240 100644 --- a/src/haptic/windows/SDL_xinputhaptic.c +++ b/src/haptic/windows/SDL_xinputhaptic.c @@ -20,6 +20,7 @@ */ #include "../../SDL_internal.h" +#include "SDL.h" #include "SDL_error.h" #include "SDL_haptic.h" #include "../SDL_syshaptic.h" @@ -47,7 +48,8 @@ SDL_XINPUT_HapticInit(void) loaded_xinput = (WIN_LoadXInputDLL() == 0); } - if (loaded_xinput) { + /* If the joystick subsystem is active, it will manage adding XInput haptic devices */ + if (loaded_xinput && !SDL_WasInit(SDL_INIT_JOYSTICK)) { DWORD i; for (i = 0; i < XUSER_MAX_COUNT; i++) { SDL_XINPUT_HapticMaybeAddDevice(i);