Recover gamepad state when add events are missed
Some checks are pending
Build / setup (push) Waiting to run
Build / build-appimage (push) Blocked by required conditions
Build / build-steamlink (push) Blocked by required conditions
Build / build-windows-macos (push) Blocked by required conditions

This commit is contained in:
Joey Yakimowich-Payne 2026-02-12 02:00:45 -07:00
commit e005587806
2 changed files with 42 additions and 5 deletions

View file

@ -63,6 +63,40 @@ SdlInputHandler::findStateForGamepad(SDL_JoystickID id)
return nullptr; return nullptr;
} }
GamepadState*
SdlInputHandler::ensureStateForGamepad(SDL_JoystickID id)
{
GamepadState* state = findStateForGamepad(id);
if (state != nullptr) {
return state;
}
cleanupDetachedGamepads();
const int joystickCount = SDL_NumJoysticks();
for (int deviceIndex = 0; deviceIndex < joystickCount; deviceIndex++) {
if (!SDL_IsGameController(deviceIndex)) {
continue;
}
if (SDL_JoystickGetDeviceInstanceID(deviceIndex) != id) {
continue;
}
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Recovering gamepad state for missing add event (instance ID: %d)",
id);
SDL_ControllerDeviceEvent controllerEvent = {};
controllerEvent.type = SDL_CONTROLLERDEVICEADDED;
controllerEvent.which = deviceIndex;
handleControllerDeviceEvent(&controllerEvent);
break;
}
return findStateForGamepad(id);
}
void SdlInputHandler::cleanupDetachedGamepads() void SdlInputHandler::cleanupDetachedGamepads()
{ {
for (int i = 0; i < MAX_GAMEPADS; i++) { for (int i = 0; i < MAX_GAMEPADS; i++) {
@ -226,7 +260,7 @@ Uint32 SdlInputHandler::mouseEmulationTimerCallback(Uint32 interval, void *param
void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event) void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event)
{ {
SDL_JoystickID gameControllerId = event->which; SDL_JoystickID gameControllerId = event->which;
GamepadState* state = findStateForGamepad(gameControllerId); GamepadState* state = ensureStateForGamepad(gameControllerId);
if (state == NULL) { if (state == NULL) {
return; return;
} }
@ -296,7 +330,7 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
return; return;
} }
GamepadState* state = findStateForGamepad(event->which); GamepadState* state = ensureStateForGamepad(event->which);
if (state == NULL) { if (state == NULL) {
return; return;
} }
@ -516,7 +550,7 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* event) void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* event)
{ {
GamepadState* state = findStateForGamepad(event->which); GamepadState* state = ensureStateForGamepad(event->which);
if (state == NULL) { if (state == NULL) {
return; return;
} }
@ -555,7 +589,7 @@ void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* eve
void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* event) void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* event)
{ {
GamepadState* state = findStateForGamepad(event->which); GamepadState* state = ensureStateForGamepad(event->which);
if (state == NULL) { if (state == NULL) {
return; return;
} }
@ -586,7 +620,7 @@ void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent*
void SdlInputHandler::handleJoystickBatteryEvent(SDL_JoyBatteryEvent* event) void SdlInputHandler::handleJoystickBatteryEvent(SDL_JoyBatteryEvent* event)
{ {
GamepadState* state = findStateForGamepad(event->which); GamepadState* state = ensureStateForGamepad(event->which);
if (state == NULL) { if (state == NULL) {
return; return;
} }

View file

@ -185,6 +185,9 @@ private:
GamepadState* GamepadState*
findStateForGamepad(SDL_JoystickID id); findStateForGamepad(SDL_JoystickID id);
GamepadState*
ensureStateForGamepad(SDL_JoystickID id);
void cleanupDetachedGamepads(); void cleanupDetachedGamepads();
void sendGamepadState(GamepadState* state); void sendGamepadState(GamepadState* state);