jjsullivan5196 / wvkbd

On-screen keyboard for wlroots
GNU General Public License v3.0
286 stars 55 forks source link

Control key modifier stays on after keypress and Capslock doesn't redraw shifted keys #83

Closed RoninTech closed 2 months ago

RoninTech commented 3 months ago

Hi,

Just started using this great onscreen keyboard after moving to Wayland on a Pi 5 with the latest 64bit Raspberry Pi OS. I'm also using the latest wvkbd, 0.15.

I use tmux a lot and noticed that when I issue my <ctrl><a> prefix combo, the <ctrl> key stays active. For instance, <ctrl><a> <q> should display the pane number, but to send this 3 key sequence I have to hit 4 onscreen keys, as I need to hit <ctrl> a second time to turn off the modifier.

Before switching to Wayland I used the Onboard X11 keyboard on my old Pi 4. I just pulled it out and confirmed that the modifiers in Onboard are one shot and automatically disable themselves after a single key.

Is it possible to make modifiers, other than <capslock>, one shot? I just checked and <shift> seems to work as expected but <ctrl>, <alt> and <super> seem to stay locked and need to be manually turned off by a second keypress.

I also noticed that when I hit <shift>, the keyboard is redrawn to show the shifted keys. However when I hit <capslock>, the screen does not get redrawn, and all keys remain showing their lower case value. Shouldn't <capslock> also cause a keyboard redraw to show the upper case keys?

Thanks.

P.S. I'm using the modified desktop layout from @nine7nine and @FearlessSpiff which makes it easier to find these.

RX14 commented 2 months ago

I'll second the desire for an option for modifier keys to be cancelled after one keypress like shift.

proycon commented 2 months ago

It makes sense to make this configurable I guess, so that users can choose (via a command line parameter and/or environment variable) whether they want certain modifiers to be sticky or not.

proycon commented 2 months ago

I also noticed that when I hit , the keyboard is redrawn to show the shifted keys. However when I hit , the screen does not get redrawn, and all keys remain showing their lower case value. Shouldn't also cause a keyboard redraw to show the upper case keys?

Agreed, that would be nicer.

RoninTech commented 2 months ago

This change to kbd_unpress_key() in keyboard.c makes the control, alt and super keys behave as one shot vs permanent modifiers. So now they work the same as how the shift modifier works. This makes wvkbd match all the other onscreen keyboards out there where all modifiers except capslock are one shot:

void kbd_unpress_key(struct kbd *kb, uint32_t time) { bool unlatch_shift, unlatch_ctrl, unlatch_alt, unlatch_super; unlatch_shift = unlatch_ctrl = unlatch_alt = unlatch_super = false; ` if (kb->last_press) { unlatch_shift = (kb->mods & Shift) == Shift; unlatch_ctrl = (kb->mods & Ctrl) == Ctrl; unlatch_alt = (kb->mods & Alt) == Alt; unlatch_super = (kb->mods & Super) == Super; 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_shift||unlatch_ctrl||unlatch_alt||unlatch_super) { 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->last_press->code == KEY_SPACE) && (unlatch_shift == Shift)) { // shift + space is tab zwp_virtual_keyboard_v1_key(kb->vkbd, time, KEY_TAB, WL_KEYBOARD_KEY_STATE_RELEASED); } else { zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code, WL_KEYBOARD_KEY_STATE_RELEASED); } } 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) { kbd_draw_layout(kb); } else { kbd_draw_key(kb, kb->last_press, Unpress); } kb->last_press = NULL; } }`

I wasn't able to find where to make the change so that pressing capslock updates the keys on the screen, similar to when shift is pressed.

EDIT: Fired up the debugger and figured out why capslock wasn't causing the shifted keys to be redrawn. The first line of kbd_draw_key() in keyboard.c needs to look like this:

kbd_draw_key(struct kbd *kb, struct key *k, enum key_draw_type type) { const char *label = ((kb->mods & Shift)||(kb->mods & CapsLock)) ? k->shift_label : k->label;

RX14 commented 2 months ago

A further enhancement could be to make the modifiers sticky if you hold them for longer. Then both behaviors are easily accessible at runtime.

proycon commented 2 months ago

On Sun Sep 1, 2024 at 11:50 AM CEST, Stephanie Wilde-Hobbs wrote:

A further enhancement could be to make the modifiers sticky if you hold them for longer. Then both behaviors are easily accessible at runtime.

Many virtual keyboard do that indeed, but wvkbd opts for a behaviour more similar to hardware keyboards: holding a key means repeatedly outputting it. But perhaps that doesn't mean much for modifier keys and it might indeed work out the way you suggest.