Implement the tick event
This makes our tests less flaky, shorter, and more readable. fixes #2988
This commit is contained in:
@ -47,6 +47,8 @@ our @EXPORT = qw(
|
||||
wait_for_unmap
|
||||
$x
|
||||
kill_all_windows
|
||||
events_for
|
||||
listen_for_binding
|
||||
);
|
||||
|
||||
=head1 NAME
|
||||
@ -900,6 +902,86 @@ sub kill_all_windows {
|
||||
cmd '[title=".*"] kill';
|
||||
}
|
||||
|
||||
=head2 events_for($subscribecb, [ $rettype ], [ $eventcbs ])
|
||||
|
||||
Helper function which returns an array containing all events of type $rettype
|
||||
which were generated by i3 while $subscribecb was running.
|
||||
|
||||
Set $eventcbs to subscribe to multiple event types and/or perform your own event
|
||||
aggregation.
|
||||
|
||||
=cut
|
||||
sub events_for {
|
||||
my ($subscribecb, $rettype, $eventcbs) = @_;
|
||||
|
||||
my @events;
|
||||
$eventcbs //= {};
|
||||
if (defined($rettype)) {
|
||||
$eventcbs->{$rettype} = sub { push @events, shift };
|
||||
}
|
||||
my $subscribed = AnyEvent->condvar;
|
||||
my $flushed = AnyEvent->condvar;
|
||||
$eventcbs->{tick} = sub {
|
||||
my ($event) = @_;
|
||||
if ($event->{first}) {
|
||||
$subscribed->send($event);
|
||||
} else {
|
||||
$flushed->send($event);
|
||||
}
|
||||
};
|
||||
my $i3 = i3(get_socket_path(0));
|
||||
$i3->connect->recv;
|
||||
$i3->subscribe($eventcbs)->recv;
|
||||
$subscribed->recv;
|
||||
# Subscription established, run the callback.
|
||||
$subscribecb->();
|
||||
# Now generate a tick event, which we know we’ll receive (and at which point
|
||||
# all other events have been received).
|
||||
my $nonce = int(rand(255)) + 1;
|
||||
$i3->send_tick($nonce);
|
||||
|
||||
my $tick = $flushed->recv;
|
||||
$tester->is_eq($tick->{payload}, $nonce, 'tick nonce received');
|
||||
return @events;
|
||||
}
|
||||
|
||||
=head2 listen_for_binding($cb)
|
||||
|
||||
Helper function to evaluate whether sending KeyPress/KeyRelease events via XTEST
|
||||
triggers an i3 key binding or not. Expects key bindings to be configured in the
|
||||
form “bindsym <binding> nop <binding>”, e.g. “bindsym Mod4+Return nop
|
||||
Mod4+Return”.
|
||||
|
||||
is(listen_for_binding(
|
||||
sub {
|
||||
xtest_key_press(133); # Super_L
|
||||
xtest_key_press(36); # Return
|
||||
xtest_key_release(36); # Return
|
||||
xtest_key_release(133); # Super_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Mod4+Return',
|
||||
'triggered the "Mod4+Return" keybinding');
|
||||
|
||||
=cut
|
||||
|
||||
sub listen_for_binding {
|
||||
my ($cb) = @_;
|
||||
my $triggered = AnyEvent->condvar;
|
||||
my @events = events_for(
|
||||
$cb,
|
||||
'binding');
|
||||
|
||||
$tester->is_eq(scalar @events, 1, 'Received precisely one event');
|
||||
$tester->is_eq($events[0]->{change}, 'run', 'change is "run"');
|
||||
# We look at the command (which is “nop <binding>”) because that is easier
|
||||
# than re-assembling the string representation of $event->{binding}.
|
||||
my $command = $events[0]->{binding}->{command};
|
||||
$command =~ s/^nop //g;
|
||||
return $command;
|
||||
}
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael Stapelberg <michael@i3wm.org>
|
||||
|
Reference in New Issue
Block a user