Skip to content

Commit

Permalink
Regrab buttons on mode change (#5554)
Browse files Browse the repository at this point in the history
Unfortunately, grabbing / ungrabbing doesn't seem to work correctly in
xvfb so we can't really test this.

I also fixed the deduplication code in bindings_get_buttons_to_grab().
  • Loading branch information
orestisfl committed Jun 30, 2023
1 parent 866e3dd commit e6b4117
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 4 deletions.
1 change: 1 addition & 0 deletions release-notes/bugfixes/3-bindsym-button-mode
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fix mouse bindings in modes
14 changes: 10 additions & 4 deletions src/bindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ void switch_mode(const char *new_mode) {
current_binding_mode = mode->name;
translate_keysyms();
grab_all_keys(conn);
regrab_all_buttons(conn);

/* Reset all B_UPON_KEYRELEASE_IGNORE_MODS bindings to avoid possibly
* activating one of them. */
Expand Down Expand Up @@ -1008,7 +1009,7 @@ bool load_keymap(void) {
int *bindings_get_buttons_to_grab(void) {
/* Let's make the reasonable assumption that there's no more than 25
* buttons. */
int num_max = 25;
const int num_max = 25;

int buffer[num_max];
int num = 0;
Expand All @@ -1034,12 +1035,17 @@ int *bindings_get_buttons_to_grab(void) {
}

/* Avoid duplicates. */
bool exists = false;
for (int i = 0; i < num; i++) {
if (buffer[i] == button)
continue;
if (buffer[i] == button) {
exists = true;
break;
}
}

buffer[num++] = button;
if (!exists) {
buffer[num++] = button;
}
}
buffer[num++] = 0;

Expand Down
89 changes: 89 additions & 0 deletions testcases/t/320-mouse-bindings.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!perl
# vim:ts=4:sw=4:expandtab
#
# Please read the following documents before working on tests:
# • https://build.i3wm.org/docs/testsuite.html
# (or docs/testsuite)
#
# • https://build.i3wm.org/docs/lib-i3test.html
# (alternatively: perldoc ./testcases/lib/i3test.pm)
#
# • https://build.i3wm.org/docs/ipc.html
# (or docs/ipc)
#
# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
# (unless you are already familiar with Perl)
#
# Test button bindsyms
use i3test i3_config => <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
focus_follows_mouse no
for_window[class="mark_A"] mark A
for_window[class="mark_B"] mark B
for_window[class="mark_C"] mark C
for_window[class="mark_D"] mark D
bindsym button1 --whole-window [con_mark=A] focus
bindsym button2 --whole-window [con_mark=B] focus
bindsym button4 --whole-window [con_mark=B] focus
mode "testmode" {
bindsym button4 --whole-window [con_mark=C] focus
bindsym button5 --whole-window [con_mark=D] focus
}
default_border pixel 0
EOT
use i3test::XTEST;

sub button {
my ($button, $window, $msg) = @_;
xtest_button_press($button, 5, 5);
xtest_button_release($button, 5, 5);
xtest_sync_with_i3;

local $Test::Builder::Level = $Test::Builder::Level + 1;
is_focus($window, $msg);
}

sub is_focus {
my ($window, $msg) = @_;
local $Test::Builder::Level = $Test::Builder::Level + 1;
is($x->input_focus, $window->id, $msg);
}

# Leftmost window is focused on button presses that have no binding
my $L = open_window;
my $A = open_window(wm_class => 'mark_A');
my $B = open_window(wm_class => 'mark_B');
is_focus($B, 'sanity check');
is_focus(open_window, 'sanity check, other window');

button(1, $A, 'button 1 binding');
button(1, $A, 'button 1 binding, again');
button(2, $B, 'button 2 binding');
button(1, $A, 'button 1 binding');
button(3, $L, 'button 3, no binding');

# Test modes, see #4539
# Unfortunately, grabbing / ungrabbing doesn't seem to work correctly in xvfb
# so we can't really test this.

my $C = open_window(wm_class => 'mark_C');
my $D = open_window(wm_class => 'mark_D');

button(4, $B, 'button 4 binding outside mode');
button(5, $L, 'button 5 no binding outside mode');

cmd 'mode testmode';
button(4, $C, 'button 4 binding inside mode');
button(5, $D, 'button 5 binding inside mode');

cmd 'mode default';
button(4, $B, 'button 4 binding outside mode');
button(5, $L, 'button 5 no binding outside mode');

done_testing;

0 comments on commit e6b4117

Please sign in to comment.