From 82f73fca50256a5c5672775994bc218c9d4ddd5c Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 21 Oct 2021 20:44:19 +0200 Subject: [PATCH] Synchronize HID keyboard state on first event When an AOA HID keyboard is registered, CAPSLOCK and NUMLOCK are both disabled, regardless of the state of the computer keyboard. To synchronize the state, on first key event, inject CAPSLOCK and/or NUMLOCK if necessary. --- app/src/hid_keyboard.c | 47 ++++++++++++++++++++++++++++++++++++++++++ app/src/hid_keyboard.h | 2 ++ 2 files changed, 49 insertions(+) diff --git a/app/src/hid_keyboard.c b/app/src/hid_keyboard.c index e2c61b68..14c9a57b 100644 --- a/app/src/hid_keyboard.c +++ b/app/src/hid_keyboard.c @@ -240,6 +240,44 @@ convert_hid_keyboard_event(struct hid_keyboard *kb, struct hid_event *hid_event, return true; } + +static bool +push_mod_lock_state(struct hid_keyboard *kb, uint16_t sdl_mod) { + bool capslock = sdl_mod & KMOD_CAPS; + bool numlock = sdl_mod & KMOD_NUM; + if (!capslock && !numlock) { + // Nothing to do + return true; + } + + struct hid_event hid_event; + if (!hid_keyboard_event_init(&hid_event)) { + LOGW("Could not initialize HID event"); + return false; + } + +#define SC_SCANCODE_CAPSLOCK SDL_SCANCODE_CAPSLOCK +#define SC_SCANCODE_NUMLOCK SDL_SCANCODE_NUMLOCKCLEAR + unsigned i = 0; + if (capslock) { + hid_event.buffer[HID_KEYBOARD_INDEX_KEYS + i] = SC_SCANCODE_CAPSLOCK; + ++i; + } + if (numlock) { + hid_event.buffer[HID_KEYBOARD_INDEX_KEYS + i] = SC_SCANCODE_NUMLOCK; + ++i; + } + + if (!aoa_push_hid_event(kb->aoa, &hid_event)) { + LOGW("Could request HID event"); + return false; + } + + LOGD("HID keyboard state synchronized"); + + return true; +} + static void sc_key_processor_process_key(struct sc_key_processor *kp, const SDL_KeyboardEvent *event) { @@ -254,6 +292,13 @@ sc_key_processor_process_key(struct sc_key_processor *kp, struct hid_event hid_event; // Not all keys are supported, just ignore unsupported keys if (convert_hid_keyboard_event(kb, &hid_event, event)) { + if (!kb->mod_lock_synchronized) { + // Inject CAPSLOCK and/or NUMLOCK if necessary to synchronize + // keyboard state + if (push_mod_lock_state(kb, event->keysym.mod)) { + kb->mod_lock_synchronized = true; + } + } if (!aoa_push_hid_event(kb->aoa, &hid_event)) { hid_event_destroy(&hid_event); LOGW("Could request HID event"); @@ -285,6 +330,8 @@ hid_keyboard_init(struct hid_keyboard *kb, struct aoa *aoa) { // Reset all states memset(kb->keys, false, HID_KEYBOARD_KEYS); + kb->mod_lock_synchronized = false; + static const struct sc_key_processor_ops ops = { .process_key = sc_key_processor_process_key, .process_text = sc_key_processor_process_text, diff --git a/app/src/hid_keyboard.h b/app/src/hid_keyboard.h index b57070aa..58dcbc85 100644 --- a/app/src/hid_keyboard.h +++ b/app/src/hid_keyboard.h @@ -33,6 +33,8 @@ struct hid_keyboard { struct aoa *aoa; bool keys[HID_KEYBOARD_KEYS]; + + bool mod_lock_synchronized; }; bool