X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=testcases%2Flib%2Fi3test.pm.in;h=68ac1ee569827edbef609ff00c1f388d1a7a8d9b;hb=9f273f3356dc5c6094a2d5ee2f14f56364c382e2;hp=ed239241c84dadba0412c3609701d6cf957c5505;hpb=01029da8402c3c3f5115e0f75856a9dbafbf2f3d;p=i3%2Fi3 diff --git a/testcases/lib/i3test.pm.in b/testcases/lib/i3test.pm.in index ed239241..68ac1ee5 100644 --- a/testcases/lib/i3test.pm.in +++ b/testcases/lib/i3test.pm.in @@ -12,6 +12,7 @@ use AnyEvent::I3; use List::Util qw(first); use Time::HiRes qw(sleep); use Cwd qw(abs_path); +use POSIX ':sys_wait_h'; use Scalar::Util qw(blessed); use SocketActivation; use i3test::Util qw(slurp); @@ -37,6 +38,7 @@ our @EXPORT = qw( cmd sync_with_i3 exit_gracefully + exit_forcefully workspace_exists focused_ws get_socket_path @@ -49,6 +51,7 @@ our @EXPORT = qw( kill_all_windows events_for listen_for_binding + is_net_wm_state_focused ); =head1 NAME @@ -123,7 +126,7 @@ END { } else { kill(-9, $i3_pid) - or $tester->BAIL_OUT("could not kill i3"); + or $tester->BAIL_OUT("could not kill i3: $!"); waitpid $i3_pid, 0; } @@ -759,7 +762,7 @@ sub exit_gracefully { if (!$exited) { kill(9, $pid) - or $tester->BAIL_OUT("could not kill i3"); + or $tester->BAIL_OUT("could not kill i3: $!"); } if ($socketpath =~ m,^/tmp/i3-test-socket-,) { @@ -770,6 +773,47 @@ sub exit_gracefully { undef $i3_pid; } +=head2 exit_forcefully($pid, [ $signal ]) + +Tries to exit i3 forcefully by sending a signal (defaults to SIGTERM). + +You only need to use this function if you want to test signal handling +(in which case you must have launched i3 on your own with +C). + + use i3test i3_autostart => 0; + my $pid = launch_with_config($config); + # … + exit_forcefully($pid); + +=cut +sub exit_forcefully { + my ($pid, $signal) = @_; + $signal ||= 'TERM'; + + # Send the given signal to the i3 instance and wait for up to 10s + # for it to terminate. + kill($signal, $pid) + or $tester->BAIL_OUT("could not kill i3: $!"); + my $status; + my $timeout = 10; + do { + $status = waitpid $pid, WNOHANG; + + if ($status <= 0) { + sleep(1); + $timeout--; + } + } while ($status <= 0 && $timeout > 0); + + if ($status <= 0) { + kill('KILL', $pid) + or $tester->BAIL_OUT("could not kill i3: $!"); + waitpid $pid, 0; + } + undef $i3_pid; +} + =head2 get_socket_path([ $cache ]) Gets the socket path from the C atom stored on the X11 root @@ -983,6 +1027,40 @@ sub listen_for_binding { return $command; } +=head2 is_net_wm_state_focused + +Returns true if the given window has the _NET_WM_STATE_FOCUSED atom. + + ok(is_net_wm_state_focused($window), '_NET_WM_STATE_FOCUSED set'); + +=cut +sub is_net_wm_state_focused { + my ($window) = @_; + + sync_with_i3; + my $atom = $x->atom(name => '_NET_WM_STATE_FOCUSED'); + my $cookie = $x->get_property( + 0, + $window->{id}, + $x->atom(name => '_NET_WM_STATE')->id, + GET_PROPERTY_TYPE_ANY, + 0, + 4096 + ); + + my $reply = $x->get_property_reply($cookie->{sequence}); + my $len = $reply->{length}; + return 0 if $len == 0; + + my @atoms = unpack("L$len", $reply->{value}); + for (my $i = 0; $i < $len; $i++) { + return 1 if $atoms[$i] == $atom->id; + } + + return 0; +} + + =head1 AUTHOR Michael Stapelberg