From 513409db194fd45bbfb02adf686c86f43dd656e4 Mon Sep 17 00:00:00 2001 From: Nick Sanft Date: Thu, 29 Jan 2026 22:00:01 -0600 Subject: [PATCH 1/3] Initial fix --- src/app/input2/sdl/sdl_input_service.cpp | 115 +++++++++++++++++++++-- src/app/input2/sdl/sdl_input_service.hpp | 19 +++- 2 files changed, 125 insertions(+), 9 deletions(-) diff --git a/src/app/input2/sdl/sdl_input_service.cpp b/src/app/input2/sdl/sdl_input_service.cpp index 51dce4dd..d50ca1bf 100644 --- a/src/app/input2/sdl/sdl_input_service.cpp +++ b/src/app/input2/sdl/sdl_input_service.cpp @@ -5,6 +5,15 @@ #include #include +namespace { +bool isSameDevice(const firelight::input::DeviceIdentifier &left, + const firelight::input::DeviceIdentifier &right) { + return left.vendorId == right.vendorId && left.productId == right.productId && + left.productVersion == right.productVersion && + left.deviceName == right.deviceName; +} +} // namespace + namespace firelight::input { SDLInputService::SDLInputService(IControllerRepository &gamepadRepository) : m_gamepadRepository(gamepadRepository) { @@ -44,6 +53,18 @@ int SDLInputService::addGamepad(std::shared_ptr gamepad) { m_gamepads.emplace_back(gamepad); auto nextSlot = getNextAvailablePlayerIndex(); + if (m_preferredPlayerIndex.has_value()) { + const auto preferred = *m_preferredPlayerIndex; + const auto slotAvailable = + preferred >= 0 && preferred < MAX_PLAYERS && + (!m_playerSlots.contains(preferred) || + m_playerSlots[preferred] == nullptr); + if (slotAvailable) { + nextSlot = preferred; + m_reservedPlayerSlots.erase(preferred); + } + m_preferredPlayerIndex.reset(); + } if (nextSlot == -1) { gamepad->setPlayerIndex(-1); EventDispatcher::instance().publish(GamepadConnectedEvent{gamepad}); @@ -91,17 +112,38 @@ int SDLInputService::addGamepad(std::shared_ptr gamepad) { bool SDLInputService::removeGamepadByInstanceId(int instanceId) { for (auto it = m_gamepads.begin(); it != m_gamepads.end(); ++it) { if (*it && (*it)->getInstanceId() == instanceId) { - spdlog::info("Removing gamepad: {}", instanceId); + const auto deviceIdentifier = (*it)->getDeviceIdentifier(); + const auto playerIndex = (*it)->getPlayerIndex(); + const auto deviceName = (*it)->getName(); + + if (!(*it)->isWired() && playerIndex >= 0) { + m_pendingRemovals.push_back(PendingRemoval{ + .identifier = deviceIdentifier, + .playerIndex = playerIndex, + .instanceId = instanceId, + .deviceName = deviceName, + .removedAt = std::chrono::steady_clock::now(), + }); + m_reservedPlayerSlots.insert(playerIndex); + } else { + spdlog::info("Removing gamepad: {}", instanceId); + for (int i = 0; i < MAX_PLAYERS; ++i) { + if (m_playerSlots.contains(i) && m_playerSlots[i] == *it) { + m_playerSlots.erase(i); + spdlog::info("Removed player slot for player {}", i + 1); + } + } + + EventDispatcher::instance().publish( + GamepadDisconnectedEvent{playerIndex}); + } + for (int i = 0; i < MAX_PLAYERS; ++i) { if (m_playerSlots.contains(i) && m_playerSlots[i] == *it) { m_playerSlots.erase(i); - spdlog::info("Removed player slot for player {}", i + 1); } } - EventDispatcher::instance().publish( - GamepadDisconnectedEvent{(*it)->getPlayerIndex()}); - (*it)->setPlayerIndex(-1); (*it)->disconnect(); m_gamepads.erase(it); @@ -190,7 +232,7 @@ void SDLInputService::run() { spdlog::info("Starting SDL Input Service..."); while (m_running) { SDL_Event ev; - while (SDL_WaitEvent(&ev)) { + if (SDL_WaitEventTimeout(&ev, 200)) { switch (ev.type) { case SDL_CONTROLLERDEVICEADDED: openSdlGamepad(ev.cdevice.which); @@ -525,6 +567,7 @@ void SDLInputService::run() { break; } } + prunePendingRemovals(); } SDL_QuitSubSystem(m_sdlServices); @@ -637,13 +680,69 @@ void SDLInputService::openSdlGamepad(const int deviceIndex) { } } - addGamepad(std::make_shared(gameController)); + auto newGamepad = std::make_shared(gameController); + const auto deviceIdentifier = newGamepad->getDeviceIdentifier(); + const auto reconnectSlot = consumeReconnectSlot(deviceIdentifier); + if (reconnectSlot.has_value()) { + m_preferredPlayerIndex = reconnectSlot; + } + + addGamepad(std::move(newGamepad)); // Retrieve the gamepad profile and assign it to the gamepad } +void SDLInputService::prunePendingRemovals() { + if (m_pendingRemovals.empty()) { + return; + } + + const auto now = std::chrono::steady_clock::now(); + for (auto it = m_pendingRemovals.begin(); it != m_pendingRemovals.end();) { + if (now - it->removedAt < RECONNECT_GRACE) { + ++it; + continue; + } + + if (it->playerIndex >= 0) { + spdlog::info("Removing gamepad after reconnect grace: {}", + it->deviceName); + spdlog::info("Removed player slot for player {}", it->playerIndex + 1); + EventDispatcher::instance().publish( + GamepadDisconnectedEvent{it->playerIndex}); + m_reservedPlayerSlots.erase(it->playerIndex); + } + + it = m_pendingRemovals.erase(it); + } +} + +std::optional +SDLInputService::consumeReconnectSlot(const DeviceIdentifier &identifier) { + const auto now = std::chrono::steady_clock::now(); + for (auto it = m_pendingRemovals.begin(); it != m_pendingRemovals.end(); + ++it) { + if (now - it->removedAt >= RECONNECT_GRACE) { + continue; + } + if (!isSameDevice(identifier, it->identifier)) { + continue; + } + + const auto playerIndex = it->playerIndex; + m_reservedPlayerSlots.erase(playerIndex); + m_pendingRemovals.erase(it); + return playerIndex; + } + + return std::nullopt; +} + int SDLInputService::getNextAvailablePlayerIndex() const { for (int i = 0; i < MAX_PLAYERS; ++i) { + if (m_reservedPlayerSlots.contains(i)) { + continue; + } if (!m_playerSlots.contains(i) || m_playerSlots.at(i) == nullptr) { return i; } @@ -671,4 +770,4 @@ bool SDLInputService::moveGamepadToPlayerIndex(int oldIndex, int newIndex) { return true; } -} // namespace firelight::input \ No newline at end of file +} // namespace firelight::input diff --git a/src/app/input2/sdl/sdl_input_service.hpp b/src/app/input2/sdl/sdl_input_service.hpp index 04004cc7..89b735ea 100644 --- a/src/app/input2/sdl/sdl_input_service.hpp +++ b/src/app/input2/sdl/sdl_input_service.hpp @@ -5,8 +5,11 @@ #include "sdl_controller.hpp" #include #include +#include #include #include +#include +#include namespace firelight::input { @@ -60,14 +63,28 @@ class SDLInputService final : public InputService { private: static constexpr int MAX_PLAYERS = 16; + static constexpr auto RECONNECT_GRACE = std::chrono::seconds(3); + + struct PendingRemoval { + DeviceIdentifier identifier; + int playerIndex = -1; + int instanceId = -1; + std::string deviceName; + std::chrono::steady_clock::time_point removedAt; + }; void openSdlGamepad(int deviceIndex); + void prunePendingRemovals(); + std::optional consumeReconnectSlot(const DeviceIdentifier &identifier); int getNextAvailablePlayerIndex() const; bool moveGamepadToPlayerIndex(int oldIndex, int newIndex); IControllerRepository &m_gamepadRepository; std::vector> m_gamepads; std::map> m_playerSlots; + std::set m_reservedPlayerSlots; + std::vector m_pendingRemovals; + std::optional m_preferredPlayerIndex; std::shared_ptr m_keyboard; @@ -83,4 +100,4 @@ class SDLInputService final : public InputService { bool m_mousePressed = false; }; -} // namespace firelight::input \ No newline at end of file +} // namespace firelight::input From 13e81a9a5ee45b94601406fd993f16965e98e446 Mon Sep 17 00:00:00 2001 From: Nick Sanft Date: Thu, 29 Jan 2026 22:15:52 -0600 Subject: [PATCH 2/3] Removed delay --- src/app/input2/sdl/sdl_input_service.cpp | 545 ++++++++++++----------- 1 file changed, 273 insertions(+), 272 deletions(-) diff --git a/src/app/input2/sdl/sdl_input_service.cpp b/src/app/input2/sdl/sdl_input_service.cpp index d50ca1bf..58e26f3b 100644 --- a/src/app/input2/sdl/sdl_input_service.cpp +++ b/src/app/input2/sdl/sdl_input_service.cpp @@ -232,340 +232,341 @@ void SDLInputService::run() { spdlog::info("Starting SDL Input Service..."); while (m_running) { SDL_Event ev; - if (SDL_WaitEventTimeout(&ev, 200)) { - switch (ev.type) { - case SDL_CONTROLLERDEVICEADDED: - openSdlGamepad(ev.cdevice.which); - break; - case SDL_CONTROLLERDEVICEREMOVED: - removeGamepadByInstanceId(ev.cdevice.which); - break; - case SDL_CONTROLLERAXISMOTION: { - const auto joystickInstanceId = ev.cbutton.which; - std::shared_ptr gamepad; - for (const auto &g : m_gamepads) { - if (g && g->getInstanceId() == joystickInstanceId) { - gamepad = g; - break; - } - } - - if (!gamepad) { + if (!SDL_WaitEvent(&ev)) { + continue; + } + switch (ev.type) { + case SDL_CONTROLLERDEVICEADDED: + openSdlGamepad(ev.cdevice.which); + break; + case SDL_CONTROLLERDEVICEREMOVED: + removeGamepadByInstanceId(ev.cdevice.which); + break; + case SDL_CONTROLLERAXISMOTION: { + const auto joystickInstanceId = ev.cbutton.which; + std::shared_ptr gamepad; + for (const auto &g : m_gamepads) { + if (g && g->getInstanceId() == joystickInstanceId) { + gamepad = g; break; } + } - auto index = gamepad->getPlayerIndex(); - - switch (ev.caxis.axis) { - case SDL_CONTROLLER_AXIS_LEFTX: { - if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { - if (m_gamepadLastStates[index][LeftStickLeft]) { - m_gamepadLastStates[index][LeftStickLeft] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickLeft, - .pressed = false, - }); - } - - if (m_gamepadLastStates[index][LeftStickRight]) { - m_gamepadLastStates[index][LeftStickRight] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickRight, - .pressed = false, - }); - } - break; - } - if (ev.caxis.value > 8192) { - if (!m_gamepadLastStates[index][LeftStickRight]) { - m_gamepadLastStates[index][LeftStickRight] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickRight, - .pressed = true, - }); - } - break; + if (!gamepad) { + break; + } + + auto index = gamepad->getPlayerIndex(); + + switch (ev.caxis.axis) { + case SDL_CONTROLLER_AXIS_LEFTX: { + if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { + if (m_gamepadLastStates[index][LeftStickLeft]) { + m_gamepadLastStates[index][LeftStickLeft] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickLeft, + .pressed = false, + }); } - if (ev.caxis.value < -8192) { - if (!m_gamepadLastStates[index][LeftStickLeft]) { - m_gamepadLastStates[index][LeftStickLeft] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickLeft, - .pressed = true, - }); - } - break; + + if (m_gamepadLastStates[index][LeftStickRight]) { + m_gamepadLastStates[index][LeftStickRight] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickRight, + .pressed = false, + }); } break; } - case SDL_CONTROLLER_AXIS_LEFTY: { - if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { - if (m_gamepadLastStates[index][LeftStickUp]) { - m_gamepadLastStates[index][LeftStickUp] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickUp, - .pressed = false, - }); - } - - if (m_gamepadLastStates[index][LeftStickDown]) { - m_gamepadLastStates[index][LeftStickDown] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickDown, - .pressed = false, - }); - } - break; - } - if (ev.caxis.value > 8192) { - if (!m_gamepadLastStates[index][LeftStickDown]) { - m_gamepadLastStates[index][LeftStickDown] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickDown, - .pressed = true, - }); - } - break; + if (ev.caxis.value > 8192) { + if (!m_gamepadLastStates[index][LeftStickRight]) { + m_gamepadLastStates[index][LeftStickRight] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickRight, + .pressed = true, + }); } - if (ev.caxis.value < -8192) { - if (!m_gamepadLastStates[index][LeftStickUp]) { - m_gamepadLastStates[index][LeftStickUp] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickUp, - .pressed = true, - }); - } - break; + break; + } + if (ev.caxis.value < -8192) { + if (!m_gamepadLastStates[index][LeftStickLeft]) { + m_gamepadLastStates[index][LeftStickLeft] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickLeft, + .pressed = true, + }); } break; } - case SDL_CONTROLLER_AXIS_RIGHTX: { - if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { - if (m_gamepadLastStates[index][RightStickLeft]) { - m_gamepadLastStates[index][RightStickLeft] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickLeft, - .pressed = false, - }); - } - - if (m_gamepadLastStates[index][RightStickRight]) { - m_gamepadLastStates[index][RightStickRight] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickRight, - .pressed = false, - }); - } - break; + break; + } + case SDL_CONTROLLER_AXIS_LEFTY: { + if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { + if (m_gamepadLastStates[index][LeftStickUp]) { + m_gamepadLastStates[index][LeftStickUp] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickUp, + .pressed = false, + }); } - if (ev.caxis.value > 8192) { - if (!m_gamepadLastStates[index][RightStickRight]) { - m_gamepadLastStates[index][RightStickRight] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickRight, - .pressed = true, - }); - } - break; + + if (m_gamepadLastStates[index][LeftStickDown]) { + m_gamepadLastStates[index][LeftStickDown] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickDown, + .pressed = false, + }); } - if (ev.caxis.value < -8192) { - if (!m_gamepadLastStates[index][RightStickLeft]) { - m_gamepadLastStates[index][RightStickLeft] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickLeft, - .pressed = true, - }); - } - break; + break; + } + if (ev.caxis.value > 8192) { + if (!m_gamepadLastStates[index][LeftStickDown]) { + m_gamepadLastStates[index][LeftStickDown] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickDown, + .pressed = true, + }); } break; } - case SDL_CONTROLLER_AXIS_RIGHTY: { - if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { - if (m_gamepadLastStates[index][RightStickUp]) { - m_gamepadLastStates[index][RightStickUp] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickUp, - .pressed = false, - }); - } - - if (m_gamepadLastStates[index][RightStickDown]) { - m_gamepadLastStates[index][RightStickDown] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickDown, - .pressed = false, - }); - } - break; + if (ev.caxis.value < -8192) { + if (!m_gamepadLastStates[index][LeftStickUp]) { + m_gamepadLastStates[index][LeftStickUp] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickUp, + .pressed = true, + }); } - if (ev.caxis.value > 8192) { - if (!m_gamepadLastStates[index][RightStickDown]) { - m_gamepadLastStates[index][RightStickDown] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickDown, - .pressed = true, - }); - } - break; + break; + } + break; + } + case SDL_CONTROLLER_AXIS_RIGHTX: { + if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { + if (m_gamepadLastStates[index][RightStickLeft]) { + m_gamepadLastStates[index][RightStickLeft] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickLeft, + .pressed = false, + }); } - if (ev.caxis.value < -8192) { - if (!m_gamepadLastStates[index][RightStickUp]) { - m_gamepadLastStates[index][RightStickUp] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickUp, - .pressed = true, - }); - } - break; + + if (m_gamepadLastStates[index][RightStickRight]) { + m_gamepadLastStates[index][RightStickRight] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickRight, + .pressed = false, + }); } break; } - case SDL_CONTROLLER_AXIS_TRIGGERLEFT: { - if (ev.caxis.value < 8192) { - if (m_gamepadLastStates[index][LeftTrigger]) { - m_gamepadLastStates[index][LeftTrigger] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftTrigger, - .pressed = false, - }); - break; - } - - break; + if (ev.caxis.value > 8192) { + if (!m_gamepadLastStates[index][RightStickRight]) { + m_gamepadLastStates[index][RightStickRight] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickRight, + .pressed = true, + }); } - - if (!m_gamepadLastStates[index][LeftTrigger]) { - m_gamepadLastStates[index][LeftTrigger] = true; + break; + } + if (ev.caxis.value < -8192) { + if (!m_gamepadLastStates[index][RightStickLeft]) { + m_gamepadLastStates[index][RightStickLeft] = true; EventDispatcher::instance().publish(GamepadInputEvent{ .playerIndex = index, - .input = LeftTrigger, + .input = RightStickLeft, .pressed = true, }); } - break; } - case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: { - if (ev.caxis.value < 8192) { - if (m_gamepadLastStates[index][RightTrigger]) { - m_gamepadLastStates[index][RightTrigger] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightTrigger, - .pressed = false, - }); - break; - } - - break; + break; + } + case SDL_CONTROLLER_AXIS_RIGHTY: { + if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { + if (m_gamepadLastStates[index][RightStickUp]) { + m_gamepadLastStates[index][RightStickUp] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickUp, + .pressed = false, + }); } - if (!m_gamepadLastStates[index][RightTrigger]) { - m_gamepadLastStates[index][RightTrigger] = true; + if (m_gamepadLastStates[index][RightStickDown]) { + m_gamepadLastStates[index][RightStickDown] = false; EventDispatcher::instance().publish(GamepadInputEvent{ .playerIndex = index, - .input = RightTrigger, + .input = RightStickDown, + .pressed = false, + }); + } + break; + } + if (ev.caxis.value > 8192) { + if (!m_gamepadLastStates[index][RightStickDown]) { + m_gamepadLastStates[index][RightStickDown] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickDown, .pressed = true, }); } - break; } + if (ev.caxis.value < -8192) { + if (!m_gamepadLastStates[index][RightStickUp]) { + m_gamepadLastStates[index][RightStickUp] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickUp, + .pressed = true, + }); + } + break; } + break; } - case SDL_CONTROLLERBUTTONUP: { - const auto joystickInstanceId = ev.cbutton.which; - std::shared_ptr gamepad; - for (const auto &g : m_gamepads) { - if (g && g->getInstanceId() == joystickInstanceId) { - gamepad = g; + case SDL_CONTROLLER_AXIS_TRIGGERLEFT: { + if (ev.caxis.value < 8192) { + if (m_gamepadLastStates[index][LeftTrigger]) { + m_gamepadLastStates[index][LeftTrigger] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftTrigger, + .pressed = false, + }); break; } - } - if (!gamepad) { break; } - const auto input = sdlToGamepadInputs.contains(ev.cbutton.button) - ? sdlToGamepadInputs.at(ev.cbutton.button) - : None; - - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = gamepad->getPlayerIndex(), - .input = input, - .pressed = false, - }); + if (!m_gamepadLastStates[index][LeftTrigger]) { + m_gamepadLastStates[index][LeftTrigger] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftTrigger, + .pressed = true, + }); + } break; } - case SDL_CONTROLLERBUTTONDOWN: { - const auto joystickInstanceId = ev.cbutton.which; - std::shared_ptr gamepad; - for (const auto &g : m_gamepads) { - if (g && g->getInstanceId() == joystickInstanceId) { - gamepad = g; + case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: { + if (ev.caxis.value < 8192) { + if (m_gamepadLastStates[index][RightTrigger]) { + m_gamepadLastStates[index][RightTrigger] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightTrigger, + .pressed = false, + }); break; } - } - if (!gamepad) { break; } - const auto input = sdlToGamepadInputs.contains(ev.cbutton.button) - ? sdlToGamepadInputs.at(ev.cbutton.button) - : None; - - for (const auto shortcut : gamepad->getToggledShortcuts(input)) { - EventDispatcher::instance().publish(ShortcutToggledEvent{ - .playerIndex = gamepad->getPlayerIndex(), .shortcut = shortcut}); + if (!m_gamepadLastStates[index][RightTrigger]) { + m_gamepadLastStates[index][RightTrigger] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightTrigger, + .pressed = true, + }); } - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = gamepad->getPlayerIndex(), - .input = input, - .pressed = true, - }); - break; } - case SDL_KEYDOWN: - case SDL_KEYUP: - case SDL_JOYAXISMOTION: - case SDL_JOYBUTTONUP: - case SDL_JOYBUTTONDOWN: - case SDL_JOYDEVICEADDED: - case SDL_JOYDEVICEREMOVED: - spdlog::debug("Ignoring event type: {}", ev.type); + } + } + case SDL_CONTROLLERBUTTONUP: { + const auto joystickInstanceId = ev.cbutton.which; + std::shared_ptr gamepad; + for (const auto &g : m_gamepads) { + if (g && g->getInstanceId() == joystickInstanceId) { + gamepad = g; + break; + } + } + + if (!gamepad) { break; - case SDL_QUIT: - spdlog::info("Quitting SDL Input Service"); - SDL_QuitSubSystem(m_sdlServices); - SDL_Quit(); - return; - default: - spdlog::debug("Got an unhandled SDL event {}", ev.type); + } + + const auto input = sdlToGamepadInputs.contains(ev.cbutton.button) + ? sdlToGamepadInputs.at(ev.cbutton.button) + : None; + + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = gamepad->getPlayerIndex(), + .input = input, + .pressed = false, + }); + + break; + } + case SDL_CONTROLLERBUTTONDOWN: { + const auto joystickInstanceId = ev.cbutton.which; + std::shared_ptr gamepad; + for (const auto &g : m_gamepads) { + if (g && g->getInstanceId() == joystickInstanceId) { + gamepad = g; + break; + } + } + + if (!gamepad) { break; } + + const auto input = sdlToGamepadInputs.contains(ev.cbutton.button) + ? sdlToGamepadInputs.at(ev.cbutton.button) + : None; + + for (const auto shortcut : gamepad->getToggledShortcuts(input)) { + EventDispatcher::instance().publish(ShortcutToggledEvent{ + .playerIndex = gamepad->getPlayerIndex(), .shortcut = shortcut}); + } + + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = gamepad->getPlayerIndex(), + .input = input, + .pressed = true, + }); + + break; + } + case SDL_KEYDOWN: + case SDL_KEYUP: + case SDL_JOYAXISMOTION: + case SDL_JOYBUTTONUP: + case SDL_JOYBUTTONDOWN: + case SDL_JOYDEVICEADDED: + case SDL_JOYDEVICEREMOVED: + spdlog::debug("Ignoring event type: {}", ev.type); + break; + case SDL_QUIT: + spdlog::info("Quitting SDL Input Service"); + SDL_QuitSubSystem(m_sdlServices); + SDL_Quit(); + return; + default: + spdlog::debug("Got an unhandled SDL event {}", ev.type); + break; } prunePendingRemovals(); } From 3b85989b076a86ebe0e089caaa025d0f85be9ae8 Mon Sep 17 00:00:00 2001 From: Nick Sanft Date: Thu, 29 Jan 2026 22:16:56 -0600 Subject: [PATCH 3/3] Revert "Removed delay" This reverts commit 13e81a9a5ee45b94601406fd993f16965e98e446. --- src/app/input2/sdl/sdl_input_service.cpp | 545 +++++++++++------------ 1 file changed, 272 insertions(+), 273 deletions(-) diff --git a/src/app/input2/sdl/sdl_input_service.cpp b/src/app/input2/sdl/sdl_input_service.cpp index 58e26f3b..d50ca1bf 100644 --- a/src/app/input2/sdl/sdl_input_service.cpp +++ b/src/app/input2/sdl/sdl_input_service.cpp @@ -232,341 +232,340 @@ void SDLInputService::run() { spdlog::info("Starting SDL Input Service..."); while (m_running) { SDL_Event ev; - if (!SDL_WaitEvent(&ev)) { - continue; - } - switch (ev.type) { - case SDL_CONTROLLERDEVICEADDED: - openSdlGamepad(ev.cdevice.which); - break; - case SDL_CONTROLLERDEVICEREMOVED: - removeGamepadByInstanceId(ev.cdevice.which); - break; - case SDL_CONTROLLERAXISMOTION: { - const auto joystickInstanceId = ev.cbutton.which; - std::shared_ptr gamepad; - for (const auto &g : m_gamepads) { - if (g && g->getInstanceId() == joystickInstanceId) { - gamepad = g; - break; - } - } - - if (!gamepad) { + if (SDL_WaitEventTimeout(&ev, 200)) { + switch (ev.type) { + case SDL_CONTROLLERDEVICEADDED: + openSdlGamepad(ev.cdevice.which); break; - } - - auto index = gamepad->getPlayerIndex(); - - switch (ev.caxis.axis) { - case SDL_CONTROLLER_AXIS_LEFTX: { - if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { - if (m_gamepadLastStates[index][LeftStickLeft]) { - m_gamepadLastStates[index][LeftStickLeft] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickLeft, - .pressed = false, - }); + case SDL_CONTROLLERDEVICEREMOVED: + removeGamepadByInstanceId(ev.cdevice.which); + break; + case SDL_CONTROLLERAXISMOTION: { + const auto joystickInstanceId = ev.cbutton.which; + std::shared_ptr gamepad; + for (const auto &g : m_gamepads) { + if (g && g->getInstanceId() == joystickInstanceId) { + gamepad = g; + break; } + } - if (m_gamepadLastStates[index][LeftStickRight]) { - m_gamepadLastStates[index][LeftStickRight] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickRight, - .pressed = false, - }); - } + if (!gamepad) { break; } - if (ev.caxis.value > 8192) { - if (!m_gamepadLastStates[index][LeftStickRight]) { - m_gamepadLastStates[index][LeftStickRight] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickRight, - .pressed = true, - }); + + auto index = gamepad->getPlayerIndex(); + + switch (ev.caxis.axis) { + case SDL_CONTROLLER_AXIS_LEFTX: { + if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { + if (m_gamepadLastStates[index][LeftStickLeft]) { + m_gamepadLastStates[index][LeftStickLeft] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickLeft, + .pressed = false, + }); + } + + if (m_gamepadLastStates[index][LeftStickRight]) { + m_gamepadLastStates[index][LeftStickRight] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickRight, + .pressed = false, + }); + } + break; } - break; - } - if (ev.caxis.value < -8192) { - if (!m_gamepadLastStates[index][LeftStickLeft]) { - m_gamepadLastStates[index][LeftStickLeft] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickLeft, - .pressed = true, - }); + if (ev.caxis.value > 8192) { + if (!m_gamepadLastStates[index][LeftStickRight]) { + m_gamepadLastStates[index][LeftStickRight] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickRight, + .pressed = true, + }); + } + break; + } + if (ev.caxis.value < -8192) { + if (!m_gamepadLastStates[index][LeftStickLeft]) { + m_gamepadLastStates[index][LeftStickLeft] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickLeft, + .pressed = true, + }); + } + break; } break; } - break; - } - case SDL_CONTROLLER_AXIS_LEFTY: { - if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { - if (m_gamepadLastStates[index][LeftStickUp]) { - m_gamepadLastStates[index][LeftStickUp] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickUp, - .pressed = false, - }); + case SDL_CONTROLLER_AXIS_LEFTY: { + if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { + if (m_gamepadLastStates[index][LeftStickUp]) { + m_gamepadLastStates[index][LeftStickUp] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickUp, + .pressed = false, + }); + } + + if (m_gamepadLastStates[index][LeftStickDown]) { + m_gamepadLastStates[index][LeftStickDown] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickDown, + .pressed = false, + }); + } + break; } - - if (m_gamepadLastStates[index][LeftStickDown]) { - m_gamepadLastStates[index][LeftStickDown] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickDown, - .pressed = false, - }); + if (ev.caxis.value > 8192) { + if (!m_gamepadLastStates[index][LeftStickDown]) { + m_gamepadLastStates[index][LeftStickDown] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickDown, + .pressed = true, + }); + } + break; } - break; - } - if (ev.caxis.value > 8192) { - if (!m_gamepadLastStates[index][LeftStickDown]) { - m_gamepadLastStates[index][LeftStickDown] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickDown, - .pressed = true, - }); + if (ev.caxis.value < -8192) { + if (!m_gamepadLastStates[index][LeftStickUp]) { + m_gamepadLastStates[index][LeftStickUp] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftStickUp, + .pressed = true, + }); + } + break; } break; } - if (ev.caxis.value < -8192) { - if (!m_gamepadLastStates[index][LeftStickUp]) { - m_gamepadLastStates[index][LeftStickUp] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftStickUp, - .pressed = true, - }); + case SDL_CONTROLLER_AXIS_RIGHTX: { + if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { + if (m_gamepadLastStates[index][RightStickLeft]) { + m_gamepadLastStates[index][RightStickLeft] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickLeft, + .pressed = false, + }); + } + + if (m_gamepadLastStates[index][RightStickRight]) { + m_gamepadLastStates[index][RightStickRight] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickRight, + .pressed = false, + }); + } + break; } - break; - } - break; - } - case SDL_CONTROLLER_AXIS_RIGHTX: { - if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { - if (m_gamepadLastStates[index][RightStickLeft]) { - m_gamepadLastStates[index][RightStickLeft] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickLeft, - .pressed = false, - }); + if (ev.caxis.value > 8192) { + if (!m_gamepadLastStates[index][RightStickRight]) { + m_gamepadLastStates[index][RightStickRight] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickRight, + .pressed = true, + }); + } + break; } - - if (m_gamepadLastStates[index][RightStickRight]) { - m_gamepadLastStates[index][RightStickRight] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickRight, - .pressed = false, - }); + if (ev.caxis.value < -8192) { + if (!m_gamepadLastStates[index][RightStickLeft]) { + m_gamepadLastStates[index][RightStickLeft] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickLeft, + .pressed = true, + }); + } + break; } break; } - if (ev.caxis.value > 8192) { - if (!m_gamepadLastStates[index][RightStickRight]) { - m_gamepadLastStates[index][RightStickRight] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickRight, - .pressed = true, - }); + case SDL_CONTROLLER_AXIS_RIGHTY: { + if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { + if (m_gamepadLastStates[index][RightStickUp]) { + m_gamepadLastStates[index][RightStickUp] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickUp, + .pressed = false, + }); + } + + if (m_gamepadLastStates[index][RightStickDown]) { + m_gamepadLastStates[index][RightStickDown] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickDown, + .pressed = false, + }); + } + break; } - break; - } - if (ev.caxis.value < -8192) { - if (!m_gamepadLastStates[index][RightStickLeft]) { - m_gamepadLastStates[index][RightStickLeft] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickLeft, - .pressed = true, - }); + if (ev.caxis.value > 8192) { + if (!m_gamepadLastStates[index][RightStickDown]) { + m_gamepadLastStates[index][RightStickDown] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickDown, + .pressed = true, + }); + } + break; + } + if (ev.caxis.value < -8192) { + if (!m_gamepadLastStates[index][RightStickUp]) { + m_gamepadLastStates[index][RightStickUp] = true; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightStickUp, + .pressed = true, + }); + } + break; } break; } - break; - } - case SDL_CONTROLLER_AXIS_RIGHTY: { - if (ev.caxis.value < 8192 && ev.caxis.value > -8192) { - if (m_gamepadLastStates[index][RightStickUp]) { - m_gamepadLastStates[index][RightStickUp] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickUp, - .pressed = false, - }); - } + case SDL_CONTROLLER_AXIS_TRIGGERLEFT: { + if (ev.caxis.value < 8192) { + if (m_gamepadLastStates[index][LeftTrigger]) { + m_gamepadLastStates[index][LeftTrigger] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = LeftTrigger, + .pressed = false, + }); + break; + } - if (m_gamepadLastStates[index][RightStickDown]) { - m_gamepadLastStates[index][RightStickDown] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightStickDown, - .pressed = false, - }); + break; } - break; - } - if (ev.caxis.value > 8192) { - if (!m_gamepadLastStates[index][RightStickDown]) { - m_gamepadLastStates[index][RightStickDown] = true; + + if (!m_gamepadLastStates[index][LeftTrigger]) { + m_gamepadLastStates[index][LeftTrigger] = true; EventDispatcher::instance().publish(GamepadInputEvent{ .playerIndex = index, - .input = RightStickDown, + .input = LeftTrigger, .pressed = true, }); } + break; } - if (ev.caxis.value < -8192) { - if (!m_gamepadLastStates[index][RightStickUp]) { - m_gamepadLastStates[index][RightStickUp] = true; + case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: { + if (ev.caxis.value < 8192) { + if (m_gamepadLastStates[index][RightTrigger]) { + m_gamepadLastStates[index][RightTrigger] = false; + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = index, + .input = RightTrigger, + .pressed = false, + }); + break; + } + + break; + } + + if (!m_gamepadLastStates[index][RightTrigger]) { + m_gamepadLastStates[index][RightTrigger] = true; EventDispatcher::instance().publish(GamepadInputEvent{ .playerIndex = index, - .input = RightStickUp, + .input = RightTrigger, .pressed = true, }); } + break; } - break; + } } - case SDL_CONTROLLER_AXIS_TRIGGERLEFT: { - if (ev.caxis.value < 8192) { - if (m_gamepadLastStates[index][LeftTrigger]) { - m_gamepadLastStates[index][LeftTrigger] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftTrigger, - .pressed = false, - }); + case SDL_CONTROLLERBUTTONUP: { + const auto joystickInstanceId = ev.cbutton.which; + std::shared_ptr gamepad; + for (const auto &g : m_gamepads) { + if (g && g->getInstanceId() == joystickInstanceId) { + gamepad = g; break; } + } + if (!gamepad) { break; } - if (!m_gamepadLastStates[index][LeftTrigger]) { - m_gamepadLastStates[index][LeftTrigger] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = LeftTrigger, - .pressed = true, - }); - } + const auto input = sdlToGamepadInputs.contains(ev.cbutton.button) + ? sdlToGamepadInputs.at(ev.cbutton.button) + : None; + + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = gamepad->getPlayerIndex(), + .input = input, + .pressed = false, + }); break; } - case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: { - if (ev.caxis.value < 8192) { - if (m_gamepadLastStates[index][RightTrigger]) { - m_gamepadLastStates[index][RightTrigger] = false; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightTrigger, - .pressed = false, - }); + case SDL_CONTROLLERBUTTONDOWN: { + const auto joystickInstanceId = ev.cbutton.which; + std::shared_ptr gamepad; + for (const auto &g : m_gamepads) { + if (g && g->getInstanceId() == joystickInstanceId) { + gamepad = g; break; } - - break; - } - - if (!m_gamepadLastStates[index][RightTrigger]) { - m_gamepadLastStates[index][RightTrigger] = true; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = index, - .input = RightTrigger, - .pressed = true, - }); } - break; - } - } - } - case SDL_CONTROLLERBUTTONUP: { - const auto joystickInstanceId = ev.cbutton.which; - std::shared_ptr gamepad; - for (const auto &g : m_gamepads) { - if (g && g->getInstanceId() == joystickInstanceId) { - gamepad = g; + if (!gamepad) { break; } - } - - if (!gamepad) { - break; - } - - const auto input = sdlToGamepadInputs.contains(ev.cbutton.button) - ? sdlToGamepadInputs.at(ev.cbutton.button) - : None; - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = gamepad->getPlayerIndex(), - .input = input, - .pressed = false, - }); + const auto input = sdlToGamepadInputs.contains(ev.cbutton.button) + ? sdlToGamepadInputs.at(ev.cbutton.button) + : None; - break; - } - case SDL_CONTROLLERBUTTONDOWN: { - const auto joystickInstanceId = ev.cbutton.which; - std::shared_ptr gamepad; - for (const auto &g : m_gamepads) { - if (g && g->getInstanceId() == joystickInstanceId) { - gamepad = g; - break; + for (const auto shortcut : gamepad->getToggledShortcuts(input)) { + EventDispatcher::instance().publish(ShortcutToggledEvent{ + .playerIndex = gamepad->getPlayerIndex(), .shortcut = shortcut}); } - } - if (!gamepad) { + EventDispatcher::instance().publish(GamepadInputEvent{ + .playerIndex = gamepad->getPlayerIndex(), + .input = input, + .pressed = true, + }); + break; } - - const auto input = sdlToGamepadInputs.contains(ev.cbutton.button) - ? sdlToGamepadInputs.at(ev.cbutton.button) - : None; - - for (const auto shortcut : gamepad->getToggledShortcuts(input)) { - EventDispatcher::instance().publish(ShortcutToggledEvent{ - .playerIndex = gamepad->getPlayerIndex(), .shortcut = shortcut}); + case SDL_KEYDOWN: + case SDL_KEYUP: + case SDL_JOYAXISMOTION: + case SDL_JOYBUTTONUP: + case SDL_JOYBUTTONDOWN: + case SDL_JOYDEVICEADDED: + case SDL_JOYDEVICEREMOVED: + spdlog::debug("Ignoring event type: {}", ev.type); + break; + case SDL_QUIT: + spdlog::info("Quitting SDL Input Service"); + SDL_QuitSubSystem(m_sdlServices); + SDL_Quit(); + return; + default: + spdlog::debug("Got an unhandled SDL event {}", ev.type); + break; } - - EventDispatcher::instance().publish(GamepadInputEvent{ - .playerIndex = gamepad->getPlayerIndex(), - .input = input, - .pressed = true, - }); - - break; - } - case SDL_KEYDOWN: - case SDL_KEYUP: - case SDL_JOYAXISMOTION: - case SDL_JOYBUTTONUP: - case SDL_JOYBUTTONDOWN: - case SDL_JOYDEVICEADDED: - case SDL_JOYDEVICEREMOVED: - spdlog::debug("Ignoring event type: {}", ev.type); - break; - case SDL_QUIT: - spdlog::info("Quitting SDL Input Service"); - SDL_QuitSubSystem(m_sdlServices); - SDL_Quit(); - return; - default: - spdlog::debug("Got an unhandled SDL event {}", ev.type); - break; } prunePendingRemovals(); }