src/keyboard.c: do not end window-cycling on modifier release only

If a user lets go of the modifier (e.g. alt) before the 'normal' key (e.g.
tab) when window-cycling, we do not end the cycling until both keys have
been released.  If we end the window-cycling on release of the modifier
only, some XWayland clients such as hexchat realise that tab is pressed
(even though we did not forward the event) and because we absorb the
equivalent release event it gets stuck on repeat.

Just to clarify the position here: Issue #176 describes a behaviour
whereby dmenu gets stuck on repeat after being launched with a keybind.
This patch does not resolve that issue but reflects that in Wayland, the
client is responsible for implementing "key repeat".

Changing the key repeat rate/delay in (labwc/labwc@e62bb51) was dirty fix
that need should never have been made.
This commit is contained in:
Johan Malm 2022-08-30 15:47:00 +01:00
parent ffb2efe733
commit 20c4ffa539
3 changed files with 40 additions and 6 deletions

View file

@ -7,6 +7,8 @@
#include "labwc.h"
#include "workspaces.h"
static bool should_cancel_cycling_on_next_key_release;
static void
change_vt(struct server *server, unsigned int vt)
{
@ -33,6 +35,17 @@ keyboard_any_modifiers_pressed(struct wlr_keyboard *keyboard)
return false;
}
static void
end_cycling(struct server *server)
{
desktop_focus_and_activate_view(&server->seat, server->osd_state.cycle_view);
desktop_move_to_front(server->osd_state.cycle_view);
/* osd_finish() additionally resets cycle_view to NULL */
osd_finish(server);
should_cancel_cycling_on_next_key_release = false;
}
static void
keyboard_modifiers_notify(struct wl_listener *listener, void *data)
{
@ -46,12 +59,11 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data)
if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED
&& !keyboard_any_modifiers_pressed(keyboard)) {
if (server->osd_state.cycle_view) {
/* end cycle */
desktop_focus_and_activate_view(&server->seat,
server->osd_state.cycle_view);
desktop_move_to_front(server->osd_state.cycle_view);
/* osd_finish() additionally resets cycle_view to NULL */
osd_finish(server);
if (key_state_nr_keys()) {
should_cancel_cycling_on_next_key_release = true;
} else {
end_cycling(server);
}
}
if (seat->workspace_osd_shown_by_modifier) {
workspaces_osd_hide(seat);
@ -112,6 +124,21 @@ handle_compositor_keybindings(struct wl_listener *listener,
key_state_set_pressed(keycode,
event->state == WL_KEYBOARD_KEY_STATE_PRESSED);
/*
* If a user lets go of the modifier (e.g. alt) before the 'normal' key
* (e.g. tab) when window-cycling, we do not end the cycling until both
* keys have been released. If we end the window-cycling on release of
* the modifier only, some XWayland clients such as hexchat realise that
* tab is pressed (even though we did not forward the event) and because
* we absorb the equivalent release event it gets stuck on repeat.
*/
if (should_cancel_cycling_on_next_key_release
&& event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
end_cycling(server);
handled = true;
goto out;
}
/*
* If a press event was handled by a compositor binding, then do not
* forward the corresponding release event to clients