Ignore KeyRelease events without KeyPress
Patch status: rejected
Patch by Ari Edelkind
Long description:
When switching modes, i3 completely reconfigures the key bindings. There's a bug, such that if a mode is set up with the likes of: mode "new" { bindsym --release $mykey mode "busted" } bindsym $mykey mode "new" then i3 would switch to mode "new" when $mykey is pressed, and then to "busted" when $mykey is released. This patch fixes the bug by ensuring that, before a KeyRelease event will be acknowledged, a key has been pressed since the key bindings have been reconfigured.
To apply this patch, use:
curl http://cr.i3wm.org/patch/530/raw.patch | git am
b/src/bindings.c
27 |
@@ -15,6 +15,12 @@ |
28 |
const char *DEFAULT_BINDING_MODE = "default"; |
29 |
|
30 |
/* |
31 |
+ * Whether a key has been pressed since reconfiguring keybindings |
32 |
+ * |
33 |
+ */ |
34 |
+static bool key_pressed_in_bind_config; |
35 |
+ |
36 |
+/* |
37 |
* Returns the mode specified by `name` or creates a new mode and adds it to |
38 |
* the list of modes. |
39 |
* |
40 |
@@ -104,6 +110,7 @@ static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint |
41 |
*/ |
42 |
void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch) { |
43 |
Binding *bind; |
44 |
+ key_pressed_in_bind_config = 0; |
45 |
TAILQ_FOREACH(bind, bindings, bindings) { |
46 |
if (bind->input_type != B_KEYBOARD || |
47 |
(bind_mode_switch && (bind->mods & BIND_MODE_SWITCH) == 0) || |
48 |
@@ -131,6 +138,7 @@ Binding *get_keyboard_binding(uint16_t modifiers, bool key_release, xcb_keycode_ |
49 |
Binding *bind; |
50 |
|
51 |
if (!key_release) { |
52 |
+ key_pressed_in_bind_config = 1; |
53 |
/* On a KeyPress event, we first reset all |
54 |
* B_UPON_KEYRELEASE_IGNORE_MODS bindings back to B_UPON_KEYRELEASE */ |
55 |
TAILQ_FOREACH(bind, bindings, bindings) { |
56 |
@@ -181,7 +189,21 @@ Binding *get_keyboard_binding(uint16_t modifiers, bool key_release, xcb_keycode_ |
57 |
break; |
58 |
} |
59 |
|
60 |
- return (bind == TAILQ_END(bindings) ? NULL : bind); |
61 |
+ if (bind == TAILQ_END(bindings)) |
62 |
+ return NULL; |
63 |
+ |
64 |
+ if (key_release) { |
65 |
+ /* If we see a KeyRelease event without a KeyPress event, that means |
66 |
+ * we've reconfigured our keybindings (e.g. switched modes), and a new |
67 |
+ * keybinding was created with the same key combination as the one that |
68 |
+ * triggered the change. */ |
69 |
+ if (!key_pressed_in_bind_config) { |
70 |
+ DLOG("Ignored KeyRelease for key not pressed in this binding configuration\n"); |
71 |
+ return NULL; |
72 |
+ } |
73 |
+ } |
74 |
+ |
75 |
+ return bind; |
76 |
} |
77 |
|
78 |
/* |