[HID] Fixed issue with controller input introduced in previous commit.

Added option to switch keyboard working mode.
This commit is contained in:
Gliniak 2024-12-18 09:39:52 +01:00
parent f6ae651cc2
commit ef8619b0a8
4 changed files with 49 additions and 40 deletions

View File

@ -137,6 +137,10 @@ X_RESULT InputSystem::GetKeystroke(uint32_t user_index, uint32_t flags,
bool any_connected = false; bool any_connected = false;
for (auto& driver : drivers_) { for (auto& driver : drivers_) {
X_RESULT result = driver->GetKeystroke(user_index, flags, out_keystroke); X_RESULT result = driver->GetKeystroke(user_index, flags, out_keystroke);
if (result == X_ERROR_INVALID_PARAMETER) {
continue;
}
if (result != X_ERROR_DEVICE_NOT_CONNECTED) { if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
any_connected = true; any_connected = true;
} }

View File

@ -25,26 +25,32 @@
#include "winkey_binding_table.inc" #include "winkey_binding_table.inc"
#undef XE_HID_WINKEY_BINDING #undef XE_HID_WINKEY_BINDING
DEFINE_int32(keyboard_user_index, 0, "Controller port that keyboard emulates", DEFINE_int32(keyboard_mode, 1,
"HID.WinKey"); "Allows user do specify keyboard working mode. Possible values: 0 "
"- Disabled, 1 - Enabled, 2 - Passthrough",
"HID");
DEFINE_int32(keyboard_passthru_user_index, -1, DEFINE_int32(keyboard_user_index, 0,
"Allows keyboard to be assigned as virtual keyboard to user with " "Controller port that keyboard emulates. -1 - Keyboard usage "
"specific index. This also forces keyboard to be assigned to that " "disabled, [0, 3] - Keyboard is assigned to selected slot.",
"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",
"HID"); "HID");
namespace xe { namespace xe {
namespace hid { namespace hid {
namespace winkey { namespace winkey {
bool static IsPassThruForUserEnabled(uint32_t user_index) { bool static IsPassthroughEnabled(uint32_t user_index) {
if (cvars::keyboard_passthru_user_index == -1) { return static_cast<KeyboardMode>(cvars::keyboard_mode) ==
KeyboardMode::Passthrough;
}
bool static IsKeyboardForUserEnabled(uint32_t user_index) {
if (static_cast<KeyboardMode>(cvars::keyboard_mode) !=
KeyboardMode::Enabled) {
return false; return false;
} }
return user_index == cvars::keyboard_passthru_user_index;
return cvars::keyboard_user_index == user_index;
} }
bool __inline IsKeyToggled(uint8_t key) { 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_RESULT WinKeyInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
X_INPUT_CAPABILITIES* out_caps) { X_INPUT_CAPABILITIES* out_caps) {
if (user_index != cvars::keyboard_user_index) { if (!IsKeyboardForUserEnabled(user_index)) {
return X_ERROR_DEVICE_NOT_CONNECTED; 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_RESULT WinKeyInputDriver::GetState(uint32_t user_index,
X_INPUT_STATE* out_state) { X_INPUT_STATE* out_state) {
if (!IsPassThruForUserEnabled(user_index) && if (!IsKeyboardForUserEnabled(user_index)) {
user_index != cvars::keyboard_user_index) {
return X_ERROR_DEVICE_NOT_CONNECTED; 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_RESULT WinKeyInputDriver::SetState(uint32_t user_index,
X_INPUT_VIBRATION* vibration) { X_INPUT_VIBRATION* vibration) {
if (!IsPassThruForUserEnabled(user_index) && if (!IsKeyboardForUserEnabled(user_index)) {
user_index != cvars::keyboard_user_index) {
return X_ERROR_DEVICE_NOT_CONNECTED; 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_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
X_INPUT_KEYSTROKE* out_keystroke) { X_INPUT_KEYSTROKE* out_keystroke) {
if (!IsPassThruForUserEnabled(user_index) && // Pop from the queue.
user_index != cvars::keyboard_user_index) { 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; 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; uint16_t keystroke_flags = 0;
uint8_t hid_code = 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); bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT);
if (!IsPassThruForUserEnabled(user_index)) { if (!IsPassthroughEnabled(user_index)) {
for (const KeyBinding& b : key_bindings_) { if (IsKeyboardForUserEnabled(user_index)) {
if (b.input_key == evt.virtual_key && for (const KeyBinding& b : key_bindings_) {
((b.lowercase == b.uppercase) || (b.lowercase && !capital) || if (b.input_key == evt.virtual_key &&
(b.uppercase && capital))) { ((b.lowercase == b.uppercase) || (b.lowercase && !capital) ||
xinput_virtual_key = b.output_key; (b.uppercase && capital))) {
xinput_virtual_key = b.output_key;
}
} }
} }
} else { } else {
@ -332,7 +338,7 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
keystroke_flags |= 0x0002; // XINPUT_KEYSTROKE_KEYUP keystroke_flags |= 0x0002; // XINPUT_KEYSTROKE_KEYUP
} }
if (IsPassThruForUserEnabled(user_index)) { if (IsPassthroughEnabled(user_index)) {
if (GetKeyboardState(key_map_)) { if (GetKeyboardState(key_map_)) {
WCHAR buf; WCHAR buf;
if (ToUnicode(uint8_t(xinput_virtual_key), 0, key_map_, &buf, 1, 0) == if (ToUnicode(uint8_t(xinput_virtual_key), 0, key_map_, &buf, 1, 0) ==

View File

@ -20,6 +20,8 @@ namespace xe {
namespace hid { namespace hid {
namespace winkey { namespace winkey {
enum class KeyboardMode { Disabled, Enabled, Passthrough };
class WinKeyInputDriver final : public InputDriver { class WinKeyInputDriver final : public InputDriver {
public: public:
explicit WinKeyInputDriver(xe::ui::Window* window, size_t window_z_order); explicit WinKeyInputDriver(xe::ui::Window* window, size_t window_z_order);

View File

@ -200,9 +200,6 @@ X_RESULT XInputInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
// flags is reserved on desktop. // flags is reserved on desktop.
DWORD result; DWORD result;
if ((flags & XINPUT_FLAG_KEYBOARD) != 0) {
return X_ERROR_INVALID_PARAMETER;
}
// XInputGetKeystroke on Windows has a bug where it will return // XInputGetKeystroke on Windows has a bug where it will return
// ERROR_SUCCESS (0) even if the device is not connected: // ERROR_SUCCESS (0) even if the device is not connected:
// https://stackoverflow.com/questions/23669238/xinputgetkeystroke-returning-error-success-while-controller-is-unplugged // https://stackoverflow.com/questions/23669238/xinputgetkeystroke-returning-error-success-while-controller-is-unplugged