diff --git a/app/src/hid_keyboard.c b/app/src/hid_keyboard.c index 0004cddefb..9de1712928 100644 --- a/app/src/hid_keyboard.c +++ b/app/src/hid_keyboard.c @@ -142,6 +142,20 @@ const unsigned char REPORT_DESC[REPORT_DESC_SIZE] = { 0xC0 }; +/** + * HID keyboard events are sequence-based, every time keyboard state changes + * it sends an array of currently pressed keys, the host is responsible for + * compare events and determine which key becomes pressed and which key becomes + * released. In order to convert SDL_KeyboardEvent to HID events, we first use + * an array of keys to save each keys' state. And when a SDL_KeyboardEvent was + * emitted, we updated our state, this is done by hid_keyboard_update_state(), + * and then we use a loop to generate HID events, the sequence of array elements + * is unimportant and when too much keys pressed at the same time (more than + * report count), we should generate phantom state. This is done by + * hid_keyboard_get_hid_event(). Don't forget that modifiers should be updated + * too, even for phantom state. + */ + // See "SDL2/SDL_scancode.h". // Maybe SDL_Keycode is used by most people, // but SDL_Scancode is taken from USB HID protocol so I perfer this. @@ -152,19 +166,31 @@ static unsigned char modifiers = HID_KEYBOARD_MODIFIER_NONE; inline static unsigned char sdl_keymod_to_hid_modifiers(SDL_Keymod mod) { unsigned char modifiers = HID_KEYBOARD_MODIFIER_NONE; - // That's why you should not write code drunked. - // SDL_Keymod: NONE NONE NONE NONE RGUI LGUI RALT LALT RCTRL LCTRL NONE NONE NONE NONE RSHIFT LSHIFT - // SDL hex: 0800 0400 0200 0100 0080 0040 0002 0001 - // HID modifiers: RGUI RALT RSHIFT RCTRL LGUI LALT LSHIFT LCTRL - // HID hex: 80 40 20 10 08 04 02 01 - modifiers |= ((mod & KMOD_LCTRL) >> 6); - modifiers |= ((mod & KMOD_LSHIFT) << 1); - modifiers |= ((mod & KMOD_LALT) >> 6); - modifiers |= ((mod & KMOD_LGUI) >> 7); - modifiers |= ((mod & KMOD_RCTRL) >> 3); - modifiers |= ((mod & KMOD_RSHIFT) << 4); - modifiers |= ((mod & KMOD_RALT) >> 3); - modifiers |= ((mod & KMOD_RGUI) >> 4); + // Not so cool, but more readable, and does not rely on actual value. + if (mod & KMOD_LCTRL) { + modifiers |= HID_KEYBOARD_MODIFIER_LEFT_CONTROL; + } + if (mod & KMOD_LSHIFT) { + modifiers |= HID_KEYBOARD_MODIFIER_LEFT_SHIFT; + } + if (mod & KMOD_LALT) { + modifiers |= HID_KEYBOARD_MODIFIER_LEFT_ALT; + } + if (mod & KMOD_LGUI) { + modifiers |= HID_KEYBOARD_MODIFIER_LEFT_GUI; + } + if (mod & KMOD_RCTRL) { + modifiers |= HID_KEYBOARD_MODIFIER_RIGHT_CONTROL; + } + if (mod & KMOD_RSHIFT) { + modifiers |= HID_KEYBOARD_MODIFIER_RIGHT_SHIFT; + } + if (mod & KMOD_RALT) { + modifiers |= HID_KEYBOARD_MODIFIER_RIGHT_ALT; + } + if (mod & KMOD_RGUI) { + modifiers |= HID_KEYBOARD_MODIFIER_RIGHT_GUI; + } return modifiers; } diff --git a/app/src/input_manager.c b/app/src/input_manager.c index 2623e80eae..9df10ce33f 100644 --- a/app/src/input_manager.c +++ b/app/src/input_manager.c @@ -330,6 +330,7 @@ input_manager_process_text_input(struct input_manager *im, if (im->use_hid_over_aoa) { return; } + if (is_shortcut_mod(im, SDL_GetModState())) { // A shortcut must never generate text events return;