]> git.sur5r.net Git - i3/i3/commitdiff
Reset B_UPON_KEYRELEASE_IGNORE_MODS bindings when switching modes 3179/head
authorOrestis Floros <orestisf1993@gmail.com>
Mon, 19 Mar 2018 23:44:50 +0000 (01:44 +0200)
committerOrestis Floros <orestisf1993@gmail.com>
Tue, 20 Mar 2018 02:09:34 +0000 (04:09 +0200)
With example config:
    mode "a_mode" {
        bindcode 27 --release mode "default"
    }
    bindsym $mod+r mode "a_mode"

The first time $mod+r is pressed "a_mode" is activated like normal. When
r (bindcode 27) is pressed to exit the mode:
- On the KeyPress event the corresponding bind->release is correctly
marked as B_UPON_KEYRELEASE_IGNORE_MODS.
- On the KeyRelease event the command 'mode "default"' is executed but
bind->release is still B_UPON_KEYRELEASE_IGNORE_MODS since they are only
reset on KeyPress events.
The second time $mod+r is pressed and "a_mode" is activated and when the
r key is released the 'mode "default"' is executed even though the mods
are not matching since bind->release == B_UPON_KEYRELEASE_IGNORE_MODS.

This still doesn't catch 2 cases:
1. When the order is: press $mod -> press r -> release $mod -> release
    r. Since 'r' is released without any modifiers the binding matches.
2. With:
        mode "resize" {
            bindsym --release r mode "default"
        }
        bindsym r mode "resize"
    This is arguably correct: on the KeyPress event we switch to the mode and
    on the KeyRelease we switch back.

src/bindings.c
testcases/t/258-keypress-release.t

index 38002396b42232eea640024e2b0f9fbafe844db7..228f7a9dcf064e94275c60245f78c0a2dbd4c228 100644 (file)
@@ -649,6 +649,14 @@ void switch_mode(const char *new_mode) {
         translate_keysyms();
         grab_all_keys(conn);
 
+        /* Reset all B_UPON_KEYRELEASE_IGNORE_MODS bindings to avoid possibly
+         * activating one of them. */
+        Binding *bind;
+        TAILQ_FOREACH(bind, bindings, bindings) {
+            if (bind->release == B_UPON_KEYRELEASE_IGNORE_MODS)
+                bind->release = B_UPON_KEYRELEASE;
+        }
+
         char *event_msg;
         sasprintf(&event_msg, "{\"change\":\"%s\", \"pango_markup\":%s}",
                   mode->name, (mode->pango_markup ? "true" : "false"));
index 766a8a1bec870ca53945c556aac3499497831bb0..614164abf89cb381b82994c8252fb9f5d5e846c7 100644 (file)
@@ -36,6 +36,13 @@ bindsym --release Shift+x nop Shift+x
 # 133 == Mod4
 bindcode 133 nop 133
 bindcode --release 133 nop 133 release
+
+mode "a_mode" {
+    # 27 == r
+    bindcode 27 --release mode "default"
+}
+bindsym Mod1+r mode "a_mode"
+bindcode 27 nop do not receive
 EOT
 use i3test::XTEST;
 use ExtUtils::PkgConfig;
@@ -134,6 +141,30 @@ is(listen_for_binding(
     '133 release',
     'triggered the 133 keycode release binding');
 
+for my $i (1 .. 2) {
+    is(listen_for_binding(
+        sub {
+            xtest_key_press(64); # Alt_l
+            xtest_key_press(27); # r
+            xtest_key_release(27); # r
+            xtest_key_release(64); # Alt_l
+            xtest_sync_with_i3;
+        },
+        ),
+        'mode "a_mode"',
+        "switched to mode \"a_mode\" $i/2");
+
+    is(listen_for_binding(
+        sub {
+            xtest_key_press(27); # r
+            xtest_key_release(27); # r
+            xtest_sync_with_i3;
+        },
+        ),
+        'mode "default"',
+        "switched back to default $i/2");
+}
+
 }
 
 done_testing;