Merge dd15183faf
into 5abf67f540
This commit is contained in:
commit
0031243d9e
|
@ -131,10 +131,15 @@ X_RESULT InputSystem::GetKeystroke(uint32_t user_index, uint32_t flags,
|
||||||
if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
|
if (result != X_ERROR_DEVICE_NOT_CONNECTED) {
|
||||||
any_connected = true;
|
any_connected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == X_ERROR_SUCCESS || result == X_ERROR_EMPTY) {
|
if (result == X_ERROR_SUCCESS || result == X_ERROR_EMPTY) {
|
||||||
UpdateUsedSlot(driver.get(), user_index, any_connected);
|
UpdateUsedSlot(driver.get(), user_index, any_connected);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result == X_ERROR_EMPTY) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UpdateUsedSlot(nullptr, user_index, any_connected);
|
UpdateUsedSlot(nullptr, user_index, any_connected);
|
||||||
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
|
return any_connected ? X_ERROR_EMPTY : X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
|
|
|
@ -289,7 +289,9 @@ X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags,
|
||||||
if (!out_keystroke) {
|
if (!out_keystroke) {
|
||||||
return X_ERROR_BAD_ARGUMENTS;
|
return X_ERROR_BAD_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
if ((flags & XINPUT_FLAG_KEYBOARD) != 0) {
|
||||||
|
return X_ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
// The order of this list is also the order in which events are send if
|
// The order of this list is also the order in which events are send if
|
||||||
// multiple buttons change at once.
|
// multiple buttons change at once.
|
||||||
static_assert(sizeof(X_INPUT_GAMEPAD::buttons) == 2);
|
static_assert(sizeof(X_INPUT_GAMEPAD::buttons) == 2);
|
||||||
|
|
|
@ -28,10 +28,25 @@
|
||||||
DEFINE_int32(keyboard_user_index, 0, "Controller port that keyboard emulates",
|
DEFINE_int32(keyboard_user_index, 0, "Controller port that keyboard emulates",
|
||||||
"HID.WinKey");
|
"HID.WinKey");
|
||||||
|
|
||||||
|
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",
|
||||||
|
"HID");
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace hid {
|
namespace hid {
|
||||||
namespace winkey {
|
namespace winkey {
|
||||||
|
|
||||||
|
bool static IsPassThruForUserEnabled(uint32_t user_index) {
|
||||||
|
if (cvars::keyboard_passthru_user_index == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return user_index == cvars::keyboard_passthru_user_index;
|
||||||
|
}
|
||||||
|
|
||||||
bool __inline IsKeyToggled(uint8_t key) {
|
bool __inline IsKeyToggled(uint8_t key) {
|
||||||
return (GetKeyState(key) & 0x1) == 0x1;
|
return (GetKeyState(key) & 0x1) == 0x1;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +141,8 @@ 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 (user_index != cvars::keyboard_user_index) {
|
if (!IsPassThruForUserEnabled(user_index) &&
|
||||||
|
user_index != cvars::keyboard_user_index) {
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +257,8 @@ 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 (user_index != cvars::keyboard_user_index) {
|
if (!IsPassThruForUserEnabled(user_index) &&
|
||||||
|
user_index != cvars::keyboard_user_index) {
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +267,8 @@ 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 (user_index != cvars::keyboard_user_index) {
|
if (!IsPassThruForUserEnabled(user_index) &&
|
||||||
|
user_index != cvars::keyboard_user_index) {
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,23 +296,48 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT);
|
bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT);
|
||||||
for (const KeyBinding& b : key_bindings_) {
|
|
||||||
if (b.input_key == evt.virtual_key &&
|
if (!IsPassThruForUserEnabled(user_index)) {
|
||||||
((b.lowercase == b.uppercase) || (b.lowercase && !capital) ||
|
for (const KeyBinding& b : key_bindings_) {
|
||||||
(b.uppercase && capital))) {
|
if (b.input_key == evt.virtual_key &&
|
||||||
xinput_virtual_key = b.output_key;
|
((b.lowercase == b.uppercase) || (b.lowercase && !capital) ||
|
||||||
|
(b.uppercase && capital))) {
|
||||||
|
xinput_virtual_key = b.output_key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
xinput_virtual_key = evt.virtual_key;
|
||||||
|
|
||||||
|
if (capital) {
|
||||||
|
keystroke_flags |= 0x0008; // XINPUT_KEYSTROKE_SHIFT
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsKeyToggled(VK_CONTROL)) {
|
||||||
|
keystroke_flags |= 0x0010; // XINPUT_KEYSTROKE_CTRL
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsKeyToggled(VK_MENU)) {
|
||||||
|
keystroke_flags |= 0x0020; // XINPUT_KEYSTROKE_ALT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xinput_virtual_key != ui::VirtualKey::kNone) {
|
if (xinput_virtual_key != ui::VirtualKey::kNone) {
|
||||||
if (evt.transition == true) {
|
if (evt.transition == true) {
|
||||||
keystroke_flags |= 0x0001; // XINPUT_KEYSTROKE_KEYDOWN
|
keystroke_flags |= 0x0001; // XINPUT_KEYSTROKE_KEYDOWN
|
||||||
|
if (evt.prev_state == evt.transition) {
|
||||||
|
keystroke_flags |= 0x0004; // XINPUT_KEYSTROKE_REPEAT
|
||||||
|
}
|
||||||
} else if (evt.transition == false) {
|
} else if (evt.transition == false) {
|
||||||
keystroke_flags |= 0x0002; // XINPUT_KEYSTROKE_KEYUP
|
keystroke_flags |= 0x0002; // XINPUT_KEYSTROKE_KEYUP
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evt.prev_state == evt.transition) {
|
if (IsPassThruForUserEnabled(user_index)) {
|
||||||
keystroke_flags |= 0x0004; // XINPUT_KEYSTROKE_REPEAT
|
WCHAR buf;
|
||||||
|
if (ToUnicode(uint8_t(xinput_virtual_key), 0, key_map_, &buf, 1, 0) ==
|
||||||
|
1) {
|
||||||
|
keystroke_flags |= 0x1000; // XINPUT_KEYSTROKE_VALIDUNICODE
|
||||||
|
unicode = buf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = X_ERROR_SUCCESS;
|
result = X_ERROR_SUCCESS;
|
||||||
|
@ -303,7 +346,7 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
|
||||||
out_keystroke->virtual_key = uint16_t(xinput_virtual_key);
|
out_keystroke->virtual_key = uint16_t(xinput_virtual_key);
|
||||||
out_keystroke->unicode = unicode;
|
out_keystroke->unicode = unicode;
|
||||||
out_keystroke->flags = keystroke_flags;
|
out_keystroke->flags = keystroke_flags;
|
||||||
out_keystroke->user_index = 0;
|
out_keystroke->user_index = user_index;
|
||||||
out_keystroke->hid_code = hid_code;
|
out_keystroke->hid_code = hid_code;
|
||||||
|
|
||||||
// X_ERROR_EMPTY if no new keys
|
// X_ERROR_EMPTY if no new keys
|
||||||
|
|
|
@ -72,7 +72,7 @@ class WinKeyInputDriver final : public InputDriver {
|
||||||
xe::global_critical_region global_critical_region_;
|
xe::global_critical_region global_critical_region_;
|
||||||
std::queue<KeyEvent> key_events_;
|
std::queue<KeyEvent> key_events_;
|
||||||
std::vector<KeyBinding> key_bindings_;
|
std::vector<KeyBinding> key_bindings_;
|
||||||
|
uint8_t key_map_[256];
|
||||||
uint32_t packet_number_ = 1;
|
uint32_t packet_number_ = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,9 @@ 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
|
||||||
|
|
|
@ -25,12 +25,6 @@ using xe::hid::X_INPUT_KEYSTROKE;
|
||||||
using xe::hid::X_INPUT_STATE;
|
using xe::hid::X_INPUT_STATE;
|
||||||
using xe::hid::X_INPUT_VIBRATION;
|
using xe::hid::X_INPUT_VIBRATION;
|
||||||
|
|
||||||
constexpr uint32_t XINPUT_FLAG_GAMEPAD = 0x01;
|
|
||||||
constexpr uint32_t XINPUT_FLAG_KEYBOARD = 0x02;
|
|
||||||
constexpr uint32_t XINPUT_FLAG_MIC = 0x20; // Based on "karaoke" titles
|
|
||||||
constexpr uint32_t XINPUT_FLAG_ANYDEVICE = 0xFF;
|
|
||||||
constexpr uint32_t XINPUT_FLAG_ANY_USER = 1 << 30;
|
|
||||||
|
|
||||||
dword_result_t XAutomationpUnbindController_entry(dword_t user_index) {
|
dword_result_t XAutomationpUnbindController_entry(dword_t user_index) {
|
||||||
if (user_index > 4) {
|
if (user_index > 4) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -73,11 +67,6 @@ dword_result_t XamInputGetCapabilitiesEx_entry(
|
||||||
// should trap
|
// should trap
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & XINPUT_FLAG_ANYDEVICE) && (flags & XINPUT_FLAG_GAMEPAD) == 0) {
|
|
||||||
// Ignore any query for other types of devices.
|
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t actual_user_index = user_index;
|
uint32_t actual_user_index = user_index;
|
||||||
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
|
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
|
||||||
// Always pin user to 0.
|
// Always pin user to 0.
|
||||||
|
@ -111,11 +100,6 @@ dword_result_t XamInputGetState_entry(dword_t user_index, dword_t flags,
|
||||||
|
|
||||||
// Games call this with a NULL state ptr, probably as a query.
|
// Games call this with a NULL state ptr, probably as a query.
|
||||||
|
|
||||||
if ((flags & XINPUT_FLAG_ANYDEVICE) && (flags & XINPUT_FLAG_GAMEPAD) == 0) {
|
|
||||||
// Ignore any query for other types of devices.
|
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t actual_user_index = user_index;
|
uint32_t actual_user_index = user_index;
|
||||||
// chrispy: change this, logic is not right
|
// chrispy: change this, logic is not right
|
||||||
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
|
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
|
||||||
|
@ -164,11 +148,6 @@ dword_result_t XamInputGetKeystroke_entry(
|
||||||
return X_ERROR_BAD_ARGUMENTS;
|
return X_ERROR_BAD_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & XINPUT_FLAG_ANYDEVICE) && (flags & XINPUT_FLAG_GAMEPAD) == 0) {
|
|
||||||
// Ignore any query for other types of devices.
|
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t actual_user_index = user_index;
|
uint32_t actual_user_index = user_index;
|
||||||
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
|
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
|
||||||
// Always pin user to 0.
|
// Always pin user to 0.
|
||||||
|
@ -189,11 +168,6 @@ dword_result_t XamInputGetKeystrokeEx_entry(
|
||||||
return X_ERROR_BAD_ARGUMENTS;
|
return X_ERROR_BAD_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & XINPUT_FLAG_ANYDEVICE) && (flags & XINPUT_FLAG_GAMEPAD) == 0) {
|
|
||||||
// Ignore any query for other types of devices.
|
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t user_index = *user_index_ptr;
|
uint32_t user_index = *user_index_ptr;
|
||||||
auto input_system = kernel_state()->emulator()->input_system();
|
auto input_system = kernel_state()->emulator()->input_system();
|
||||||
auto lock = input_system->lock();
|
auto lock = input_system->lock();
|
||||||
|
|
|
@ -539,6 +539,12 @@ enum class XDeploymentType : uint32_t {
|
||||||
kUnknown = 0xFF,
|
kUnknown = 0xFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr uint32_t XINPUT_FLAG_GAMEPAD = 0x01;
|
||||||
|
constexpr uint32_t XINPUT_FLAG_KEYBOARD = 0x02;
|
||||||
|
constexpr uint32_t XINPUT_FLAG_MIC = 0x20; // Based on "karaoke" titles
|
||||||
|
constexpr uint32_t XINPUT_FLAG_ANYDEVICE = 0xFF;
|
||||||
|
constexpr uint32_t XINPUT_FLAG_ANY_USER = 1 << 30;
|
||||||
|
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
Loading…
Reference in New Issue