tests: implement sync_with_i3 and use it instead of sleep()

Also use open_standard_window() in a few more places where appropriate
This commit is contained in:
Michael Stapelberg 2011-09-23 20:37:45 +01:00
parent 3167e9ad2d
commit 38a9eabff1
27 changed files with 198 additions and 238 deletions

View File

@ -59,11 +59,9 @@ my $new_rect = $window->rect;
ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned");
$original_rect = $new_rect;
sleep 0.25;
$window->fullscreen(1);
sleep 0.25;
sync_with_i3($x);
$new_rect = $window->rect;
ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned after fullscreen");
@ -135,12 +133,12 @@ $new_rect = $swindow->rect;
ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned");
$swindow->fullscreen(1);
sleep 0.25;
sync_with_i3($x);
is(fullscreen_windows(), 1, 'amount of fullscreen windows');
$window->fullscreen(0);
sleep 0.25;
sync_with_i3($x);
is(fullscreen_windows(), 0, 'amount of fullscreen windows');
ok($swindow->mapped, 'window mapped after other fullscreen ended');
@ -152,7 +150,7 @@ ok($swindow->mapped, 'window mapped after other fullscreen ended');
###########################################################################
$swindow->fullscreen(0);
sleep 0.25;
sync_with_i3($x);
is(fullscreen_windows(), 0, 'amount of fullscreen windows after disabling');

View File

@ -2,11 +2,6 @@
# vim:ts=4:sw=4:expandtab
use i3test;
use X11::XCB qw(:all);
BEGIN {
use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection');
}
my $x = X11::XCB::Connection->new;
@ -18,16 +13,14 @@ fresh_workspace;
# Create a window so we can get a focus different from NULL
my $window = open_standard_window($x);
diag("window->id = " . $window->id);
sleep 0.25;
sync_with_i3($x);
my $focus = $x->input_focus;
diag("old focus = $focus");
# Switch to another workspace
fresh_workspace;
sync_with_i3($x);
my $new_focus = $x->input_focus;
isnt($focus, $new_focus, "Focus changed");

View File

@ -24,7 +24,7 @@ cmd 'split v';
my $top = open_standard_window($x);
my $mid = open_standard_window($x);
my $bottom = open_standard_window($x);
sleep 0.25;
##sleep 0.25;
diag("top id = " . $top->id);
diag("mid id = " . $mid->id);

View File

@ -4,11 +4,6 @@
# over an unfocused tiling client and destroying the floating one again.
use i3test;
use X11::XCB qw(:all);
BEGIN {
use_ok('X11::XCB::Window') or BAIL_OUT('Could not load X11::XCB::Window');
}
my $x = X11::XCB::Connection->new;
@ -19,30 +14,21 @@ cmd 'split h';
my $tiled_left = open_standard_window($x);
my $tiled_right = open_standard_window($x);
sleep 0.25;
sync_with_i3($x);
# Get input focus before creating the floating window
my $focus = $x->input_focus;
# Create a floating window which is smaller than the minimum enforced size of i3
my $window = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => [ 1, 1, 30, 30],
background_color => '#C0C0C0',
type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'),
);
my $window = open_standard_window($x, undef, 1);
sync_with_i3($x);
isa_ok($window, 'X11::XCB::Window');
$window->map;
sleep 1;
sleep 0.25;
is($x->input_focus, $window->id, 'floating window focused');
$window->unmap;
sleep 0.25;
# TODO: wait for unmap
sync_with_i3($x);
is($x->input_focus, $focus, 'Focus correctly restored');

View File

@ -27,9 +27,7 @@ $i3->command('9')->recv;
#####################################################################
my $top = i3test::open_standard_window($x);
sleep(0.25);
my $mid = i3test::open_standard_window($x);
sleep(0.25);
my $bottom = i3test::open_standard_window($x);
sleep(0.25);

View File

@ -21,11 +21,8 @@ cmd 'split h';
#####################################################################
my $top = open_standard_window($x);
sleep 0.25;
my $mid = open_standard_window($x);
sleep 0.25;
my $bottom = open_standard_window($x);
sleep 0.25;
diag("top id = " . $top->id);
diag("mid id = " . $mid->id);
@ -39,6 +36,7 @@ sub focus_after {
my $msg = shift;
cmd $msg;
sync_with_i3($x);
return $x->input_focus;
}

View File

@ -1,8 +1,5 @@
#!perl
# vim:ts=4:sw=4:expandtab
# Beware that this test uses workspace 9 to perform some tests (it expects
# the workspace to be empty).
# TODO: skip it by default?
use i3test;
use X11::XCB qw(:all);
@ -20,30 +17,22 @@ fresh_workspace;
#####################################################################
# Create a floating window
my $window = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => [ 0, 0, 30, 30],
background_color => '#C0C0C0',
# replace the type with 'utility' as soon as the coercion works again in X11::XCB
window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'),
);
isa_ok($window, 'X11::XCB::Window');
$window->map;
sleep 0.25;
my $window = open_standard_window($x, undef, 1);
# See if configurerequests cause window movements (they should not)
my ($a, $t) = $window->rect;
$window->rect(X11::XCB::Rect->new(x => $a->x, y => $a->y, width => $a->width, height => $a->height));
sleep 0.25;
sync_with_i3($x);
my ($na, $nt) = $window->rect;
is_deeply($na, $a, 'Rects are equal after configurerequest');
sub test_resize {
$window->rect(X11::XCB::Rect->new(x => 0, y => 0, width => 100, height => 100));
sync_with_i3($x);
my ($absolute, $top) = $window->rect;
# Make sure the width/height are different from what were gonna test, so
@ -52,7 +41,8 @@ sub test_resize {
isnt($absolute->height, 500, 'height != 500');
$window->rect(X11::XCB::Rect->new(x => 0, y => 0, width => 300, height => 500));
sleep 0.25;
sync_with_i3($x);
($absolute, $top) = $window->rect;

View File

@ -31,7 +31,7 @@ is(@urgent, 0, 'no window got the urgent flag');
# Add the urgency hint, switch to a different workspace and back again
#####################################################################
$top->add_hint('urgency');
sleep 0.5;
sync_with_i3($x);
@content = @{get_ws_content($tmp)};
@urgent = grep { $_->{urgent} } @content;
@ -48,7 +48,7 @@ cmd '[id="' . $top->id . '"] focus';
is(@urgent, 0, 'no window got the urgent flag after focusing');
$top->add_hint('urgency');
sleep 0.5;
sync_with_i3($x);
@urgent = grep { $_->{urgent} } @{get_ws_content($tmp)};
is(@urgent, 0, 'no window got the urgent flag after re-setting urgency hint');
@ -62,7 +62,7 @@ ok(!$ws->{urgent}, 'urgent flag not set on workspace');
my $otmp = fresh_workspace;
$top->add_hint('urgency');
sleep 0.5;
sync_with_i3($x);
$ws = get_ws($tmp);
ok($ws->{urgent}, 'urgent flag set on workspace');

View File

@ -12,20 +12,7 @@ ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
# Open a new window
my $x = X11::XCB::Connection->new;
my $window = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => [ 0, 0, 30, 30 ],
background_color => '#C0C0C0',
);
$window->map;
# give it some time to be picked up by the window manager
# TODO: better check for $window->mapped or something like that?
# maybe we can even wait for getting mapped?
my $c = 0;
while (@{get_ws_content($tmp)} == 0 and $c++ < 5) {
sleep 0.25;
}
my $window = open_standard_window($x);
my $content = get_ws_content($tmp);
ok(@{$content} == 1, 'window mapped');
my $win = $content->[0];
@ -114,7 +101,7 @@ ok(@{$content} == 2, 'two windows opened');
cmd '[class="special" title="left"] kill';
sleep 0.25;
sync_with_i3($x);
$content = get_ws_content($tmp);
is(@{$content}, 1, 'one window still there');

View File

@ -32,7 +32,7 @@ sleep 0.25;
$win->hints->aspect($aspect);
$x->flush;
sleep 0.25;
sync_with_i3($x);
my $rect = $win->rect;
my $ar = $rect->width / $rect->height;

View File

@ -16,6 +16,8 @@ my $tmp = fresh_workspace;
my $first = open_standard_window($x);
my $second = open_standard_window($x);
sync_with_i3($x);
is($x->input_focus, $second->id, 'second window focused');
cmd 'floating enable';
@ -34,12 +36,16 @@ $first = open_standard_window($x); # window 2
$second = open_standard_window($x); # window 3
my $third = open_standard_window($x); # window 4
sync_with_i3($x);
is($x->input_focus, $third->id, 'last container focused');
cmd 'floating enable';
cmd '[id="' . $second->id . '"] focus';
sync_with_i3($x);
is($x->input_focus, $second->id, 'second con focused');
cmd 'floating enable';
@ -47,7 +53,8 @@ cmd 'floating enable';
# now kill the third one (it's floating). focus should stay unchanged
cmd '[id="' . $third->id . '"] kill';
sleep 0.25;
# TODO: wait for unmapnotify
sync_with_i3($x);
is($x->input_focus, $second->id, 'second con still focused after killing third');
@ -63,12 +70,16 @@ $first = open_standard_window($x, '#ff0000'); # window 5
$second = open_standard_window($x, '#00ff00'); # window 6
my $third = open_standard_window($x, '#0000ff'); # window 7
sync_with_i3($x);
is($x->input_focus, $third->id, 'last container focused');
cmd 'floating enable';
cmd '[id="' . $second->id . '"] focus';
sync_with_i3($x);
is($x->input_focus, $second->id, 'second con focused');
cmd 'floating enable';
@ -77,13 +88,14 @@ cmd 'floating enable';
# also floating
cmd 'kill';
sleep 0.25;
# TODO: wait for unmapnotify
sync_with_i3($x);
is($x->input_focus, $third->id, 'third con focused');
cmd 'kill';
sleep 0.25;
# TODO: wait for unmapnotify
sync_with_i3($x);
is($x->input_focus, $first->id, 'first con focused after killing all floating cons');
@ -99,29 +111,34 @@ cmd 'layout stacked';
$second = open_standard_window($x, '#00ff00'); # window 6
$third = open_standard_window($x, '#0000ff'); # window 7
sync_with_i3($x);
is($x->input_focus, $third->id, 'last container focused');
cmd 'floating enable';
cmd '[id="' . $second->id . '"] focus';
sync_with_i3($x);
is($x->input_focus, $second->id, 'second con focused');
cmd 'floating enable';
sleep 0.5;
sync_with_i3($x);
# now kill the second one. focus should fall back to the third one, which is
# also floating
cmd 'kill';
sleep 0.25;
# TODO: wait for unmapnotify
sync_with_i3($x);
is($x->input_focus, $third->id, 'second con focused');
is($x->input_focus, $third->id, 'third con focused');
cmd 'kill';
sleep 0.25;
# TODO: wait for unmapnotify
sync_with_i3($x);
is($x->input_focus, $first->id, 'first con focused after killing all floating cons');
@ -134,6 +151,8 @@ $tmp = fresh_workspace;
$first = open_standard_window($x, '#ff0000'); # window 8
$second = open_standard_window($x, '#00ff00'); # window 9
sync_with_i3($x);
is($x->input_focus, $second->id, 'second container focused');
cmd 'floating enable';
@ -142,31 +161,31 @@ is($x->input_focus, $second->id, 'second container focused');
cmd 'focus tiling';
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $first->id, 'first (tiling) container focused');
cmd 'focus floating';
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $second->id, 'second (floating) container focused');
cmd 'focus floating';
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $second->id, 'second (floating) container still focused');
cmd 'focus mode_toggle';
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $first->id, 'first (tiling) container focused');
cmd 'focus mode_toggle';
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $second->id, 'second (floating) container focused');
@ -180,35 +199,37 @@ $first = open_standard_window($x, '#ff0000', 1); # window 10
$second = open_standard_window($x, '#00ff00', 1); # window 11
$third = open_standard_window($x, '#0000ff', 1); # window 12
sync_with_i3($x);
is($x->input_focus, $third->id, 'third container focused');
cmd 'focus left';
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $second->id, 'second container focused');
cmd 'focus left';
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $first->id, 'first container focused');
cmd 'focus left';
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $third->id, 'focus wrapped to third container');
cmd 'focus right';
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $first->id, 'focus wrapped to first container');
cmd 'focus right';
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $second->id, 'focus on second container');

View File

@ -22,20 +22,7 @@ ok(workspace_exists($tmp), "workspace $tmp exists");
my $x = X11::XCB::Connection->new;
# Create a floating window which is smaller than the minimum enforced size of i3
my $window = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => [ 0, 0, 30, 30],
background_color => '#C0C0C0',
# replace the type with 'utility' as soon as the coercion works again in X11::XCB
window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'),
);
isa_ok($window, 'X11::XCB::Window');
$window->map;
sleep 0.25;
my $window = open_standard_window($x, undef, 1);
ok($window->mapped, 'Window is mapped');
# switch to a different workspace, see if the window is still mapped?

View File

@ -21,27 +21,14 @@ my $tmp = fresh_workspace;
my $x = X11::XCB::Connection->new;
# Create a floating window which is smaller than the minimum enforced size of i3
my $window = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => [ 0, 0, 30, 30],
background_color => '#C0C0C0',
# replace the type with 'utility' as soon as the coercion works again in X11::XCB
window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'),
);
isa_ok($window, 'X11::XCB::Window');
$window->map;
sleep 0.25;
my $window = open_standard_window($x, undef, 1);
ok($window->mapped, 'Window is mapped');
# switch to a different workspace, see if the window is still mapped?
my $otmp = fresh_workspace;
sleep 0.25;
sync_with_i3($x);
ok(!$window->mapped, 'Window is not mapped after switching ws');

View File

@ -5,7 +5,6 @@
use i3test;
use X11::XCB qw(:all);
use Time::HiRes qw(sleep);
BEGIN {
use_ok('X11::XCB::Window');
@ -22,20 +21,7 @@ my $tmp = fresh_workspace;
my $x = X11::XCB::Connection->new;
# Create a floating window
my $window = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => [ 0, 0, 30, 30],
background_color => '#C0C0C0',
# replace the type with 'utility' as soon as the coercion works again in X11::XCB
window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'),
);
isa_ok($window, 'X11::XCB::Window');
$window->map;
sleep 0.25;
my $window = open_standard_window($x, undef, 1);
ok($window->mapped, 'Window is mapped');
my $ws = get_ws($tmp);
@ -45,17 +31,7 @@ is(@{$ws->{floating_nodes}}, 1, 'one floating node');
is(@{$nodes}, 0, 'no tiling nodes');
# Create a tiling window
my $twindow = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => [ 0, 0, 30, 30],
background_color => '#C0C0C0',
);
isa_ok($twindow, 'X11::XCB::Window');
$twindow->map;
sleep 0.25;
my $twindow = open_standard_window($x);
($nodes, $focus) = get_ws_content($tmp);
@ -78,20 +54,7 @@ is(@{$ws->{floating_nodes}}, 0, 'no floating nodes so far');
is(@{$ws->{nodes}}, 1, 'one tiling node (stacked con)');
# Create a floating window
my $window = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => [ 0, 0, 30, 30],
background_color => '#C0C0C0',
# replace the type with 'utility' as soon as the coercion works again in X11::XCB
window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'),
);
isa_ok($window, 'X11::XCB::Window');
$window->map;
sleep 0.25;
my $window = open_standard_window($x, undef, 1);
ok($window->mapped, 'Window is mapped');
$ws = get_ws($tmp);

View File

@ -4,7 +4,6 @@
# bug introduced by 77d0d42ed2d7ac8cafe267c92b35a81c1b9491eb
use i3test;
use X11::XCB qw(:all);
use Time::HiRes qw(sleep);
BEGIN {
use_ok('X11::XCB::Window');
@ -26,11 +25,10 @@ sub check_order {
my $tmp = fresh_workspace;
my $left = open_standard_window($x);
sleep 0.25;
my $mid = open_standard_window($x);
sleep 0.25;
my $right = open_standard_window($x);
sleep 0.25;
sync_with_i3($x);
diag("left = " . $left->id . ", mid = " . $mid->id . ", right = " . $right->id);

View File

@ -15,9 +15,9 @@ my $tmp = fresh_workspace;
cmd 'split v';
my $top = open_standard_window($x);
sleep 0.25;
my $bottom = open_standard_window($x);
sleep 0.25;
sync_with_i3($x);
diag("top = " . $top->id . ", bottom = " . $bottom->id);
@ -55,9 +55,7 @@ $tmp = fresh_workspace;
cmd 'split v';
$top = open_standard_window($x);
sleep 0.25;
$bottom = open_standard_window($x);
sleep 0.25;
cmd 'split h';
cmd 'layout stacked';
@ -79,7 +77,6 @@ is($nodes->[1]->{percent}, 0.75, 'bottom window got 75%');
$tmp = fresh_workspace;
$top = open_standard_window($x);
sleep 0.25;
cmd 'floating enable';

View File

@ -18,11 +18,8 @@ my $x = X11::XCB::Connection->new;
my $tmp = fresh_workspace;
my $left = open_standard_window($x);
sleep 0.25;
my $mid = open_standard_window($x);
sleep 0.25;
my $right = open_standard_window($x);
sleep 0.25;
cmd 'move before v';
cmd 'move after h';

View File

@ -2,7 +2,6 @@
# vim:ts=4:sw=4:expandtab
#
use X11::XCB qw(:all);
use Time::HiRes qw(sleep);
use i3test;
BEGIN {
@ -14,13 +13,10 @@ my $x = X11::XCB::Connection->new;
my $tmp = fresh_workspace;
my $left = open_standard_window($x);
sleep 0.25;
my $mid = open_standard_window($x);
sleep 0.25;
cmd 'split v';
my $bottom = open_standard_window($x);
sleep 0.25;
my ($nodes, $focus) = get_ws_content($tmp);
@ -31,20 +27,7 @@ my ($nodes, $focus) = get_ws_content($tmp);
my $x = X11::XCB::Connection->new;
# Create a floating window
my $window = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => [ 0, 0, 30, 30],
background_color => '#C0C0C0',
# replace the type with 'utility' as soon as the coercion works again in X11::XCB
window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'),
);
isa_ok($window, 'X11::XCB::Window');
$window->map;
sleep 0.25;
my $window = open_standard_window($x, undef, 1);
ok($window->mapped, 'Window is mapped');
($nodes, $focus) = get_ws_content($tmp);

View File

@ -17,11 +17,8 @@ my $x = X11::XCB::Connection->new;
my $tmp = fresh_workspace;
my $left = open_standard_window($x);
sleep 0.25;
my $mid = open_standard_window($x);
sleep 0.25;
my $right = open_standard_window($x);
sleep 0.25;
# go to workspace level
cmd 'level up';

View File

@ -17,20 +17,20 @@ my $tmp = fresh_workspace;
# open a tiling window on the first workspace
open_standard_window($x);
sleep 0.25;
#sleep 0.25;
my $first = get_focused($tmp);
# on a different ws, open a floating window
my $otmp = fresh_workspace;
open_standard_window($x);
sleep 0.25;
#sleep 0.25;
my $float = get_focused($otmp);
cmd 'mode toggle';
sleep 0.25;
#sleep 0.25;
# move the floating con to first workspace
cmd "move workspace $tmp";
sleep 0.25;
#sleep 0.25;
# switch to the first ws and check focus
is(get_focused($tmp), $float, 'floating client correctly focused');

View File

@ -30,7 +30,7 @@ cmp_ok($absolute->{width}, '>', 400, 'i3 raised the width');
cmp_ok($absolute->{height}, '>', 150, 'i3 raised the height');
cmd 'floating toggle';
sleep 0.25;
sync_with_i3($x);
($absolute, $top) = $window->rect;

View File

@ -56,7 +56,7 @@ cmd "move workspace $tmp2";
# verify that the third window has the focus
sleep 0.25;
sync_with_i3($x);
is($x->input_focus, $third->id, 'third window focused');

View File

@ -52,7 +52,7 @@ is($docknode->{rect}->{height}, 30, 'dock node has unchanged height');
$window->add_hint('urgency');
sleep 0.25;
sync_with_i3($x);
does_i3_live;

View File

@ -16,25 +16,18 @@ BEGIN {
my $x = X11::XCB::Connection->new;
my $window = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => [ 0, 0, 30, 30 ],
background_color => '#00ff00',
event_mask => [ 'structure_notify' ],
);
my $window = open_standard_window($x);
$window->name('Window 1');
$window->map;
sync_with_i3($x);
diag('window mapped');
sleep 0.5;
is($window->state, ICCCM_WM_STATE_NORMAL, 'WM_STATE normal');
$window->unmap;
sleep 0.5;
# TODO: wait for unmapnotify
sync_with_i3($x);
is($window->state, ICCCM_WM_STATE_WITHDRAWN, 'WM_STATE withdrawn');

View File

@ -30,6 +30,8 @@ ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
my $first = open_standard_window($x);
my $second = open_standard_window($x);
sync_with_i3($x);
is($x->input_focus, $second->id, 'second window focused');
ok(@{get_ws_content($tmp)} == 2, 'two containers opened');
isnt($content[0]->{layout}, 'stacked', 'layout not stacked');
@ -57,6 +59,8 @@ ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
$first = open_standard_window($x);
$second = open_standard_window($x);
sync_with_i3($x);
is($x->input_focus, $second->id, 'second window focused');
my @content = @{get_ws_content($tmp)};
ok(@content == 1, 'one con at workspace level');

View File

@ -73,6 +73,9 @@ cmd 'layout tabbed';
cmd 'focus parent';
$third = open_standard_window($x);
sync_with_i3($x);
is($x->input_focus, $third->id, 'third window focused');
cmd 'focus left';

View File

@ -40,6 +40,7 @@ our @EXPORT = qw(
my $tester = Test::Builder->new();
my $_cached_socket_path = undef;
my $_sync_window = undef;
my $tmp_socket_path = undef;
BEGIN {
@ -66,6 +67,44 @@ use warnings;
goto \&Exporter::import;
}
#
# Waits for the next event and calls the given callback for every event to
# determine if this is the event we are waiting for.
#
# Can be used to wait until a window is mapped, until a ClientMessage is
# received, etc.
#
# wait_for_event $x, 0.25, sub { $_[0]->{response_type} == MAP_NOTIFY };
#
sub wait_for_event {
my ($x, $timeout, $cb) = @_;
my $cv = AE::cv;
my $prep = EV::prepare sub {
$x->flush;
};
my $check = EV::check sub {
while (defined(my $event = $x->poll_for_event)) {
if ($cb->($event)) {
$cv->send(1);
last;
}
}
};
my $watcher = EV::io $x->get_file_descriptor, EV::READ, sub {
# do nothing, we only need this watcher so that EV picks up the events
};
# Trigger timeout after $timeout seconds (can be fractional)
my $timeout = AE::timer $timeout, 0, sub { say STDERR "timeout"; $cv->send(0) };
my $result = $cv->recv;
return $result;
}
sub open_standard_window {
my ($x, $color, $floating) = @_;
@ -88,29 +127,7 @@ sub open_standard_window {
$window->name('Window ' . counter_window());
$window->map;
# wait for the mapped event with a timeout of 0.25s
my $cv = AE::cv;
my $prep = EV::prepare sub {
$x->flush;
};
my $check = EV::check sub {
while (defined(my $event = $x->poll_for_event)) {
if ($event->{response_type} == MAP_NOTIFY) {
$cv->send(0)
}
}
};
my $watcher = EV::io $x->get_file_descriptor, EV::READ, sub {
# do nothing, we only need this watcher so that EV picks up the events
};
# Trigger timeout after 0.25s
my $timeout = AE::timer 0.5, 0, sub { say STDERR "timeout"; $cv->send(1) };
my $result = $cv->recv;
wait_for_event $x, 0.5, sub { $_[0]->{response_type} == MAP_NOTIFY };
return $window;
}
@ -239,6 +256,69 @@ sub focused_ws {
}
}
#
# Sends an I3_SYNC ClientMessage with a random value to the root window.
# i3 will reply with the same value, but, due to the order of events it
# processes, only after all other events are done.
#
# This can be used to ensure the results of a cmd 'focus left' are pushed to
# X11 and that $x->input_focus returns the correct value afterwards.
#
# See also docs/testsuite for a long explanation
#
sub sync_with_i3 {
my ($x) = @_;
# Since we need a (mapped) window for receiving a ClientMessage, we create
# one on the first call of sync_with_i3. It will be re-used in all
# subsequent calls.
if (!defined($_sync_window)) {
$_sync_window = $x->root->create_child(
class => WINDOW_CLASS_INPUT_OUTPUT,
rect => X11::XCB::Rect->new(x => -15, y => -15, width => 10, height => 10 ),
override_redirect => 1,
background_color => '#ff0000',
event_mask => [ 'structure_notify' ],
);
$_sync_window->map;
wait_for_event $x, 0.5, sub { $_[0]->{response_type} == MAP_NOTIFY };
}
my $root = $x->root->id;
# Generate a random number to identify this particular ClientMessage.
my $myrnd = int(rand(255)) + 1;
# Generate a ClientMessage, see xcb_client_message_t
my $msg = pack "CCSLLLLLLL",
CLIENT_MESSAGE, # response_type
32, # format
0, # sequence
$root, # destination window
$x->atom(name => 'I3_SYNC')->id,
$_sync_window->id, # data[0]: our own window id
$myrnd, # data[1]: a random value to identify the request
0,
0,
0;
# Send it to the root window -- since i3 uses the SubstructureRedirect
# event mask, it will get the ClientMessage.
$x->send_event(0, $root, EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg);
# now wait until the reply is here
return wait_for_event $x, 1, sub {
my ($event) = @_;
# TODO: const
return 0 unless $event->{response_type} == 161;
my ($win, $rnd) = unpack "LL", $event->{data};
return ($rnd == $myrnd);
};
}
sub does_i3_live {
my $tree = i3(get_socket_path())->get_tree->recv;
my @nodes = @{$tree->{nodes}};