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.
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"));
# 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;
'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;