From 948b9c818a71ecca332f889b303cf3374d22dc9a Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 18 Oct 2023 00:42:59 -0500 Subject: [PATCH] Add workarounds for some SDL joystick index issues --- app/gui/sdlgamepadkeynavigation.cpp | 12 +++++++++++- app/streaming/input/gamepad.cpp | 18 ++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/app/gui/sdlgamepadkeynavigation.cpp b/app/gui/sdlgamepadkeynavigation.cpp index 9d73ea64..4f457d1e 100644 --- a/app/gui/sdlgamepadkeynavigation.cpp +++ b/app/gui/sdlgamepadkeynavigation.cpp @@ -191,7 +191,17 @@ void SdlGamepadKeyNavigation::onPollingTimerFired() case SDL_CONTROLLERDEVICEADDED: SDL_GameController* gc = SDL_GameControllerOpen(event.cdevice.which); if (gc != nullptr) { - m_Gamepads.append(gc); + // SDL_CONTROLLERDEVICEADDED can be reported multiple times for the same + // gamepad in rare cases, because SDL doesn't fixup the device index in + // the SDL_CONTROLLERDEVICEADDED event if an unopened gamepad disappears + // before we've processed the add event. + if (!m_Gamepads.contains(gc)) { + m_Gamepads.append(gc); + } + else { + // We already have this game controller open + SDL_GameControllerClose(gc); + } } break; } diff --git a/app/streaming/input/gamepad.cpp b/app/streaming/input/gamepad.cpp index ba255c2e..b68be8fb 100644 --- a/app/streaming/input/gamepad.cpp +++ b/app/streaming/input/gamepad.cpp @@ -46,8 +46,8 @@ SdlInputHandler::findStateForGamepad(SDL_JoystickID id) } } - // This should only happen with too many gamepads - SDL_assert(SDL_NumJoysticks() > MAX_GAMEPADS); + // We can get a spurious removal event if the device is removed + // before or during SDL_GameControllerOpen(). This is fine to ignore. return nullptr; } @@ -466,6 +466,20 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve return; } + // SDL_CONTROLLERDEVICEADDED can be reported multiple times for the same + // gamepad in rare cases, because SDL doesn't fixup the device index in + // the SDL_CONTROLLERDEVICEADDED event if an unopened gamepad disappears + // before we've processed the add event. + for (int i = 0; i < MAX_GAMEPADS; i++) { + if (m_GamepadState[i].controller == controller) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Received duplicate add event for controller index: %d", + event->which); + SDL_GameControllerClose(controller); + return; + } + } + // We used to use SDL_GameControllerGetPlayerIndex() here but that // can lead to strange issues due to bugs in Windows where an Xbox // controller will join as player 2, even though no player 1 controller