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.
This commit is contained in:
Cameron Gutman 2021-11-09 01:43:44 -06:00
parent b2ce22a077
commit 715e7bda22
2 changed files with 22 additions and 10 deletions

View File

@ -20,6 +20,7 @@
*/ */
#include "../../SDL_internal.h" #include "../../SDL_internal.h"
#include "SDL.h"
#include "SDL_error.h" #include "SDL_error.h"
#include "SDL_haptic.h" #include "SDL_haptic.h"
#include "../SDL_syshaptic.h" #include "../SDL_syshaptic.h"
@ -70,6 +71,7 @@ SDL_DINPUT_HapticInit(void)
{ {
HRESULT ret; HRESULT ret;
HINSTANCE instance; HINSTANCE instance;
DWORD devClass;
if (dinput != NULL) { /* Already open. */ if (dinput != NULL) { /* Already open. */
return SDL_SetError("Haptic: SubSystem already open."); return SDL_SetError("Haptic: SubSystem already open.");
@ -103,8 +105,14 @@ SDL_DINPUT_HapticInit(void)
} }
/* Look for haptic devices. */ /* Look for haptic devices. */
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, ret = IDirectInput8_EnumDevices(dinput,
0, devClass,
EnumHapticsCallback, EnumHapticsCallback,
NULL, NULL,
DIEDFL_FORCEFEEDBACK | DIEDFL_FORCEFEEDBACK |
@ -113,6 +121,8 @@ SDL_DINPUT_HapticInit(void)
SDL_SYS_HapticQuit(); SDL_SYS_HapticQuit();
return DI_SetError("Enumerating DirectInput devices", ret); return DI_SetError("Enumerating DirectInput devices", ret);
} }
}
return 0; return 0;
} }

View File

@ -20,6 +20,7 @@
*/ */
#include "../../SDL_internal.h" #include "../../SDL_internal.h"
#include "SDL.h"
#include "SDL_error.h" #include "SDL_error.h"
#include "SDL_haptic.h" #include "SDL_haptic.h"
#include "../SDL_syshaptic.h" #include "../SDL_syshaptic.h"
@ -47,7 +48,8 @@ SDL_XINPUT_HapticInit(void)
loaded_xinput = (WIN_LoadXInputDLL() == 0); 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; DWORD i;
for (i = 0; i < XUSER_MAX_COUNT; i++) { for (i = 0; i < XUSER_MAX_COUNT; i++) {
SDL_XINPUT_HapticMaybeAddDevice(i); SDL_XINPUT_HapticMaybeAddDevice(i);