mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-02-06 00:39:54 +00:00
Add support for keyboard input that is not normalized to US English layout
This is used by the soft keyboards on Android and iOS
This commit is contained in:
parent
ae7ae8a870
commit
4e04604696
@ -59,8 +59,22 @@ namespace input {
|
|||||||
gamepad_mask[id] = false;
|
gamepad_mask[id] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef uint32_t key_press_id_t;
|
||||||
|
key_press_id_t
|
||||||
|
make_kpid(uint16_t vk, uint8_t flags) {
|
||||||
|
return (key_press_id_t) vk << 8 | flags;
|
||||||
|
}
|
||||||
|
uint16_t
|
||||||
|
vk_from_kpid(key_press_id_t kpid) {
|
||||||
|
return kpid >> 8;
|
||||||
|
}
|
||||||
|
uint8_t
|
||||||
|
flags_from_kpid(key_press_id_t kpid) {
|
||||||
|
return kpid & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
static task_pool_util::TaskPool::task_id_t key_press_repeat_id {};
|
static task_pool_util::TaskPool::task_id_t key_press_repeat_id {};
|
||||||
static std::unordered_map<short, bool> key_press {};
|
static std::unordered_map<key_press_id_t, bool> key_press {};
|
||||||
static std::array<std::uint8_t, 5> mouse_press {};
|
static std::array<std::uint8_t, 5> mouse_press {};
|
||||||
|
|
||||||
static platf::input_t platf_input;
|
static platf::input_t platf_input;
|
||||||
@ -449,16 +463,16 @@ namespace input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
repeat_key(short key_code) {
|
repeat_key(uint16_t key_code, uint8_t flags) {
|
||||||
// If key no longer pressed, stop repeating
|
// If key no longer pressed, stop repeating
|
||||||
if (!key_press[key_code]) {
|
if (!key_press[make_kpid(key_code, flags)]) {
|
||||||
key_press_repeat_id = nullptr;
|
key_press_repeat_id = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
platf::keyboard(platf_input, map_keycode(key_code), false);
|
platf::keyboard(platf_input, map_keycode(key_code), false, flags);
|
||||||
|
|
||||||
key_press_repeat_id = task_pool.pushDelayed(repeat_key, config::input.key_repeat_period, key_code).task_id;
|
key_press_repeat_id = task_pool.pushDelayed(repeat_key, config::input.key_repeat_period, key_code, flags).task_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -470,7 +484,7 @@ namespace input {
|
|||||||
auto release = util::endian::little(packet->header.magic) == KEY_UP_EVENT_MAGIC;
|
auto release = util::endian::little(packet->header.magic) == KEY_UP_EVENT_MAGIC;
|
||||||
auto keyCode = packet->keyCode & 0x00FF;
|
auto keyCode = packet->keyCode & 0x00FF;
|
||||||
|
|
||||||
auto &pressed = key_press[keyCode];
|
auto &pressed = key_press[make_kpid(keyCode, packet->flags)];
|
||||||
if (!pressed) {
|
if (!pressed) {
|
||||||
if (!release) {
|
if (!release) {
|
||||||
// A new key has been pressed down, we need to check for key combo's
|
// A new key has been pressed down, we need to check for key combo's
|
||||||
@ -484,7 +498,7 @@ namespace input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config::input.key_repeat_delay.count() > 0) {
|
if (config::input.key_repeat_delay.count() > 0) {
|
||||||
key_press_repeat_id = task_pool.pushDelayed(repeat_key, config::input.key_repeat_delay, keyCode).task_id;
|
key_press_repeat_id = task_pool.pushDelayed(repeat_key, config::input.key_repeat_delay, keyCode, packet->flags).task_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -500,7 +514,7 @@ namespace input {
|
|||||||
pressed = !release;
|
pressed = !release;
|
||||||
|
|
||||||
update_shortcutFlags(&input->shortcutFlags, map_keycode(keyCode), release);
|
update_shortcutFlags(&input->shortcutFlags, map_keycode(keyCode), release);
|
||||||
platf::keyboard(platf_input, map_keycode(keyCode), release);
|
platf::keyboard(platf_input, map_keycode(keyCode), release, packet->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -731,7 +745,7 @@ namespace input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto &kp : key_press) {
|
for (auto &kp : key_press) {
|
||||||
platf::keyboard(platf_input, kp.first & 0x00FF, true);
|
platf::keyboard(platf_input, vk_from_kpid(kp.first) & 0x00FF, true, flags_from_kpid(kp.first));
|
||||||
key_press[kp.first] = false;
|
key_press[kp.first] = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -436,7 +436,7 @@ namespace platf {
|
|||||||
void
|
void
|
||||||
hscroll(input_t &input, int distance);
|
hscroll(input_t &input, int distance);
|
||||||
void
|
void
|
||||||
keyboard(input_t &input, uint16_t modcode, bool release);
|
keyboard(input_t &input, uint16_t modcode, bool release, uint8_t flags);
|
||||||
void
|
void
|
||||||
gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state);
|
gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state);
|
||||||
void
|
void
|
||||||
|
@ -1337,14 +1337,15 @@ namespace platf {
|
|||||||
* @param input The input_t instance to use.
|
* @param input The input_t instance to use.
|
||||||
* @param modcode The moonlight key code.
|
* @param modcode The moonlight key code.
|
||||||
* @param release Whether the event was a press (false) or a release (true)
|
* @param release Whether the event was a press (false) or a release (true)
|
||||||
|
* @param flags SS_KBE_FLAG_* values
|
||||||
*
|
*
|
||||||
* EXAMPLES:
|
* EXAMPLES:
|
||||||
* ```cpp
|
* ```cpp
|
||||||
* x_keyboard(input, 0x5A, false); // Press Z
|
* x_keyboard(input, 0x5A, false, 0); // Press Z
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
x_keyboard(input_t &input, uint16_t modcode, bool release) {
|
x_keyboard(input_t &input, uint16_t modcode, bool release, uint8_t flags) {
|
||||||
#ifdef SUNSHINE_BUILD_X11
|
#ifdef SUNSHINE_BUILD_X11
|
||||||
auto keycode = keysym(modcode);
|
auto keycode = keysym(modcode);
|
||||||
if (keycode.keysym == UNKNOWN) {
|
if (keycode.keysym == UNKNOWN) {
|
||||||
@ -1371,17 +1372,18 @@ namespace platf {
|
|||||||
* @param input The input_t instance to use.
|
* @param input The input_t instance to use.
|
||||||
* @param modcode The moonlight key code.
|
* @param modcode The moonlight key code.
|
||||||
* @param release Whether the event was a press (false) or a release (true)
|
* @param release Whether the event was a press (false) or a release (true)
|
||||||
|
* @param flags SS_KBE_FLAG_* values
|
||||||
*
|
*
|
||||||
* EXAMPLES:
|
* EXAMPLES:
|
||||||
* ```cpp
|
* ```cpp
|
||||||
* keyboard(input, 0x5A, false); // Press Z
|
* keyboard(input, 0x5A, false, 0); // Press Z
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
keyboard(input_t &input, uint16_t modcode, bool release) {
|
keyboard(input_t &input, uint16_t modcode, bool release, uint8_t flags) {
|
||||||
auto keyboard = ((input_raw_t *) input.get())->keyboard_input.get();
|
auto keyboard = ((input_raw_t *) input.get())->keyboard_input.get();
|
||||||
if (!keyboard) {
|
if (!keyboard) {
|
||||||
x_keyboard(input, modcode, release);
|
x_keyboard(input, modcode, release, flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ const KeyCodeMap kKeyCodesMap[] = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
keyboard(input_t &input, uint16_t modcode, bool release) {
|
keyboard(input_t &input, uint16_t modcode, bool release, uint8_t flags) {
|
||||||
auto key = keysym(modcode);
|
auto key = keysym(modcode);
|
||||||
|
|
||||||
BOOST_LOG(debug) << "got keycode: 0x"sv << std::hex << modcode << ", translated to: 0x" << std::hex << key << ", release:" << release;
|
BOOST_LOG(debug) << "got keycode: 0x"sv << std::hex << modcode << ", translated to: 0x" << std::hex << key << ", release:" << release;
|
||||||
|
@ -338,15 +338,16 @@ namespace platf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
keyboard(input_t &input, uint16_t modcode, bool release) {
|
keyboard(input_t &input, uint16_t modcode, bool release, uint8_t flags) {
|
||||||
auto raw = (input_raw_t *) input.get();
|
auto raw = (input_raw_t *) input.get();
|
||||||
|
|
||||||
INPUT i {};
|
INPUT i {};
|
||||||
i.type = INPUT_KEYBOARD;
|
i.type = INPUT_KEYBOARD;
|
||||||
auto &ki = i.ki;
|
auto &ki = i.ki;
|
||||||
|
|
||||||
// For some reason, MapVirtualKey(VK_LWIN, MAPVK_VK_TO_VSC) doesn't seem to work :/
|
// If the client did not normalize this VK code to a US English layout, we can't accurately convert it to a scancode.
|
||||||
if (modcode != VK_LWIN && modcode != VK_RWIN && modcode != VK_PAUSE && raw->keyboard_layout != NULL) {
|
if (!(flags & SS_KBE_FLAG_NON_NORMALIZED) && modcode != VK_LWIN && modcode != VK_RWIN && modcode != VK_PAUSE && raw->keyboard_layout != NULL) {
|
||||||
|
// For some reason, MapVirtualKey(VK_LWIN, MAPVK_VK_TO_VSC) doesn't seem to work :/
|
||||||
ki.wScan = MapVirtualKeyEx(modcode, MAPVK_VK_TO_VSC, raw->keyboard_layout);
|
ki.wScan = MapVirtualKeyEx(modcode, MAPVK_VK_TO_VSC, raw->keyboard_layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,7 +356,7 @@ namespace platf {
|
|||||||
ki.dwFlags = KEYEVENTF_SCANCODE;
|
ki.dwFlags = KEYEVENTF_SCANCODE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// If there is no scancode mapping, send it as a regular VK event.
|
// If there is no scancode mapping or it's non-normalized, send it as a regular VK event.
|
||||||
ki.wVk = modcode;
|
ki.wVk = modcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user