]> git.mdlowis.com Git - proto/labwc.git/commitdiff
src/keyboard.c: do not end window-cycling on modifier release only
authorJohan Malm <jgm323@gmail.com>
Tue, 30 Aug 2022 14:47:00 +0000 (15:47 +0100)
committerJohan Malm <jgm323@gmail.com>
Wed, 21 Sep 2022 20:25:13 +0000 (21:25 +0100)
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.

include/key-state.h
src/key-state.c
src/keyboard.c

index 1e7e5410c9edd0e7b14a5d8b57d5dc2b6ad19078..cfe9df9c52e83a790520673cc4e79e6fa5c15e0f 100644 (file)
@@ -6,5 +6,6 @@ void key_state_set_pressed(uint32_t keycode, bool ispressed);
 void key_state_store_pressed_keys_as_bound(void);
 bool key_state_corresponding_press_event_was_bound(uint32_t keycode);
 void key_state_bound_key_remove(uint32_t keycode);
+int key_state_nr_keys(void);
 
 #endif /* __LABWC_KEY_STATE_H */
index bc4844f6dcb6836fb9f83dde9ba5595b01832e8e..0c53cf9f56f89e9743923e5f1a4a349f88d8c4f3 100644 (file)
@@ -68,3 +68,9 @@ key_state_bound_key_remove(uint32_t keycode)
 {
        remove_key(&bound, keycode);
 }
+
+int
+key_state_nr_keys(void)
+{
+       return bound.nr_keys;
+}
index bdcb6c3138811d2dd3a8ccc7fbe03fe81cb227d9..ae68b8f5b6aa6fad06abc866e9487dad761167b4 100644 (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