From b0eff372393a79e597c5c345c739b7d574f6c444 Mon Sep 17 00:00:00 2001 From: Willow Barraco Date: Thu, 17 Apr 2025 18:00:31 +0200 Subject: [PATCH] Send modifiers keyboard.key additionaly to keyboard.modifiers At the moment we just use keyboard.modifiers to maintain our clients modifiers states. But we should also send the associated key codes. Clients like wlvncc need them to actually send the keys to the remote compositor. We got no clear way to map our modifier enums to key codes. So I added this zwp_virtual_keyboard_v1_key_mods method. I think I tried most of the use-cases. The hardest part was arround the Shift+Space that send Tab. We have to depress the Shift key, reset the modifiers, send the Tab key, and finally depress back Shift and its modifier. I've tested a bit the Code with .code_mod (and .reset_mod), but I'm not that sure what their behavior should be. Signed-off-by: Maarten van Gompel --- keyboard.c | 71 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/keyboard.c b/keyboard.c index 8aab410..d650518 100644 --- a/keyboard.c +++ b/keyboard.c @@ -274,12 +274,28 @@ kbd_get_layer_index(struct kbd *kb, struct layout *l) return 0; } +void +zwp_virtual_keyboard_v1_key_mods(struct zwp_virtual_keyboard_v1 *vkbd, uint32_t time, uint32_t mods, enum wl_keyboard_key_state state) +{ + if ((mods & Shift) == Shift) + zwp_virtual_keyboard_v1_key(vkbd, time, KEY_LEFTSHIFT, state); + if ((mods & CapsLock) == CapsLock) + zwp_virtual_keyboard_v1_key(vkbd, time, KEY_CAPSLOCK, state); + if ((mods & Ctrl) == Ctrl) + zwp_virtual_keyboard_v1_key(vkbd, time, KEY_LEFTCTRL, state); + if ((mods & Alt) == Alt) + zwp_virtual_keyboard_v1_key(vkbd, time, KEY_LEFTALT, state); + if ((mods & Super) == Super) + zwp_virtual_keyboard_v1_key(vkbd, time, KEY_LEFTMETA, state); + if ((mods & AltGr) == AltGr) + zwp_virtual_keyboard_v1_key(vkbd, time, KEY_RIGHTALT, state); +} + void kbd_unpress_key(struct kbd *kb, uint32_t time) { - bool unlatch_shift, unlatch_ctrl, unlatch_alt, unlatch_super, unlatch_altgr; - unlatch_shift = unlatch_ctrl = unlatch_alt = unlatch_super = unlatch_altgr = false; - + bool unlatch_shift, unlatch_ctrl, unlatch_alt, unlatch_super, unlatch_altgr, unlatch_tab; + unlatch_shift = unlatch_ctrl = unlatch_alt = unlatch_super = unlatch_altgr = unlatch_tab = false; if (kb->last_press) { unlatch_shift = (kb->mods & Shift) == Shift; unlatch_ctrl = (kb->mods & Ctrl) == Ctrl; @@ -287,22 +303,15 @@ kbd_unpress_key(struct kbd *kb, uint32_t time) unlatch_super = (kb->mods & Super) == Super; unlatch_altgr = (kb->mods & AltGr) == AltGr; - if (unlatch_shift) kb->mods ^= Shift; - if (unlatch_ctrl) kb->mods ^= Ctrl; - if (unlatch_alt) kb->mods ^= Alt; - if (unlatch_super) kb->mods ^= Super; - if (unlatch_altgr) kb->mods ^= AltGr; - - if (unlatch_shift||unlatch_ctrl||unlatch_alt||unlatch_super||unlatch_altgr) { - zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0); - } - if (kb->last_press->type == Copy) { zwp_virtual_keyboard_v1_key(kb->vkbd, time, 127, // COMP key WL_KEYBOARD_KEY_STATE_RELEASED); } else { if ((kb->shift_space_is_tab) && (kb->last_press->code == KEY_SPACE) && (unlatch_shift)) { // shift + space is tab + unlatch_shift = false; + unlatch_tab = true; + kb->mods ^= Shift; zwp_virtual_keyboard_v1_key(kb->vkbd, time, KEY_TAB, WL_KEYBOARD_KEY_STATE_RELEASED); } else { @@ -312,10 +321,35 @@ kbd_unpress_key(struct kbd *kb, uint32_t time) } } + if (unlatch_shift) { + kb->mods ^= Shift; + zwp_virtual_keyboard_v1_key_mods(kb->vkbd, time, Shift, WL_KEYBOARD_KEY_STATE_RELEASED); + } + if (unlatch_ctrl) { + kb->mods ^= Ctrl; + zwp_virtual_keyboard_v1_key_mods(kb->vkbd, time, Ctrl, WL_KEYBOARD_KEY_STATE_RELEASED); + } + if (unlatch_alt) { + kb->mods ^= Alt; + zwp_virtual_keyboard_v1_key_mods(kb->vkbd, time, Alt, WL_KEYBOARD_KEY_STATE_RELEASED); + } + if (unlatch_super) { + kb->mods ^= Super; + zwp_virtual_keyboard_v1_key_mods(kb->vkbd, time, Super, WL_KEYBOARD_KEY_STATE_RELEASED); + } + if (unlatch_altgr) { + kb->mods ^= AltGr; + zwp_virtual_keyboard_v1_key_mods(kb->vkbd, time, AltGr, WL_KEYBOARD_KEY_STATE_RELEASED); + } + + if (unlatch_shift||unlatch_ctrl||unlatch_alt||unlatch_super||unlatch_altgr||unlatch_tab) { + zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0); + } + if (kb->compose >= 2) { kb->compose = 0; kbd_switch_layout(kb, kb->last_abc_layout, kb->last_abc_index); - } else if (unlatch_shift||unlatch_ctrl||unlatch_alt||unlatch_super||unlatch_altgr) { + } else if (unlatch_shift||unlatch_ctrl||unlatch_alt||unlatch_super||unlatch_altgr||unlatch_tab) { kbd_draw_layout(kb); } else { kbd_draw_key(kb, kb->last_press, Unpress); @@ -392,6 +426,7 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) switch (k->type) { case Code: if (k->code_mod) { + zwp_virtual_keyboard_v1_key_mods(kb->vkbd, time, k->code_mod, WL_KEYBOARD_KEY_STATE_PRESSED); if (k->reset_mod) { zwp_virtual_keyboard_v1_modifiers(kb->vkbd, k->code_mod, 0, 0, 0); @@ -406,7 +441,8 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) kbd_draw_key(kb, k, Press); if ((kb->shift_space_is_tab) && (k->code == KEY_SPACE) && (kb->mods & Shift)) { // shift space is tab - zwp_virtual_keyboard_v1_modifiers(kb->vkbd, 0, 0, 0, 0); + zwp_virtual_keyboard_v1_key_mods(kb->vkbd, time, Shift, WL_KEYBOARD_KEY_STATE_RELEASED); + zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods ^ Shift, 0, 0, 0); zwp_virtual_keyboard_v1_key(kb->vkbd, time, KEY_TAB, WL_KEYBOARD_KEY_STATE_PRESSED); } else { @@ -423,6 +459,11 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) break; case Mod: kb->mods ^= k->code; + if (kb->mods & k->code) { + zwp_virtual_keyboard_v1_key_mods(kb->vkbd, time, k->code, WL_KEYBOARD_KEY_STATE_PRESSED); + } else { + zwp_virtual_keyboard_v1_key_mods(kb->vkbd, time, k->code, WL_KEYBOARD_KEY_STATE_RELEASED); + } if ((k->code == Shift) || (k->code == CapsLock)) { kbd_draw_layout(kb); } else {