[HID] Honor `is_active()` in SDL input backend.

This commit is contained in:
Joel Linn 2020-11-28 15:46:25 +01:00 committed by Rick Gibbed
parent 7931dbe180
commit ff56fbdf46
2 changed files with 32 additions and 8 deletions

View File

@ -193,7 +193,11 @@ X_RESULT SDLInputDriver::GetState(uint32_t user_index,
return X_ERROR_BAD_ARGUMENTS;
}
QueueControllerUpdate();
auto is_active = this->is_active();
if (is_active) {
QueueControllerUpdate();
}
std::unique_lock<std::mutex> guard(controllers_mutex_);
@ -203,12 +207,20 @@ X_RESULT SDLInputDriver::GetState(uint32_t user_index,
}
// Make sure packet_number is only incremented by 1, even if there have been
// multiple updates between GetState calls.
if (controller->state_changed) {
// multiple updates between GetState calls. Also track `is_active` to
// increment the packet number if it changed.
if ((is_active != controller->is_active) ||
(is_active && controller->state_changed)) {
controller->state.packet_number++;
controller->is_active = is_active;
controller->state_changed = false;
}
*out_state = controller->state;
std::memcpy(out_state, &controller->state, sizeof(*out_state));
if (!is_active) {
// Simulate an "untouched" controller. When we become active again the
// pressed buttons aren't lost and will be visible again.
std::memset(&out_state->gamepad, 0, sizeof(out_state->gamepad));
}
return X_ERROR_SUCCESS;
}
@ -242,6 +254,8 @@ X_RESULT SDLInputDriver::SetState(uint32_t user_index,
X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags,
X_INPUT_KEYSTROKE* out_keystroke) {
// TODO(JoelLinn): Figure out the flags
// https://github.com/evilC/UCR/blob/0489929e2a8e39caa3484c67f3993d3fba39e46f/Libraries/XInput.ahk#L85-L98
assert(sdl_events_initialized_ && sdl_gamecontroller_initialized_);
bool user_any = users == 0xFF;
if (users >= HID_SDL_USER_COUNT && !user_any) {
@ -296,7 +310,11 @@ X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags,
X_INPUT_GAMEPAD_VK_RTHUMB_DOWNLEFT,
};
QueueControllerUpdate();
auto is_active = this->is_active();
if (is_active) {
QueueControllerUpdate();
}
std::unique_lock<std::mutex> guard(controllers_mutex_);
@ -311,8 +329,13 @@ X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags,
}
}
const uint64_t curr_butts = controller->state.gamepad.buttons |
AnalogToKeyfield(controller->state.gamepad);
// If input is not active (e.g. due to a dialog overlay), force buttons to
// "unpressed". The algorithm will automatically send UP events when
// `is_active()` goes low and DOWN events when it goes high again.
const uint64_t curr_butts =
is_active ? (controller->state.gamepad.buttons |
AnalogToKeyfield(controller->state.gamepad))
: uint64_t(0);
KeystrokeState& last = keystroke_states_.at(user_index);
// Handle repeating

View File

@ -44,8 +44,9 @@ class SDLInputDriver : public InputDriver {
protected:
struct ControllerState {
SDL_GameController* sdl;
bool state_changed;
X_INPUT_STATE state;
bool state_changed;
bool is_active;
};
enum class RepeatState {