From ef8619b0a8612b25b143aa23b5eb872cbdb1bc3d Mon Sep 17 00:00:00 2001 From: Gliniak Date: Wed, 18 Dec 2024 09:39:52 +0100 Subject: [PATCH] [HID] Fixed issue with controller input introduced in previous commit. Added option to switch keyboard working mode. --- src/xenia/hid/input_system.cc | 4 ++ src/xenia/hid/winkey/winkey_input_driver.cc | 80 +++++++++++---------- src/xenia/hid/winkey/winkey_input_driver.h | 2 + src/xenia/hid/xinput/xinput_input_driver.cc | 3 - 4 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/xenia/hid/input_system.cc b/src/xenia/hid/input_system.cc index d414c7bc5..29a76f749 100644 --- a/src/xenia/hid/input_system.cc +++ b/src/xenia/hid/input_system.cc @@ -137,6 +137,10 @@ X_RESULT InputSystem::GetKeystroke(uint32_t user_index, uint32_t flags, bool any_connected = false; for (auto& driver : drivers_) { X_RESULT result = driver->GetKeystroke(user_index, flags, out_keystroke); + if (result == X_ERROR_INVALID_PARAMETER) { + continue; + } + if (result != X_ERROR_DEVICE_NOT_CONNECTED) { any_connected = true; } diff --git a/src/xenia/hid/winkey/winkey_input_driver.cc b/src/xenia/hid/winkey/winkey_input_driver.cc index f3ca3a4cb..5dd55b295 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.cc +++ b/src/xenia/hid/winkey/winkey_input_driver.cc @@ -25,26 +25,32 @@ #include "winkey_binding_table.inc" #undef XE_HID_WINKEY_BINDING -DEFINE_int32(keyboard_user_index, 0, "Controller port that keyboard emulates", - "HID.WinKey"); +DEFINE_int32(keyboard_mode, 1, + "Allows user do specify keyboard working mode. Possible values: 0 " + "- Disabled, 1 - Enabled, 2 - Passthrough", + "HID"); -DEFINE_int32(keyboard_passthru_user_index, -1, - "Allows keyboard to be assigned as virtual keyboard to user with " - "specific index. This also forces keyboard to be assigned to that " - "slot to be interpreted as controller. Possible values: -1 - " - "Disabled (Keyboard is in " - "gamepad mode), [0, 3] - Keyboard is assigned as VK for that user", +DEFINE_int32(keyboard_user_index, 0, + "Controller port that keyboard emulates. -1 - Keyboard usage " + "disabled, [0, 3] - Keyboard is assigned to selected slot.", "HID"); namespace xe { namespace hid { namespace winkey { -bool static IsPassThruForUserEnabled(uint32_t user_index) { - if (cvars::keyboard_passthru_user_index == -1) { +bool static IsPassthroughEnabled(uint32_t user_index) { + return static_cast(cvars::keyboard_mode) == + KeyboardMode::Passthrough; +} + +bool static IsKeyboardForUserEnabled(uint32_t user_index) { + if (static_cast(cvars::keyboard_mode) != + KeyboardMode::Enabled) { return false; } - return user_index == cvars::keyboard_passthru_user_index; + + return cvars::keyboard_user_index == user_index; } bool __inline IsKeyToggled(uint8_t key) { @@ -120,7 +126,7 @@ X_STATUS WinKeyInputDriver::Setup() { return X_STATUS_SUCCESS; } X_RESULT WinKeyInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags, X_INPUT_CAPABILITIES* out_caps) { - if (user_index != cvars::keyboard_user_index) { + if (!IsKeyboardForUserEnabled(user_index)) { return X_ERROR_DEVICE_NOT_CONNECTED; } @@ -142,8 +148,7 @@ X_RESULT WinKeyInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags, X_RESULT WinKeyInputDriver::GetState(uint32_t user_index, X_INPUT_STATE* out_state) { - if (!IsPassThruForUserEnabled(user_index) && - user_index != cvars::keyboard_user_index) { + if (!IsKeyboardForUserEnabled(user_index)) { return X_ERROR_DEVICE_NOT_CONNECTED; } @@ -258,8 +263,7 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index, X_RESULT WinKeyInputDriver::SetState(uint32_t user_index, X_INPUT_VIBRATION* vibration) { - if (!IsPassThruForUserEnabled(user_index) && - user_index != cvars::keyboard_user_index) { + if (!IsKeyboardForUserEnabled(user_index)) { return X_ERROR_DEVICE_NOT_CONNECTED; } @@ -268,8 +272,20 @@ 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 (!IsPassThruForUserEnabled(user_index) && - user_index != cvars::keyboard_user_index) { + // Pop from the queue. + KeyEvent evt; + { + auto global_lock = global_critical_region_.Acquire(); + if (key_events_.empty()) { + // No keys! + return X_ERROR_EMPTY; + } + evt = key_events_.front(); + key_events_.pop(); + } + + if (!IsKeyboardForUserEnabled(user_index) && + !IsPassthroughEnabled(user_index)) { return X_ERROR_DEVICE_NOT_CONNECTED; } @@ -284,26 +300,16 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, uint16_t keystroke_flags = 0; uint8_t hid_code = 0; - // Pop from the queue. - KeyEvent evt; - { - auto global_lock = global_critical_region_.Acquire(); - if (key_events_.empty()) { - // No keys! - return X_ERROR_EMPTY; - } - evt = key_events_.front(); - key_events_.pop(); - } - bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT); - if (!IsPassThruForUserEnabled(user_index)) { - for (const KeyBinding& b : key_bindings_) { - if (b.input_key == evt.virtual_key && - ((b.lowercase == b.uppercase) || (b.lowercase && !capital) || - (b.uppercase && capital))) { - xinput_virtual_key = b.output_key; + if (!IsPassthroughEnabled(user_index)) { + if (IsKeyboardForUserEnabled(user_index)) { + for (const KeyBinding& b : key_bindings_) { + if (b.input_key == evt.virtual_key && + ((b.lowercase == b.uppercase) || (b.lowercase && !capital) || + (b.uppercase && capital))) { + xinput_virtual_key = b.output_key; + } } } } else { @@ -332,7 +338,7 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, keystroke_flags |= 0x0002; // XINPUT_KEYSTROKE_KEYUP } - if (IsPassThruForUserEnabled(user_index)) { + if (IsPassthroughEnabled(user_index)) { if (GetKeyboardState(key_map_)) { WCHAR buf; if (ToUnicode(uint8_t(xinput_virtual_key), 0, key_map_, &buf, 1, 0) == diff --git a/src/xenia/hid/winkey/winkey_input_driver.h b/src/xenia/hid/winkey/winkey_input_driver.h index 631c4c6a7..541ef864b 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.h +++ b/src/xenia/hid/winkey/winkey_input_driver.h @@ -20,6 +20,8 @@ namespace xe { namespace hid { namespace winkey { +enum class KeyboardMode { Disabled, Enabled, Passthrough }; + class WinKeyInputDriver final : public InputDriver { public: explicit WinKeyInputDriver(xe::ui::Window* window, size_t window_z_order); diff --git a/src/xenia/hid/xinput/xinput_input_driver.cc b/src/xenia/hid/xinput/xinput_input_driver.cc index 8a9274bc5..62e659e1c 100644 --- a/src/xenia/hid/xinput/xinput_input_driver.cc +++ b/src/xenia/hid/xinput/xinput_input_driver.cc @@ -200,9 +200,6 @@ X_RESULT XInputInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, // flags is reserved on desktop. DWORD result; - if ((flags & XINPUT_FLAG_KEYBOARD) != 0) { - return X_ERROR_INVALID_PARAMETER; - } // XInputGetKeystroke on Windows has a bug where it will return // ERROR_SUCCESS (0) even if the device is not connected: // https://stackoverflow.com/questions/23669238/xinputgetkeystroke-returning-error-success-while-controller-is-unplugged