[UI] Add simple support for controller usage in UI

- Disabled unnecessary hotkeys thread when it is not used
- Removed problematic xam_exports static initialization
- Moved xam_dialogs_shown_ and xam_nui_dialogs_shown_ to XamState
This commit is contained in:
Gliniak
2025-08-11 21:56:13 +02:00
committed by Radosław Gliński
parent 2e9c459846
commit 9054a29483
17 changed files with 221 additions and 154 deletions

View File

@@ -16,6 +16,10 @@
namespace xe {
namespace hid {
constexpr int32_t X_INPUT_GAMEPAD_LEFT_THUMB_DEADZONE = 7849;
constexpr int32_t X_INPUT_GAMEPAD_RIGHT_THUMB_DEADZONE = 8689;
constexpr uint8_t X_INPUT_GAMEPAD_TRIGGER_THRESHOLD = 30;
enum X_INPUT_CAPS {
X_INPUT_CAPS_FFB_SUPPORTED = 0x0001,
X_INPUT_CAPS_WIRELESS = 0x0002,

View File

@@ -46,10 +46,6 @@ class InputDriver {
virtual InputType GetInputType() const = 0;
void set_is_active_callback(std::function<bool()> is_active_callback) {
is_active_callback_ = is_active_callback;
}
protected:
explicit InputDriver(xe::ui::Window* window, size_t window_z_order)
: window_(window), window_z_order_(window_z_order) {}
@@ -57,14 +53,9 @@ class InputDriver {
xe::ui::Window* window() const { return window_; }
size_t window_z_order() const { return window_z_order_; }
bool is_active() const {
return !is_active_callback_ || is_active_callback_();
}
private:
xe::ui::Window* window_;
size_t window_z_order_;
std::function<bool()> is_active_callback_ = nullptr;
};
} // namespace hid

View File

@@ -219,11 +219,7 @@ X_RESULT SDLInputDriver::GetState(uint32_t user_index,
return X_ERROR_BAD_ARGUMENTS;
}
auto is_active = this->is_active();
if (is_active) {
QueueControllerUpdate();
}
QueueControllerUpdate();
auto controller = GetControllerState(user_index);
if (!controller) {
@@ -233,18 +229,10 @@ 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. Also track `is_active` to
// increment the packet number if it changed.
if ((is_active != controller->is_active) ||
(is_active && controller->state_changed)) {
if (controller->is_active || controller->state_changed) {
controller->state.packet_number++;
controller->is_active = is_active;
controller->state_changed = false;
}
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;
}
@@ -332,11 +320,7 @@ X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags,
ui::VirtualKey::kXInputPadRThumbDownLeft,
};
auto is_active = this->is_active();
if (is_active) {
QueueControllerUpdate();
}
QueueControllerUpdate();
for (uint32_t user_index = (user_any ? 0 : users);
user_index < (user_any ? HID_SDL_USER_COUNT : users + 1); user_index++) {
@@ -352,10 +336,8 @@ X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags,
// 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);
const uint64_t curr_butts = controller->state.gamepad.buttons |
AnalogToKeyfield(controller->state.gamepad);
KeystrokeState& last = keystroke_states_.at(user_index);
// Handle repeating

View File

@@ -169,7 +169,7 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index,
int16_t thumb_rx = 0;
int16_t thumb_ry = 0;
if (window()->HasFocus() && is_active()) {
if (window()->HasFocus()) {
bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT);
for (const KeyBinding& b : key_bindings_) {
if (((b.lowercase == b.uppercase) || (b.lowercase && !capital) ||
@@ -283,10 +283,6 @@ X_RESULT WinKeyInputDriver::SetState(uint32_t user_index,
X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
X_INPUT_KEYSTROKE* out_keystroke) {
if (!is_active()) {
return X_ERROR_DEVICE_NOT_CONNECTED;
}
if (!IsKeyboardForUserEnabled(user_index) && !IsPassthroughEnabled()) {
return X_ERROR_DEVICE_NOT_CONNECTED;
}
@@ -382,8 +378,8 @@ void WinKeyInputDriver::WinKeyWindowInputListener::OnKeyUp(ui::KeyEvent& e) {
}
void WinKeyInputDriver::OnKey(ui::KeyEvent& e, bool is_down) {
if (!is_active() || static_cast<KeyboardMode>(cvars::keyboard_mode) ==
KeyboardMode::Disabled) {
if (static_cast<KeyboardMode>(cvars::keyboard_mode) ==
KeyboardMode::Disabled) {
return;
}

View File

@@ -164,17 +164,13 @@ X_RESULT XInputInputDriver::GetState(uint32_t user_index,
}
out_state->packet_number = native_state.state.dwPacketNumber;
if (is_active()) {
out_state->gamepad.buttons = native_state.state.Gamepad.wButtons;
out_state->gamepad.left_trigger = native_state.state.Gamepad.bLeftTrigger;
out_state->gamepad.right_trigger = native_state.state.Gamepad.bRightTrigger;
out_state->gamepad.thumb_lx = native_state.state.Gamepad.sThumbLX;
out_state->gamepad.thumb_ly = native_state.state.Gamepad.sThumbLY;
out_state->gamepad.thumb_rx = native_state.state.Gamepad.sThumbRX;
out_state->gamepad.thumb_ry = native_state.state.Gamepad.sThumbRY;
} else {
std::memset(&out_state->gamepad, 0, sizeof(out_state->gamepad));
}
out_state->gamepad.buttons = native_state.state.Gamepad.wButtons;
out_state->gamepad.left_trigger = native_state.state.Gamepad.bLeftTrigger;
out_state->gamepad.right_trigger = native_state.state.Gamepad.bRightTrigger;
out_state->gamepad.thumb_lx = native_state.state.Gamepad.sThumbLX;
out_state->gamepad.thumb_ly = native_state.state.Gamepad.sThumbLY;
out_state->gamepad.thumb_rx = native_state.state.Gamepad.sThumbRX;
out_state->gamepad.thumb_ry = native_state.state.Gamepad.sThumbRY;
return result;
}
@@ -226,10 +222,6 @@ X_RESULT XInputInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
return result;
}
if (!is_active()) {
return X_ERROR_EMPTY;
}
out_keystroke->virtual_key = native_keystroke.VirtualKey;
out_keystroke->unicode = native_keystroke.Unicode;
out_keystroke->flags = native_keystroke.Flags;