From: Michael Stapelberg Date: Sat, 8 Oct 2011 13:38:50 +0000 (+0100) Subject: tests: rename files (00x-*.t is basic stuff, >=100-*.t are tests using IPC) X-Git-Tag: 4.1~117 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=ae1ab9eb273cd2e75f834500d7386d81a925f753;p=i3%2Fi3 tests: rename files (00x-*.t is basic stuff, >=100-*.t are tests using IPC) --- diff --git a/testcases/t/00-load.t b/testcases/t/00-load.t deleted file mode 100644 index 5dfc5c69..00000000 --- a/testcases/t/00-load.t +++ /dev/null @@ -1,10 +0,0 @@ -#!perl - -use Test::More tests => 2; - -BEGIN { - use_ok( 'X11::XCB::Connection' ); - use_ok( 'X11::XCB::Window' ); -} - -diag( "Testing i3, Perl $], $^X" ); diff --git a/testcases/t/000-load-deps.t b/testcases/t/000-load-deps.t new file mode 100644 index 00000000..5dfc5c69 --- /dev/null +++ b/testcases/t/000-load-deps.t @@ -0,0 +1,10 @@ +#!perl + +use Test::More tests => 2; + +BEGIN { + use_ok( 'X11::XCB::Connection' ); + use_ok( 'X11::XCB::Window' ); +} + +diag( "Testing i3, Perl $], $^X" ); diff --git a/testcases/t/001-tile.t b/testcases/t/001-tile.t new file mode 100644 index 00000000..0db3b83b --- /dev/null +++ b/testcases/t/001-tile.t @@ -0,0 +1,32 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; +use X11::XCB qw(:all); + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +my $original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); + +my $window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => $original_rect, + background_color => '#C0C0C0', +); + +isa_ok($window, 'X11::XCB::Window'); + +is_deeply($window->rect, $original_rect, "rect unmodified before mapping"); + +$window->map; + +sleep(0.25); + +my $new_rect = $window->rect; +ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned"); + +done_testing; diff --git a/testcases/t/002-i3-sync.t b/testcases/t/002-i3-sync.t new file mode 100644 index 00000000..7518c949 --- /dev/null +++ b/testcases/t/002-i3-sync.t @@ -0,0 +1,15 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# checks if i3 supports I3_SYNC +# +use X11::XCB qw(:all); +use X11::XCB::Connection; +use i3test; + +my $x = X11::XCB::Connection->new; + +my $result = sync_with_i3($x); +ok($result, 'syncing was successful'); + +done_testing; diff --git a/testcases/t/003-ipc.t b/testcases/t/003-ipc.t new file mode 100644 index 00000000..982ece7e --- /dev/null +++ b/testcases/t/003-ipc.t @@ -0,0 +1,26 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; + +my $x = X11::XCB::Connection->new; + +fresh_workspace; + +##################################################################### +# Ensure IPC works by switching workspaces +##################################################################### + +# Create a window so we can get a focus different from NULL +my $window = open_window($x); + +my $focus = $x->input_focus; + +# Switch to another workspace +fresh_workspace; + +sync_with_i3($x); +my $new_focus = $x->input_focus; +isnt($focus, $new_focus, "Focus changed"); + +done_testing; diff --git a/testcases/t/004-unmanaged.t b/testcases/t/004-unmanaged.t new file mode 100644 index 00000000..1ef934ee --- /dev/null +++ b/testcases/t/004-unmanaged.t @@ -0,0 +1,33 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; +use X11::XCB qw(:all); + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +my $original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); + +my $window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => $original_rect, + override_redirect => 1, + background_color => '#C0C0C0', +); + +isa_ok($window, 'X11::XCB::Window'); + +is_deeply($window->rect, $original_rect, "rect unmodified before mapping"); + +$window->map; + +my $new_rect = $window->rect; +isa_ok($new_rect, 'X11::XCB::Rect'); + +is_deeply($new_rect, $original_rect, "window untouched"); + +done_testing; diff --git a/testcases/t/005-floating.t b/testcases/t/005-floating.t new file mode 100644 index 00000000..d605328d --- /dev/null +++ b/testcases/t/005-floating.t @@ -0,0 +1,93 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; +use X11::XCB qw(:all); + +BEGIN { + use_ok('X11::XCB::Window'); +} + +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'), + event_mask => [ 'structure_notify' ], +); + +isa_ok($window, 'X11::XCB::Window'); + +$window->map; + +wait_for_map $x; + +my ($absolute, $top) = $window->rect; + +ok($window->mapped, 'Window is mapped'); +cmp_ok($absolute->{width}, '>=', 75, 'i3 raised the width to 75'); +cmp_ok($absolute->{height}, '>=', 50, 'i3 raised the height to 50'); + +ok($absolute->{x} != 0 && $absolute->{y} != 0, 'i3 did not map it to (0x0)'); + +$window->unmap; + +$window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 1, 1, 80, 90], + background_color => '#C0C0C0', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'), + event_mask => [ 'structure_notify' ], +); + +isa_ok($window, 'X11::XCB::Window'); + +$window->map; + +wait_for_map $x; + +($absolute, $top) = $window->rect; + +cmp_ok($absolute->{width}, '==', 80, "i3 let the width at 80"); +cmp_ok($absolute->{height}, '==', 90, "i3 let the height at 90"); + +# We need to compare the position with decorations due to the way +# we do decoration rendering (on the parent frame) in the tree branch +cmp_ok($top->{x}, '==', 1, 'i3 mapped it to x=1'); +cmp_ok($top->{y}, '==', 19, 'i3 mapped it to y=18'); + +$window->unmap; + +##################################################################### +# check that a tiling window which is then made floating still has +# at least the size of its initial geometry +##################################################################### + +$window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 1, 1, 80, 90], + background_color => '#C0C0C0', + #window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'), + event_mask => [ 'structure_notify' ], +); + +isa_ok($window, 'X11::XCB::Window'); + +$window->map; + +wait_for_map $x; + +cmd 'floating enable'; + +($absolute, $top) = $window->rect; + +cmp_ok($absolute->{width}, '==', 80, "i3 let the width at 80"); +cmp_ok($absolute->{height}, '==', 90, "i3 let the height at 90"); + +$window->unmap; + +done_testing; diff --git a/testcases/t/01-tile.t b/testcases/t/01-tile.t deleted file mode 100644 index 0db3b83b..00000000 --- a/testcases/t/01-tile.t +++ /dev/null @@ -1,32 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; -use X11::XCB qw(:all); - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -my $original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); - -my $window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => $original_rect, - background_color => '#C0C0C0', -); - -isa_ok($window, 'X11::XCB::Window'); - -is_deeply($window->rect, $original_rect, "rect unmodified before mapping"); - -$window->map; - -sleep(0.25); - -my $new_rect = $window->rect; -ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned"); - -done_testing; diff --git a/testcases/t/02-fullscreen.t b/testcases/t/02-fullscreen.t deleted file mode 100644 index ae8c63f6..00000000 --- a/testcases/t/02-fullscreen.t +++ /dev/null @@ -1,172 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; -use X11::XCB qw(:all); -use List::Util qw(first); - -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -sub fullscreen_windows { - scalar grep { $_->{fullscreen_mode} != 0 } @{get_ws_content($tmp)} -} - -# get the output of this workspace -my $tree = $i3->get_tree->recv; -my @outputs = @{$tree->{nodes}}; -my $output; -for my $o (@outputs) { - # get the first CT_CON of each output - my $content = first { $_->{type} == 2 } @{$o->{nodes}}; - if (defined(first { $_->{name} eq $tmp } @{$content->{nodes}})) { - $output = $o; - last; - } -} - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -################################## -# map a window, then fullscreen it -################################## - -my $original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); - -my $window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => $original_rect, - background_color => '#C0C0C0', - event_mask => [ 'structure_notify' ], -); - -isa_ok($window, 'X11::XCB::Window'); - -is_deeply($window->rect, $original_rect, "rect unmodified before mapping"); - -$window->map; - -wait_for_map $x; - -# open another container to make the window get only half of the screen -cmd 'open'; - -my $new_rect = $window->rect; -ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned"); -$original_rect = $new_rect; - -$window->fullscreen(1); - -sync_with_i3($x); - -$new_rect = $window->rect; -ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned after fullscreen"); - -my $orect = $output->{rect}; -my $wrect = $new_rect; - -# see if the window really is fullscreen. 20 px for borders are allowed -my $threshold = 20; -ok(($wrect->{x} - $orect->{x}) < $threshold, 'x coordinate fullscreen'); -ok(($wrect->{y} - $orect->{y}) < $threshold, 'y coordinate fullscreen'); -ok(abs($wrect->{width} - $orect->{width}) < $threshold, 'width coordinate fullscreen'); -ok(abs($wrect->{height} - $orect->{height}) < $threshold, 'height coordinate fullscreen'); - - -$window->unmap; - -######################################################### -# test with a window which is fullscreened before mapping -######################################################### - -# open another container because the empty one will swallow the window we -# map in a second -cmd 'open'; - -$original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); -$window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => $original_rect, - background_color => 61440, - event_mask => [ 'structure_notify' ], -); - -is_deeply($window->rect, $original_rect, "rect unmodified before mapping"); - -$window->fullscreen(1); -$window->map; - -wait_for_map $x; - -$new_rect = $window->rect; -ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned after fullscreen"); -ok($window->mapped, "Window is mapped after opening it in fullscreen mode"); - -$wrect = $new_rect; - -# see if the window really is fullscreen. 20 px for borders are allowed -ok(($wrect->{x} - $orect->{x}) < $threshold, 'x coordinate fullscreen'); -ok(($wrect->{y} - $orect->{y}) < $threshold, 'y coordinate fullscreen'); -ok(abs($wrect->{width} - $orect->{width}) < $threshold, 'width coordinate fullscreen'); -ok(abs($wrect->{height} - $orect->{height}) < $threshold, 'height coordinate fullscreen'); - -############################################################################### -# test if setting two windows in fullscreen mode at the same time does not work -############################################################################### - -$original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); -my $swindow = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => $original_rect, - background_color => '#C0C0C0', - event_mask => [ 'structure_notify' ], -); - -$swindow->map; - -sync_with_i3($x); - -ok(!$swindow->mapped, 'window not mapped while fullscreen window active'); - -$new_rect = $swindow->rect; -ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned"); - -$swindow->fullscreen(1); -sync_with_i3($x); - -is(fullscreen_windows(), 1, 'amount of fullscreen windows'); - -$window->fullscreen(0); -sync_with_i3($x); -is(fullscreen_windows(), 0, 'amount of fullscreen windows'); - -ok($swindow->mapped, 'window mapped after other fullscreen ended'); - -########################################################################### -# as $swindow is out of state at the moment (it requested to be fullscreen, -# but the WM denied), we check what happens if we go out of fullscreen now -# (nothing should happen) -########################################################################### - -$swindow->fullscreen(0); -sync_with_i3($x); - -is(fullscreen_windows(), 0, 'amount of fullscreen windows after disabling'); - -cmd 'fullscreen'; - -is(fullscreen_windows(), 1, 'amount of fullscreen windows after fullscreen command'); - -cmd 'fullscreen'; - -is(fullscreen_windows(), 0, 'amount of fullscreen windows after fullscreen command'); - -# clean up the workspace so that it will be cleaned when switching away -cmd 'kill' for (@{get_ws_content($tmp)}); - -done_testing; diff --git a/testcases/t/03-unmanaged.t b/testcases/t/03-unmanaged.t deleted file mode 100644 index 1ef934ee..00000000 --- a/testcases/t/03-unmanaged.t +++ /dev/null @@ -1,33 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; -use X11::XCB qw(:all); - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -my $original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); - -my $window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => $original_rect, - override_redirect => 1, - background_color => '#C0C0C0', -); - -isa_ok($window, 'X11::XCB::Window'); - -is_deeply($window->rect, $original_rect, "rect unmodified before mapping"); - -$window->map; - -my $new_rect = $window->rect; -isa_ok($new_rect, 'X11::XCB::Rect'); - -is_deeply($new_rect, $original_rect, "window untouched"); - -done_testing; diff --git a/testcases/t/04-floating.t b/testcases/t/04-floating.t deleted file mode 100644 index d605328d..00000000 --- a/testcases/t/04-floating.t +++ /dev/null @@ -1,93 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; -use X11::XCB qw(:all); - -BEGIN { - use_ok('X11::XCB::Window'); -} - -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'), - event_mask => [ 'structure_notify' ], -); - -isa_ok($window, 'X11::XCB::Window'); - -$window->map; - -wait_for_map $x; - -my ($absolute, $top) = $window->rect; - -ok($window->mapped, 'Window is mapped'); -cmp_ok($absolute->{width}, '>=', 75, 'i3 raised the width to 75'); -cmp_ok($absolute->{height}, '>=', 50, 'i3 raised the height to 50'); - -ok($absolute->{x} != 0 && $absolute->{y} != 0, 'i3 did not map it to (0x0)'); - -$window->unmap; - -$window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 1, 1, 80, 90], - background_color => '#C0C0C0', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'), - event_mask => [ 'structure_notify' ], -); - -isa_ok($window, 'X11::XCB::Window'); - -$window->map; - -wait_for_map $x; - -($absolute, $top) = $window->rect; - -cmp_ok($absolute->{width}, '==', 80, "i3 let the width at 80"); -cmp_ok($absolute->{height}, '==', 90, "i3 let the height at 90"); - -# We need to compare the position with decorations due to the way -# we do decoration rendering (on the parent frame) in the tree branch -cmp_ok($top->{x}, '==', 1, 'i3 mapped it to x=1'); -cmp_ok($top->{y}, '==', 19, 'i3 mapped it to y=18'); - -$window->unmap; - -##################################################################### -# check that a tiling window which is then made floating still has -# at least the size of its initial geometry -##################################################################### - -$window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 1, 1, 80, 90], - background_color => '#C0C0C0', - #window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'), - event_mask => [ 'structure_notify' ], -); - -isa_ok($window, 'X11::XCB::Window'); - -$window->map; - -wait_for_map $x; - -cmd 'floating enable'; - -($absolute, $top) = $window->rect; - -cmp_ok($absolute->{width}, '==', 80, "i3 let the width at 80"); -cmp_ok($absolute->{height}, '==', 90, "i3 let the height at 90"); - -$window->unmap; - -done_testing; diff --git a/testcases/t/05-ipc.t b/testcases/t/05-ipc.t deleted file mode 100644 index 982ece7e..00000000 --- a/testcases/t/05-ipc.t +++ /dev/null @@ -1,26 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; - -my $x = X11::XCB::Connection->new; - -fresh_workspace; - -##################################################################### -# Ensure IPC works by switching workspaces -##################################################################### - -# Create a window so we can get a focus different from NULL -my $window = open_window($x); - -my $focus = $x->input_focus; - -# Switch to another workspace -fresh_workspace; - -sync_with_i3($x); -my $new_focus = $x->input_focus; -isnt($focus, $new_focus, "Focus changed"); - -done_testing; diff --git a/testcases/t/06-focus.t b/testcases/t/06-focus.t deleted file mode 100644 index 5ded494f..00000000 --- a/testcases/t/06-focus.t +++ /dev/null @@ -1,97 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -##################################################################### -# Create two windows and make sure focus switching works -##################################################################### - -# Change mode of the container to "default" for following tests -cmd 'layout default'; -cmd 'split v'; - -my $top = open_window($x); -my $mid = open_window($x); -my $bottom = open_window($x); - -# -# Returns the input focus after sending the given command to i3 via IPC -# end sleeping for half a second to make sure i3 reacted -# -sub focus_after { - my $msg = shift; - - cmd $msg; - sync_with_i3 $x; - return $x->input_focus; -} - -$focus = $x->input_focus; -is($focus, $bottom->id, "Latest window focused"); - -$focus = focus_after('focus up'); -is($focus, $mid->id, "Middle window focused"); - -$focus = focus_after('focus up'); -is($focus, $top->id, "Top window focused"); - -##################################################################### -# Test focus wrapping -##################################################################### - -$focus = focus_after('focus up'); -is($focus, $bottom->id, "Bottom window focused (wrapping to the top works)"); - -$focus = focus_after('focus down'); -is($focus, $top->id, "Top window focused (wrapping to the bottom works)"); - -############################################### -# Test focus with empty containers and colspan -############################################### - -#my $otmp = get_unused_workspace(); -#$i3->command("workspace $otmp")->recv; -# -#$top = i3test::open_standard_window($x); -#$bottom = i3test::open_standard_window($x); -#sleep 0.25; -# -#$focus = focus_after("mj"); -#$focus = focus_after("mh"); -#$focus = focus_after("k"); -#is($focus, $bottom->id, "Selecting top window without snapping doesn't work"); -# -#$focus = focus_after("sl"); -#is($focus, $bottom->id, "Bottom window focused"); -# -#$focus = focus_after("k"); -#is($focus, $top->id, "Top window focused"); -# -## Same thing, but left/right instead of top/bottom -# -#my $o2tmp = get_unused_workspace(); -#$i3->command("workspace $o2tmp")->recv; -# -#my $left = i3test::open_standard_window($x); -#my $right = i3test::open_standard_window($x); -#sleep 0.25; -# -#$focus = focus_after("ml"); -#$focus = focus_after("h"); -#$focus = focus_after("mk"); -#$focus = focus_after("l"); -#is($focus, $left->id, "Selecting right window without snapping doesn't work"); -# -#$focus = focus_after("sj"); -#is($focus, $left->id, "left window focused"); -# -#$focus = focus_after("l"); -#is($focus, $right->id, "right window focused"); - - -done_testing; diff --git a/testcases/t/07-move.t b/testcases/t/07-move.t deleted file mode 100644 index 6e35ebe4..00000000 --- a/testcases/t/07-move.t +++ /dev/null @@ -1,82 +0,0 @@ -#!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 tests => 8; -use X11::XCB qw(:all); -use Time::HiRes qw(sleep); - -BEGIN { - use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); -} - -SKIP: { - skip "Testcase not yet modified for new move concept", 7; - -my $x = X11::XCB::Connection->new; - -my $i3 = i3; - -# Switch to the nineth workspace -$i3->command('9')->recv; - -##################################################################### -# Create two windows and make sure focus switching works -##################################################################### - -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); - -diag("top id = " . $top->id); -diag("mid id = " . $mid->id); -diag("bottom id = " . $bottom->id); - -# -# Returns the input focus after sending the given command to i3 via IPC -# end sleeping for half a second to make sure i3 reacted -# -sub focus_after { - my $msg = shift; - - $i3->command($msg)->recv; - return $x->input_focus; -} - -$focus = $x->input_focus; -is($focus, $bottom->id, "Latest window focused"); - -$focus = focus_after("ml"); -is($focus, $bottom->id, "Right window still focused"); - -$focus = focus_after("h"); -is($focus, $mid->id, "Middle window focused"); - -##################################################################### -# Now move to the top window, move right, then move left again -# (e.g., does i3 remember the focus in the last container?) -##################################################################### - -$focus = focus_after("k"); -is($focus, $top->id, "Top window focused"); - -$focus = focus_after("l"); -is($focus, $bottom->id, "Right window focused"); - -$focus = focus_after("h"); -is($focus, $top->id, "Top window focused"); - -##################################################################### -# Move window cross-workspace -##################################################################### - -for my $cmd (qw(m12 t m13 12 13)) { - $i3->command($cmd)->recv; -} -ok(1, "Still living"); -} diff --git a/testcases/t/08-focus-stack.t b/testcases/t/08-focus-stack.t deleted file mode 100644 index b5be284c..00000000 --- a/testcases/t/08-focus-stack.t +++ /dev/null @@ -1,30 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# Checks if the focus is correctly restored, when creating a floating client -# over an unfocused tiling client and destroying the floating one again. - -use i3test; - -my $x = X11::XCB::Connection->new; - -fresh_workspace; - -cmd 'split h'; -my $tiled_left = open_window($x); -my $tiled_right = open_window($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 = open_floating_window($x); - -is($x->input_focus, $window->id, 'floating window focused'); - -$window->unmap; - -wait_for_unmap($x); - -is($x->input_focus, $focus, 'Focus correctly restored'); - -done_testing; diff --git a/testcases/t/09-stacking.t b/testcases/t/09-stacking.t deleted file mode 100644 index cc285f32..00000000 --- a/testcases/t/09-stacking.t +++ /dev/null @@ -1,130 +0,0 @@ -#!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 tests => 22; -use X11::XCB qw(:all); -use Time::HiRes qw(sleep); - -BEGIN { - use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); -} - -SKIP: { - skip "stacking test not yet updated", 21; - -my $x = X11::XCB::Connection->new; - -my $i3 = i3; - -# Switch to the nineth workspace -$i3->command('9')->recv; - -##################################################################### -# Create two windows and make sure focus switching works -##################################################################### - -my $top = i3test::open_standard_window($x); -my $mid = i3test::open_standard_window($x); -my $bottom = i3test::open_standard_window($x); -sleep(0.25); - -diag("top id = " . $top->id); -diag("mid id = " . $mid->id); -diag("bottom id = " . $bottom->id); - -# -# Returns the input focus after sending the given command to i3 via IPC -# end sleeping for half a second to make sure i3 reacted -# -sub focus_after { - my $msg = shift; - - $i3->command($msg)->recv; - return $x->input_focus; -} - -$focus = $x->input_focus; -is($focus, $bottom->id, "Latest window focused"); - -$focus = focus_after("s"); -is($focus, $bottom->id, "Last window still focused"); - -$focus = focus_after("k"); -is($focus, $mid->id, "Middle window focused"); - -$focus = focus_after("k"); -is($focus, $top->id, "Top window focused"); - -##################################################################### -# Test focus wrapping -##################################################################### - -$focus = focus_after("k"); -is($focus, $bottom->id, "Bottom window focused (wrapping to the top works)"); - -$focus = focus_after("j"); -is($focus, $top->id, "Top window focused (wrapping to the bottom works)"); - -##################################################################### -# Restore of focus after moving windows out/into the stack -##################################################################### - -$focus = focus_after("ml"); -is($focus, $top->id, "Top window still focused (focus after moving)"); - -$focus = focus_after("h"); -is($focus, $bottom->id, "Bottom window focused (focus after moving)"); - -my $new = i3test::open_standard_window($x); -sleep(0.25); - -# By now, we have this layout: -# ---------------- -# | mid | -# | bottom | top -# | new | -# ---------------- - -$focus = focus_after("l"); -is($focus, $top->id, "Got top window"); - -$focus = focus_after("mh"); -is($focus, $top->id, "Moved it into the stack"); - -$focus = focus_after("k"); -is($focus, $new->id, "Window above is new"); - -$focus = focus_after("k"); -is($focus, $bottom->id, "Window above is bottom"); - -$focus = focus_after("k"); -is($focus, $mid->id, "Window above is mid"); - -$focus = focus_after("k"); -is($focus, $top->id, "At top again"); - -$focus = focus_after("ml"); -is($focus, $top->id, "Still at top, moved out"); - -$focus = focus_after("h"); -is($focus, $mid->id, "At mid again"); - -$focus = focus_after("j"); -is($focus, $bottom->id, "At bottom again"); - -$focus = focus_after("l"); -is($focus, $top->id, "At top again"); - -$focus = focus_after("mh"); -is($focus, $top->id, "Still at top, moved into"); - -$focus = focus_after("k"); -is($focus, $bottom->id, "Window above is bottom"); - -$focus = focus_after("k"); -is($focus, $mid->id, "Window above is mid"); - -} diff --git a/testcases/t/10-dock.t b/testcases/t/10-dock.t deleted file mode 100644 index cad54c26..00000000 --- a/testcases/t/10-dock.t +++ /dev/null @@ -1,196 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; -use X11::XCB qw(:all); -use List::Util qw(first); - -BEGIN { - use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); -} - -my $x = X11::XCB::Connection->new; - -##################################################################### -# verify that there is no dock window yet -##################################################################### - -# Children of all dockareas -my @docked = get_dock_clients; -is(@docked, 0, 'no dock clients yet'); - -##################################################################### -# Create a dock window and see if it gets managed -##################################################################### - -my $screens = $x->screens; - -# Get the primary screen -my $primary = first { $_->primary } @{$screens}; - -# TODO: focus the primary screen before -my $window = open_window($x, { - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), - }); - -my $rect = $window->rect; -is($rect->width, $primary->rect->width, 'dock client is as wide as the screen'); -is($rect->height, 30, 'height is unchanged'); - -##################################################################### -# check that we can find it in the layout tree at the expected position -##################################################################### - -@docked = get_dock_clients('top'); -is(@docked, 1, 'one dock client found'); - -# verify the position/size -my $docknode = $docked[0]; - -is($docknode->{rect}->{x}, 0, 'dock node placed at x=0'); -is($docknode->{rect}->{y}, 0, 'dock node placed at y=0'); -is($docknode->{rect}->{width}, $primary->rect->width, 'dock node as wide as the screen'); -is($docknode->{rect}->{height}, 30, 'dock node has unchanged height'); - -##################################################################### -# check that re-configuring the height works -##################################################################### - -$window->rect(X11::XCB::Rect->new(x => 0, y => 0, width => 50, height => 40)); - -sync_with_i3 $x; - -@docked = get_dock_clients('top'); -is(@docked, 1, 'one dock client found'); - -# verify the position/size -$docknode = $docked[0]; - -is($docknode->{rect}->{x}, 0, 'dock node placed at x=0'); -is($docknode->{rect}->{y}, 0, 'dock node placed at y=0'); -is($docknode->{rect}->{width}, $primary->rect->width, 'dock node as wide as the screen'); -is($docknode->{rect}->{height}, 40, 'dock height changed'); - -$window->destroy; - -wait_for_unmap $x; - -@docked = get_dock_clients(); -is(@docked, 0, 'no more dock clients'); - -##################################################################### -# check if it gets placed on bottom (by coordinates) -##################################################################### - -$window = open_window($x, { - rect => [ 0, 1000, 30, 30 ], - background_color => '#FF0000', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), - }); - -my $rect = $window->rect; -is($rect->width, $primary->rect->width, 'dock client is as wide as the screen'); -is($rect->height, 30, 'height is unchanged'); - -@docked = get_dock_clients('bottom'); -is(@docked, 1, 'dock client on bottom'); - -$window->destroy; - -wait_for_unmap $x; - -@docked = get_dock_clients(); -is(@docked, 0, 'no more dock clients'); - -##################################################################### -# check if it gets placed on bottom (by hint) -##################################################################### - -$window = open_window($x, { - dont_map => 1, - rect => [ 0, 1000, 30, 30 ], - background_color => '#FF0000', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), - }); - -$window->_create(); - -# Add a _NET_WM_STRUT_PARTIAL hint -my $atomname = $x->atom(name => '_NET_WM_STRUT_PARTIAL'); -my $atomtype = $x->atom(name => 'CARDINAL'); - -$x->change_property( - PROP_MODE_REPLACE, - $window->id, - $atomname->id, - $atomtype->id, - 32, # 32 bit integer - 12, - pack('L12', 0, 0, 16, 0, 0, 0, 0, 0, 0, 1280, 0, 0) -); - -$window->map; - -wait_for_map $x; - -@docked = get_dock_clients('top'); -is(@docked, 1, 'dock client on top'); - -$window->destroy; - -wait_for_unmap $x; - -@docked = get_dock_clients(); -is(@docked, 0, 'no more dock clients'); - -$window = open_window($x, { - dont_map => 1, - rect => [ 0, 1000, 30, 30 ], - background_color => '#FF0000', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), - }); - -$window->_create(); - -# Add a _NET_WM_STRUT_PARTIAL hint -my $atomname = $x->atom(name => '_NET_WM_STRUT_PARTIAL'); -my $atomtype = $x->atom(name => 'CARDINAL'); - -$x->change_property( - PROP_MODE_REPLACE, - $window->id, - $atomname->id, - $atomtype->id, - 32, # 32 bit integer - 12, - pack('L12', 0, 0, 0, 16, 0, 0, 0, 0, 0, 1280, 0, 0) -); - -$window->map; - -wait_for_map $x; - -@docked = get_dock_clients('bottom'); -is(@docked, 1, 'dock client on bottom'); - -$window->destroy; - - -##################################################################### -# regression test: transient dock client -##################################################################### - -$fwindow = open_window($x, { - dont_map => 1, - background_color => '#FF0000', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), - }); - -$fwindow->transient_for($window); -$fwindow->map; - -wait_for_map $x; - -does_i3_live; - -done_testing; diff --git a/testcases/t/100-fullscreen.t b/testcases/t/100-fullscreen.t new file mode 100644 index 00000000..ae8c63f6 --- /dev/null +++ b/testcases/t/100-fullscreen.t @@ -0,0 +1,172 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; +use X11::XCB qw(:all); +use List::Util qw(first); + +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +sub fullscreen_windows { + scalar grep { $_->{fullscreen_mode} != 0 } @{get_ws_content($tmp)} +} + +# get the output of this workspace +my $tree = $i3->get_tree->recv; +my @outputs = @{$tree->{nodes}}; +my $output; +for my $o (@outputs) { + # get the first CT_CON of each output + my $content = first { $_->{type} == 2 } @{$o->{nodes}}; + if (defined(first { $_->{name} eq $tmp } @{$content->{nodes}})) { + $output = $o; + last; + } +} + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +################################## +# map a window, then fullscreen it +################################## + +my $original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); + +my $window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => $original_rect, + background_color => '#C0C0C0', + event_mask => [ 'structure_notify' ], +); + +isa_ok($window, 'X11::XCB::Window'); + +is_deeply($window->rect, $original_rect, "rect unmodified before mapping"); + +$window->map; + +wait_for_map $x; + +# open another container to make the window get only half of the screen +cmd 'open'; + +my $new_rect = $window->rect; +ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned"); +$original_rect = $new_rect; + +$window->fullscreen(1); + +sync_with_i3($x); + +$new_rect = $window->rect; +ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned after fullscreen"); + +my $orect = $output->{rect}; +my $wrect = $new_rect; + +# see if the window really is fullscreen. 20 px for borders are allowed +my $threshold = 20; +ok(($wrect->{x} - $orect->{x}) < $threshold, 'x coordinate fullscreen'); +ok(($wrect->{y} - $orect->{y}) < $threshold, 'y coordinate fullscreen'); +ok(abs($wrect->{width} - $orect->{width}) < $threshold, 'width coordinate fullscreen'); +ok(abs($wrect->{height} - $orect->{height}) < $threshold, 'height coordinate fullscreen'); + + +$window->unmap; + +######################################################### +# test with a window which is fullscreened before mapping +######################################################### + +# open another container because the empty one will swallow the window we +# map in a second +cmd 'open'; + +$original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); +$window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => $original_rect, + background_color => 61440, + event_mask => [ 'structure_notify' ], +); + +is_deeply($window->rect, $original_rect, "rect unmodified before mapping"); + +$window->fullscreen(1); +$window->map; + +wait_for_map $x; + +$new_rect = $window->rect; +ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned after fullscreen"); +ok($window->mapped, "Window is mapped after opening it in fullscreen mode"); + +$wrect = $new_rect; + +# see if the window really is fullscreen. 20 px for borders are allowed +ok(($wrect->{x} - $orect->{x}) < $threshold, 'x coordinate fullscreen'); +ok(($wrect->{y} - $orect->{y}) < $threshold, 'y coordinate fullscreen'); +ok(abs($wrect->{width} - $orect->{width}) < $threshold, 'width coordinate fullscreen'); +ok(abs($wrect->{height} - $orect->{height}) < $threshold, 'height coordinate fullscreen'); + +############################################################################### +# test if setting two windows in fullscreen mode at the same time does not work +############################################################################### + +$original_rect = X11::XCB::Rect->new(x => 0, y => 0, width => 30, height => 30); +my $swindow = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => $original_rect, + background_color => '#C0C0C0', + event_mask => [ 'structure_notify' ], +); + +$swindow->map; + +sync_with_i3($x); + +ok(!$swindow->mapped, 'window not mapped while fullscreen window active'); + +$new_rect = $swindow->rect; +ok(!eq_deeply($new_rect, $original_rect), "Window got repositioned"); + +$swindow->fullscreen(1); +sync_with_i3($x); + +is(fullscreen_windows(), 1, 'amount of fullscreen windows'); + +$window->fullscreen(0); +sync_with_i3($x); +is(fullscreen_windows(), 0, 'amount of fullscreen windows'); + +ok($swindow->mapped, 'window mapped after other fullscreen ended'); + +########################################################################### +# as $swindow is out of state at the moment (it requested to be fullscreen, +# but the WM denied), we check what happens if we go out of fullscreen now +# (nothing should happen) +########################################################################### + +$swindow->fullscreen(0); +sync_with_i3($x); + +is(fullscreen_windows(), 0, 'amount of fullscreen windows after disabling'); + +cmd 'fullscreen'; + +is(fullscreen_windows(), 1, 'amount of fullscreen windows after fullscreen command'); + +cmd 'fullscreen'; + +is(fullscreen_windows(), 0, 'amount of fullscreen windows after fullscreen command'); + +# clean up the workspace so that it will be cleaned when switching away +cmd 'kill' for (@{get_ws_content($tmp)}); + +done_testing; diff --git a/testcases/t/101-focus.t b/testcases/t/101-focus.t new file mode 100644 index 00000000..5ded494f --- /dev/null +++ b/testcases/t/101-focus.t @@ -0,0 +1,97 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +##################################################################### +# Create two windows and make sure focus switching works +##################################################################### + +# Change mode of the container to "default" for following tests +cmd 'layout default'; +cmd 'split v'; + +my $top = open_window($x); +my $mid = open_window($x); +my $bottom = open_window($x); + +# +# Returns the input focus after sending the given command to i3 via IPC +# end sleeping for half a second to make sure i3 reacted +# +sub focus_after { + my $msg = shift; + + cmd $msg; + sync_with_i3 $x; + return $x->input_focus; +} + +$focus = $x->input_focus; +is($focus, $bottom->id, "Latest window focused"); + +$focus = focus_after('focus up'); +is($focus, $mid->id, "Middle window focused"); + +$focus = focus_after('focus up'); +is($focus, $top->id, "Top window focused"); + +##################################################################### +# Test focus wrapping +##################################################################### + +$focus = focus_after('focus up'); +is($focus, $bottom->id, "Bottom window focused (wrapping to the top works)"); + +$focus = focus_after('focus down'); +is($focus, $top->id, "Top window focused (wrapping to the bottom works)"); + +############################################### +# Test focus with empty containers and colspan +############################################### + +#my $otmp = get_unused_workspace(); +#$i3->command("workspace $otmp")->recv; +# +#$top = i3test::open_standard_window($x); +#$bottom = i3test::open_standard_window($x); +#sleep 0.25; +# +#$focus = focus_after("mj"); +#$focus = focus_after("mh"); +#$focus = focus_after("k"); +#is($focus, $bottom->id, "Selecting top window without snapping doesn't work"); +# +#$focus = focus_after("sl"); +#is($focus, $bottom->id, "Bottom window focused"); +# +#$focus = focus_after("k"); +#is($focus, $top->id, "Top window focused"); +# +## Same thing, but left/right instead of top/bottom +# +#my $o2tmp = get_unused_workspace(); +#$i3->command("workspace $o2tmp")->recv; +# +#my $left = i3test::open_standard_window($x); +#my $right = i3test::open_standard_window($x); +#sleep 0.25; +# +#$focus = focus_after("ml"); +#$focus = focus_after("h"); +#$focus = focus_after("mk"); +#$focus = focus_after("l"); +#is($focus, $left->id, "Selecting right window without snapping doesn't work"); +# +#$focus = focus_after("sj"); +#is($focus, $left->id, "left window focused"); +# +#$focus = focus_after("l"); +#is($focus, $right->id, "right window focused"); + + +done_testing; diff --git a/testcases/t/102-dock.t b/testcases/t/102-dock.t new file mode 100644 index 00000000..cad54c26 --- /dev/null +++ b/testcases/t/102-dock.t @@ -0,0 +1,196 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; +use X11::XCB qw(:all); +use List::Util qw(first); + +BEGIN { + use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); +} + +my $x = X11::XCB::Connection->new; + +##################################################################### +# verify that there is no dock window yet +##################################################################### + +# Children of all dockareas +my @docked = get_dock_clients; +is(@docked, 0, 'no dock clients yet'); + +##################################################################### +# Create a dock window and see if it gets managed +##################################################################### + +my $screens = $x->screens; + +# Get the primary screen +my $primary = first { $_->primary } @{$screens}; + +# TODO: focus the primary screen before +my $window = open_window($x, { + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + }); + +my $rect = $window->rect; +is($rect->width, $primary->rect->width, 'dock client is as wide as the screen'); +is($rect->height, 30, 'height is unchanged'); + +##################################################################### +# check that we can find it in the layout tree at the expected position +##################################################################### + +@docked = get_dock_clients('top'); +is(@docked, 1, 'one dock client found'); + +# verify the position/size +my $docknode = $docked[0]; + +is($docknode->{rect}->{x}, 0, 'dock node placed at x=0'); +is($docknode->{rect}->{y}, 0, 'dock node placed at y=0'); +is($docknode->{rect}->{width}, $primary->rect->width, 'dock node as wide as the screen'); +is($docknode->{rect}->{height}, 30, 'dock node has unchanged height'); + +##################################################################### +# check that re-configuring the height works +##################################################################### + +$window->rect(X11::XCB::Rect->new(x => 0, y => 0, width => 50, height => 40)); + +sync_with_i3 $x; + +@docked = get_dock_clients('top'); +is(@docked, 1, 'one dock client found'); + +# verify the position/size +$docknode = $docked[0]; + +is($docknode->{rect}->{x}, 0, 'dock node placed at x=0'); +is($docknode->{rect}->{y}, 0, 'dock node placed at y=0'); +is($docknode->{rect}->{width}, $primary->rect->width, 'dock node as wide as the screen'); +is($docknode->{rect}->{height}, 40, 'dock height changed'); + +$window->destroy; + +wait_for_unmap $x; + +@docked = get_dock_clients(); +is(@docked, 0, 'no more dock clients'); + +##################################################################### +# check if it gets placed on bottom (by coordinates) +##################################################################### + +$window = open_window($x, { + rect => [ 0, 1000, 30, 30 ], + background_color => '#FF0000', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + }); + +my $rect = $window->rect; +is($rect->width, $primary->rect->width, 'dock client is as wide as the screen'); +is($rect->height, 30, 'height is unchanged'); + +@docked = get_dock_clients('bottom'); +is(@docked, 1, 'dock client on bottom'); + +$window->destroy; + +wait_for_unmap $x; + +@docked = get_dock_clients(); +is(@docked, 0, 'no more dock clients'); + +##################################################################### +# check if it gets placed on bottom (by hint) +##################################################################### + +$window = open_window($x, { + dont_map => 1, + rect => [ 0, 1000, 30, 30 ], + background_color => '#FF0000', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + }); + +$window->_create(); + +# Add a _NET_WM_STRUT_PARTIAL hint +my $atomname = $x->atom(name => '_NET_WM_STRUT_PARTIAL'); +my $atomtype = $x->atom(name => 'CARDINAL'); + +$x->change_property( + PROP_MODE_REPLACE, + $window->id, + $atomname->id, + $atomtype->id, + 32, # 32 bit integer + 12, + pack('L12', 0, 0, 16, 0, 0, 0, 0, 0, 0, 1280, 0, 0) +); + +$window->map; + +wait_for_map $x; + +@docked = get_dock_clients('top'); +is(@docked, 1, 'dock client on top'); + +$window->destroy; + +wait_for_unmap $x; + +@docked = get_dock_clients(); +is(@docked, 0, 'no more dock clients'); + +$window = open_window($x, { + dont_map => 1, + rect => [ 0, 1000, 30, 30 ], + background_color => '#FF0000', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + }); + +$window->_create(); + +# Add a _NET_WM_STRUT_PARTIAL hint +my $atomname = $x->atom(name => '_NET_WM_STRUT_PARTIAL'); +my $atomtype = $x->atom(name => 'CARDINAL'); + +$x->change_property( + PROP_MODE_REPLACE, + $window->id, + $atomname->id, + $atomtype->id, + 32, # 32 bit integer + 12, + pack('L12', 0, 0, 0, 16, 0, 0, 0, 0, 0, 1280, 0, 0) +); + +$window->map; + +wait_for_map $x; + +@docked = get_dock_clients('bottom'); +is(@docked, 1, 'dock client on bottom'); + +$window->destroy; + + +##################################################################### +# regression test: transient dock client +##################################################################### + +$fwindow = open_window($x, { + dont_map => 1, + background_color => '#FF0000', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + }); + +$fwindow->transient_for($window); +$fwindow->map; + +wait_for_map $x; + +does_i3_live; + +done_testing; diff --git a/testcases/t/103-move.t b/testcases/t/103-move.t new file mode 100644 index 00000000..6e35ebe4 --- /dev/null +++ b/testcases/t/103-move.t @@ -0,0 +1,82 @@ +#!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 tests => 8; +use X11::XCB qw(:all); +use Time::HiRes qw(sleep); + +BEGIN { + use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); +} + +SKIP: { + skip "Testcase not yet modified for new move concept", 7; + +my $x = X11::XCB::Connection->new; + +my $i3 = i3; + +# Switch to the nineth workspace +$i3->command('9')->recv; + +##################################################################### +# Create two windows and make sure focus switching works +##################################################################### + +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); + +diag("top id = " . $top->id); +diag("mid id = " . $mid->id); +diag("bottom id = " . $bottom->id); + +# +# Returns the input focus after sending the given command to i3 via IPC +# end sleeping for half a second to make sure i3 reacted +# +sub focus_after { + my $msg = shift; + + $i3->command($msg)->recv; + return $x->input_focus; +} + +$focus = $x->input_focus; +is($focus, $bottom->id, "Latest window focused"); + +$focus = focus_after("ml"); +is($focus, $bottom->id, "Right window still focused"); + +$focus = focus_after("h"); +is($focus, $mid->id, "Middle window focused"); + +##################################################################### +# Now move to the top window, move right, then move left again +# (e.g., does i3 remember the focus in the last container?) +##################################################################### + +$focus = focus_after("k"); +is($focus, $top->id, "Top window focused"); + +$focus = focus_after("l"); +is($focus, $bottom->id, "Right window focused"); + +$focus = focus_after("h"); +is($focus, $top->id, "Top window focused"); + +##################################################################### +# Move window cross-workspace +##################################################################### + +for my $cmd (qw(m12 t m13 12 13)) { + $i3->command($cmd)->recv; +} +ok(1, "Still living"); +} diff --git a/testcases/t/104-focus-stack.t b/testcases/t/104-focus-stack.t new file mode 100644 index 00000000..b5be284c --- /dev/null +++ b/testcases/t/104-focus-stack.t @@ -0,0 +1,30 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# Checks if the focus is correctly restored, when creating a floating client +# over an unfocused tiling client and destroying the floating one again. + +use i3test; + +my $x = X11::XCB::Connection->new; + +fresh_workspace; + +cmd 'split h'; +my $tiled_left = open_window($x); +my $tiled_right = open_window($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 = open_floating_window($x); + +is($x->input_focus, $window->id, 'floating window focused'); + +$window->unmap; + +wait_for_unmap($x); + +is($x->input_focus, $focus, 'Focus correctly restored'); + +done_testing; diff --git a/testcases/t/105-stacking.t b/testcases/t/105-stacking.t new file mode 100644 index 00000000..cc285f32 --- /dev/null +++ b/testcases/t/105-stacking.t @@ -0,0 +1,130 @@ +#!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 tests => 22; +use X11::XCB qw(:all); +use Time::HiRes qw(sleep); + +BEGIN { + use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); +} + +SKIP: { + skip "stacking test not yet updated", 21; + +my $x = X11::XCB::Connection->new; + +my $i3 = i3; + +# Switch to the nineth workspace +$i3->command('9')->recv; + +##################################################################### +# Create two windows and make sure focus switching works +##################################################################### + +my $top = i3test::open_standard_window($x); +my $mid = i3test::open_standard_window($x); +my $bottom = i3test::open_standard_window($x); +sleep(0.25); + +diag("top id = " . $top->id); +diag("mid id = " . $mid->id); +diag("bottom id = " . $bottom->id); + +# +# Returns the input focus after sending the given command to i3 via IPC +# end sleeping for half a second to make sure i3 reacted +# +sub focus_after { + my $msg = shift; + + $i3->command($msg)->recv; + return $x->input_focus; +} + +$focus = $x->input_focus; +is($focus, $bottom->id, "Latest window focused"); + +$focus = focus_after("s"); +is($focus, $bottom->id, "Last window still focused"); + +$focus = focus_after("k"); +is($focus, $mid->id, "Middle window focused"); + +$focus = focus_after("k"); +is($focus, $top->id, "Top window focused"); + +##################################################################### +# Test focus wrapping +##################################################################### + +$focus = focus_after("k"); +is($focus, $bottom->id, "Bottom window focused (wrapping to the top works)"); + +$focus = focus_after("j"); +is($focus, $top->id, "Top window focused (wrapping to the bottom works)"); + +##################################################################### +# Restore of focus after moving windows out/into the stack +##################################################################### + +$focus = focus_after("ml"); +is($focus, $top->id, "Top window still focused (focus after moving)"); + +$focus = focus_after("h"); +is($focus, $bottom->id, "Bottom window focused (focus after moving)"); + +my $new = i3test::open_standard_window($x); +sleep(0.25); + +# By now, we have this layout: +# ---------------- +# | mid | +# | bottom | top +# | new | +# ---------------- + +$focus = focus_after("l"); +is($focus, $top->id, "Got top window"); + +$focus = focus_after("mh"); +is($focus, $top->id, "Moved it into the stack"); + +$focus = focus_after("k"); +is($focus, $new->id, "Window above is new"); + +$focus = focus_after("k"); +is($focus, $bottom->id, "Window above is bottom"); + +$focus = focus_after("k"); +is($focus, $mid->id, "Window above is mid"); + +$focus = focus_after("k"); +is($focus, $top->id, "At top again"); + +$focus = focus_after("ml"); +is($focus, $top->id, "Still at top, moved out"); + +$focus = focus_after("h"); +is($focus, $mid->id, "At mid again"); + +$focus = focus_after("j"); +is($focus, $bottom->id, "At bottom again"); + +$focus = focus_after("l"); +is($focus, $top->id, "At top again"); + +$focus = focus_after("mh"); +is($focus, $top->id, "Still at top, moved into"); + +$focus = focus_after("k"); +is($focus, $bottom->id, "Window above is bottom"); + +$focus = focus_after("k"); +is($focus, $mid->id, "Window above is mid"); + +} diff --git a/testcases/t/11-goto.t b/testcases/t/11-goto.t deleted file mode 100644 index 903fa0c4..00000000 --- a/testcases/t/11-goto.t +++ /dev/null @@ -1,77 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; -use File::Temp; - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -cmd 'split h'; - -##################################################################### -# Create two windows and make sure focus switching works -##################################################################### - -my $top = open_window($x); -my $mid = open_window($x); -my $bottom = open_window($x); - -# -# Returns the input focus after sending the given command to i3 via IPC -# and syncing with i3 -# -sub focus_after { - my $msg = shift; - - cmd $msg; - sync_with_i3($x); - return $x->input_focus; -} - -$focus = $x->input_focus; -is($focus, $bottom->id, "Latest window focused"); - -$focus = focus_after('focus left'); -is($focus, $mid->id, "Middle window focused"); - -##################################################################### -# Now goto a mark which does not exist -##################################################################### - -my $random_mark = mktemp('mark.XXXXXX'); - -$focus = focus_after(qq|[con_mark="$random_mark"] focus|); -is($focus, $mid->id, "focus unchanged"); - -cmd "mark $random_mark"; - -$focus = focus_after('focus left'); -is($focus, $top->id, "Top window focused"); - -$focus = focus_after(qq|[con_mark="$random_mark"] focus|); -is($focus, $mid->id, "goto worked"); - -# check that we can specify multiple criteria - -$focus = focus_after('focus left'); -is($focus, $top->id, "Top window focused"); - -$focus = focus_after(qq|[con_mark="$random_mark" con_mark="$random_mark"] focus|); -is($focus, $mid->id, "goto worked"); - -##################################################################### -# Check whether the focus command will switch to a different -# workspace if necessary -##################################################################### - -my $tmp2 = fresh_workspace; - -is(focused_ws(), $tmp2, 'tmp2 now focused'); - -cmd qq|[con_mark="$random_mark"] focus|; - -is(focused_ws(), $tmp, 'tmp now focused'); - -done_testing; diff --git a/testcases/t/111-goto.t b/testcases/t/111-goto.t new file mode 100644 index 00000000..903fa0c4 --- /dev/null +++ b/testcases/t/111-goto.t @@ -0,0 +1,77 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; +use File::Temp; + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +cmd 'split h'; + +##################################################################### +# Create two windows and make sure focus switching works +##################################################################### + +my $top = open_window($x); +my $mid = open_window($x); +my $bottom = open_window($x); + +# +# Returns the input focus after sending the given command to i3 via IPC +# and syncing with i3 +# +sub focus_after { + my $msg = shift; + + cmd $msg; + sync_with_i3($x); + return $x->input_focus; +} + +$focus = $x->input_focus; +is($focus, $bottom->id, "Latest window focused"); + +$focus = focus_after('focus left'); +is($focus, $mid->id, "Middle window focused"); + +##################################################################### +# Now goto a mark which does not exist +##################################################################### + +my $random_mark = mktemp('mark.XXXXXX'); + +$focus = focus_after(qq|[con_mark="$random_mark"] focus|); +is($focus, $mid->id, "focus unchanged"); + +cmd "mark $random_mark"; + +$focus = focus_after('focus left'); +is($focus, $top->id, "Top window focused"); + +$focus = focus_after(qq|[con_mark="$random_mark"] focus|); +is($focus, $mid->id, "goto worked"); + +# check that we can specify multiple criteria + +$focus = focus_after('focus left'); +is($focus, $top->id, "Top window focused"); + +$focus = focus_after(qq|[con_mark="$random_mark" con_mark="$random_mark"] focus|); +is($focus, $mid->id, "goto worked"); + +##################################################################### +# Check whether the focus command will switch to a different +# workspace if necessary +##################################################################### + +my $tmp2 = fresh_workspace; + +is(focused_ws(), $tmp2, 'tmp2 now focused'); + +cmd qq|[con_mark="$random_mark"] focus|; + +is(focused_ws(), $tmp, 'tmp now focused'); + +done_testing; diff --git a/testcases/t/112-floating-resize.t b/testcases/t/112-floating-resize.t new file mode 100644 index 00000000..ac3387a9 --- /dev/null +++ b/testcases/t/112-floating-resize.t @@ -0,0 +1,65 @@ +#!perl +# 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; + +fresh_workspace; + +##################################################################### +# Create a floating window and see if resizing works +##################################################################### + +my $window = open_floating_window($x); + +# 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)); + +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 we’re gonna test, so + # that the test will work. + isnt($absolute->width, 300, 'width != 300'); + isnt($absolute->height, 500, 'height != 500'); + + $window->rect(X11::XCB::Rect->new(x => 0, y => 0, width => 300, height => 500)); + + sync_with_i3($x); + + ($absolute, $top) = $window->rect; + + is($absolute->width, 300, 'width = 300'); + is($absolute->height, 500, 'height = 500'); +} + +# Test with default border +test_resize; + +# Test borderless +cmd 'border none'; + +test_resize; + +# Test with 1-px-border +cmd 'border 1pixel'; + +test_resize; + +done_testing; diff --git a/testcases/t/113-urgent.t b/testcases/t/113-urgent.t new file mode 100644 index 00000000..7954408f --- /dev/null +++ b/testcases/t/113-urgent.t @@ -0,0 +1,75 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; +use X11::XCB qw(:all); +use List::Util qw(first); + +BEGIN { + use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); +} + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +##################################################################### +# Create two windows and put them in stacking mode +##################################################################### + +cmd 'split v'; + +my $top = open_window($x); +my $bottom = open_window($x); + +my @urgent = grep { $_->{urgent} } @{get_ws_content($tmp)}; +is(@urgent, 0, 'no window got the urgent flag'); + +# cmd 'layout stacking'; + +##################################################################### +# Add the urgency hint, switch to a different workspace and back again +##################################################################### +$top->add_hint('urgency'); +sync_with_i3($x); + +@content = @{get_ws_content($tmp)}; +@urgent = grep { $_->{urgent} } @content; +$top_info = first { $_->{window} == $top->id } @content; +$bottom_info = first { $_->{window} == $bottom->id } @content; + +ok($top_info->{urgent}, 'top window is marked urgent'); +ok(!$bottom_info->{urgent}, 'bottom window is not marked urgent'); +is(@urgent, 1, 'exactly one window got the urgent flag'); + +cmd '[id="' . $top->id . '"] focus'; + +@urgent = grep { $_->{urgent} } @{get_ws_content($tmp)}; +is(@urgent, 0, 'no window got the urgent flag after focusing'); + +$top->add_hint('urgency'); +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'); + +##################################################################### +# Check if the workspace urgency hint gets set/cleared correctly +##################################################################### +my $ws = get_ws($tmp); +ok(!$ws->{urgent}, 'urgent flag not set on workspace'); + +my $otmp = fresh_workspace; + +$top->add_hint('urgency'); +sync_with_i3($x); + +$ws = get_ws($tmp); +ok($ws->{urgent}, 'urgent flag set on workspace'); + +cmd "workspace $tmp"; + +$ws = get_ws($tmp); +ok(!$ws->{urgent}, 'urgent flag not set on workspace after switching'); + +done_testing; diff --git a/testcases/t/114-client-leader.t b/testcases/t/114-client-leader.t new file mode 100644 index 00000000..6f7ffce0 --- /dev/null +++ b/testcases/t/114-client-leader.t @@ -0,0 +1,96 @@ +#!perl +# 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; + +my $tmp = fresh_workspace; + +#################################################################################### +# first part: test if a floating window will be correctly positioned above its leader +# +# This is verified by opening two windows, then opening a floating window above the +# right one, then above the left one. If the floating windows are all positioned alike, +# one of both (depending on your screen resolution) will be positioned wrong. +#################################################################################### + +my $left = open_window($x, { name => 'Left' }); +my $right = open_window($x, { name => 'Right' }); + +my ($abs, $rgeom) = $right->rect; + +my $child = open_floating_window($x, { + dont_map => 1, + name => 'Child window', + }); +$child->client_leader($right); +$child->map; + +ok(wait_for_map($x), 'child window mapped'); + +my $cgeom; +($abs, $cgeom) = $child->rect; +cmp_ok($cgeom->x, '>=', $rgeom->x, 'Child X >= right container X'); + +my $child2 = open_floating_window($x, { + dont_map => 1, + name => 'Child window 2', + }); +$child2->client_leader($left); +$child2->map; + +ok(wait_for_map($x), 'second child window mapped'); + +($abs, $cgeom) = $child2->rect; +cmp_ok(($cgeom->x + $cgeom->width), '<', $rgeom->x, 'child above left window'); + +# check wm_transient_for +my $fwindow = open_window($x, { dont_map => 1 }); +$fwindow->transient_for($right); +$fwindow->map; + +ok(wait_for_map($x), 'transient window mapped'); + +my ($absolute, $top) = $fwindow->rect; +ok($absolute->{x} != 0 && $absolute->{y} != 0, 'i3 did not map it to (0x0)'); + +SKIP: { + skip "(workspace placement by client_leader not yet implemented)", 3; + +##################################################################### +# Create a parent window +##################################################################### + +my $window = open_window($x, { dont_map => 1, name => 'Parent window' }); +$window->map; + +ok(wait_for_map($x), 'parent window mapped'); + +######################################################################### +# Switch to a different workspace and open a child window. It should be opened +# on the old workspace. +######################################################################### +fresh_workspace; + +my $child = open_window($x, { dont_map => 1, name => 'Child window' }); +$child->client_leader($window); +$child->map; + +ok(wait_for_map($x), 'child window mapped'); + +isnt($x->input_focus, $child->id, "Child window focused"); + +# Switch back +cmd "workspace $tmp"; + +is($x->input_focus, $child->id, "Child window focused"); + +} + +done_testing; diff --git a/testcases/t/115-ipc-workspaces.t b/testcases/t/115-ipc-workspaces.t new file mode 100644 index 00000000..4d9a0294 --- /dev/null +++ b/testcases/t/115-ipc-workspaces.t @@ -0,0 +1,24 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; + +my $i3 = i3(get_socket_path()); + +#################### +# Request workspaces +#################### + +SKIP: { + skip "IPC API not yet stabilized", 2; + +my $workspaces = $i3->get_workspaces->recv; + +ok(@{$workspaces} > 0, "More than zero workspaces found"); + +#my $name_exists = all { defined($_->{name}) } @{$workspaces}; +#ok($name_exists, "All workspaces have a name"); + +} + +done_testing; diff --git a/testcases/t/116-nestedcons.t b/testcases/t/116-nestedcons.t new file mode 100644 index 00000000..4b3958a1 --- /dev/null +++ b/testcases/t/116-nestedcons.t @@ -0,0 +1,84 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; +use List::Util qw(first); + +# to not depend on List::MoreUtils +sub all (&@) { + my $cb = shift; + for (@_) { + return 0 unless $cb->(); + } + return 1; +} + +sub none (&@) { + my $cb = shift; + for (@_) { + return 0 if $cb->(); + } + return 1; +} + +my $i3 = i3(get_socket_path()); + +#################### +# Request tree +#################### + +my $tree = $i3->get_tree->recv; + +my $expected = { + fullscreen_mode => 0, + nodes => ignore(), + window => undef, + name => 'root', + orientation => ignore(), + type => 0, + id => ignore(), + rect => ignore(), + window_rect => ignore(), + geometry => ignore(), + swallows => ignore(), + percent => undef, + layout => 'default', + focus => ignore(), + focused => JSON::XS::false, + urgent => JSON::XS::false, + border => 'normal', + 'floating_nodes' => ignore(), +}; + +cmp_deeply($tree, $expected, 'root node OK'); + +my @nodes = @{$tree->{nodes}}; + +ok(@nodes > 0, 'root node has at least one leaf'); + +ok((all { $_->{type} == 1 } @nodes), 'all nodes are of type CT_OUTPUT'); +ok((none { defined($_->{window}) } @nodes), 'no CT_OUTPUT contains a window'); +ok((all { @{$_->{nodes}} > 0 } @nodes), 'all nodes have at least one leaf (workspace)'); +my @workspaces; +for my $ws (@nodes) { + my $content = first { $_->{type} == 2 } @{$ws->{nodes}}; + @workspaces = (@workspaces, @{$content->{nodes}}); +} + +ok((all { $_->{type} == 4 } @workspaces), 'all workspaces are of type CT_WORKSPACE'); +#ok((all { @{$_->{nodes}} == 0 } @workspaces), 'all workspaces are empty yet'); +ok((none { defined($_->{window}) } @workspaces), 'no CT_OUTPUT contains a window'); + +# TODO: get the focused container + +$i3->command('open')->recv; + +# TODO: get the focused container, check if it changed. +# TODO: get the old focused container, check if there is a new child + +#diag(Dumper(\@workspaces)); + +#diag(Dumper($tree)); + + +done_testing; diff --git a/testcases/t/117-workspace.t b/testcases/t/117-workspace.t new file mode 100644 index 00000000..3c3b6cc6 --- /dev/null +++ b/testcases/t/117-workspace.t @@ -0,0 +1,120 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests whether we can switch to a non-existant workspace +# (necessary for further tests) +# +use List::Util qw(first); +use i3test; + +# to ensure that workspace 1 stays open +cmd 'open'; + +my $tmp = fresh_workspace; +ok(workspace_exists($tmp), 'workspace created'); +# if the workspace could not be created, we cannot run any other test +# (every test starts by creating its workspace) +if (!workspace_exists($tmp)) { + BAIL_OUT('Cannot create workspace, further tests make no sense'); +} + +my $otmp = fresh_workspace; +diag("Other temporary workspace name: $otmp\n"); + +# As the old workspace was empty, it should get +# cleaned up as we switch away from it +cmd "workspace $otmp"; +ok(!workspace_exists($tmp), 'old workspace cleaned up'); + +# Switch to the same workspace again to make sure it doesn’t get cleaned up +cmd "workspace $otmp"; +cmd "workspace $otmp"; +ok(workspace_exists($otmp), 'other workspace still exists'); + + +##################################################################### +# check if the workspace next / prev commands work +##################################################################### + +cmd 'workspace next'; + +ok(!workspace_exists('next'), 'workspace "next" does not exist'); + +cmd "workspace $tmp"; +cmd 'open'; + +ok(workspace_exists($tmp), 'workspace created'); + +cmd "workspace $otmp"; +cmd 'open'; + +ok(workspace_exists($tmp), 'workspace tmp still exists'); +ok(workspace_exists($otmp), 'workspace otmp created'); + +is(focused_ws(), $otmp, 'focused workspace is otmp'); + +cmd 'workspace prev'; +is(focused_ws(), $tmp, 'focused workspace is tmp after workspace prev'); + +cmd 'workspace next'; +is(focused_ws(), $otmp, 'focused workspace is otmp after workspace next'); + + +##################################################################### +# check that wrapping works +##################################################################### + +cmd 'workspace next'; +is(focused_ws(), '1', 'focused workspace is 1 after workspace next'); + +cmd 'workspace next'; +is(focused_ws(), $tmp, 'focused workspace is tmp after workspace next'); + +cmd 'workspace next'; +is(focused_ws(), $otmp, 'focused workspace is otmp after workspace next'); + + +cmd 'workspace prev'; +is(focused_ws(), $tmp, 'focused workspace is tmp after workspace prev'); + +cmd 'workspace prev'; +is(focused_ws(), '1', 'focused workspace is tmp after workspace prev'); + +cmd 'workspace prev'; +is(focused_ws(), $otmp, 'focused workspace is otmp after workspace prev'); + + +##################################################################### +# check if we can change to "next" / "prev" +##################################################################### + +cmd 'workspace "next"'; + +ok(workspace_exists('next'), 'workspace "next" exists'); +is(focused_ws(), 'next', 'now on workspace next'); + +cmd 'workspace "prev"'; + +ok(workspace_exists('prev'), 'workspace "prev" exists'); +is(focused_ws(), 'prev', 'now on workspace prev'); + +##################################################################### +# check that the numbers are assigned/recognized correctly +##################################################################### + +cmd "workspace 3: $tmp"; +my $ws = get_ws("3: $tmp"); +ok(defined($ws), "workspace 3: $tmp was created"); +is($ws->{num}, 3, 'workspace number is 3'); + +cmd "workspace 0: $tmp"; +my $ws = get_ws("0: $tmp"); +ok(defined($ws), "workspace 0: $tmp was created"); +is($ws->{num}, 0, 'workspace number is 0'); + +cmd "workspace aa: $tmp"; +my $ws = get_ws("aa: $tmp"); +ok(defined($ws), "workspace aa: $tmp was created"); +is($ws->{num}, -1, 'workspace number is -1'); + +done_testing; diff --git a/testcases/t/118-openkill.t b/testcases/t/118-openkill.t new file mode 100644 index 00000000..e2a729c5 --- /dev/null +++ b/testcases/t/118-openkill.t @@ -0,0 +1,40 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests whether opening an empty container and killing it again works +# +use List::Util qw(first); +use i3test; + +my $tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +# Open a new container +cmd 'open'; + +ok(@{get_ws_content($tmp)} == 1, 'container opened'); + +cmd 'kill'; +ok(@{get_ws_content($tmp)} == 0, 'container killed'); + +############################################################## +# open two containers and kill the one which is not focused +# by its ID to test if the parser correctly matches the window +############################################################## + +cmd 'open'; +cmd 'open'; +ok(@{get_ws_content($tmp)} == 2, 'two containers opened'); + +my $content = get_ws_content($tmp); +my $not_focused = first { !$_->{focused} } @{$content}; +my $id = $not_focused->{id}; + +cmd "[con_id=\"$id\"] kill"; + +$content = get_ws_content($tmp); +ok(@{$content} == 1, 'one container killed'); +ok($content->[0]->{id} != $id, 'correct window killed'); + +done_testing; diff --git a/testcases/t/119-match.t b/testcases/t/119-match.t new file mode 100644 index 00000000..8b9d21d3 --- /dev/null +++ b/testcases/t/119-match.t @@ -0,0 +1,170 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests all kinds of matching methods +# +use i3test; +use X11::XCB qw(:all); + +my $tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +# Open a new window +my $x = X11::XCB::Connection->new; +my $window = open_window($x); +my $content = get_ws_content($tmp); +ok(@{$content} == 1, 'window mapped'); +my $win = $content->[0]; + +###################################################################### +# first test that matches which should not match this window really do +# not match it +###################################################################### +# TODO: specify more match types +# we can match on any (non-empty) class here since that window does not have +# WM_CLASS set +cmd q|[class=".*"] kill|; +cmd q|[con_id="99999"] kill|; + +$content = get_ws_content($tmp); +ok(@{$content} == 1, 'window still there'); + +# now kill the window +cmd 'nop now killing the window'; +my $id = $win->{id}; +cmd qq|[con_id="$id"] kill|; + +wait_for_unmap $x; + +cmd 'nop checking if its gone'; +$content = get_ws_content($tmp); +ok(@{$content} == 0, 'window killed'); + +# TODO: same test, but with pcre expressions + +###################################################################### +# check that multiple criteria work are checked with a logical AND, +# not a logical OR (that is, matching is not cancelled after the first +# criterion matches). +###################################################################### + +$tmp = fresh_workspace; + +# TODO: move to X11::XCB +sub set_wm_class { + my ($id, $class, $instance) = @_; + + # Add a _NET_WM_STRUT_PARTIAL hint + my $atomname = $x->atom(name => 'WM_CLASS'); + my $atomtype = $x->atom(name => 'STRING'); + + $x->change_property( + PROP_MODE_REPLACE, + $id, + $atomname->id, + $atomtype->id, + 8, + length($class) + length($instance) + 2, + "$instance\x00$class\x00" + ); +} + +my $left = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + event_mask => [ 'structure_notify' ], +); + +$left->_create; +set_wm_class($left->id, 'special', 'special'); +$left->name('left'); +$left->map; +ok(wait_for_map($x), 'left window mapped'); + +my $right = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + event_mask => [ 'structure_notify' ], +); + +$right->_create; +set_wm_class($right->id, 'special', 'special'); +$right->name('right'); +$right->map; +ok(wait_for_map($x), 'right window mapped'); + +# two windows should be here +$content = get_ws_content($tmp); +ok(@{$content} == 2, 'two windows opened'); + +cmd '[class="special" title="left"] kill'; + +sync_with_i3($x); + +$content = get_ws_content($tmp); +is(@{$content}, 1, 'one window still there'); + +###################################################################### +# check that regular expressions work +###################################################################### + +$tmp = fresh_workspace; + +$left = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + event_mask => [ 'structure_notify' ], +); + +$left->_create; +set_wm_class($left->id, 'special7', 'special7'); +$left->name('left'); +$left->map; +ok(wait_for_map($x), 'left window mapped'); + +# two windows should be here +$content = get_ws_content($tmp); +ok(@{$content} == 1, 'window opened'); + +cmd '[class="^special[0-9]$"] kill'; + +wait_for_unmap $x; + +$content = get_ws_content($tmp); +is(@{$content}, 0, 'window killed'); + +###################################################################### +# check that UTF-8 works when matching +###################################################################### + +$tmp = fresh_workspace; + +$left = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + event_mask => [ 'structure_notify' ], +); + +$left->_create; +set_wm_class($left->id, 'special7', 'special7'); +$left->name('ä 3'); +$left->map; +ok(wait_for_map($x), 'left window mapped'); + +# two windows should be here +$content = get_ws_content($tmp); +ok(@{$content} == 1, 'window opened'); + +cmd '[title="^\w [3]$"] kill'; + +wait_for_unmap $x; + +$content = get_ws_content($tmp); +is(@{$content}, 0, 'window killed'); + +done_testing; diff --git a/testcases/t/12-floating-resize.t b/testcases/t/12-floating-resize.t deleted file mode 100644 index ac3387a9..00000000 --- a/testcases/t/12-floating-resize.t +++ /dev/null @@ -1,65 +0,0 @@ -#!perl -# 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; - -fresh_workspace; - -##################################################################### -# Create a floating window and see if resizing works -##################################################################### - -my $window = open_floating_window($x); - -# 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)); - -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 we’re gonna test, so - # that the test will work. - isnt($absolute->width, 300, 'width != 300'); - isnt($absolute->height, 500, 'height != 500'); - - $window->rect(X11::XCB::Rect->new(x => 0, y => 0, width => 300, height => 500)); - - sync_with_i3($x); - - ($absolute, $top) = $window->rect; - - is($absolute->width, 300, 'width = 300'); - is($absolute->height, 500, 'height = 500'); -} - -# Test with default border -test_resize; - -# Test borderless -cmd 'border none'; - -test_resize; - -# Test with 1-px-border -cmd 'border 1pixel'; - -test_resize; - -done_testing; diff --git a/testcases/t/120-multiple-cmds.t b/testcases/t/120-multiple-cmds.t new file mode 100644 index 00000000..784329fb --- /dev/null +++ b/testcases/t/120-multiple-cmds.t @@ -0,0 +1,56 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests multiple commands (using ';') and multiple operations (using ',') +# +use i3test; + +my $tmp = fresh_workspace; + +sub multiple_cmds { + my ($cmd) = @_; + + cmd 'open'; + cmd 'open'; + ok(@{get_ws_content($tmp)} == 2, 'two containers opened'); + + cmd $cmd; + ok(@{get_ws_content($tmp)} == 0, "both containers killed (cmd = $cmd)"); +} +multiple_cmds('kill;kill'); +multiple_cmds('kill; kill'); +multiple_cmds('kill ; kill'); +multiple_cmds('kill ;kill'); +multiple_cmds('kill ;kill'); +multiple_cmds('kill ; kill'); +multiple_cmds("kill;\tkill"); +multiple_cmds("kill\t;kill"); +multiple_cmds("kill\t;\tkill"); +multiple_cmds("kill\t ;\tkill"); +multiple_cmds("kill\t ;\t kill"); +multiple_cmds("kill \t ; \t kill"); + +##################################################################### +# test if un-quoted strings are handled correctly +##################################################################### + +$tmp = fresh_workspace; +cmd 'open'; +my $unused = get_unused_workspace; +ok(!($unused ~~ @{get_workspace_names()}), 'workspace does not exist yet'); +cmd "move workspace $unused; nop parser test"; +ok(($unused ~~ @{get_workspace_names()}), 'workspace exists after moving'); + +##################################################################### +# quote the workspace name and use a ; (command separator) in its name +##################################################################### + +$unused = get_unused_workspace; +$unused .= ';a'; +ok(!($unused ~~ @{get_workspace_names()}), 'workspace does not exist yet'); +cmd qq|move workspace "$unused"; nop parser test|; +ok(($unused ~~ @{get_workspace_names()}), 'workspace exists after moving'); + +# TODO: need a non-invasive command before implementing a test which uses ',' + +done_testing; diff --git a/testcases/t/121-next-prev.t b/testcases/t/121-next-prev.t new file mode 100644 index 00000000..447be315 --- /dev/null +++ b/testcases/t/121-next-prev.t @@ -0,0 +1,76 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests focus switching (next/prev) +# +use i3test; + +my $tmp = fresh_workspace; + +###################################################################### +# Open one container, verify that 'focus down' and 'focus right' do nothing +###################################################################### +cmd 'open'; + +my ($nodes, $focus) = get_ws_content($tmp); +my $old_focused = $focus->[0]; + +cmd 'focus down'; +($nodes, $focus) = get_ws_content($tmp); +is($focus->[0], $old_focused, 'focus did not change with only one con'); + +cmd 'focus right'; +($nodes, $focus) = get_ws_content($tmp); +is($focus->[0], $old_focused, 'focus did not change with only one con'); + +###################################################################### +# Open another container, verify that 'focus right' switches +###################################################################### +my $left = $old_focused; + +cmd 'open'; +($nodes, $focus) = get_ws_content($tmp); +isnt($old_focused, $focus->[0], 'new container is focused'); +my $mid = $focus->[0]; + +cmd 'open'; +($nodes, $focus) = get_ws_content($tmp); +isnt($old_focused, $focus->[0], 'new container is focused'); +my $right = $focus->[0]; + +cmd 'focus right'; +($nodes, $focus) = get_ws_content($tmp); +isnt($focus->[0], $right, 'focus did change'); +is($focus->[0], $left, 'left container focused (wrapping)'); + +cmd 'focus right'; +($nodes, $focus) = get_ws_content($tmp); +is($focus->[0], $mid, 'middle container focused'); + +cmd 'focus right'; +($nodes, $focus) = get_ws_content($tmp); +is($focus->[0], $right, 'right container focused'); + +cmd 'focus left'; +($nodes, $focus) = get_ws_content($tmp); +is($focus->[0], $mid, 'middle container focused'); + +cmd 'focus left'; +($nodes, $focus) = get_ws_content($tmp); +is($focus->[0], $left, 'left container focused'); + +cmd 'focus left'; +($nodes, $focus) = get_ws_content($tmp); +is($focus->[0], $right, 'right container focused'); + + +###################################################################### +# Test focus command +###################################################################### + +cmd qq|[con_id="$mid"] focus|; +($nodes, $focus) = get_ws_content($tmp); +is($focus->[0], $mid, 'middle container focused'); + + +done_testing; diff --git a/testcases/t/122-split.t b/testcases/t/122-split.t new file mode 100644 index 00000000..3484c7fc --- /dev/null +++ b/testcases/t/122-split.t @@ -0,0 +1,92 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests splitting +# +use i3test; +use X11::XCB qw(:all); + +my $tmp = fresh_workspace; + +my $ws = get_ws($tmp); +is($ws->{orientation}, 'horizontal', 'orientation horizontal by default'); +cmd 'split v'; +$ws = get_ws($tmp); +is($ws->{orientation}, 'vertical', 'split v changes workspace orientation'); + +###################################################################### +# Open two containers, split, open another container. Then verify +# the layout is like we expect it to be +###################################################################### +cmd 'open'; +cmd 'open'; +my $content = get_ws_content($tmp); + +is(@{$content}, 2, 'two containers on workspace level'); +my $first = $content->[0]; +my $second = $content->[1]; + +is(@{$first->{nodes}}, 0, 'first container has no children'); +is(@{$second->{nodes}}, 0, 'second container has no children (yet)'); +my $old_name = $second->{name}; + + +cmd 'split h'; +cmd 'open'; + +$content = get_ws_content($tmp); + +is(@{$content}, 2, 'two containers on workspace level'); +$first = $content->[0]; +$second = $content->[1]; + +is(@{$first->{nodes}}, 0, 'first container has no children'); +isnt($second->{name}, $old_name, 'second container was replaced'); +is($second->{orientation}, 'horizontal', 'orientation is horizontal'); +is(@{$second->{nodes}}, 2, 'second container has 2 children'); +is($second->{nodes}->[0]->{name}, $old_name, 'found old second container'); + +# TODO: extend this test-case (test next/prev) +# - wrapping (no horizontal switch possible, goes level-up) +# - going level-up "manually" + +###################################################################### +# Test splitting multiple times without actually creating windows +###################################################################### + +$tmp = fresh_workspace; + +$ws = get_ws($tmp); +is($ws->{orientation}, 'horizontal', 'orientation horizontal by default'); +cmd 'split v'; +$ws = get_ws($tmp); +is($ws->{orientation}, 'vertical', 'split v changes workspace orientation'); + +cmd 'open'; +my @content = @{get_ws_content($tmp)}; + +# recursively sums up all nodes and their children +sub sum_nodes { + my ($nodes) = @_; + + return 0 if !@{$nodes}; + + my @children = (map { @{$_->{nodes}} } @{$nodes}, + map { @{$_->{'floating_nodes'}} } @{$nodes}); + + return @{$nodes} + sum_nodes(\@children); +} + +my $old_count = sum_nodes(\@content); +cmd 'split v'; + +@content = @{get_ws_content($tmp)}; +$old_count = sum_nodes(\@content); + +cmd 'split v'; + +@content = @{get_ws_content($tmp)}; +my $count = sum_nodes(\@content); +is($count, $old_count, 'not more windows after splitting again'); + +done_testing; diff --git a/testcases/t/124-move.t b/testcases/t/124-move.t new file mode 100644 index 00000000..4df3a2a1 --- /dev/null +++ b/testcases/t/124-move.t @@ -0,0 +1,134 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests moving. Basically, there are four different code-paths: +# 1) move a container which cannot be moved (single container on a workspace) +# 2) move a container before another single container +# 3) move a container inside another container +# 4) move a container in a different direction so that we need to go up in tree +# +use i3test; + +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +###################################################################### +# 1) move a container which cannot be moved +###################################################################### + +cmd 'open'; + +my $old_content = get_ws_content($tmp); +is(@{$old_content}, 1, 'one container on this workspace'); + +my $first = $old_content->[0]->{id}; + +#cmd 'move before h'; +#cmd 'move before v'; +#cmd 'move after v'; +#cmd 'move after h'; + +my $content = get_ws_content($tmp); +#is_deeply($old_content, $content, 'workspace unmodified after useless moves'); + +###################################################################### +# 2) move a container before another single container +###################################################################### + +cmd 'open'; +$content = get_ws_content($tmp); +is(@{$content}, 2, 'two containers on this workspace'); +my $second = $content->[1]->{id}; + +is($content->[0]->{id}, $first, 'first container unmodified'); + +# Move the second container before the first one (→ swap them) +cmd 'move left'; +$content = get_ws_content($tmp); +is($content->[0]->{id}, $second, 'first container modified'); + +# We should not be able to move any further +cmd 'move left'; +$content = get_ws_content($tmp); +is($content->[0]->{id}, $second, 'first container unmodified'); + +# Now move in the other direction +cmd 'move right'; +$content = get_ws_content($tmp); +is($content->[0]->{id}, $first, 'first container modified'); + +# We should not be able to move any further +cmd 'move right'; +$content = get_ws_content($tmp); +is($content->[0]->{id}, $first, 'first container unmodified'); + +###################################################################### +# 3) move a container inside another container +###################################################################### + +# Split the current (second) container and create a new container on workspace +# level. Our layout looks like this now: +# -------------------------- +# | | second | | +# | first | ------ | third | +# | | | | +# -------------------------- +cmd 'split v'; +cmd 'focus parent'; +cmd 'open'; + +$content = get_ws_content($tmp); +is(@{$content}, 3, 'three containers on this workspace'); +my $third = $content->[2]->{id}; + +cmd 'move left'; +$content = get_ws_content($tmp); +is(@{$content}, 2, 'only two containers on this workspace'); +my $nodes = $content->[1]->{nodes}; +is($nodes->[0]->{id}, $second, 'second container on top'); +is($nodes->[1]->{id}, $third, 'third container on bottom'); + +###################################################################### +# move it inside the split container +###################################################################### + +cmd 'move up'; +$nodes = get_ws_content($tmp)->[1]->{nodes}; +is($nodes->[0]->{id}, $third, 'third container on top'); +is($nodes->[1]->{id}, $second, 'second container on bottom'); + +# move it outside again +cmd 'move left'; +$content = get_ws_content($tmp); +is(@{$content}, 3, 'three nodes on this workspace'); + +# due to automatic flattening/cleanup, the remaining split container +# will be replaced by the con itself, so we will still have 3 nodes +cmd 'move right'; +$content = get_ws_content($tmp); +is(@{$content}, 2, 'two nodes on this workspace'); + +###################################################################### +# 4) We create two v-split containers on the workspace, then we move +# all Cons from the left v-split to the right one. The old vsplit +# container needs to be closed. Verify that it will be closed. +###################################################################### + +my $otmp = fresh_workspace; + +cmd "open"; +cmd "open"; +cmd "split v"; +cmd "open"; +cmd 'focus left'; +cmd "split v"; +cmd "open"; +cmd "move right"; +cmd 'focus left'; +cmd "move right"; + +$content = get_ws_content($otmp); +is(@{$content}, 1, 'only one nodes on this workspace'); + +done_testing; diff --git a/testcases/t/126-regress-close.t b/testcases/t/126-regress-close.t new file mode 100644 index 00000000..8aec87d7 --- /dev/null +++ b/testcases/t/126-regress-close.t @@ -0,0 +1,18 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression: closing of floating clients did crash i3 when closing the +# container which contained this client. +# +use i3test; + +fresh_workspace; + +cmd 'open'; +cmd 'mode toggle'; +cmd 'kill'; +cmd 'kill'; + +does_i3_live; + +done_testing; diff --git a/testcases/t/127-regress-floating-parent.t b/testcases/t/127-regress-floating-parent.t new file mode 100644 index 00000000..52b8b9c0 --- /dev/null +++ b/testcases/t/127-regress-floating-parent.t @@ -0,0 +1,41 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression: make a container floating, kill its parent, make it tiling again +# +use i3test; + +my $tmp = fresh_workspace; + +cmd 'open'; +my $left = get_focused($tmp); +cmd 'open'; +my $old = get_focused($tmp); +cmd 'split v'; +cmd 'open'; +my $floating = get_focused($tmp); +diag("focused floating: " . get_focused($tmp)); +cmd 'mode toggle'; +# TODO: eliminate this race conditition +sleep 1; + +# kill old container +cmd qq|[con_id="$old"] focus|; +is(get_focused($tmp), $old, 'old container focused'); +cmd 'kill'; + +# kill left container +cmd qq|[con_id="$left"] focus|; +is(get_focused($tmp), $left, 'old container focused'); +cmd 'kill'; + +# focus floating window, make it tiling again +cmd qq|[con_id="$floating"] focus|; +is(get_focused($tmp), $floating, 'floating window focused'); + +sleep 1; +cmd 'mode toggle'; + +does_i3_live; + +done_testing; diff --git a/testcases/t/128-open-order.t b/testcases/t/128-open-order.t new file mode 100644 index 00000000..b638e708 --- /dev/null +++ b/testcases/t/128-open-order.t @@ -0,0 +1,37 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Check if new containers are opened after the currently focused one instead +# of always at the end +use List::Util qw(first); +use i3test; + +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +# Open two new container +my $first = open_empty_con($i3); + +ok(@{get_ws_content($tmp)} == 1, 'containers opened'); + +my $second = open_empty_con($i3); + +isnt($first, $second, 'different container focused'); + +############################################################## +# see if new containers open after the currently focused +############################################################## + +cmd qq|[con_id="$first"] focus|; +cmd 'open'; +$content = get_ws_content($tmp); +ok(@{$content} == 3, 'three containers opened'); + +is($content->[0]->{id}, $first, 'first container unmodified'); +isnt($content->[1]->{id}, $second, 'second container replaced'); +is($content->[2]->{id}, $second, 'third container unmodified'); + +done_testing; diff --git a/testcases/t/129-focus-after-close.t b/testcases/t/129-focus-after-close.t new file mode 100644 index 00000000..8d225613 --- /dev/null +++ b/testcases/t/129-focus-after-close.t @@ -0,0 +1,122 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Check if the focus is correctly restored after closing windows. +# +use i3test; +use X11::XCB qw(:all); +use List::Util qw(first); + +my $x = X11::XCB::Connection->new; + +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +my $first = open_empty_con($i3); +my $second = open_empty_con($i3); + +cmd 'split v'; + +my ($nodes, $focus) = get_ws_content($tmp); + +ok(!$nodes->[1]->{focused}, 'split container not focused'); +cmd 'focus parent'; +($nodes, $focus) = get_ws_content($tmp); +ok($nodes->[1]->{focused}, 'split container focused after focus parent'); + +my $third = open_empty_con($i3); + +isnt(get_focused($tmp), $second, 'different container focused'); + +# We have the following layout now (con is focused): +# .----------------. +# | split | | +# | .----. | con | +# | | cn | | | +# | `----' | | +# `----------------' + +############################################################## +# see if the focus goes down to $first (not to its split parent) +# when closing $second +############################################################## + +cmd 'kill'; +# TODO: this testcase sometimes has different outcomes when the +# sleep is missing. why? +sleep 0.25; +($nodes, $focus) = get_ws_content($tmp); +is($nodes->[1]->{nodes}->[0]->{id}, $second, 'second container found'); +ok($nodes->[1]->{nodes}->[0]->{focused}, 'second container focused'); + +############################################################## +# another case, using a slightly different layout (regression) +############################################################## + +$tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +cmd 'split v'; +$first = open_empty_con($i3); +my $bottom = open_empty_con($i3); + +cmd 'focus up'; +cmd 'split h'; +my $middle = open_empty_con($i3); +my $right = open_empty_con($i3); +cmd 'focus down'; + +# We have the following layout now (second is focused): +# .----------------------------. +# | .------------------------. | +# | | first | middle | right | | +# | `------------------------' | +# |----------------------------| +# | | +# | second | +# | | +# `----------------------------' + +# Check if the focus is restored to $right when we close $second +cmd 'kill'; + +is(get_focused($tmp), $right, 'top right container focused (in focus stack)'); + +($nodes, $focus) = get_ws_content($tmp); +my $tr = first { $_->{id} eq $right } @{$nodes->[0]->{nodes}}; +is($tr->{focused}, 1, 'top right container really has focus'); + +############################################################## +# check if focus is correct after closing an unfocused window +############################################################## + +$tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +$first = open_empty_con($i3); +$middle = open_empty_con($i3); +# XXX: the $right empty con will be filled with the x11 window we are creating afterwards +$right = open_empty_con($i3); +my $win = open_window($x, { background_color => '#00ff00' }); + +cmd qq|[con_id="$middle"] focus|; +$win->destroy; + +sleep 0.25; + +is(get_focused($tmp), $middle, 'middle container focused'); + +############################################################## +# and now for something completely different: +# check if the pointer position is relevant when restoring focus +# (it should not be relevant, of course) +############################################################## + +# TODO: add test code as soon as I can reproduce it + +done_testing; diff --git a/testcases/t/13-urgent.t b/testcases/t/13-urgent.t deleted file mode 100644 index 7954408f..00000000 --- a/testcases/t/13-urgent.t +++ /dev/null @@ -1,75 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; -use X11::XCB qw(:all); -use List::Util qw(first); - -BEGIN { - use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); -} - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -##################################################################### -# Create two windows and put them in stacking mode -##################################################################### - -cmd 'split v'; - -my $top = open_window($x); -my $bottom = open_window($x); - -my @urgent = grep { $_->{urgent} } @{get_ws_content($tmp)}; -is(@urgent, 0, 'no window got the urgent flag'); - -# cmd 'layout stacking'; - -##################################################################### -# Add the urgency hint, switch to a different workspace and back again -##################################################################### -$top->add_hint('urgency'); -sync_with_i3($x); - -@content = @{get_ws_content($tmp)}; -@urgent = grep { $_->{urgent} } @content; -$top_info = first { $_->{window} == $top->id } @content; -$bottom_info = first { $_->{window} == $bottom->id } @content; - -ok($top_info->{urgent}, 'top window is marked urgent'); -ok(!$bottom_info->{urgent}, 'bottom window is not marked urgent'); -is(@urgent, 1, 'exactly one window got the urgent flag'); - -cmd '[id="' . $top->id . '"] focus'; - -@urgent = grep { $_->{urgent} } @{get_ws_content($tmp)}; -is(@urgent, 0, 'no window got the urgent flag after focusing'); - -$top->add_hint('urgency'); -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'); - -##################################################################### -# Check if the workspace urgency hint gets set/cleared correctly -##################################################################### -my $ws = get_ws($tmp); -ok(!$ws->{urgent}, 'urgent flag not set on workspace'); - -my $otmp = fresh_workspace; - -$top->add_hint('urgency'); -sync_with_i3($x); - -$ws = get_ws($tmp); -ok($ws->{urgent}, 'urgent flag set on workspace'); - -cmd "workspace $tmp"; - -$ws = get_ws($tmp); -ok(!$ws->{urgent}, 'urgent flag not set on workspace after switching'); - -done_testing; diff --git a/testcases/t/130-close-empty-split.t b/testcases/t/130-close-empty-split.t new file mode 100644 index 00000000..57855cd5 --- /dev/null +++ b/testcases/t/130-close-empty-split.t @@ -0,0 +1,82 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Check if empty split containers are automatically closed. +# +use i3test; + +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +my $first = open_empty_con($i3); +my $second = open_empty_con($i3); +cmd qq|[con_id="$first"] focus|; + +cmd 'split v'; + +($nodes, $focus) = get_ws_content($tmp); + +is($nodes->[0]->{focused}, 0, 'split container not focused'); + +# focus the split container +cmd 'level up'; +($nodes, $focus) = get_ws_content($tmp); +my $split = $focus->[0]; +cmd 'level down'; + +my $second = open_empty_con($i3); + +isnt($first, $second, 'different container focused'); + +############################################################## +# close both windows and see if the split container still exists +############################################################## + +cmd 'kill'; +cmd 'kill'; +($nodes, $focus) = get_ws_content($tmp); +isnt($nodes->[0]->{id}, $split, 'split container closed'); + +############################################################## +# same thing but this time we are moving the cons away instead +# of killing them +############################################################## + +$tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +$first = open_empty_con($i3); +$second = open_empty_con($i3); +cmd qq|[con_id="$first"] focus|; + +cmd 'split v'; + +($nodes, $focus) = get_ws_content($tmp); + +is($nodes->[0]->{focused}, 0, 'split container not focused'); + +# focus the split container +cmd 'level up'; +($nodes, $focus) = get_ws_content($tmp); +my $split = $focus->[0]; +cmd 'level down'; + +my $second = open_empty_con($i3); + +isnt($first, $second, 'different container focused'); + +############################################################## +# close both windows and see if the split container still exists +############################################################## + +my $otmp = get_unused_workspace(); +cmd "move workspace $otmp"; +cmd "move workspace $otmp"; +($nodes, $focus) = get_ws_content($tmp); +isnt($nodes->[0]->{id}, $split, 'split container closed'); + +done_testing; diff --git a/testcases/t/131-stacking-order.t b/testcases/t/131-stacking-order.t new file mode 100644 index 00000000..9c1e74ca --- /dev/null +++ b/testcases/t/131-stacking-order.t @@ -0,0 +1,52 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Check if stacking containers can be used independantly of +# the split mode (horizontal/vertical) of the underlying +# container. +# +use i3test; + +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +# Enforce vertical split mode +cmd 'split v'; + +my $first = open_empty_con($i3); +my $second = open_empty_con($i3); + +isnt($first, $second, 'two different containers opened'); + +############################################################## +# change mode to stacking and cycle through the containers +############################################################## + +cmd 'layout stacking'; +is(get_focused($tmp), $second, 'second container still focused'); + +cmd 'focus down'; +is(get_focused($tmp), $first, 'first container focused'); + +cmd 'focus up'; +is(get_focused($tmp), $second, 'second container focused again'); + +############################################################## +# now change the orientation to horizontal and cycle +############################################################## + +cmd 'focus parent'; +cmd 'split h'; +cmd 'focus child'; + +cmd 'focus down'; +is(get_focused($tmp), $first, 'first container focused'); + +cmd 'focus up'; +is(get_focused($tmp), $second, 'second container focused again'); + + +done_testing; diff --git a/testcases/t/132-move-workspace.t b/testcases/t/132-move-workspace.t new file mode 100644 index 00000000..82e59dd1 --- /dev/null +++ b/testcases/t/132-move-workspace.t @@ -0,0 +1,95 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Checks if the 'move workspace' command works correctly +# +use i3test; + +my $i3 = i3(get_socket_path()); + +# We move the pointer out of our way to avoid a bug where the focus will +# be set to the window under the cursor +my $x = X11::XCB::Connection->new; +$x->root->warp_pointer(0, 0); + +my $tmp = get_unused_workspace(); +my $tmp2 = get_unused_workspace(); +cmd "workspace $tmp"; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +my $first = open_empty_con($i3); +my $second = open_empty_con($i3); +ok(@{get_ws_content($tmp)} == 2, 'two containers on first ws'); + +cmd "workspace $tmp2"; +ok(@{get_ws_content($tmp2)} == 0, 'no containers on second ws yet'); + +cmd "workspace $tmp"; + +cmd "move workspace $tmp2"; +ok(@{get_ws_content($tmp)} == 1, 'one container on first ws anymore'); +ok(@{get_ws_content($tmp2)} == 1, 'one container on second ws'); +my ($nodes, $focus) = get_ws_content($tmp2); + +is($focus->[0], $second, 'same container on different ws'); + +($nodes, $focus) = get_ws_content($tmp); +ok($nodes->[0]->{focused}, 'first container focused on first ws'); + +################################################################### +# check if 'move workspace next' and 'move workspace prev' work +################################################################### + +# Open two containers on the first workspace, one container on the second +# workspace. Because the workspaces are named, they will be sorted by order of +# creation. +$tmp = get_unused_workspace(); +$tmp2 = get_unused_workspace(); +cmd "workspace $tmp"; +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); +$first = open_empty_con($i3); +$second = open_empty_con($i3); +ok(@{get_ws_content($tmp)} == 2, 'two containers on first ws'); + +cmd "workspace $tmp2"; +ok(@{get_ws_content($tmp2)} == 0, 'no containers yet'); +my $third = open_empty_con($i3); +ok(@{get_ws_content($tmp2)} == 1, 'one container on second ws'); + +# go back to the first workspace, move one of the containers to the next one +cmd "workspace $tmp"; +cmd 'move workspace next'; +ok(@{get_ws_content($tmp)} == 1, 'one container on first ws'); +ok(@{get_ws_content($tmp2)} == 2, 'two containers on second ws'); + +# go to the second workspace and move two containers to the first one +cmd "workspace $tmp2"; +cmd 'move workspace prev'; +cmd 'move workspace prev'; +ok(@{get_ws_content($tmp)} == 3, 'three containers on first ws'); +ok(@{get_ws_content($tmp2)} == 0, 'no containers on second ws'); + +################################################################### +# check if floating cons are moved to new workspaces properly +# (that is, if they are floating on the target ws, too) +################################################################### + +$tmp = get_unused_workspace(); +$tmp2 = get_unused_workspace(); +cmd "workspace $tmp"; + +cmd "open"; +cmd "floating toggle"; + +my $ws = get_ws($tmp); +is(@{$ws->{nodes}}, 0, 'no nodes on workspace'); +is(@{$ws->{floating_nodes}}, 1, 'one floating node on workspace'); + +cmd "move workspace $tmp2"; + +$ws = get_ws($tmp2); +is(@{$ws->{nodes}}, 0, 'no nodes on workspace'); +is(@{$ws->{floating_nodes}}, 1, 'one floating node on workspace'); + +done_testing; diff --git a/testcases/t/133-size-hints.t b/testcases/t/133-size-hints.t new file mode 100644 index 00000000..d2d77e8e --- /dev/null +++ b/testcases/t/133-size-hints.t @@ -0,0 +1,35 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Checks if size hints are interpreted correctly. +# +use i3test; + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + +my $win = open_window($x, { dont_map => 1 }); +# XXX: we should check screen size. in screens with an AR of 2.0, +# this is not a good idea. +my $aspect = X11::XCB::Sizehints::Aspect->new; +$aspect->min_num(600); +$aspect->min_den(300); +$aspect->max_num(600); +$aspect->max_den(300); +$win->_create; +$win->map; +wait_for_map $x; +$win->hints->aspect($aspect); +$x->flush; + +sync_with_i3($x); + +my $rect = $win->rect; +my $ar = $rect->width / $rect->height; +diag("Aspect ratio = $ar"); +ok(($ar > 1.90) && ($ar < 2.10), 'Aspect ratio about 2.0'); + +done_testing; diff --git a/testcases/t/134-invalid-command.t b/testcases/t/134-invalid-command.t new file mode 100644 index 00000000..d58985e3 --- /dev/null +++ b/testcases/t/134-invalid-command.t @@ -0,0 +1,12 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# +# +use i3test; + +cmd 'blargh!'; + +does_i3_live; + +done_testing; diff --git a/testcases/t/135-floating-focus.t b/testcases/t/135-floating-focus.t new file mode 100644 index 00000000..4c5b562f --- /dev/null +++ b/testcases/t/135-floating-focus.t @@ -0,0 +1,228 @@ +#!perl +# vim:ts=4:sw=4:expandtab + +use i3test; +use X11::XCB qw(:all); +use X11::XCB::Connection; + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +############################################################################# +# 1: see if focus stays the same when toggling tiling/floating mode +############################################################################# + +my $first = open_window($x); +my $second = open_window($x); + +is($x->input_focus, $second->id, 'second window focused'); + +cmd 'floating enable'; +cmd 'floating disable'; + +is($x->input_focus, $second->id, 'second window still focused after mode toggle'); + +############################################################################# +# 2: see if focus stays on the current floating window if killing another +# floating window +############################################################################# + +$tmp = fresh_workspace; + +$first = open_window($x); # window 2 +$second = open_window($x); # window 3 +my $third = open_window($x); # window 4 + +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'; + +# now kill the third one (it's floating). focus should stay unchanged +cmd '[id="' . $third->id . '"] kill'; + +# TODO: wait for unmapnotify +sync_with_i3($x); + +is($x->input_focus, $second->id, 'second con still focused after killing third'); + + +############################################################################# +# 3: see if the focus gets reverted correctly when closing floating clients +# (first to the next floating client, then to the last focused tiling client) +############################################################################# + +$tmp = fresh_workspace; + +$first = open_window($x, '#ff0000'); # window 5 +$second = open_window($x, '#00ff00'); # window 6 +my $third = open_window($x, '#0000ff'); # window 7 + +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'; + +# now kill the second one. focus should fall back to the third one, which is +# also floating +cmd 'kill'; + +# TODO: wait for unmapnotify +sync_with_i3($x); + +is($x->input_focus, $third->id, 'third con focused'); + +cmd 'kill'; +# TODO: wait for unmapnotify +sync_with_i3($x); + +is($x->input_focus, $first->id, 'first con focused after killing all floating cons'); + +############################################################################# +# 4: same test as 3, but with another split con +############################################################################# + +$tmp = fresh_workspace; + +$first = open_window($x, { background_color => '#ff0000' }); # window 5 +cmd 'split v'; +cmd 'layout stacked'; +$second = open_window($x, { background_color => '#00ff00' }); # window 6 +$third = open_window($x, { background_color => '#0000ff' }); # window 7 + +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'; + +sync_with_i3($x); + +# now kill the second one. focus should fall back to the third one, which is +# also floating +cmd 'kill'; + +# TODO: wait for unmapnotify +sync_with_i3($x); + +is($x->input_focus, $third->id, 'third con focused'); + +cmd 'kill'; +# TODO: wait for unmapnotify +sync_with_i3($x); + +is($x->input_focus, $first->id, 'first con focused after killing all floating cons'); + +############################################################################# +# 5: see if the 'focus tiling' and 'focus floating' commands work +############################################################################# + +$tmp = fresh_workspace; + +$first = open_window($x, { background_color => '#ff0000' }); # window 8 +$second = open_window($x, { background_color => '#00ff00' }); # window 9 + +sync_with_i3($x); + +is($x->input_focus, $second->id, 'second container focused'); + +cmd 'floating enable'; + +is($x->input_focus, $second->id, 'second container focused'); + +cmd 'focus tiling'; + +sync_with_i3($x); + +is($x->input_focus, $first->id, 'first (tiling) container focused'); + +cmd 'focus floating'; + +sync_with_i3($x); + +is($x->input_focus, $second->id, 'second (floating) container focused'); + +cmd 'focus floating'; + +sync_with_i3($x); + +is($x->input_focus, $second->id, 'second (floating) container still focused'); + +cmd 'focus mode_toggle'; + +sync_with_i3($x); + +is($x->input_focus, $first->id, 'first (tiling) container focused'); + +cmd 'focus mode_toggle'; + +sync_with_i3($x); + +is($x->input_focus, $second->id, 'second (floating) container focused'); + +############################################################################# +# 6: see if switching floating focus using the focus left/right command works +############################################################################# + +$tmp = fresh_workspace; + +$first = open_floating_window($x, { background_color => '#ff0000' });# window 10 +$second = open_floating_window($x, { background_color => '#00ff00' }); # window 11 +$third = open_floating_window($x, { background_color => '#0000ff' }); # window 12 + +sync_with_i3($x); + +is($x->input_focus, $third->id, 'third container focused'); + +cmd 'focus left'; + +sync_with_i3($x); + +is($x->input_focus, $second->id, 'second container focused'); + +cmd 'focus left'; + +sync_with_i3($x); + +is($x->input_focus, $first->id, 'first container focused'); + +cmd 'focus left'; + +sync_with_i3($x); + +is($x->input_focus, $third->id, 'focus wrapped to third container'); + +cmd 'focus right'; + +sync_with_i3($x); + +is($x->input_focus, $first->id, 'focus wrapped to first container'); + +cmd 'focus right'; + +sync_with_i3($x); + +is($x->input_focus, $second->id, 'focus on second container'); + +done_testing; diff --git a/testcases/t/136-floating-ws-empty.t b/testcases/t/136-floating-ws-empty.t new file mode 100644 index 00000000..a6e0e405 --- /dev/null +++ b/testcases/t/136-floating-ws-empty.t @@ -0,0 +1,35 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# Regression test: when only having a floating window on a workspace, it should not be deleted. + +use i3test; +use X11::XCB qw(:all); + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +############################################################################# +# 1: open a floating window, get it mapped +############################################################################# + +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 = open_floating_window($x); +ok($window->mapped, 'Window is mapped'); + +# switch to a different workspace, see if the window is still mapped? + +my $otmp = fresh_workspace; + +ok(workspace_exists($otmp), "new workspace $otmp exists"); +ok(workspace_exists($tmp), "old workspace $tmp still exists"); + +done_testing; diff --git a/testcases/t/137-floating-unmap.t b/testcases/t/137-floating-unmap.t new file mode 100644 index 00000000..ab1a33d3 --- /dev/null +++ b/testcases/t/137-floating-unmap.t @@ -0,0 +1,37 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# Regression test: Floating windows were not correctly unmapped when switching +# to a different workspace. + +use i3test; +use X11::XCB qw(:all); + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +############################################################################# +# 1: open a floating window, get it mapped +############################################################################# + +my $x = X11::XCB::Connection->new; + +# Create a floating window which is smaller than the minimum enforced size of i3 +my $window = open_floating_window($x); +ok($window->mapped, 'Window is mapped'); + +# switch to a different workspace, see if the window is still mapped? + +my $otmp = fresh_workspace; + +sync_with_i3($x); + +ok(!$window->mapped, 'Window is not mapped after switching ws'); + +cmd "nop testcase done"; + +done_testing; diff --git a/testcases/t/138-floating-attach.t b/testcases/t/138-floating-attach.t new file mode 100644 index 00000000..b08190a2 --- /dev/null +++ b/testcases/t/138-floating-attach.t @@ -0,0 +1,71 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# Regression test: New windows were attached to the container of a floating window +# if only a floating window is present on the workspace. + +use i3test; +use X11::XCB qw(:all); + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +############################################################################# +# 1: open a floating window, get it mapped +############################################################################# + +my $x = X11::XCB::Connection->new; + +# Create a floating window +my $window = open_floating_window($x); +ok($window->mapped, 'Window is mapped'); + +my $ws = get_ws($tmp); +my ($nodes, $focus) = get_ws_content($tmp); + +is(@{$ws->{floating_nodes}}, 1, 'one floating node'); +is(@{$nodes}, 0, 'no tiling nodes'); + +# Create a tiling window +my $twindow = open_window($x); + +($nodes, $focus) = get_ws_content($tmp); + +is(@{$nodes}, 1, 'one tiling node'); + +############################################################################# +# 2: similar case: floating windows should be attached at the currently focused +# position in the workspace (for example a stack), not just at workspace level. +############################################################################# + +$tmp = fresh_workspace; + +my $first = open_window($x); +my $second = open_window($x); + +cmd 'layout stacked'; + +$ws = get_ws($tmp); +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 = open_floating_window($x); +ok($window->mapped, 'Window is mapped'); + +$ws = get_ws($tmp); +is(@{$ws->{floating_nodes}}, 1, 'one floating nodes'); +is(@{$ws->{nodes}}, 1, 'one tiling node (stacked con)'); + +my $third = open_window($x); + + +$ws = get_ws($tmp); +is(@{$ws->{floating_nodes}}, 1, 'one floating nodes'); +is(@{$ws->{nodes}}, 1, 'one tiling node (stacked con)'); + +done_testing; diff --git a/testcases/t/139-ws-numbers.t b/testcases/t/139-ws-numbers.t new file mode 100644 index 00000000..31f013ef --- /dev/null +++ b/testcases/t/139-ws-numbers.t @@ -0,0 +1,60 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# Check if numbered workspaces and named workspaces are sorted in the right way +# in get_workspaces IPC output (necessary for i3bar etc.). +use i3test; +use X11::XCB qw(:all); + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $i3 = i3(get_socket_path()); +my $x = X11::XCB::Connection->new; + +sub check_order { + my ($msg) = @_; + + my @ws = @{$i3->get_workspaces->recv}; + my @nums = map { $_->{num} } grep { defined($_->{num}) } @ws; + my @sorted = sort @nums; + + cmp_deeply(\@nums, \@sorted, $msg); +} + +check_order('workspace order alright before testing'); + +############################################################################# +# open a window to keep this ws open +############################################################################# + +cmd "workspace 93"; + +open_window($x); + +my @ws = @{$i3->get_workspaces->recv}; +my @f = grep { defined($_->{num}) && $_->{num} == 93 } @ws; +is(@f, 1, 'ws 93 found by num'); +check_order('workspace order alright after opening 93'); + +cmd "workspace 92"; +open_window($x); +check_order('workspace order alright after opening 92'); + +cmd "workspace 94"; +open_window($x); +check_order('workspace order alright after opening 94'); + +cmd "workspace 96"; +open_window($x); +check_order('workspace order alright after opening 96'); + +cmd "workspace foo"; +open_window($x); +check_order('workspace order alright after opening foo'); + +cmd "workspace 91"; +open_window($x); +check_order('workspace order alright after opening 91'); + +done_testing; diff --git a/testcases/t/14-client-leader.t b/testcases/t/14-client-leader.t deleted file mode 100644 index 6f7ffce0..00000000 --- a/testcases/t/14-client-leader.t +++ /dev/null @@ -1,96 +0,0 @@ -#!perl -# 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; - -my $tmp = fresh_workspace; - -#################################################################################### -# first part: test if a floating window will be correctly positioned above its leader -# -# This is verified by opening two windows, then opening a floating window above the -# right one, then above the left one. If the floating windows are all positioned alike, -# one of both (depending on your screen resolution) will be positioned wrong. -#################################################################################### - -my $left = open_window($x, { name => 'Left' }); -my $right = open_window($x, { name => 'Right' }); - -my ($abs, $rgeom) = $right->rect; - -my $child = open_floating_window($x, { - dont_map => 1, - name => 'Child window', - }); -$child->client_leader($right); -$child->map; - -ok(wait_for_map($x), 'child window mapped'); - -my $cgeom; -($abs, $cgeom) = $child->rect; -cmp_ok($cgeom->x, '>=', $rgeom->x, 'Child X >= right container X'); - -my $child2 = open_floating_window($x, { - dont_map => 1, - name => 'Child window 2', - }); -$child2->client_leader($left); -$child2->map; - -ok(wait_for_map($x), 'second child window mapped'); - -($abs, $cgeom) = $child2->rect; -cmp_ok(($cgeom->x + $cgeom->width), '<', $rgeom->x, 'child above left window'); - -# check wm_transient_for -my $fwindow = open_window($x, { dont_map => 1 }); -$fwindow->transient_for($right); -$fwindow->map; - -ok(wait_for_map($x), 'transient window mapped'); - -my ($absolute, $top) = $fwindow->rect; -ok($absolute->{x} != 0 && $absolute->{y} != 0, 'i3 did not map it to (0x0)'); - -SKIP: { - skip "(workspace placement by client_leader not yet implemented)", 3; - -##################################################################### -# Create a parent window -##################################################################### - -my $window = open_window($x, { dont_map => 1, name => 'Parent window' }); -$window->map; - -ok(wait_for_map($x), 'parent window mapped'); - -######################################################################### -# Switch to a different workspace and open a child window. It should be opened -# on the old workspace. -######################################################################### -fresh_workspace; - -my $child = open_window($x, { dont_map => 1, name => 'Child window' }); -$child->client_leader($window); -$child->map; - -ok(wait_for_map($x), 'child window mapped'); - -isnt($x->input_focus, $child->id, "Child window focused"); - -# Switch back -cmd "workspace $tmp"; - -is($x->input_focus, $child->id, "Child window focused"); - -} - -done_testing; diff --git a/testcases/t/140-focus-lost.t b/testcases/t/140-focus-lost.t new file mode 100644 index 00000000..fb77f01e --- /dev/null +++ b/testcases/t/140-focus-lost.t @@ -0,0 +1,45 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# Regression: Check if the focus stays the same when switching the layout +# bug introduced by 77d0d42ed2d7ac8cafe267c92b35a81c1b9491eb +use i3test; +use X11::XCB qw(:all); + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $i3 = i3(get_socket_path()); +my $x = X11::XCB::Connection->new; + +sub check_order { + my ($msg) = @_; + + my @ws = @{$i3->get_workspaces->recv}; + my @nums = map { $_->{num} } grep { defined($_->{num}) } @ws; + my @sorted = sort @nums; + + cmp_deeply(\@nums, \@sorted, $msg); +} + +my $tmp = fresh_workspace; + +my $left = open_window($x); +my $mid = open_window($x); +my $right = open_window($x); + +sync_with_i3($x); + +diag("left = " . $left->id . ", mid = " . $mid->id . ", right = " . $right->id); + +is($x->input_focus, $right->id, 'Right window focused'); + +cmd 'focus left'; + +is($x->input_focus, $mid->id, 'Mid window focused'); + +cmd 'layout stacked'; + +is($x->input_focus, $mid->id, 'Mid window focused'); + +done_testing; diff --git a/testcases/t/141-resize.t b/testcases/t/141-resize.t new file mode 100644 index 00000000..8691a044 --- /dev/null +++ b/testcases/t/141-resize.t @@ -0,0 +1,143 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# Tests resizing tiling containers +use i3test; +use X11::XCB qw(:all); + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +cmd 'split v'; + +my $top = open_window($x); +my $bottom = open_window($x); + +sync_with_i3($x); + +diag("top = " . $top->id . ", bottom = " . $bottom->id); + +is($x->input_focus, $bottom->id, 'Bottom window focused'); + +############################################################ +# resize +############################################################ + +cmd 'resize grow up 10 px or 25 ppt'; + +my ($nodes, $focus) = get_ws_content($tmp); + +is($nodes->[0]->{percent}, 0.25, 'top window got only 25%'); +is($nodes->[1]->{percent}, 0.75, 'bottom window got 75%'); + + +############################################################ +# split and check if the 'percent' factor is still correct +############################################################ + +cmd 'split h'; + +($nodes, $focus) = get_ws_content($tmp); + +is($nodes->[0]->{percent}, 0.25, 'top window got only 25%'); +is($nodes->[1]->{percent}, 0.75, 'bottom window got 75%'); + +############################################################ +# checks that resizing within stacked/tabbed cons works +############################################################ + +$tmp = fresh_workspace; + +cmd 'split v'; + +$top = open_window($x); +$bottom = open_window($x); + +cmd 'split h'; +cmd 'layout stacked'; + +($nodes, $focus) = get_ws_content($tmp); +is($nodes->[0]->{percent}, 0.5, 'top window got 50%'); +is($nodes->[1]->{percent}, 0.5, 'bottom window got 50%'); + +cmd 'resize grow up 10 px or 25 ppt'; + +($nodes, $focus) = get_ws_content($tmp); +is($nodes->[0]->{percent}, 0.25, 'top window got 25%'); +is($nodes->[1]->{percent}, 0.75, 'bottom window got 75%'); + +############################################################ +# checks that resizing floating windows works +############################################################ + +$tmp = fresh_workspace; + +$top = open_window($x); + +cmd 'floating enable'; + +my @content = @{get_ws($tmp)->{floating_nodes}}; +cmp_ok(@content, '==', 1, 'one floating node on this ws'); + +# up +my $oldrect = $content[0]->{rect}; + +cmd 'resize grow up 10 px or 25 ppt'; + +@content = @{get_ws($tmp)->{floating_nodes}}; +cmp_ok($content[0]->{rect}->{y}, '<', $oldrect->{y}, 'y smaller than before'); +cmp_ok($content[0]->{rect}->{y}, '==', $oldrect->{y} - 10, 'y exactly 10 px smaller'); +cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x untouched'); +cmp_ok($content[0]->{rect}->{height}, '>', $oldrect->{height}, 'height bigger than before'); +cmp_ok($content[0]->{rect}->{height}, '==', $oldrect->{height} + 10, 'height exactly 10 px higher'); +cmp_ok($content[0]->{rect}->{width}, '==', $oldrect->{width}, 'x untouched'); + +# up, but with a different amount of px +$oldrect = $content[0]->{rect}; + +cmd 'resize grow up 12 px or 25 ppt'; + +@content = @{get_ws($tmp)->{floating_nodes}}; +cmp_ok($content[0]->{rect}->{y}, '<', $oldrect->{y}, 'y smaller than before'); +cmp_ok($content[0]->{rect}->{y}, '==', $oldrect->{y} - 12, 'y exactly 10 px smaller'); +cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x untouched'); +cmp_ok($content[0]->{rect}->{height}, '>', $oldrect->{height}, 'height bigger than before'); +cmp_ok($content[0]->{rect}->{height}, '==', $oldrect->{height} + 12, 'height exactly 10 px higher'); +cmp_ok($content[0]->{rect}->{width}, '==', $oldrect->{width}, 'x untouched'); + +# left +$oldrect = $content[0]->{rect}; + +cmd 'resize grow left 10 px or 25 ppt'; + +@content = @{get_ws($tmp)->{floating_nodes}}; +cmp_ok($content[0]->{rect}->{x}, '<', $oldrect->{x}, 'x smaller than before'); +cmp_ok($content[0]->{rect}->{width}, '>', $oldrect->{width}, 'width bigger than before'); + +# right +$oldrect = $content[0]->{rect}; + +cmd 'resize grow right 10 px or 25 ppt'; + +@content = @{get_ws($tmp)->{floating_nodes}}; +cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x the same as before'); +cmp_ok($content[0]->{rect}->{y}, '==', $oldrect->{y}, 'y the same as before'); +cmp_ok($content[0]->{rect}->{width}, '>', $oldrect->{width}, 'width bigger than before'); +cmp_ok($content[0]->{rect}->{height}, '==', $oldrect->{height}, 'height the same as before'); + +# down +$oldrect = $content[0]->{rect}; + +cmd 'resize grow down 10 px or 25 ppt'; + +@content = @{get_ws($tmp)->{floating_nodes}}; +cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x the same as before'); +cmp_ok($content[0]->{rect}->{y}, '==', $oldrect->{y}, 'y the same as before'); +cmp_ok($content[0]->{rect}->{height}, '>', $oldrect->{height}, 'height bigger than before'); +cmp_ok($content[0]->{rect}->{width}, '==', $oldrect->{width}, 'width the same as before'); + +done_testing; diff --git a/testcases/t/142-regress-move-floating.t b/testcases/t/142-regress-move-floating.t new file mode 100644 index 00000000..6b2df806 --- /dev/null +++ b/testcases/t/142-regress-move-floating.t @@ -0,0 +1,17 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression: move a floating window to a different workspace crashes i3 +# +use i3test; + +my $tmp = fresh_workspace; +my $otmp = get_unused_workspace(); + +cmd 'open'; +cmd 'mode toggle'; +cmd "move workspace $otmp"; + +does_i3_live; + +done_testing; diff --git a/testcases/t/143-regress-floating-restart.t b/testcases/t/143-regress-floating-restart.t new file mode 100644 index 00000000..babbb574 --- /dev/null +++ b/testcases/t/143-regress-floating-restart.t @@ -0,0 +1,23 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression: floating windows are tiling after restarting, closing them crashes i3 +# +use i3test; + +my $tmp = fresh_workspace; + +cmd 'open'; +cmd 'mode toggle'; +cmd 'restart'; + +sleep 0.5; + +diag('Checking if i3 still lives'); + +does_i3_live; + +my $ws = get_ws($tmp); +diag('ws = ' . Dumper($ws)); + +done_testing; diff --git a/testcases/t/144-regress-floating-resize.t b/testcases/t/144-regress-floating-resize.t new file mode 100644 index 00000000..de33eeb3 --- /dev/null +++ b/testcases/t/144-regress-floating-resize.t @@ -0,0 +1,37 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression: when resizing two containers on a workspace, opening a floating +# client, then closing it again, i3 will re-distribute the space on the +# workspace as if a tiling container was closed, leading to the containers +# taking much more space than they possibly could. +# +use i3test; +use List::Util qw(sum); + +my $tmp = fresh_workspace; + +cmd 'exec /usr/bin/urxvt'; +sleep 0.5; +cmd 'exec /usr/bin/urxvt'; +sleep 0.5; +my ($nodes, $focus) = get_ws_content($tmp); +my $old_sum = sum map { $_->{rect}->{width} } @{$nodes}; +#cmd 'open'; +cmd 'resize grow left 10 px or 25 ppt'; +cmd 'split v'; +#cmd 'open'; +cmd 'exec /usr/bin/urxvt'; +sleep 0.5; +cmd 'mode toggle'; +sleep 0.5; +cmd 'kill'; + +sleep 0.5; + +($nodes, $focus) = get_ws_content($tmp); +my $new_sum = sum map { $_->{rect}->{width} } @{$nodes}; + +is($old_sum, $new_sum, 'combined container width is still equal'); + +done_testing; diff --git a/testcases/t/145-flattening.t b/testcases/t/145-flattening.t new file mode 100644 index 00000000..904252e7 --- /dev/null +++ b/testcases/t/145-flattening.t @@ -0,0 +1,31 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# by moving the window in the opposite orientation that its parent has, we +# force i3 to create a new split container with the appropriate orientation. +# However, when doing that two times in a row, we end up with two split +# containers which are then redundant (workspace is horizontal, then v-split, +# then h-split – we could just append the children of the latest h-split to the +# workspace itself). +# +# This testcase checks that the tree is properly flattened after moving. +# +use X11::XCB qw(:all); +use i3test; + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +my $left = open_window($x); +my $mid = open_window($x); +my $right = open_window($x); + +cmd 'move before v'; +cmd 'move after h'; +my $ws = get_ws($tmp); + +is($ws->{orientation}, 'horizontal', 'workspace orientation is horizontal'); +is(@{$ws->{nodes}}, 3, 'all three windows on workspace level'); + +done_testing; diff --git a/testcases/t/146-floating-reinsert.t b/testcases/t/146-floating-reinsert.t new file mode 100644 index 00000000..bc1302bb --- /dev/null +++ b/testcases/t/146-floating-reinsert.t @@ -0,0 +1,44 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +use X11::XCB qw(:all); +use i3test; + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +my $left = open_window($x); +my $mid = open_window($x); + +cmd 'split v'; +my $bottom = open_window($x); + +my ($nodes, $focus) = get_ws_content($tmp); + +############################################################################# +# 1: open a floating window, get it mapped +############################################################################# + +# Create a floating window +my $window = open_floating_window($x); +ok($window->mapped, 'Window is mapped'); + +($nodes, $focus) = get_ws_content($tmp); +is(@{$nodes->[1]->{nodes}}, 2, 'two windows in split con'); + +############################################################################# +# 2: make it tiling, see where it ends up +############################################################################# + +cmd 'floating toggle'; + +my ($nodes, $focus) = get_ws_content($tmp); + +is(@{$nodes->[1]->{nodes}}, 3, 'three windows in split con after floating toggle'); + +done_testing; diff --git a/testcases/t/147-regress-floatingmove.t b/testcases/t/147-regress-floatingmove.t new file mode 100644 index 00000000..771ace32 --- /dev/null +++ b/testcases/t/147-regress-floatingmove.t @@ -0,0 +1,44 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression test for moving a con outside of a floating con when there are no +# tiling cons on a workspace +# +use X11::XCB qw(:all); +use Time::HiRes qw(sleep); +use i3test; + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +my $left = open_window($x); +my $mid = open_window($x); +my $right = open_window($x); + +# go to workspace level +cmd 'level up'; +sleep 0.25; + +# make it floating +cmd 'mode toggle'; +sleep 0.25; + +# move the con outside the floating con +cmd 'move before v'; +sleep 0.25; + +does_i3_live; + +# move another con outside +cmd '[id="' . $mid->id . '"] focus'; +cmd 'move before v'; +sleep 0.25; + +does_i3_live; + +done_testing; diff --git a/testcases/t/148-regress-floatingmovews.t b/testcases/t/148-regress-floatingmovews.t new file mode 100644 index 00000000..6f9dfc40 --- /dev/null +++ b/testcases/t/148-regress-floatingmovews.t @@ -0,0 +1,38 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression test for correct focus behaviour when moving a floating con to +# another workspace. +# +use X11::XCB qw(:all); +use i3test; + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +# open a tiling window on the first workspace +open_window($x); +#sleep 0.25; +my $first = get_focused($tmp); + +# on a different ws, open a floating window +my $otmp = fresh_workspace; +open_window($x); +#sleep 0.25; +my $float = get_focused($otmp); +cmd 'mode toggle'; +#sleep 0.25; + +# move the floating con to first workspace +cmd "move workspace $tmp"; +#sleep 0.25; + +# switch to the first ws and check focus +is(get_focused($tmp), $float, 'floating client correctly focused'); + +done_testing; diff --git a/testcases/t/15-ipc-workspaces.t b/testcases/t/15-ipc-workspaces.t deleted file mode 100644 index 4d9a0294..00000000 --- a/testcases/t/15-ipc-workspaces.t +++ /dev/null @@ -1,24 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; - -my $i3 = i3(get_socket_path()); - -#################### -# Request workspaces -#################### - -SKIP: { - skip "IPC API not yet stabilized", 2; - -my $workspaces = $i3->get_workspaces->recv; - -ok(@{$workspaces} > 0, "More than zero workspaces found"); - -#my $name_exists = all { defined($_->{name}) } @{$workspaces}; -#ok($name_exists, "All workspaces have a name"); - -} - -done_testing; diff --git a/testcases/t/150-regress-dock-restart.t b/testcases/t/150-regress-dock-restart.t new file mode 100644 index 00000000..e294e6bd --- /dev/null +++ b/testcases/t/150-regress-dock-restart.t @@ -0,0 +1,97 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression test for inplace restarting with dock clients +# +use X11::XCB qw(:all); +use i3test; + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +##################################################################### +# verify that there is no dock window yet +##################################################################### + +# Children of all dockareas +my @docked = get_dock_clients; + +is(@docked, 0, 'no dock clients yet'); + +# open a dock client + +my $window = open_window($x, { + background_color => '#FF0000', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + }); + +##################################################################### +# check that we can find it in the layout tree at the expected position +##################################################################### + +@docked = get_dock_clients; +is(@docked, 1, 'one dock client found'); + +# verify the height +my $docknode = $docked[0]; + +is($docknode->{rect}->{height}, 30, 'dock node has unchanged height'); + +# perform an inplace-restart +cmd 'restart'; + +sleep 0.25; + +does_i3_live; + + +##################################################################### +# check that we can still find the dock client +##################################################################### + +@docked = get_dock_clients; +is(@docked, 1, 'one dock client found'); +$docknode = $docked[0]; + +is($docknode->{rect}->{height}, 30, 'dock node has unchanged height after restart'); + +$window->destroy; + +wait_for_unmap $x; + +@docked = get_dock_clients; +is(@docked, 0, 'no dock clients found'); + +##################################################################### +# create a dock client with a 1px border +##################################################################### + +$window = open_window($x, { + border => 1, + rect => [ 0, 0, 30, 20 ], + background_color => '#00FF00', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + }); + +@docked = get_dock_clients; +is(@docked, 1, 'one dock client found'); +$docknode = $docked[0]; + +is($docknode->{rect}->{height}, 20, 'dock node has unchanged height'); + +cmd 'restart'; +sleep 0.25; + +@docked = get_dock_clients; +is(@docked, 1, 'one dock client found'); +$docknode = $docked[0]; + +is($docknode->{rect}->{height}, 20, 'dock node has unchanged height'); + + +done_testing; diff --git a/testcases/t/151-regress-float-size.t b/testcases/t/151-regress-float-size.t new file mode 100644 index 00000000..881ef8c1 --- /dev/null +++ b/testcases/t/151-regress-float-size.t @@ -0,0 +1,17 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression test for setting a window to floating, tiling and opening a new window +# +use i3test; + +fresh_workspace; + +cmd 'open'; +cmd 'mode toggle'; +cmd 'mode toggle'; +cmd 'open'; + +does_i3_live; + +done_testing; diff --git a/testcases/t/152-regress-level-up.t b/testcases/t/152-regress-level-up.t new file mode 100644 index 00000000..678cdd9c --- /dev/null +++ b/testcases/t/152-regress-level-up.t @@ -0,0 +1,18 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression test for using level-up to get to the 'content'-container and +# toggle floating +# +use i3test; + +fresh_workspace; + +cmd 'open'; +cmd 'level up'; +cmd 'level up'; +cmd 'mode toggle'; + +does_i3_live; + +done_testing; diff --git a/testcases/t/153-floating-originalsize.t b/testcases/t/153-floating-originalsize.t new file mode 100644 index 00000000..db0b6e9c --- /dev/null +++ b/testcases/t/153-floating-originalsize.t @@ -0,0 +1,40 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Test if the requested width/height is set after making the window floating. +# +use X11::XCB qw(:all); +use i3test; + +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 = open_window($x, { rect => [ 0, 0, 400, 150 ] }); + +my ($absolute, $top) = $window->rect; + +ok($window->mapped, 'Window is mapped'); +cmp_ok($absolute->{width}, '>', 400, 'i3 raised the width'); +cmp_ok($absolute->{height}, '>', 150, 'i3 raised the height'); + +cmd 'floating toggle'; +sync_with_i3($x); + +($absolute, $top) = $window->rect; + +diag('new width: ' . $absolute->{width}); +diag('new height: ' . $absolute->{height}); + +# we compare with a tolerance of ± 20 pixels for borders in each direction +# (overkill, but hey) +cmp_ok($absolute->{width}, '>', 400-20, 'width now > 380'); +cmp_ok($absolute->{width}, '<', 400+20, 'width now < 420'); +cmp_ok($absolute->{height}, '>', 150-20, 'height now > 130'); +cmp_ok($absolute->{height}, '<', 150+20, 'height now < 170'); + +#cmp_ok($absolute->{width}, '>=', 75, 'i3 raised the width to 75'); +#cmp_ok($absolute->{height}, '>=', 50, 'i3 raised the height to 50'); + +done_testing; diff --git a/testcases/t/154-regress-multiple-dock.t b/testcases/t/154-regress-multiple-dock.t new file mode 100644 index 00000000..21cb9696 --- /dev/null +++ b/testcases/t/154-regress-multiple-dock.t @@ -0,0 +1,57 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression test for closing one of multiple dock clients +# +use X11::XCB qw(:all); +use i3test; + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +##################################################################### +# verify that there is no dock window yet +##################################################################### + +# Children of all dockareas +my @docked = get_dock_clients; + +is(@docked, 0, 'no dock clients yet'); + +##################################################################### +# open a dock client +##################################################################### + +my $first = open_window($x, { + background_color => '#FF0000', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + }); + +##################################################################### +# Open a second dock client +##################################################################### + +my $second = open_window($x, { + background_color => '#FF0000', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + }); + +##################################################################### +# Kill the second dock client +##################################################################### +cmd "nop destroying dock client"; +$second->destroy; + +##################################################################### +# Now issue a focus command +##################################################################### +cmd 'next v'; + +does_i3_live; + +done_testing; diff --git a/testcases/t/155-floating-split-size.t b/testcases/t/155-floating-split-size.t new file mode 100644 index 00000000..5de05e8b --- /dev/null +++ b/testcases/t/155-floating-split-size.t @@ -0,0 +1,57 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Test to see if i3 combines the geometry of all children in a split container +# when setting the split container to floating +# +use X11::XCB qw(:all); +use i3test; + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +##################################################################### +# open a window with 200x80 +##################################################################### + +my $first = open_window($x, { + rect => [ 0, 0, 200, 80], + background_color => '#FF0000', + }); + +##################################################################### +# Open a second window with 300x90 +##################################################################### + +my $second = open_window($x, { + rect => [ 0, 0, 300, 90], + background_color => '#00FF00', + }); + +##################################################################### +# Set the parent to floating +##################################################################### +cmd 'nop setting floating'; +cmd 'focus parent'; +cmd 'floating enable'; + +##################################################################### +# Get geometry of the first floating node (the split container) +##################################################################### + +my @nodes = @{get_ws($tmp)->{floating_nodes}}; +my $rect = $nodes[0]->{rect}; + +# we compare the width with ± 20 pixels for borders +cmp_ok($rect->{width}, '>', 500-20, 'width now > 480'); +cmp_ok($rect->{width}, '<', 500+20, 'width now < 520'); +# we compare the height with ± 40 pixels for decorations +cmp_ok($rect->{height}, '>', 90-40, 'width now > 50'); +cmp_ok($rect->{height}, '<', 90+40, 'width now < 130'); + +done_testing; diff --git a/testcases/t/156-fullscreen-focus.t b/testcases/t/156-fullscreen-focus.t new file mode 100644 index 00000000..a559b5a5 --- /dev/null +++ b/testcases/t/156-fullscreen-focus.t @@ -0,0 +1,71 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Test if new containers get focused when there is a fullscreen container at +# the time of launching the new one. +# +use X11::XCB qw(:all); +use i3test; + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +##################################################################### +# open the left window +##################################################################### + +my $left = open_window($x, { background_color => '#ff0000' }); + +is($x->input_focus, $left->id, 'left window focused'); + +diag("left = " . $left->id); + +##################################################################### +# Open the right window +##################################################################### + +my $right = open_window($x, { background_color => '#00ff00' }); + +diag("right = " . $right->id); + +##################################################################### +# Set the right window to fullscreen +##################################################################### +cmd 'nop setting fullscreen'; +cmd 'fullscreen'; + +##################################################################### +# Open a third window +##################################################################### + +my $third = open_window($x, { + background_color => '#0000ff', + name => 'Third window', + dont_map => 1, + }); + +$third->map; + +sync_with_i3 $x; + +diag("third = " . $third->id); + +# move the fullscreen window to a different ws + +my $tmp2 = get_unused_workspace; + +cmd "move workspace $tmp2"; + +# verify that the third window has the focus + +sync_with_i3($x); + +is($x->input_focus, $third->id, 'third window focused'); + +done_testing; diff --git a/testcases/t/157-regress-fullscreen-level-up.t b/testcases/t/157-regress-fullscreen-level-up.t new file mode 100644 index 00000000..7a101dbc --- /dev/null +++ b/testcases/t/157-regress-fullscreen-level-up.t @@ -0,0 +1,48 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression test: level up should be a noop during fullscreen mode +# +use X11::XCB qw(:all); +use i3test; + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; + +my $tmp = fresh_workspace; + +##################################################################### +# open a window, verify it’s not in fullscreen mode +##################################################################### + +my $win = open_window($x); + +my $nodes = get_ws_content $tmp; +is(@$nodes, 1, 'exactly one client'); +is($nodes->[0]->{fullscreen_mode}, 0, 'client not fullscreen'); + +##################################################################### +# make it fullscreen +##################################################################### + +cmd 'nop making fullscreen'; +cmd 'fullscreen'; + +my $nodes = get_ws_content $tmp; +is($nodes->[0]->{fullscreen_mode}, 1, 'client fullscreen now'); + +##################################################################### +# send level up, try to un-fullscreen +##################################################################### +cmd 'level up'; +cmd 'fullscreen'; + +my $nodes = get_ws_content $tmp; +is($nodes->[0]->{fullscreen_mode}, 0, 'client not fullscreen any longer'); + +does_i3_live; + +done_testing; diff --git a/testcases/t/158-wm_take_focus.t b/testcases/t/158-wm_take_focus.t new file mode 100644 index 00000000..a90ce1c3 --- /dev/null +++ b/testcases/t/158-wm_take_focus.t @@ -0,0 +1,44 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests if the WM_TAKE_FOCUS protocol is correctly handled by i3 +# +use X11::XCB qw(:all); +use i3test; +use v5.10; + +my $x = X11::XCB::Connection->new; + +subtest 'Window without WM_TAKE_FOCUS', sub { + fresh_workspace; + + my $window = open_window($x); + + ok(!wait_for_event($x, 1, sub { $_[0]->{response_type} == 161 }), 'did not receive ClientMessage'); + + done_testing; +}; + +subtest 'Window with WM_TAKE_FOCUS', sub { + fresh_workspace; + + my $take_focus = $x->atom(name => 'WM_TAKE_FOCUS'); + + my $window = open_window($x, { + dont_map => 1, + protocols => [ $take_focus ], + }); + + $window->map; + + ok(wait_for_event($x, 1, sub { + return 0 unless $_[0]->{response_type} == 161; + my ($data, $time) = unpack("L2", $_[0]->{data}); + return ($data == $take_focus->id); + }), 'got ClientMessage with WM_TAKE_FOCUS atom'); + + done_testing; +}; + + +done_testing; diff --git a/testcases/t/159-socketpaths.t b/testcases/t/159-socketpaths.t new file mode 100644 index 00000000..eb6bd79f --- /dev/null +++ b/testcases/t/159-socketpaths.t @@ -0,0 +1,70 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 +# +# Tests if the various ipc_socket_path options are correctly handled +# +use i3test; +use File::Temp qw(tempfile tempdir); +use POSIX qw(getuid); +use v5.10; + +##################################################################### +# default case: socket will be created in /tmp/i3-/ipc-socket. +##################################################################### + +my $config = < +##################################################################### + +my $rtdir = tempdir(CLEANUP => 1); + +ok(! -e "$rtdir/i3", "$rtdir/i3 does not exist yet"); + +$ENV{XDG_RUNTIME_DIR} = $rtdir; + +$pid = launch_with_config($config, 1); + +ok(-d "$rtdir/i3", "$rtdir/i3 exists and is a directory"); +$socketpath = "$rtdir/i3/ipc-socket." . $pid; +ok(-S $socketpath, "file $socketpath exists and is a socket"); + +exit_gracefully($pid); + +##################################################################### +# configuration file case: socket gets placed whereever we specify +##################################################################### + +my $tmpdir = tempdir(CLEANUP => 1); +$socketpath = $tmpdir . "/config.sock"; +ok(! -e $socketpath, "$socketpath does not exist yet"); + +$config = <(); - } - return 1; -} - -sub none (&@) { - my $cb = shift; - for (@_) { - return 0 if $cb->(); - } - return 1; -} - -my $i3 = i3(get_socket_path()); - -#################### -# Request tree -#################### - -my $tree = $i3->get_tree->recv; - -my $expected = { - fullscreen_mode => 0, - nodes => ignore(), - window => undef, - name => 'root', - orientation => ignore(), - type => 0, - id => ignore(), - rect => ignore(), - window_rect => ignore(), - geometry => ignore(), - swallows => ignore(), - percent => undef, - layout => 'default', - focus => ignore(), - focused => JSON::XS::false, - urgent => JSON::XS::false, - border => 'normal', - 'floating_nodes' => ignore(), -}; - -cmp_deeply($tree, $expected, 'root node OK'); - -my @nodes = @{$tree->{nodes}}; - -ok(@nodes > 0, 'root node has at least one leaf'); - -ok((all { $_->{type} == 1 } @nodes), 'all nodes are of type CT_OUTPUT'); -ok((none { defined($_->{window}) } @nodes), 'no CT_OUTPUT contains a window'); -ok((all { @{$_->{nodes}} > 0 } @nodes), 'all nodes have at least one leaf (workspace)'); -my @workspaces; -for my $ws (@nodes) { - my $content = first { $_->{type} == 2 } @{$ws->{nodes}}; - @workspaces = (@workspaces, @{$content->{nodes}}); -} - -ok((all { $_->{type} == 4 } @workspaces), 'all workspaces are of type CT_WORKSPACE'); -#ok((all { @{$_->{nodes}} == 0 } @workspaces), 'all workspaces are empty yet'); -ok((none { defined($_->{window}) } @workspaces), 'no CT_OUTPUT contains a window'); - -# TODO: get the focused container - -$i3->command('open')->recv; - -# TODO: get the focused container, check if it changed. -# TODO: get the old focused container, check if there is a new child - -#diag(Dumper(\@workspaces)); - -#diag(Dumper($tree)); - - -done_testing; diff --git a/testcases/t/161-regress-borders-restart.t b/testcases/t/161-regress-borders-restart.t new file mode 100644 index 00000000..c5e3ef80 --- /dev/null +++ b/testcases/t/161-regress-borders-restart.t @@ -0,0 +1,39 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression test to check if borders are correctly restored after an inplace +# restart. +# found in eb8ad348b28e243cba1972e802ca8ee636472fc9 +# +use X11::XCB qw(:all); +use List::Util qw(first); +use i3test; + +my $x = X11::XCB::Connection->new; +my $i3 = i3(get_socket_path()); +my $tmp = fresh_workspace; +my $window = open_window($x); + +sub get_border_style { + my @content = @{get_ws_content($tmp)}; + my $wininfo = first { $_->{window} == $window->id } @content; + + return $wininfo->{border}; +} + +is(get_border_style(), 'normal', 'border style normal'); + +cmd 'border 1pixel'; + +is(get_border_style(), '1pixel', 'border style 1pixel after changing'); + +# perform an inplace-restart +cmd 'restart'; + +sleep 0.25; + +does_i3_live; + +is(get_border_style(), '1pixel', 'border style still 1pixel after restart'); + +done_testing; diff --git a/testcases/t/162-regress-dock-urgent.t b/testcases/t/162-regress-dock-urgent.t new file mode 100644 index 00000000..5fb88129 --- /dev/null +++ b/testcases/t/162-regress-dock-urgent.t @@ -0,0 +1,59 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression test for setting the urgent hint on dock clients. +# found in 4be3178d4d360c2996217d811e61161c84d25898 +# +use X11::XCB qw(:all); +use i3test; + +BEGIN { + use_ok('X11::XCB::Window'); +} + +my $x = X11::XCB::Connection->new; +my $i3 = i3(get_socket_path()); + +my $tmp = fresh_workspace; + +##################################################################### +# verify that there is no dock window yet +##################################################################### + +# Children of all dockareas +my @docked = get_dock_clients; + +is(@docked, 0, 'no dock clients yet'); + +# open a dock client + +my $window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30], + background_color => '#FF0000', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), +); + +$window->map; + +sleep 0.25; + +##################################################################### +# check that we can find it in the layout tree at the expected position +##################################################################### + +@docked = get_dock_clients; +is(@docked, 1, 'one dock client found'); + +# verify the height +my $docknode = $docked[0]; + +is($docknode->{rect}->{height}, 30, 'dock node has unchanged height'); + +$window->add_hint('urgency'); + +sync_with_i3($x); + +does_i3_live; + +done_testing; diff --git a/testcases/t/163-wm-state.t b/testcases/t/163-wm-state.t new file mode 100644 index 00000000..e55d8682 --- /dev/null +++ b/testcases/t/163-wm-state.t @@ -0,0 +1,24 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests if WM_STATE is WM_STATE_NORMAL when mapped and WM_STATE_WITHDRAWN when +# unmapped. +# +use X11::XCB qw(:all); +use i3test; + +my $x = X11::XCB::Connection->new; + +my $window = open_window($x); + +sync_with_i3($x); + +is($window->state, ICCCM_WM_STATE_NORMAL, 'WM_STATE normal'); + +$window->unmap; + +wait_for_unmap $x; + +is($window->state, ICCCM_WM_STATE_WITHDRAWN, 'WM_STATE withdrawn'); + +done_testing; diff --git a/testcases/t/164-kill-win-vs-client.t b/testcases/t/164-kill-win-vs-client.t new file mode 100644 index 00000000..ef45a789 --- /dev/null +++ b/testcases/t/164-kill-win-vs-client.t @@ -0,0 +1,66 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests if WM_STATE is WM_STATE_NORMAL when mapped and WM_STATE_WITHDRAWN when +# unmapped. +# +use i3test; + +my $x = X11::XCB::Connection->new; + +sub two_windows { + my $tmp = fresh_workspace; + + ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); + + my $first = open_window($x); + my $second = open_window($x); + + sync_with_i3 $x; + + is($x->input_focus, $second->id, 'second window focused'); + ok(@{get_ws_content($tmp)} == 2, 'two containers opened'); + + return $tmp; +} + +############################################################## +# 1: open two windows (in the same client), kill one and see if +# the other one is still there +############################################################## + +my $tmp = two_windows; + +cmd 'kill'; + +sleep 0.25; + +ok(@{get_ws_content($tmp)} == 1, 'one container left after killing'); + +############################################################## +# 2: same test case as test 1, but with the explicit variant +# 'kill window' +############################################################## + +my $tmp = two_windows; + +cmd 'kill window'; + +sleep 0.25; + +ok(@{get_ws_content($tmp)} == 1, 'one container left after killing'); + +############################################################## +# 3: open two windows (in the same client), use 'kill client' +# and check if both are gone +############################################################## + +my $tmp = two_windows; + +cmd 'kill client'; + +sleep 0.25; + +ok(@{get_ws_content($tmp)} == 0, 'no containers left after killing'); + +done_testing; diff --git a/testcases/t/165-for_window.t b/testcases/t/165-for_window.t new file mode 100644 index 00000000..cc100132 --- /dev/null +++ b/testcases/t/165-for_window.t @@ -0,0 +1,469 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 +# +# +use X11::XCB qw(:all); +use X11::XCB::Connection; +use i3test; + +my $x = X11::XCB::Connection->new; + +############################################################## +# 1: test the following directive: +# for_window [class="borderless"] border none +# by first creating a window with a different class (should get +# the normal border), then creating a window with the class +# "borderless" (should get no border) +############################################################## + +my $config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#00ff00', + event_mask => [ 'structure_notify' ], +); + +$window->name('Border window'); +$window->map; +wait_for_map $x; + +my @content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'normal', 'normal border'); + +$window->unmap; +wait_for_unmap $x; + +my @content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 0, 'no more nodes'); +diag('content = '. Dumper(\@content)); + +$window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#00ff00', + event_mask => [ 'structure_notify' ], +); + +$window->_create; + +# TODO: move this to X11::XCB::Window +sub set_wm_class { + my ($id, $class, $instance) = @_; + + # Add a _NET_WM_STRUT_PARTIAL hint + my $atomname = $x->atom(name => 'WM_CLASS'); + my $atomtype = $x->atom(name => 'STRING'); + + $x->change_property( + PROP_MODE_REPLACE, + $id, + $atomname->id, + $atomtype->id, + 8, + length($class) + length($instance) + 2, + "$instance\x00$class\x00" + ); +} + +set_wm_class($window->id, 'borderless', 'borderless'); +$window->name('Borderless window'); +$window->map; +wait_for_map $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'none', 'no border'); + +$window->unmap; +wait_for_unmap $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 0, 'no more nodes'); + +exit_gracefully($pid); + +############################################################## +# 2: match on the title, check if for_window is really executed +# only once +############################################################## + +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#00ff00', + event_mask => [ 'structure_notify' ], +); + +$window->name('special title'); +$window->map; +wait_for_map $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'normal', 'normal border'); + +$window->name('special borderless title'); +sync_with_i3 $x; + +@content = @{get_ws_content($tmp)}; +is($content[0]->{border}, 'none', 'no border'); + +$window->name('special title'); +sync_with_i3 $x; + +cmd 'border normal'; + +@content = @{get_ws_content($tmp)}; +is($content[0]->{border}, 'normal', 'border reset to normal'); + +$window->name('special borderless title'); +sync_with_i3 $x; + +@content = @{get_ws_content($tmp)}; +is($content[0]->{border}, 'normal', 'still normal border'); + +$window->unmap; +wait_for_unmap $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 0, 'no more nodes'); + +exit_gracefully($pid); + +############################################################## +# 3: match on the title, set border style *and* a mark +############################################################## + +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#00ff00', + event_mask => [ 'structure_notify' ], +); + +$window->name('special mark title'); +$window->map; +wait_for_map $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'none', 'no border'); + +my $other = open_window($x); + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 2, 'two nodes'); +is($content[0]->{border}, 'none', 'no border'); +is($content[1]->{border}, 'normal', 'normal border'); +ok(!$content[0]->{focused}, 'first one not focused'); + +cmd qq|[con_mark="bleh"] focus|; + +@content = @{get_ws_content($tmp)}; +ok($content[0]->{focused}, 'first node focused'); + +exit_gracefully($pid); + +############################################################## +# 4: multiple criteria for the for_window command +############################################################## + +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#00ff00', + event_mask => [ 'structure_notify' ], +); + +$window->_create; + +set_wm_class($window->id, 'borderless', 'borderless'); +$window->name('usethis'); +$window->map; +wait_for_map $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'none', 'no border'); + +cmd 'kill'; +wait_for_unmap $x; +$window->destroy; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 0, 'no nodes on this workspace now'); + +$window->_create; + +set_wm_class($window->id, 'borderless', 'borderless'); +$window->name('notthis'); +$window->map; +wait_for_map $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'normal', 'no border'); + + +exit_gracefully($pid); + +############################################################## +# 5: check that a class criterion does not match the instance +############################################################## + +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#00ff00', + event_mask => [ 'structure_notify' ], +); + +$window->_create; + +set_wm_class($window->id, 'bar', 'foo'); +$window->name('usethis'); +$window->map; +wait_for_map $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'normal', 'normal border, not matched'); + +exit_gracefully($pid); + +############################################################## +# 6: check that the 'instance' criterion works +############################################################## + +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#00ff00', + event_mask => [ 'structure_notify' ], +); + +$window->_create; + +set_wm_class($window->id, 'bar', 'foo'); +$window->name('usethis'); +$window->map; +wait_for_map $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'none', 'no border'); + +exit_gracefully($pid); + +############################################################## +# 7: check that invalid criteria don’t end up matching all windows +############################################################## + +# this configuration is broken because "asdf" is not a valid integer +# the for_window should therefore recognize this error and don’t add the +# assignment +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#00ff00', + event_mask => [ 'structure_notify' ], +); + +$window->_create; + +set_wm_class($window->id, 'bar', 'foo'); +$window->name('usethis'); +$window->map; +wait_for_map $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'normal', 'normal border'); + +exit_gracefully($pid); + +############################################################## +# 8: check that the role criterion works properly +############################################################## + +# this configuration is broken because "asdf" is not a valid integer +# the for_window should therefore recognize this error and don’t add the +# assignment +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#00ff00', + event_mask => [ 'structure_notify' ], +); + +$window->_create; + +my $atomname = $x->atom(name => 'WM_WINDOW_ROLE'); +my $atomtype = $x->atom(name => 'STRING'); +$x->change_property( + PROP_MODE_REPLACE, + $window->id, + $atomname->id, + $atomtype->id, + 8, + length("i3test") + 1, + "i3test\x00" +); + +$window->name('usethis'); +$window->map; +wait_for_map $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'none', 'no border (window_role)'); + +exit_gracefully($pid); + +############################################################## +# 9: another test for the window_role, but this time it changes +# *after* the window has been mapped +############################################################## + +# this configuration is broken because "asdf" is not a valid integer +# the for_window should therefore recognize this error and don’t add the +# assignment +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#00ff00', + event_mask => [ 'structure_notify' ], +); + +$window->_create; + +$window->name('usethis'); +$window->map; +wait_for_map $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'normal', 'normal border (window_role 2)'); + +$atomname = $x->atom(name => 'WM_WINDOW_ROLE'); +$atomtype = $x->atom(name => 'STRING'); +$x->change_property( + PROP_MODE_REPLACE, + $window->id, + $atomname->id, + $atomtype->id, + 8, + length("i3test") + 1, + "i3test\x00" +); + +$x->flush; + +sync_with_i3 $x; + +@content = @{get_ws_content($tmp)}; +cmp_ok(@content, '==', 1, 'one node on this workspace now'); +is($content[0]->{border}, 'none', 'no border (window_role 2)'); + +exit_gracefully($pid); + + +done_testing; diff --git a/testcases/t/166-assign.t b/testcases/t/166-assign.t new file mode 100644 index 00000000..4844f5b5 --- /dev/null +++ b/testcases/t/166-assign.t @@ -0,0 +1,286 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 +# +# Tests if assignments work +# +use i3test; +use X11::XCB qw(:all); +use X11::XCB::Connection; +use v5.10; + +my $x = X11::XCB::Connection->new; + +# TODO: move to X11::XCB +sub set_wm_class { + my ($id, $class, $instance) = @_; + + # Add a _NET_WM_STRUT_PARTIAL hint + my $atomname = $x->atom(name => 'WM_CLASS'); + my $atomtype = $x->atom(name => 'STRING'); + + $x->change_property( + PROP_MODE_REPLACE, + $id, + $atomname->id, + $atomtype->id, + 8, + length($class) + length($instance) + 2, + "$instance\x00$class\x00" + ); +} + + +##################################################################### +# start a window and see that it does not get assigned with an empty config +##################################################################### + +my $config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + event_mask => [ 'structure_notify' ], +); + +$window->_create; +set_wm_class($window->id, 'special', 'special'); +$window->name('special window'); +$window->map; +wait_for_map $x; + +ok(@{get_ws_content($tmp)} == 1, 'special window got managed to current (random) workspace'); + +exit_gracefully($pid); + +$window->destroy; + +##################################################################### +# start a window and see that it gets assigned to a formerly unused +# workspace +##################################################################### + +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + event_mask => [ 'structure_notify' ], +); + +$window->_create; +set_wm_class($window->id, 'special', 'special'); +$window->name('special window'); +$window->map; +wait_for_map $x; + +ok(@{get_ws_content($tmp)} == 0, 'still no containers'); +ok("targetws" ~~ @{get_workspace_names()}, 'targetws exists'); + +$window->destroy; + +exit_gracefully($pid); + +sleep 0.25; + +##################################################################### +# start a window and see that it gets assigned to a workspace which has content +# already, next to the existing node. +##################################################################### + +$pid = launch_with_config($config); + +# initialize the target workspace, then go to a fresh one +ok(!("targetws" ~~ @{get_workspace_names()}), 'targetws does not exist yet'); +cmd 'workspace targetws'; +cmp_ok(@{get_ws_content('targetws')}, '==', 0, 'no containers on targetws yet'); +cmd 'open'; +cmp_ok(@{get_ws_content('targetws')}, '==', 1, 'one container on targetws'); +$tmp = fresh_workspace; + +ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); +ok("targetws" ~~ @{get_workspace_names()}, 'targetws does not exist yet'); + +my $window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + event_mask => [ 'structure_notify' ], +); + +$window->_create; +set_wm_class($window->id, 'special', 'special'); +$window->name('special window'); +$window->map; + +# We use sync_with_i3 instead of wait_for_map here because i3 will not actually +# map the window -- it will be assigned to a different workspace and will only +# be mapped once you switch to that workspace +sync_with_i3 $x; + +ok(@{get_ws_content($tmp)} == 0, 'still no containers'); +ok(@{get_ws_content('targetws')} == 2, 'two containers on targetws'); + +exit_gracefully($pid); + +##################################################################### +# start a window and see that it gets assigned to a workspace which has content +# already, next to the existing node. +##################################################################### + +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + event_mask => [ 'structure_notify' ], +); + +$window->_create; +set_wm_class($window->id, 'special', 'special'); +$window->name('special window'); +$window->map; +wait_for_map $x; + +my $content = get_ws($tmp); +ok(@{$content->{nodes}} == 0, 'no tiling cons'); +ok(@{$content->{floating_nodes}} == 1, 'one floating con'); + +$window->destroy; + +exit_gracefully($pid); + +sleep 0.25; + +##################################################################### +# make sure that assignments are case-insensitive in the old syntax. +##################################################################### + +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + event_mask => [ 'structure_notify' ], +); + +$window->_create; +set_wm_class($window->id, 'SPEcial', 'SPEcial'); +$window->name('special window'); +$window->map; +wait_for_map $x; + +my $content = get_ws($tmp); +ok(@{$content->{nodes}} == 0, 'no tiling cons'); +ok(@{$content->{floating_nodes}} == 1, 'one floating con'); + +$window->destroy; + +exit_gracefully($pid); + +sleep 0.25; + +##################################################################### +# regression test: dock clients with floating assignments should not crash +# (instead, nothing should happen - dock clients can’t float) +# ticket #501 +##################################################################### + +$config = <root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), + event_mask => [ 'structure_notify' ], +); + +$window->_create; +set_wm_class($window->id, 'special', 'special'); +$window->name('special window'); +$window->map; +wait_for_map $x; + +my $content = get_ws($tmp); +ok(@{$content->{nodes}} == 0, 'no tiling cons'); +ok(@{$content->{floating_nodes}} == 0, 'one floating con'); +@docked = get_dock_clients; +is(@docked, 2, 'two dock clients now'); + +$window->destroy; + +does_i3_live; + +exit_gracefully($pid); + +sleep 0.25; + +done_testing; diff --git a/testcases/t/167-workspace_layout.t b/testcases/t/167-workspace_layout.t new file mode 100644 index 00000000..e4b18adf --- /dev/null +++ b/testcases/t/167-workspace_layout.t @@ -0,0 +1,127 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 +# +# Tests the workspace_layout config option. +# + +use i3test; +use X11::XCB qw(:all); +use X11::XCB::Connection; + +my $x = X11::XCB::Connection->new; + +##################################################################### +# 1: check that with an empty config, cons are place next to each +# other and no split containers are created +##################################################################### + +my $config = <input_focus, $second->id, 'second window focused'); +ok(@{get_ws_content($tmp)} == 2, 'two containers opened'); +isnt($content[0]->{layout}, 'stacked', 'layout not stacked'); +isnt($content[1]->{layout}, 'stacked', 'layout not stacked'); + +exit_gracefully($pid); + +##################################################################### +# 2: set workspace_layout stacked, check that when opening two cons, +# they end up in a stacked con +##################################################################### + +$config = <input_focus, $second->id, 'second window focused'); +my @content = @{get_ws_content($tmp)}; +ok(@content == 1, 'one con at workspace level'); +is($content[0]->{layout}, 'stacked', 'layout stacked'); + +##################################################################### +# 3: focus parent, open two new cons, check that they end up in a stacked +# con +##################################################################### + +cmd 'focus parent'; +my $right_top = open_window($x); +my $right_bot = open_window($x); + +@content = @{get_ws_content($tmp)}; +is(@content, 2, 'two cons at workspace level after focus parent'); +is($content[0]->{layout}, 'stacked', 'layout stacked'); +is($content[1]->{layout}, 'stacked', 'layout stacked'); + +##################################################################### +# 4: move one of the cons to the right, check that it will end up in +# a stacked con +##################################################################### + +cmd 'move right'; + +@content = @{get_ws_content($tmp)}; +is(@content, 3, 'three cons at workspace level after move'); +is($content[0]->{layout}, 'stacked', 'layout stacked'); +is($content[1]->{layout}, 'stacked', 'layout stacked'); +is($content[2]->{layout}, 'stacked', 'layout stacked'); + +##################################################################### +# 5: move it to the left again, check that the stacked con is deleted +##################################################################### + +cmd 'move left'; + +@content = @{get_ws_content($tmp)}; +is(@content, 2, 'two cons at workspace level after moving back'); +is($content[0]->{layout}, 'stacked', 'layout stacked'); +is($content[1]->{layout}, 'stacked', 'layout stacked'); + +##################################################################### +# 6: move it to a different workspace, check that it ends up in a +# stacked con +##################################################################### + +my $otmp = get_unused_workspace; + +cmd "move workspace $otmp"; + +@content = @{get_ws_content($tmp)}; +is(@content, 2, 'still two cons on this workspace'); +is($content[0]->{layout}, 'stacked', 'layout stacked'); +is($content[1]->{layout}, 'stacked', 'layout stacked'); + +@content = @{get_ws_content($otmp)}; +is(@content, 1, 'one con on target workspace'); +is($content[0]->{layout}, 'stacked', 'layout stacked'); + +exit_gracefully($pid); + +done_testing; diff --git a/testcases/t/168-regress-fullscreen-restart.t b/testcases/t/168-regress-fullscreen-restart.t new file mode 100644 index 00000000..1418b402 --- /dev/null +++ b/testcases/t/168-regress-fullscreen-restart.t @@ -0,0 +1,28 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Verifies that i3 survives inplace restarts with fullscreen containers +# +use i3test; +use X11::XCB qw(:all); +use X11::XCB::Connection; + +my $x = X11::XCB::Connection->new; + +fresh_workspace; + +open_window($x); +open_window($x); + +cmd 'layout stacking'; +sleep 1; + +cmd 'fullscreen'; +sleep 1; + +cmd 'restart'; +sleep 1; + +does_i3_live; + +done_testing; diff --git a/testcases/t/169-border-toggle.t b/testcases/t/169-border-toggle.t new file mode 100644 index 00000000..aec8df6c --- /dev/null +++ b/testcases/t/169-border-toggle.t @@ -0,0 +1,40 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Tests if the 'border toggle' command works correctly +# +use i3test; + +my $tmp = fresh_workspace; + +cmd 'open'; + +my @nodes = @{get_ws_content($tmp)}; +is(@nodes, 1, 'one container on this workspace'); +is($nodes[0]->{border}, 'normal', 'border style normal'); + +cmd 'border 1pixel'; +@nodes = @{get_ws_content($tmp)}; +is($nodes[0]->{border}, '1pixel', 'border style 1pixel'); + +cmd 'border none'; +@nodes = @{get_ws_content($tmp)}; +is($nodes[0]->{border}, 'none', 'border style none'); + +cmd 'border normal'; +@nodes = @{get_ws_content($tmp)}; +is($nodes[0]->{border}, 'normal', 'border style back to normal'); + +cmd 'border toggle'; +@nodes = @{get_ws_content($tmp)}; +is($nodes[0]->{border}, 'none', 'border style none'); + +cmd 'border toggle'; +@nodes = @{get_ws_content($tmp)}; +is($nodes[0]->{border}, '1pixel', 'border style 1pixel'); + +cmd 'border toggle'; +@nodes = @{get_ws_content($tmp)}; +is($nodes[0]->{border}, 'normal', 'border style back to normal'); + +done_testing; diff --git a/testcases/t/17-workspace.t b/testcases/t/17-workspace.t deleted file mode 100644 index 3c3b6cc6..00000000 --- a/testcases/t/17-workspace.t +++ /dev/null @@ -1,120 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests whether we can switch to a non-existant workspace -# (necessary for further tests) -# -use List::Util qw(first); -use i3test; - -# to ensure that workspace 1 stays open -cmd 'open'; - -my $tmp = fresh_workspace; -ok(workspace_exists($tmp), 'workspace created'); -# if the workspace could not be created, we cannot run any other test -# (every test starts by creating its workspace) -if (!workspace_exists($tmp)) { - BAIL_OUT('Cannot create workspace, further tests make no sense'); -} - -my $otmp = fresh_workspace; -diag("Other temporary workspace name: $otmp\n"); - -# As the old workspace was empty, it should get -# cleaned up as we switch away from it -cmd "workspace $otmp"; -ok(!workspace_exists($tmp), 'old workspace cleaned up'); - -# Switch to the same workspace again to make sure it doesn’t get cleaned up -cmd "workspace $otmp"; -cmd "workspace $otmp"; -ok(workspace_exists($otmp), 'other workspace still exists'); - - -##################################################################### -# check if the workspace next / prev commands work -##################################################################### - -cmd 'workspace next'; - -ok(!workspace_exists('next'), 'workspace "next" does not exist'); - -cmd "workspace $tmp"; -cmd 'open'; - -ok(workspace_exists($tmp), 'workspace created'); - -cmd "workspace $otmp"; -cmd 'open'; - -ok(workspace_exists($tmp), 'workspace tmp still exists'); -ok(workspace_exists($otmp), 'workspace otmp created'); - -is(focused_ws(), $otmp, 'focused workspace is otmp'); - -cmd 'workspace prev'; -is(focused_ws(), $tmp, 'focused workspace is tmp after workspace prev'); - -cmd 'workspace next'; -is(focused_ws(), $otmp, 'focused workspace is otmp after workspace next'); - - -##################################################################### -# check that wrapping works -##################################################################### - -cmd 'workspace next'; -is(focused_ws(), '1', 'focused workspace is 1 after workspace next'); - -cmd 'workspace next'; -is(focused_ws(), $tmp, 'focused workspace is tmp after workspace next'); - -cmd 'workspace next'; -is(focused_ws(), $otmp, 'focused workspace is otmp after workspace next'); - - -cmd 'workspace prev'; -is(focused_ws(), $tmp, 'focused workspace is tmp after workspace prev'); - -cmd 'workspace prev'; -is(focused_ws(), '1', 'focused workspace is tmp after workspace prev'); - -cmd 'workspace prev'; -is(focused_ws(), $otmp, 'focused workspace is otmp after workspace prev'); - - -##################################################################### -# check if we can change to "next" / "prev" -##################################################################### - -cmd 'workspace "next"'; - -ok(workspace_exists('next'), 'workspace "next" exists'); -is(focused_ws(), 'next', 'now on workspace next'); - -cmd 'workspace "prev"'; - -ok(workspace_exists('prev'), 'workspace "prev" exists'); -is(focused_ws(), 'prev', 'now on workspace prev'); - -##################################################################### -# check that the numbers are assigned/recognized correctly -##################################################################### - -cmd "workspace 3: $tmp"; -my $ws = get_ws("3: $tmp"); -ok(defined($ws), "workspace 3: $tmp was created"); -is($ws->{num}, 3, 'workspace number is 3'); - -cmd "workspace 0: $tmp"; -my $ws = get_ws("0: $tmp"); -ok(defined($ws), "workspace 0: $tmp was created"); -is($ws->{num}, 0, 'workspace number is 0'); - -cmd "workspace aa: $tmp"; -my $ws = get_ws("aa: $tmp"); -ok(defined($ws), "workspace aa: $tmp was created"); -is($ws->{num}, -1, 'workspace number is -1'); - -done_testing; diff --git a/testcases/t/170-force_focus_wrapping.t b/testcases/t/170-force_focus_wrapping.t new file mode 100644 index 00000000..8a990f23 --- /dev/null +++ b/testcases/t/170-force_focus_wrapping.t @@ -0,0 +1,97 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 +# +# Tests if the 'force_focus_wrapping' config directive works correctly. +# +use i3test; +use X11::XCB qw(:all); +use X11::XCB::Connection; + +my $x = X11::XCB::Connection->new; + +##################################################################### +# 1: test the wrapping behaviour without force_focus_wrapping +##################################################################### + +my $config = <input_focus, $third->id, 'third window focused'); + +cmd 'focus left'; +is($x->input_focus, $second->id, 'second window focused'); + +cmd 'focus left'; +is($x->input_focus, $first->id, 'first window focused'); + +# now test the wrapping +cmd 'focus left'; +is($x->input_focus, $second->id, 'second window focused'); + +# but focusing right should not wrap now, but instead focus the third window +cmd 'focus right'; +is($x->input_focus, $third->id, 'third window focused'); + +exit_gracefully($pid); + +##################################################################### +# 2: test the wrapping behaviour with force_focus_wrapping +##################################################################### + +$config = <input_focus, $third->id, 'third window focused'); + +cmd 'focus left'; +is($x->input_focus, $second->id, 'second window focused'); + +cmd 'focus left'; +is($x->input_focus, $first->id, 'first window focused'); + +# now test the wrapping +cmd 'focus left'; +is($x->input_focus, $second->id, 'second window focused'); + +# focusing right should now be forced to wrap +cmd 'focus right'; +is($x->input_focus, $first->id, 'first window focused'); + +exit_gracefully($pid); + +done_testing; diff --git a/testcases/t/171-config-migrate.t b/testcases/t/171-config-migrate.t new file mode 100644 index 00000000..7948db6c --- /dev/null +++ b/testcases/t/171-config-migrate.t @@ -0,0 +1,349 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 +# +# Tests if i3-migrate-config-to-v4 correctly migrates all config file +# directives and commands +# +use i3test; +use Cwd qw(abs_path); +use File::Temp qw(tempfile tempdir); +use v5.10; + +# reads in a whole file +sub slurp { + open my $fh, '<', shift; + local $/; + <$fh>; +} + +sub migrate_config { + my ($config) = @_; + + my ($fh, $tmpfile) = tempfile('/tmp/i3-migrate-cfg.XXXXXX', UNLINK => 1); + print $fh $config; + close($fh); + + my $cmd = "sh -c 'exec " . abs_path("../i3-migrate-config-to-v4") . " --v3 <$tmpfile'"; + return [ split /\n/, qx($cmd) ]; +} + +sub line_exists { + my ($lines, $pattern) = @_; + + for my $line (@$lines) { + return 1 if $line =~ $pattern; + } + + return 0 +} + +##################################################################### +# check that some directives remain untouched +##################################################################### + +my $input = <new; + +############################################################## +# 1: i3 should start with workspace '1' +############################################################## + +my $config = <get_marks->recv; +} + +############################################################## +# 1: check that get_marks returns no marks yet +############################################################## + +my $tmp = fresh_workspace; + +my $marks = get_marks(); +cmp_deeply($marks, [], 'no marks set so far'); + +############################################################## +# 2: check that setting a mark is reflected in the get_marks reply +############################################################## + +cmd 'open'; +cmd 'mark foo'; + +cmp_deeply(get_marks(), [ 'foo' ], 'mark foo set'); + +############################################################## +# 3: check that the mark is gone after killing the container +############################################################## + +cmd 'kill'; + +cmp_deeply(get_marks(), [ ], 'mark gone'); + +############################################################## +# 4: check that duplicate marks are included twice in the get_marks reply +############################################################## + +cmd 'open'; +cmd 'mark bar'; + +cmd 'open'; +cmd 'mark bar'; + +cmp_deeply(get_marks(), [ 'bar', 'bar' ], 'duplicate mark found twice'); + +done_testing; diff --git a/testcases/t/173-regress-focus-assign.t b/testcases/t/173-regress-focus-assign.t new file mode 100644 index 00000000..70414af3 --- /dev/null +++ b/testcases/t/173-regress-focus-assign.t @@ -0,0 +1,95 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 +# +# Regression: Checks if focus is stolen when a window is managed which is +# assigned to an invisible workspace +# +use i3test; +use X11::XCB qw(:all); +use X11::XCB::Connection; +use v5.10; + +my $x = X11::XCB::Connection->new; + +# TODO: move to X11::XCB +sub set_wm_class { + my ($id, $class, $instance) = @_; + + # Add a _NET_WM_STRUT_PARTIAL hint + my $atomname = $x->atom(name => 'WM_CLASS'); + my $atomtype = $x->atom(name => 'STRING'); + + $x->change_property( + PROP_MODE_REPLACE, + $id, + $atomname->id, + $atomtype->id, + 8, + length($class) + length($instance) + 2, + "$instance\x00$class\x00" + ); +} + + +##################################################################### +# start a window and see that it does not get assigned with an empty config +##################################################################### + +my $config = <{focused}, 'current workspace focused'); + +my $window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', +); + +$window->_create; +set_wm_class($window->id, 'special', 'special'); +$window->name('special window'); +$window->map; +sleep 0.25; + + +ok(@{get_ws_content($tmp)} == 0, 'special window not on current workspace'); +ok(@{get_ws_content('targetws')} == 1, 'special window on targetws'); +ok(get_ws($tmp)->{focused}, 'current workspace still focused'); + +##################################################################### +# the same test, but with a floating window +##################################################################### + +$window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 0, 0, 30, 30 ], + background_color => '#0000ff', + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'), +); + +$window->_create; +set_wm_class($window->id, 'special', 'special'); +$window->name('special window'); +$window->map; +sleep 0.25; + + +ok(@{get_ws_content($tmp)} == 0, 'special window not on current workspace'); +ok(@{get_ws_content('targetws')} == 1, 'special window on targetws'); +ok(get_ws($tmp)->{focused}, 'current workspace still focused'); + +exit_gracefully($pid); + +$window->destroy; + +done_testing; diff --git a/testcases/t/174-border-config.t b/testcases/t/174-border-config.t new file mode 100644 index 00000000..cc1f5c90 --- /dev/null +++ b/testcases/t/174-border-config.t @@ -0,0 +1,116 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 +# +# Tests the new_window and new_float config option. +# + +use i3test; + +my $x = X11::XCB::Connection->new; + +##################################################################### +# 1: check that new windows start with 'normal' border unless configured +# otherwise +##################################################################### + +my $config = <{border}, 'normal', 'border normal by default'); + +exit_gracefully($pid); + +##################################################################### +# 2: check that new tiling windows start with '1pixel' border when +# configured +##################################################################### + +$config = <{border}, '1pixel', 'border normal by default'); + +exit_gracefully($pid); + +##################################################################### +# 3: check that new floating windows start with 'normal' border unless +# configured otherwise +##################################################################### + +$config = <{floating_nodes}}; +ok(@floating == 1, 'one floating container opened'); +my $floatingcon = $floating[0]; +is($floatingcon->{nodes}->[0]->{border}, 'normal', 'border normal by default'); + +exit_gracefully($pid); + +##################################################################### +# 4: check that new floating windows start with '1pixel' border when +# configured +##################################################################### + +$config = <{floating_nodes}}; +ok(@floating == 1, 'one floating container opened'); +$floatingcon = $floating[0]; +is($floatingcon->{nodes}->[0]->{border}, '1pixel', 'border normal by default'); + +exit_gracefully($pid); + +done_testing; diff --git a/testcases/t/174-regress-focus-toggle.t b/testcases/t/174-regress-focus-toggle.t new file mode 100644 index 00000000..469d1be8 --- /dev/null +++ b/testcases/t/174-regress-focus-toggle.t @@ -0,0 +1,17 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Regression: Checks if i3 still lives after using 'focus mode_toggle' on an +# empty workspace. This regression was fixed in +# 0848844f2d41055f6ffc69af1149d7a873460976. +# +use i3test; +use v5.10; + +my $tmp = fresh_workspace; + +cmd 'focus mode_toggle'; + +does_i3_live; + +done_testing; diff --git a/testcases/t/18-openkill.t b/testcases/t/18-openkill.t deleted file mode 100644 index e2a729c5..00000000 --- a/testcases/t/18-openkill.t +++ /dev/null @@ -1,40 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests whether opening an empty container and killing it again works -# -use List::Util qw(first); -use i3test; - -my $tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -# Open a new container -cmd 'open'; - -ok(@{get_ws_content($tmp)} == 1, 'container opened'); - -cmd 'kill'; -ok(@{get_ws_content($tmp)} == 0, 'container killed'); - -############################################################## -# open two containers and kill the one which is not focused -# by its ID to test if the parser correctly matches the window -############################################################## - -cmd 'open'; -cmd 'open'; -ok(@{get_ws_content($tmp)} == 2, 'two containers opened'); - -my $content = get_ws_content($tmp); -my $not_focused = first { !$_->{focused} } @{$content}; -my $id = $not_focused->{id}; - -cmd "[con_id=\"$id\"] kill"; - -$content = get_ws_content($tmp); -ok(@{$content} == 1, 'one container killed'); -ok($content->[0]->{id} != $id, 'correct window killed'); - -done_testing; diff --git a/testcases/t/19-match.t b/testcases/t/19-match.t deleted file mode 100644 index 8b9d21d3..00000000 --- a/testcases/t/19-match.t +++ /dev/null @@ -1,170 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests all kinds of matching methods -# -use i3test; -use X11::XCB qw(:all); - -my $tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -# Open a new window -my $x = X11::XCB::Connection->new; -my $window = open_window($x); -my $content = get_ws_content($tmp); -ok(@{$content} == 1, 'window mapped'); -my $win = $content->[0]; - -###################################################################### -# first test that matches which should not match this window really do -# not match it -###################################################################### -# TODO: specify more match types -# we can match on any (non-empty) class here since that window does not have -# WM_CLASS set -cmd q|[class=".*"] kill|; -cmd q|[con_id="99999"] kill|; - -$content = get_ws_content($tmp); -ok(@{$content} == 1, 'window still there'); - -# now kill the window -cmd 'nop now killing the window'; -my $id = $win->{id}; -cmd qq|[con_id="$id"] kill|; - -wait_for_unmap $x; - -cmd 'nop checking if its gone'; -$content = get_ws_content($tmp); -ok(@{$content} == 0, 'window killed'); - -# TODO: same test, but with pcre expressions - -###################################################################### -# check that multiple criteria work are checked with a logical AND, -# not a logical OR (that is, matching is not cancelled after the first -# criterion matches). -###################################################################### - -$tmp = fresh_workspace; - -# TODO: move to X11::XCB -sub set_wm_class { - my ($id, $class, $instance) = @_; - - # Add a _NET_WM_STRUT_PARTIAL hint - my $atomname = $x->atom(name => 'WM_CLASS'); - my $atomtype = $x->atom(name => 'STRING'); - - $x->change_property( - PROP_MODE_REPLACE, - $id, - $atomname->id, - $atomtype->id, - 8, - length($class) + length($instance) + 2, - "$instance\x00$class\x00" - ); -} - -my $left = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - event_mask => [ 'structure_notify' ], -); - -$left->_create; -set_wm_class($left->id, 'special', 'special'); -$left->name('left'); -$left->map; -ok(wait_for_map($x), 'left window mapped'); - -my $right = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - event_mask => [ 'structure_notify' ], -); - -$right->_create; -set_wm_class($right->id, 'special', 'special'); -$right->name('right'); -$right->map; -ok(wait_for_map($x), 'right window mapped'); - -# two windows should be here -$content = get_ws_content($tmp); -ok(@{$content} == 2, 'two windows opened'); - -cmd '[class="special" title="left"] kill'; - -sync_with_i3($x); - -$content = get_ws_content($tmp); -is(@{$content}, 1, 'one window still there'); - -###################################################################### -# check that regular expressions work -###################################################################### - -$tmp = fresh_workspace; - -$left = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - event_mask => [ 'structure_notify' ], -); - -$left->_create; -set_wm_class($left->id, 'special7', 'special7'); -$left->name('left'); -$left->map; -ok(wait_for_map($x), 'left window mapped'); - -# two windows should be here -$content = get_ws_content($tmp); -ok(@{$content} == 1, 'window opened'); - -cmd '[class="^special[0-9]$"] kill'; - -wait_for_unmap $x; - -$content = get_ws_content($tmp); -is(@{$content}, 0, 'window killed'); - -###################################################################### -# check that UTF-8 works when matching -###################################################################### - -$tmp = fresh_workspace; - -$left = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - event_mask => [ 'structure_notify' ], -); - -$left->_create; -set_wm_class($left->id, 'special7', 'special7'); -$left->name('ä 3'); -$left->map; -ok(wait_for_map($x), 'left window mapped'); - -# two windows should be here -$content = get_ws_content($tmp); -ok(@{$content} == 1, 'window opened'); - -cmd '[title="^\w [3]$"] kill'; - -wait_for_unmap $x; - -$content = get_ws_content($tmp); -is(@{$content}, 0, 'window killed'); - -done_testing; diff --git a/testcases/t/20-multiple-cmds.t b/testcases/t/20-multiple-cmds.t deleted file mode 100644 index 784329fb..00000000 --- a/testcases/t/20-multiple-cmds.t +++ /dev/null @@ -1,56 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests multiple commands (using ';') and multiple operations (using ',') -# -use i3test; - -my $tmp = fresh_workspace; - -sub multiple_cmds { - my ($cmd) = @_; - - cmd 'open'; - cmd 'open'; - ok(@{get_ws_content($tmp)} == 2, 'two containers opened'); - - cmd $cmd; - ok(@{get_ws_content($tmp)} == 0, "both containers killed (cmd = $cmd)"); -} -multiple_cmds('kill;kill'); -multiple_cmds('kill; kill'); -multiple_cmds('kill ; kill'); -multiple_cmds('kill ;kill'); -multiple_cmds('kill ;kill'); -multiple_cmds('kill ; kill'); -multiple_cmds("kill;\tkill"); -multiple_cmds("kill\t;kill"); -multiple_cmds("kill\t;\tkill"); -multiple_cmds("kill\t ;\tkill"); -multiple_cmds("kill\t ;\t kill"); -multiple_cmds("kill \t ; \t kill"); - -##################################################################### -# test if un-quoted strings are handled correctly -##################################################################### - -$tmp = fresh_workspace; -cmd 'open'; -my $unused = get_unused_workspace; -ok(!($unused ~~ @{get_workspace_names()}), 'workspace does not exist yet'); -cmd "move workspace $unused; nop parser test"; -ok(($unused ~~ @{get_workspace_names()}), 'workspace exists after moving'); - -##################################################################### -# quote the workspace name and use a ; (command separator) in its name -##################################################################### - -$unused = get_unused_workspace; -$unused .= ';a'; -ok(!($unused ~~ @{get_workspace_names()}), 'workspace does not exist yet'); -cmd qq|move workspace "$unused"; nop parser test|; -ok(($unused ~~ @{get_workspace_names()}), 'workspace exists after moving'); - -# TODO: need a non-invasive command before implementing a test which uses ',' - -done_testing; diff --git a/testcases/t/21-next-prev.t b/testcases/t/21-next-prev.t deleted file mode 100644 index 447be315..00000000 --- a/testcases/t/21-next-prev.t +++ /dev/null @@ -1,76 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests focus switching (next/prev) -# -use i3test; - -my $tmp = fresh_workspace; - -###################################################################### -# Open one container, verify that 'focus down' and 'focus right' do nothing -###################################################################### -cmd 'open'; - -my ($nodes, $focus) = get_ws_content($tmp); -my $old_focused = $focus->[0]; - -cmd 'focus down'; -($nodes, $focus) = get_ws_content($tmp); -is($focus->[0], $old_focused, 'focus did not change with only one con'); - -cmd 'focus right'; -($nodes, $focus) = get_ws_content($tmp); -is($focus->[0], $old_focused, 'focus did not change with only one con'); - -###################################################################### -# Open another container, verify that 'focus right' switches -###################################################################### -my $left = $old_focused; - -cmd 'open'; -($nodes, $focus) = get_ws_content($tmp); -isnt($old_focused, $focus->[0], 'new container is focused'); -my $mid = $focus->[0]; - -cmd 'open'; -($nodes, $focus) = get_ws_content($tmp); -isnt($old_focused, $focus->[0], 'new container is focused'); -my $right = $focus->[0]; - -cmd 'focus right'; -($nodes, $focus) = get_ws_content($tmp); -isnt($focus->[0], $right, 'focus did change'); -is($focus->[0], $left, 'left container focused (wrapping)'); - -cmd 'focus right'; -($nodes, $focus) = get_ws_content($tmp); -is($focus->[0], $mid, 'middle container focused'); - -cmd 'focus right'; -($nodes, $focus) = get_ws_content($tmp); -is($focus->[0], $right, 'right container focused'); - -cmd 'focus left'; -($nodes, $focus) = get_ws_content($tmp); -is($focus->[0], $mid, 'middle container focused'); - -cmd 'focus left'; -($nodes, $focus) = get_ws_content($tmp); -is($focus->[0], $left, 'left container focused'); - -cmd 'focus left'; -($nodes, $focus) = get_ws_content($tmp); -is($focus->[0], $right, 'right container focused'); - - -###################################################################### -# Test focus command -###################################################################### - -cmd qq|[con_id="$mid"] focus|; -($nodes, $focus) = get_ws_content($tmp); -is($focus->[0], $mid, 'middle container focused'); - - -done_testing; diff --git a/testcases/t/22-split.t b/testcases/t/22-split.t deleted file mode 100644 index 3484c7fc..00000000 --- a/testcases/t/22-split.t +++ /dev/null @@ -1,92 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests splitting -# -use i3test; -use X11::XCB qw(:all); - -my $tmp = fresh_workspace; - -my $ws = get_ws($tmp); -is($ws->{orientation}, 'horizontal', 'orientation horizontal by default'); -cmd 'split v'; -$ws = get_ws($tmp); -is($ws->{orientation}, 'vertical', 'split v changes workspace orientation'); - -###################################################################### -# Open two containers, split, open another container. Then verify -# the layout is like we expect it to be -###################################################################### -cmd 'open'; -cmd 'open'; -my $content = get_ws_content($tmp); - -is(@{$content}, 2, 'two containers on workspace level'); -my $first = $content->[0]; -my $second = $content->[1]; - -is(@{$first->{nodes}}, 0, 'first container has no children'); -is(@{$second->{nodes}}, 0, 'second container has no children (yet)'); -my $old_name = $second->{name}; - - -cmd 'split h'; -cmd 'open'; - -$content = get_ws_content($tmp); - -is(@{$content}, 2, 'two containers on workspace level'); -$first = $content->[0]; -$second = $content->[1]; - -is(@{$first->{nodes}}, 0, 'first container has no children'); -isnt($second->{name}, $old_name, 'second container was replaced'); -is($second->{orientation}, 'horizontal', 'orientation is horizontal'); -is(@{$second->{nodes}}, 2, 'second container has 2 children'); -is($second->{nodes}->[0]->{name}, $old_name, 'found old second container'); - -# TODO: extend this test-case (test next/prev) -# - wrapping (no horizontal switch possible, goes level-up) -# - going level-up "manually" - -###################################################################### -# Test splitting multiple times without actually creating windows -###################################################################### - -$tmp = fresh_workspace; - -$ws = get_ws($tmp); -is($ws->{orientation}, 'horizontal', 'orientation horizontal by default'); -cmd 'split v'; -$ws = get_ws($tmp); -is($ws->{orientation}, 'vertical', 'split v changes workspace orientation'); - -cmd 'open'; -my @content = @{get_ws_content($tmp)}; - -# recursively sums up all nodes and their children -sub sum_nodes { - my ($nodes) = @_; - - return 0 if !@{$nodes}; - - my @children = (map { @{$_->{nodes}} } @{$nodes}, - map { @{$_->{'floating_nodes'}} } @{$nodes}); - - return @{$nodes} + sum_nodes(\@children); -} - -my $old_count = sum_nodes(\@content); -cmd 'split v'; - -@content = @{get_ws_content($tmp)}; -$old_count = sum_nodes(\@content); - -cmd 'split v'; - -@content = @{get_ws_content($tmp)}; -my $count = sum_nodes(\@content); -is($count, $old_count, 'not more windows after splitting again'); - -done_testing; diff --git a/testcases/t/24-move.t b/testcases/t/24-move.t deleted file mode 100644 index 4df3a2a1..00000000 --- a/testcases/t/24-move.t +++ /dev/null @@ -1,134 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests moving. Basically, there are four different code-paths: -# 1) move a container which cannot be moved (single container on a workspace) -# 2) move a container before another single container -# 3) move a container inside another container -# 4) move a container in a different direction so that we need to go up in tree -# -use i3test; - -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -###################################################################### -# 1) move a container which cannot be moved -###################################################################### - -cmd 'open'; - -my $old_content = get_ws_content($tmp); -is(@{$old_content}, 1, 'one container on this workspace'); - -my $first = $old_content->[0]->{id}; - -#cmd 'move before h'; -#cmd 'move before v'; -#cmd 'move after v'; -#cmd 'move after h'; - -my $content = get_ws_content($tmp); -#is_deeply($old_content, $content, 'workspace unmodified after useless moves'); - -###################################################################### -# 2) move a container before another single container -###################################################################### - -cmd 'open'; -$content = get_ws_content($tmp); -is(@{$content}, 2, 'two containers on this workspace'); -my $second = $content->[1]->{id}; - -is($content->[0]->{id}, $first, 'first container unmodified'); - -# Move the second container before the first one (→ swap them) -cmd 'move left'; -$content = get_ws_content($tmp); -is($content->[0]->{id}, $second, 'first container modified'); - -# We should not be able to move any further -cmd 'move left'; -$content = get_ws_content($tmp); -is($content->[0]->{id}, $second, 'first container unmodified'); - -# Now move in the other direction -cmd 'move right'; -$content = get_ws_content($tmp); -is($content->[0]->{id}, $first, 'first container modified'); - -# We should not be able to move any further -cmd 'move right'; -$content = get_ws_content($tmp); -is($content->[0]->{id}, $first, 'first container unmodified'); - -###################################################################### -# 3) move a container inside another container -###################################################################### - -# Split the current (second) container and create a new container on workspace -# level. Our layout looks like this now: -# -------------------------- -# | | second | | -# | first | ------ | third | -# | | | | -# -------------------------- -cmd 'split v'; -cmd 'focus parent'; -cmd 'open'; - -$content = get_ws_content($tmp); -is(@{$content}, 3, 'three containers on this workspace'); -my $third = $content->[2]->{id}; - -cmd 'move left'; -$content = get_ws_content($tmp); -is(@{$content}, 2, 'only two containers on this workspace'); -my $nodes = $content->[1]->{nodes}; -is($nodes->[0]->{id}, $second, 'second container on top'); -is($nodes->[1]->{id}, $third, 'third container on bottom'); - -###################################################################### -# move it inside the split container -###################################################################### - -cmd 'move up'; -$nodes = get_ws_content($tmp)->[1]->{nodes}; -is($nodes->[0]->{id}, $third, 'third container on top'); -is($nodes->[1]->{id}, $second, 'second container on bottom'); - -# move it outside again -cmd 'move left'; -$content = get_ws_content($tmp); -is(@{$content}, 3, 'three nodes on this workspace'); - -# due to automatic flattening/cleanup, the remaining split container -# will be replaced by the con itself, so we will still have 3 nodes -cmd 'move right'; -$content = get_ws_content($tmp); -is(@{$content}, 2, 'two nodes on this workspace'); - -###################################################################### -# 4) We create two v-split containers on the workspace, then we move -# all Cons from the left v-split to the right one. The old vsplit -# container needs to be closed. Verify that it will be closed. -###################################################################### - -my $otmp = fresh_workspace; - -cmd "open"; -cmd "open"; -cmd "split v"; -cmd "open"; -cmd 'focus left'; -cmd "split v"; -cmd "open"; -cmd "move right"; -cmd 'focus left'; -cmd "move right"; - -$content = get_ws_content($otmp); -is(@{$content}, 1, 'only one nodes on this workspace'); - -done_testing; diff --git a/testcases/t/26-regress-close.t b/testcases/t/26-regress-close.t deleted file mode 100644 index 8aec87d7..00000000 --- a/testcases/t/26-regress-close.t +++ /dev/null @@ -1,18 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression: closing of floating clients did crash i3 when closing the -# container which contained this client. -# -use i3test; - -fresh_workspace; - -cmd 'open'; -cmd 'mode toggle'; -cmd 'kill'; -cmd 'kill'; - -does_i3_live; - -done_testing; diff --git a/testcases/t/27-regress-floating-parent.t b/testcases/t/27-regress-floating-parent.t deleted file mode 100644 index 52b8b9c0..00000000 --- a/testcases/t/27-regress-floating-parent.t +++ /dev/null @@ -1,41 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression: make a container floating, kill its parent, make it tiling again -# -use i3test; - -my $tmp = fresh_workspace; - -cmd 'open'; -my $left = get_focused($tmp); -cmd 'open'; -my $old = get_focused($tmp); -cmd 'split v'; -cmd 'open'; -my $floating = get_focused($tmp); -diag("focused floating: " . get_focused($tmp)); -cmd 'mode toggle'; -# TODO: eliminate this race conditition -sleep 1; - -# kill old container -cmd qq|[con_id="$old"] focus|; -is(get_focused($tmp), $old, 'old container focused'); -cmd 'kill'; - -# kill left container -cmd qq|[con_id="$left"] focus|; -is(get_focused($tmp), $left, 'old container focused'); -cmd 'kill'; - -# focus floating window, make it tiling again -cmd qq|[con_id="$floating"] focus|; -is(get_focused($tmp), $floating, 'floating window focused'); - -sleep 1; -cmd 'mode toggle'; - -does_i3_live; - -done_testing; diff --git a/testcases/t/28-open-order.t b/testcases/t/28-open-order.t deleted file mode 100644 index b638e708..00000000 --- a/testcases/t/28-open-order.t +++ /dev/null @@ -1,37 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Check if new containers are opened after the currently focused one instead -# of always at the end -use List::Util qw(first); -use i3test; - -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -# Open two new container -my $first = open_empty_con($i3); - -ok(@{get_ws_content($tmp)} == 1, 'containers opened'); - -my $second = open_empty_con($i3); - -isnt($first, $second, 'different container focused'); - -############################################################## -# see if new containers open after the currently focused -############################################################## - -cmd qq|[con_id="$first"] focus|; -cmd 'open'; -$content = get_ws_content($tmp); -ok(@{$content} == 3, 'three containers opened'); - -is($content->[0]->{id}, $first, 'first container unmodified'); -isnt($content->[1]->{id}, $second, 'second container replaced'); -is($content->[2]->{id}, $second, 'third container unmodified'); - -done_testing; diff --git a/testcases/t/29-focus-after-close.t b/testcases/t/29-focus-after-close.t deleted file mode 100644 index 8d225613..00000000 --- a/testcases/t/29-focus-after-close.t +++ /dev/null @@ -1,122 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Check if the focus is correctly restored after closing windows. -# -use i3test; -use X11::XCB qw(:all); -use List::Util qw(first); - -my $x = X11::XCB::Connection->new; - -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -my $first = open_empty_con($i3); -my $second = open_empty_con($i3); - -cmd 'split v'; - -my ($nodes, $focus) = get_ws_content($tmp); - -ok(!$nodes->[1]->{focused}, 'split container not focused'); -cmd 'focus parent'; -($nodes, $focus) = get_ws_content($tmp); -ok($nodes->[1]->{focused}, 'split container focused after focus parent'); - -my $third = open_empty_con($i3); - -isnt(get_focused($tmp), $second, 'different container focused'); - -# We have the following layout now (con is focused): -# .----------------. -# | split | | -# | .----. | con | -# | | cn | | | -# | `----' | | -# `----------------' - -############################################################## -# see if the focus goes down to $first (not to its split parent) -# when closing $second -############################################################## - -cmd 'kill'; -# TODO: this testcase sometimes has different outcomes when the -# sleep is missing. why? -sleep 0.25; -($nodes, $focus) = get_ws_content($tmp); -is($nodes->[1]->{nodes}->[0]->{id}, $second, 'second container found'); -ok($nodes->[1]->{nodes}->[0]->{focused}, 'second container focused'); - -############################################################## -# another case, using a slightly different layout (regression) -############################################################## - -$tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -cmd 'split v'; -$first = open_empty_con($i3); -my $bottom = open_empty_con($i3); - -cmd 'focus up'; -cmd 'split h'; -my $middle = open_empty_con($i3); -my $right = open_empty_con($i3); -cmd 'focus down'; - -# We have the following layout now (second is focused): -# .----------------------------. -# | .------------------------. | -# | | first | middle | right | | -# | `------------------------' | -# |----------------------------| -# | | -# | second | -# | | -# `----------------------------' - -# Check if the focus is restored to $right when we close $second -cmd 'kill'; - -is(get_focused($tmp), $right, 'top right container focused (in focus stack)'); - -($nodes, $focus) = get_ws_content($tmp); -my $tr = first { $_->{id} eq $right } @{$nodes->[0]->{nodes}}; -is($tr->{focused}, 1, 'top right container really has focus'); - -############################################################## -# check if focus is correct after closing an unfocused window -############################################################## - -$tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -$first = open_empty_con($i3); -$middle = open_empty_con($i3); -# XXX: the $right empty con will be filled with the x11 window we are creating afterwards -$right = open_empty_con($i3); -my $win = open_window($x, { background_color => '#00ff00' }); - -cmd qq|[con_id="$middle"] focus|; -$win->destroy; - -sleep 0.25; - -is(get_focused($tmp), $middle, 'middle container focused'); - -############################################################## -# and now for something completely different: -# check if the pointer position is relevant when restoring focus -# (it should not be relevant, of course) -############################################################## - -# TODO: add test code as soon as I can reproduce it - -done_testing; diff --git a/testcases/t/30-close-empty-split.t b/testcases/t/30-close-empty-split.t deleted file mode 100644 index 57855cd5..00000000 --- a/testcases/t/30-close-empty-split.t +++ /dev/null @@ -1,82 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Check if empty split containers are automatically closed. -# -use i3test; - -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -my $first = open_empty_con($i3); -my $second = open_empty_con($i3); -cmd qq|[con_id="$first"] focus|; - -cmd 'split v'; - -($nodes, $focus) = get_ws_content($tmp); - -is($nodes->[0]->{focused}, 0, 'split container not focused'); - -# focus the split container -cmd 'level up'; -($nodes, $focus) = get_ws_content($tmp); -my $split = $focus->[0]; -cmd 'level down'; - -my $second = open_empty_con($i3); - -isnt($first, $second, 'different container focused'); - -############################################################## -# close both windows and see if the split container still exists -############################################################## - -cmd 'kill'; -cmd 'kill'; -($nodes, $focus) = get_ws_content($tmp); -isnt($nodes->[0]->{id}, $split, 'split container closed'); - -############################################################## -# same thing but this time we are moving the cons away instead -# of killing them -############################################################## - -$tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -$first = open_empty_con($i3); -$second = open_empty_con($i3); -cmd qq|[con_id="$first"] focus|; - -cmd 'split v'; - -($nodes, $focus) = get_ws_content($tmp); - -is($nodes->[0]->{focused}, 0, 'split container not focused'); - -# focus the split container -cmd 'level up'; -($nodes, $focus) = get_ws_content($tmp); -my $split = $focus->[0]; -cmd 'level down'; - -my $second = open_empty_con($i3); - -isnt($first, $second, 'different container focused'); - -############################################################## -# close both windows and see if the split container still exists -############################################################## - -my $otmp = get_unused_workspace(); -cmd "move workspace $otmp"; -cmd "move workspace $otmp"; -($nodes, $focus) = get_ws_content($tmp); -isnt($nodes->[0]->{id}, $split, 'split container closed'); - -done_testing; diff --git a/testcases/t/31-stacking-order.t b/testcases/t/31-stacking-order.t deleted file mode 100644 index 9c1e74ca..00000000 --- a/testcases/t/31-stacking-order.t +++ /dev/null @@ -1,52 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Check if stacking containers can be used independantly of -# the split mode (horizontal/vertical) of the underlying -# container. -# -use i3test; - -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -# Enforce vertical split mode -cmd 'split v'; - -my $first = open_empty_con($i3); -my $second = open_empty_con($i3); - -isnt($first, $second, 'two different containers opened'); - -############################################################## -# change mode to stacking and cycle through the containers -############################################################## - -cmd 'layout stacking'; -is(get_focused($tmp), $second, 'second container still focused'); - -cmd 'focus down'; -is(get_focused($tmp), $first, 'first container focused'); - -cmd 'focus up'; -is(get_focused($tmp), $second, 'second container focused again'); - -############################################################## -# now change the orientation to horizontal and cycle -############################################################## - -cmd 'focus parent'; -cmd 'split h'; -cmd 'focus child'; - -cmd 'focus down'; -is(get_focused($tmp), $first, 'first container focused'); - -cmd 'focus up'; -is(get_focused($tmp), $second, 'second container focused again'); - - -done_testing; diff --git a/testcases/t/32-move-workspace.t b/testcases/t/32-move-workspace.t deleted file mode 100644 index 82e59dd1..00000000 --- a/testcases/t/32-move-workspace.t +++ /dev/null @@ -1,95 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Checks if the 'move workspace' command works correctly -# -use i3test; - -my $i3 = i3(get_socket_path()); - -# We move the pointer out of our way to avoid a bug where the focus will -# be set to the window under the cursor -my $x = X11::XCB::Connection->new; -$x->root->warp_pointer(0, 0); - -my $tmp = get_unused_workspace(); -my $tmp2 = get_unused_workspace(); -cmd "workspace $tmp"; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -my $first = open_empty_con($i3); -my $second = open_empty_con($i3); -ok(@{get_ws_content($tmp)} == 2, 'two containers on first ws'); - -cmd "workspace $tmp2"; -ok(@{get_ws_content($tmp2)} == 0, 'no containers on second ws yet'); - -cmd "workspace $tmp"; - -cmd "move workspace $tmp2"; -ok(@{get_ws_content($tmp)} == 1, 'one container on first ws anymore'); -ok(@{get_ws_content($tmp2)} == 1, 'one container on second ws'); -my ($nodes, $focus) = get_ws_content($tmp2); - -is($focus->[0], $second, 'same container on different ws'); - -($nodes, $focus) = get_ws_content($tmp); -ok($nodes->[0]->{focused}, 'first container focused on first ws'); - -################################################################### -# check if 'move workspace next' and 'move workspace prev' work -################################################################### - -# Open two containers on the first workspace, one container on the second -# workspace. Because the workspaces are named, they will be sorted by order of -# creation. -$tmp = get_unused_workspace(); -$tmp2 = get_unused_workspace(); -cmd "workspace $tmp"; -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); -$first = open_empty_con($i3); -$second = open_empty_con($i3); -ok(@{get_ws_content($tmp)} == 2, 'two containers on first ws'); - -cmd "workspace $tmp2"; -ok(@{get_ws_content($tmp2)} == 0, 'no containers yet'); -my $third = open_empty_con($i3); -ok(@{get_ws_content($tmp2)} == 1, 'one container on second ws'); - -# go back to the first workspace, move one of the containers to the next one -cmd "workspace $tmp"; -cmd 'move workspace next'; -ok(@{get_ws_content($tmp)} == 1, 'one container on first ws'); -ok(@{get_ws_content($tmp2)} == 2, 'two containers on second ws'); - -# go to the second workspace and move two containers to the first one -cmd "workspace $tmp2"; -cmd 'move workspace prev'; -cmd 'move workspace prev'; -ok(@{get_ws_content($tmp)} == 3, 'three containers on first ws'); -ok(@{get_ws_content($tmp2)} == 0, 'no containers on second ws'); - -################################################################### -# check if floating cons are moved to new workspaces properly -# (that is, if they are floating on the target ws, too) -################################################################### - -$tmp = get_unused_workspace(); -$tmp2 = get_unused_workspace(); -cmd "workspace $tmp"; - -cmd "open"; -cmd "floating toggle"; - -my $ws = get_ws($tmp); -is(@{$ws->{nodes}}, 0, 'no nodes on workspace'); -is(@{$ws->{floating_nodes}}, 1, 'one floating node on workspace'); - -cmd "move workspace $tmp2"; - -$ws = get_ws($tmp2); -is(@{$ws->{nodes}}, 0, 'no nodes on workspace'); -is(@{$ws->{floating_nodes}}, 1, 'one floating node on workspace'); - -done_testing; diff --git a/testcases/t/33-size-hints.t b/testcases/t/33-size-hints.t deleted file mode 100644 index d2d77e8e..00000000 --- a/testcases/t/33-size-hints.t +++ /dev/null @@ -1,35 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Checks if size hints are interpreted correctly. -# -use i3test; - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - -my $win = open_window($x, { dont_map => 1 }); -# XXX: we should check screen size. in screens with an AR of 2.0, -# this is not a good idea. -my $aspect = X11::XCB::Sizehints::Aspect->new; -$aspect->min_num(600); -$aspect->min_den(300); -$aspect->max_num(600); -$aspect->max_den(300); -$win->_create; -$win->map; -wait_for_map $x; -$win->hints->aspect($aspect); -$x->flush; - -sync_with_i3($x); - -my $rect = $win->rect; -my $ar = $rect->width / $rect->height; -diag("Aspect ratio = $ar"); -ok(($ar > 1.90) && ($ar < 2.10), 'Aspect ratio about 2.0'); - -done_testing; diff --git a/testcases/t/34-invalid-command.t b/testcases/t/34-invalid-command.t deleted file mode 100644 index d58985e3..00000000 --- a/testcases/t/34-invalid-command.t +++ /dev/null @@ -1,12 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# -# -use i3test; - -cmd 'blargh!'; - -does_i3_live; - -done_testing; diff --git a/testcases/t/35-floating-focus.t b/testcases/t/35-floating-focus.t deleted file mode 100644 index 4c5b562f..00000000 --- a/testcases/t/35-floating-focus.t +++ /dev/null @@ -1,228 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab - -use i3test; -use X11::XCB qw(:all); -use X11::XCB::Connection; - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -############################################################################# -# 1: see if focus stays the same when toggling tiling/floating mode -############################################################################# - -my $first = open_window($x); -my $second = open_window($x); - -is($x->input_focus, $second->id, 'second window focused'); - -cmd 'floating enable'; -cmd 'floating disable'; - -is($x->input_focus, $second->id, 'second window still focused after mode toggle'); - -############################################################################# -# 2: see if focus stays on the current floating window if killing another -# floating window -############################################################################# - -$tmp = fresh_workspace; - -$first = open_window($x); # window 2 -$second = open_window($x); # window 3 -my $third = open_window($x); # window 4 - -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'; - -# now kill the third one (it's floating). focus should stay unchanged -cmd '[id="' . $third->id . '"] kill'; - -# TODO: wait for unmapnotify -sync_with_i3($x); - -is($x->input_focus, $second->id, 'second con still focused after killing third'); - - -############################################################################# -# 3: see if the focus gets reverted correctly when closing floating clients -# (first to the next floating client, then to the last focused tiling client) -############################################################################# - -$tmp = fresh_workspace; - -$first = open_window($x, '#ff0000'); # window 5 -$second = open_window($x, '#00ff00'); # window 6 -my $third = open_window($x, '#0000ff'); # window 7 - -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'; - -# now kill the second one. focus should fall back to the third one, which is -# also floating -cmd 'kill'; - -# TODO: wait for unmapnotify -sync_with_i3($x); - -is($x->input_focus, $third->id, 'third con focused'); - -cmd 'kill'; -# TODO: wait for unmapnotify -sync_with_i3($x); - -is($x->input_focus, $first->id, 'first con focused after killing all floating cons'); - -############################################################################# -# 4: same test as 3, but with another split con -############################################################################# - -$tmp = fresh_workspace; - -$first = open_window($x, { background_color => '#ff0000' }); # window 5 -cmd 'split v'; -cmd 'layout stacked'; -$second = open_window($x, { background_color => '#00ff00' }); # window 6 -$third = open_window($x, { background_color => '#0000ff' }); # window 7 - -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'; - -sync_with_i3($x); - -# now kill the second one. focus should fall back to the third one, which is -# also floating -cmd 'kill'; - -# TODO: wait for unmapnotify -sync_with_i3($x); - -is($x->input_focus, $third->id, 'third con focused'); - -cmd 'kill'; -# TODO: wait for unmapnotify -sync_with_i3($x); - -is($x->input_focus, $first->id, 'first con focused after killing all floating cons'); - -############################################################################# -# 5: see if the 'focus tiling' and 'focus floating' commands work -############################################################################# - -$tmp = fresh_workspace; - -$first = open_window($x, { background_color => '#ff0000' }); # window 8 -$second = open_window($x, { background_color => '#00ff00' }); # window 9 - -sync_with_i3($x); - -is($x->input_focus, $second->id, 'second container focused'); - -cmd 'floating enable'; - -is($x->input_focus, $second->id, 'second container focused'); - -cmd 'focus tiling'; - -sync_with_i3($x); - -is($x->input_focus, $first->id, 'first (tiling) container focused'); - -cmd 'focus floating'; - -sync_with_i3($x); - -is($x->input_focus, $second->id, 'second (floating) container focused'); - -cmd 'focus floating'; - -sync_with_i3($x); - -is($x->input_focus, $second->id, 'second (floating) container still focused'); - -cmd 'focus mode_toggle'; - -sync_with_i3($x); - -is($x->input_focus, $first->id, 'first (tiling) container focused'); - -cmd 'focus mode_toggle'; - -sync_with_i3($x); - -is($x->input_focus, $second->id, 'second (floating) container focused'); - -############################################################################# -# 6: see if switching floating focus using the focus left/right command works -############################################################################# - -$tmp = fresh_workspace; - -$first = open_floating_window($x, { background_color => '#ff0000' });# window 10 -$second = open_floating_window($x, { background_color => '#00ff00' }); # window 11 -$third = open_floating_window($x, { background_color => '#0000ff' }); # window 12 - -sync_with_i3($x); - -is($x->input_focus, $third->id, 'third container focused'); - -cmd 'focus left'; - -sync_with_i3($x); - -is($x->input_focus, $second->id, 'second container focused'); - -cmd 'focus left'; - -sync_with_i3($x); - -is($x->input_focus, $first->id, 'first container focused'); - -cmd 'focus left'; - -sync_with_i3($x); - -is($x->input_focus, $third->id, 'focus wrapped to third container'); - -cmd 'focus right'; - -sync_with_i3($x); - -is($x->input_focus, $first->id, 'focus wrapped to first container'); - -cmd 'focus right'; - -sync_with_i3($x); - -is($x->input_focus, $second->id, 'focus on second container'); - -done_testing; diff --git a/testcases/t/36-floating-ws-empty.t b/testcases/t/36-floating-ws-empty.t deleted file mode 100644 index a6e0e405..00000000 --- a/testcases/t/36-floating-ws-empty.t +++ /dev/null @@ -1,35 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# Regression test: when only having a floating window on a workspace, it should not be deleted. - -use i3test; -use X11::XCB qw(:all); - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -############################################################################# -# 1: open a floating window, get it mapped -############################################################################# - -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 = open_floating_window($x); -ok($window->mapped, 'Window is mapped'); - -# switch to a different workspace, see if the window is still mapped? - -my $otmp = fresh_workspace; - -ok(workspace_exists($otmp), "new workspace $otmp exists"); -ok(workspace_exists($tmp), "old workspace $tmp still exists"); - -done_testing; diff --git a/testcases/t/37-floating-unmap.t b/testcases/t/37-floating-unmap.t deleted file mode 100644 index ab1a33d3..00000000 --- a/testcases/t/37-floating-unmap.t +++ /dev/null @@ -1,37 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# Regression test: Floating windows were not correctly unmapped when switching -# to a different workspace. - -use i3test; -use X11::XCB qw(:all); - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -############################################################################# -# 1: open a floating window, get it mapped -############################################################################# - -my $x = X11::XCB::Connection->new; - -# Create a floating window which is smaller than the minimum enforced size of i3 -my $window = open_floating_window($x); -ok($window->mapped, 'Window is mapped'); - -# switch to a different workspace, see if the window is still mapped? - -my $otmp = fresh_workspace; - -sync_with_i3($x); - -ok(!$window->mapped, 'Window is not mapped after switching ws'); - -cmd "nop testcase done"; - -done_testing; diff --git a/testcases/t/38-floating-attach.t b/testcases/t/38-floating-attach.t deleted file mode 100644 index b08190a2..00000000 --- a/testcases/t/38-floating-attach.t +++ /dev/null @@ -1,71 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# Regression test: New windows were attached to the container of a floating window -# if only a floating window is present on the workspace. - -use i3test; -use X11::XCB qw(:all); - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -############################################################################# -# 1: open a floating window, get it mapped -############################################################################# - -my $x = X11::XCB::Connection->new; - -# Create a floating window -my $window = open_floating_window($x); -ok($window->mapped, 'Window is mapped'); - -my $ws = get_ws($tmp); -my ($nodes, $focus) = get_ws_content($tmp); - -is(@{$ws->{floating_nodes}}, 1, 'one floating node'); -is(@{$nodes}, 0, 'no tiling nodes'); - -# Create a tiling window -my $twindow = open_window($x); - -($nodes, $focus) = get_ws_content($tmp); - -is(@{$nodes}, 1, 'one tiling node'); - -############################################################################# -# 2: similar case: floating windows should be attached at the currently focused -# position in the workspace (for example a stack), not just at workspace level. -############################################################################# - -$tmp = fresh_workspace; - -my $first = open_window($x); -my $second = open_window($x); - -cmd 'layout stacked'; - -$ws = get_ws($tmp); -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 = open_floating_window($x); -ok($window->mapped, 'Window is mapped'); - -$ws = get_ws($tmp); -is(@{$ws->{floating_nodes}}, 1, 'one floating nodes'); -is(@{$ws->{nodes}}, 1, 'one tiling node (stacked con)'); - -my $third = open_window($x); - - -$ws = get_ws($tmp); -is(@{$ws->{floating_nodes}}, 1, 'one floating nodes'); -is(@{$ws->{nodes}}, 1, 'one tiling node (stacked con)'); - -done_testing; diff --git a/testcases/t/39-ws-numbers.t b/testcases/t/39-ws-numbers.t deleted file mode 100644 index 31f013ef..00000000 --- a/testcases/t/39-ws-numbers.t +++ /dev/null @@ -1,60 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# Check if numbered workspaces and named workspaces are sorted in the right way -# in get_workspaces IPC output (necessary for i3bar etc.). -use i3test; -use X11::XCB qw(:all); - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $i3 = i3(get_socket_path()); -my $x = X11::XCB::Connection->new; - -sub check_order { - my ($msg) = @_; - - my @ws = @{$i3->get_workspaces->recv}; - my @nums = map { $_->{num} } grep { defined($_->{num}) } @ws; - my @sorted = sort @nums; - - cmp_deeply(\@nums, \@sorted, $msg); -} - -check_order('workspace order alright before testing'); - -############################################################################# -# open a window to keep this ws open -############################################################################# - -cmd "workspace 93"; - -open_window($x); - -my @ws = @{$i3->get_workspaces->recv}; -my @f = grep { defined($_->{num}) && $_->{num} == 93 } @ws; -is(@f, 1, 'ws 93 found by num'); -check_order('workspace order alright after opening 93'); - -cmd "workspace 92"; -open_window($x); -check_order('workspace order alright after opening 92'); - -cmd "workspace 94"; -open_window($x); -check_order('workspace order alright after opening 94'); - -cmd "workspace 96"; -open_window($x); -check_order('workspace order alright after opening 96'); - -cmd "workspace foo"; -open_window($x); -check_order('workspace order alright after opening foo'); - -cmd "workspace 91"; -open_window($x); -check_order('workspace order alright after opening 91'); - -done_testing; diff --git a/testcases/t/40-focus-lost.t b/testcases/t/40-focus-lost.t deleted file mode 100644 index fb77f01e..00000000 --- a/testcases/t/40-focus-lost.t +++ /dev/null @@ -1,45 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# Regression: Check if the focus stays the same when switching the layout -# bug introduced by 77d0d42ed2d7ac8cafe267c92b35a81c1b9491eb -use i3test; -use X11::XCB qw(:all); - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $i3 = i3(get_socket_path()); -my $x = X11::XCB::Connection->new; - -sub check_order { - my ($msg) = @_; - - my @ws = @{$i3->get_workspaces->recv}; - my @nums = map { $_->{num} } grep { defined($_->{num}) } @ws; - my @sorted = sort @nums; - - cmp_deeply(\@nums, \@sorted, $msg); -} - -my $tmp = fresh_workspace; - -my $left = open_window($x); -my $mid = open_window($x); -my $right = open_window($x); - -sync_with_i3($x); - -diag("left = " . $left->id . ", mid = " . $mid->id . ", right = " . $right->id); - -is($x->input_focus, $right->id, 'Right window focused'); - -cmd 'focus left'; - -is($x->input_focus, $mid->id, 'Mid window focused'); - -cmd 'layout stacked'; - -is($x->input_focus, $mid->id, 'Mid window focused'); - -done_testing; diff --git a/testcases/t/41-resize.t b/testcases/t/41-resize.t deleted file mode 100644 index 8691a044..00000000 --- a/testcases/t/41-resize.t +++ /dev/null @@ -1,143 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# Tests resizing tiling containers -use i3test; -use X11::XCB qw(:all); - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -cmd 'split v'; - -my $top = open_window($x); -my $bottom = open_window($x); - -sync_with_i3($x); - -diag("top = " . $top->id . ", bottom = " . $bottom->id); - -is($x->input_focus, $bottom->id, 'Bottom window focused'); - -############################################################ -# resize -############################################################ - -cmd 'resize grow up 10 px or 25 ppt'; - -my ($nodes, $focus) = get_ws_content($tmp); - -is($nodes->[0]->{percent}, 0.25, 'top window got only 25%'); -is($nodes->[1]->{percent}, 0.75, 'bottom window got 75%'); - - -############################################################ -# split and check if the 'percent' factor is still correct -############################################################ - -cmd 'split h'; - -($nodes, $focus) = get_ws_content($tmp); - -is($nodes->[0]->{percent}, 0.25, 'top window got only 25%'); -is($nodes->[1]->{percent}, 0.75, 'bottom window got 75%'); - -############################################################ -# checks that resizing within stacked/tabbed cons works -############################################################ - -$tmp = fresh_workspace; - -cmd 'split v'; - -$top = open_window($x); -$bottom = open_window($x); - -cmd 'split h'; -cmd 'layout stacked'; - -($nodes, $focus) = get_ws_content($tmp); -is($nodes->[0]->{percent}, 0.5, 'top window got 50%'); -is($nodes->[1]->{percent}, 0.5, 'bottom window got 50%'); - -cmd 'resize grow up 10 px or 25 ppt'; - -($nodes, $focus) = get_ws_content($tmp); -is($nodes->[0]->{percent}, 0.25, 'top window got 25%'); -is($nodes->[1]->{percent}, 0.75, 'bottom window got 75%'); - -############################################################ -# checks that resizing floating windows works -############################################################ - -$tmp = fresh_workspace; - -$top = open_window($x); - -cmd 'floating enable'; - -my @content = @{get_ws($tmp)->{floating_nodes}}; -cmp_ok(@content, '==', 1, 'one floating node on this ws'); - -# up -my $oldrect = $content[0]->{rect}; - -cmd 'resize grow up 10 px or 25 ppt'; - -@content = @{get_ws($tmp)->{floating_nodes}}; -cmp_ok($content[0]->{rect}->{y}, '<', $oldrect->{y}, 'y smaller than before'); -cmp_ok($content[0]->{rect}->{y}, '==', $oldrect->{y} - 10, 'y exactly 10 px smaller'); -cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x untouched'); -cmp_ok($content[0]->{rect}->{height}, '>', $oldrect->{height}, 'height bigger than before'); -cmp_ok($content[0]->{rect}->{height}, '==', $oldrect->{height} + 10, 'height exactly 10 px higher'); -cmp_ok($content[0]->{rect}->{width}, '==', $oldrect->{width}, 'x untouched'); - -# up, but with a different amount of px -$oldrect = $content[0]->{rect}; - -cmd 'resize grow up 12 px or 25 ppt'; - -@content = @{get_ws($tmp)->{floating_nodes}}; -cmp_ok($content[0]->{rect}->{y}, '<', $oldrect->{y}, 'y smaller than before'); -cmp_ok($content[0]->{rect}->{y}, '==', $oldrect->{y} - 12, 'y exactly 10 px smaller'); -cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x untouched'); -cmp_ok($content[0]->{rect}->{height}, '>', $oldrect->{height}, 'height bigger than before'); -cmp_ok($content[0]->{rect}->{height}, '==', $oldrect->{height} + 12, 'height exactly 10 px higher'); -cmp_ok($content[0]->{rect}->{width}, '==', $oldrect->{width}, 'x untouched'); - -# left -$oldrect = $content[0]->{rect}; - -cmd 'resize grow left 10 px or 25 ppt'; - -@content = @{get_ws($tmp)->{floating_nodes}}; -cmp_ok($content[0]->{rect}->{x}, '<', $oldrect->{x}, 'x smaller than before'); -cmp_ok($content[0]->{rect}->{width}, '>', $oldrect->{width}, 'width bigger than before'); - -# right -$oldrect = $content[0]->{rect}; - -cmd 'resize grow right 10 px or 25 ppt'; - -@content = @{get_ws($tmp)->{floating_nodes}}; -cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x the same as before'); -cmp_ok($content[0]->{rect}->{y}, '==', $oldrect->{y}, 'y the same as before'); -cmp_ok($content[0]->{rect}->{width}, '>', $oldrect->{width}, 'width bigger than before'); -cmp_ok($content[0]->{rect}->{height}, '==', $oldrect->{height}, 'height the same as before'); - -# down -$oldrect = $content[0]->{rect}; - -cmd 'resize grow down 10 px or 25 ppt'; - -@content = @{get_ws($tmp)->{floating_nodes}}; -cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x the same as before'); -cmp_ok($content[0]->{rect}->{y}, '==', $oldrect->{y}, 'y the same as before'); -cmp_ok($content[0]->{rect}->{height}, '>', $oldrect->{height}, 'height bigger than before'); -cmp_ok($content[0]->{rect}->{width}, '==', $oldrect->{width}, 'width the same as before'); - -done_testing; diff --git a/testcases/t/42-regress-move-floating.t b/testcases/t/42-regress-move-floating.t deleted file mode 100644 index 6b2df806..00000000 --- a/testcases/t/42-regress-move-floating.t +++ /dev/null @@ -1,17 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression: move a floating window to a different workspace crashes i3 -# -use i3test; - -my $tmp = fresh_workspace; -my $otmp = get_unused_workspace(); - -cmd 'open'; -cmd 'mode toggle'; -cmd "move workspace $otmp"; - -does_i3_live; - -done_testing; diff --git a/testcases/t/43-regress-floating-restart.t b/testcases/t/43-regress-floating-restart.t deleted file mode 100644 index babbb574..00000000 --- a/testcases/t/43-regress-floating-restart.t +++ /dev/null @@ -1,23 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression: floating windows are tiling after restarting, closing them crashes i3 -# -use i3test; - -my $tmp = fresh_workspace; - -cmd 'open'; -cmd 'mode toggle'; -cmd 'restart'; - -sleep 0.5; - -diag('Checking if i3 still lives'); - -does_i3_live; - -my $ws = get_ws($tmp); -diag('ws = ' . Dumper($ws)); - -done_testing; diff --git a/testcases/t/44-regress-floating-resize.t b/testcases/t/44-regress-floating-resize.t deleted file mode 100644 index de33eeb3..00000000 --- a/testcases/t/44-regress-floating-resize.t +++ /dev/null @@ -1,37 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression: when resizing two containers on a workspace, opening a floating -# client, then closing it again, i3 will re-distribute the space on the -# workspace as if a tiling container was closed, leading to the containers -# taking much more space than they possibly could. -# -use i3test; -use List::Util qw(sum); - -my $tmp = fresh_workspace; - -cmd 'exec /usr/bin/urxvt'; -sleep 0.5; -cmd 'exec /usr/bin/urxvt'; -sleep 0.5; -my ($nodes, $focus) = get_ws_content($tmp); -my $old_sum = sum map { $_->{rect}->{width} } @{$nodes}; -#cmd 'open'; -cmd 'resize grow left 10 px or 25 ppt'; -cmd 'split v'; -#cmd 'open'; -cmd 'exec /usr/bin/urxvt'; -sleep 0.5; -cmd 'mode toggle'; -sleep 0.5; -cmd 'kill'; - -sleep 0.5; - -($nodes, $focus) = get_ws_content($tmp); -my $new_sum = sum map { $_->{rect}->{width} } @{$nodes}; - -is($old_sum, $new_sum, 'combined container width is still equal'); - -done_testing; diff --git a/testcases/t/45-flattening.t b/testcases/t/45-flattening.t deleted file mode 100644 index 904252e7..00000000 --- a/testcases/t/45-flattening.t +++ /dev/null @@ -1,31 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# by moving the window in the opposite orientation that its parent has, we -# force i3 to create a new split container with the appropriate orientation. -# However, when doing that two times in a row, we end up with two split -# containers which are then redundant (workspace is horizontal, then v-split, -# then h-split – we could just append the children of the latest h-split to the -# workspace itself). -# -# This testcase checks that the tree is properly flattened after moving. -# -use X11::XCB qw(:all); -use i3test; - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -my $left = open_window($x); -my $mid = open_window($x); -my $right = open_window($x); - -cmd 'move before v'; -cmd 'move after h'; -my $ws = get_ws($tmp); - -is($ws->{orientation}, 'horizontal', 'workspace orientation is horizontal'); -is(@{$ws->{nodes}}, 3, 'all three windows on workspace level'); - -done_testing; diff --git a/testcases/t/46-floating-reinsert.t b/testcases/t/46-floating-reinsert.t deleted file mode 100644 index bc1302bb..00000000 --- a/testcases/t/46-floating-reinsert.t +++ /dev/null @@ -1,44 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -use X11::XCB qw(:all); -use i3test; - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -my $left = open_window($x); -my $mid = open_window($x); - -cmd 'split v'; -my $bottom = open_window($x); - -my ($nodes, $focus) = get_ws_content($tmp); - -############################################################################# -# 1: open a floating window, get it mapped -############################################################################# - -# Create a floating window -my $window = open_floating_window($x); -ok($window->mapped, 'Window is mapped'); - -($nodes, $focus) = get_ws_content($tmp); -is(@{$nodes->[1]->{nodes}}, 2, 'two windows in split con'); - -############################################################################# -# 2: make it tiling, see where it ends up -############################################################################# - -cmd 'floating toggle'; - -my ($nodes, $focus) = get_ws_content($tmp); - -is(@{$nodes->[1]->{nodes}}, 3, 'three windows in split con after floating toggle'); - -done_testing; diff --git a/testcases/t/47-regress-floatingmove.t b/testcases/t/47-regress-floatingmove.t deleted file mode 100644 index 771ace32..00000000 --- a/testcases/t/47-regress-floatingmove.t +++ /dev/null @@ -1,44 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression test for moving a con outside of a floating con when there are no -# tiling cons on a workspace -# -use X11::XCB qw(:all); -use Time::HiRes qw(sleep); -use i3test; - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -my $left = open_window($x); -my $mid = open_window($x); -my $right = open_window($x); - -# go to workspace level -cmd 'level up'; -sleep 0.25; - -# make it floating -cmd 'mode toggle'; -sleep 0.25; - -# move the con outside the floating con -cmd 'move before v'; -sleep 0.25; - -does_i3_live; - -# move another con outside -cmd '[id="' . $mid->id . '"] focus'; -cmd 'move before v'; -sleep 0.25; - -does_i3_live; - -done_testing; diff --git a/testcases/t/48-regress-floatingmovews.t b/testcases/t/48-regress-floatingmovews.t deleted file mode 100644 index 6f9dfc40..00000000 --- a/testcases/t/48-regress-floatingmovews.t +++ /dev/null @@ -1,38 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression test for correct focus behaviour when moving a floating con to -# another workspace. -# -use X11::XCB qw(:all); -use i3test; - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -# open a tiling window on the first workspace -open_window($x); -#sleep 0.25; -my $first = get_focused($tmp); - -# on a different ws, open a floating window -my $otmp = fresh_workspace; -open_window($x); -#sleep 0.25; -my $float = get_focused($otmp); -cmd 'mode toggle'; -#sleep 0.25; - -# move the floating con to first workspace -cmd "move workspace $tmp"; -#sleep 0.25; - -# switch to the first ws and check focus -is(get_focused($tmp), $float, 'floating client correctly focused'); - -done_testing; diff --git a/testcases/t/50-regress-dock-restart.t b/testcases/t/50-regress-dock-restart.t deleted file mode 100644 index e294e6bd..00000000 --- a/testcases/t/50-regress-dock-restart.t +++ /dev/null @@ -1,97 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression test for inplace restarting with dock clients -# -use X11::XCB qw(:all); -use i3test; - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -##################################################################### -# verify that there is no dock window yet -##################################################################### - -# Children of all dockareas -my @docked = get_dock_clients; - -is(@docked, 0, 'no dock clients yet'); - -# open a dock client - -my $window = open_window($x, { - background_color => '#FF0000', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), - }); - -##################################################################### -# check that we can find it in the layout tree at the expected position -##################################################################### - -@docked = get_dock_clients; -is(@docked, 1, 'one dock client found'); - -# verify the height -my $docknode = $docked[0]; - -is($docknode->{rect}->{height}, 30, 'dock node has unchanged height'); - -# perform an inplace-restart -cmd 'restart'; - -sleep 0.25; - -does_i3_live; - - -##################################################################### -# check that we can still find the dock client -##################################################################### - -@docked = get_dock_clients; -is(@docked, 1, 'one dock client found'); -$docknode = $docked[0]; - -is($docknode->{rect}->{height}, 30, 'dock node has unchanged height after restart'); - -$window->destroy; - -wait_for_unmap $x; - -@docked = get_dock_clients; -is(@docked, 0, 'no dock clients found'); - -##################################################################### -# create a dock client with a 1px border -##################################################################### - -$window = open_window($x, { - border => 1, - rect => [ 0, 0, 30, 20 ], - background_color => '#00FF00', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), - }); - -@docked = get_dock_clients; -is(@docked, 1, 'one dock client found'); -$docknode = $docked[0]; - -is($docknode->{rect}->{height}, 20, 'dock node has unchanged height'); - -cmd 'restart'; -sleep 0.25; - -@docked = get_dock_clients; -is(@docked, 1, 'one dock client found'); -$docknode = $docked[0]; - -is($docknode->{rect}->{height}, 20, 'dock node has unchanged height'); - - -done_testing; diff --git a/testcases/t/51-regress-float-size.t b/testcases/t/51-regress-float-size.t deleted file mode 100644 index 881ef8c1..00000000 --- a/testcases/t/51-regress-float-size.t +++ /dev/null @@ -1,17 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression test for setting a window to floating, tiling and opening a new window -# -use i3test; - -fresh_workspace; - -cmd 'open'; -cmd 'mode toggle'; -cmd 'mode toggle'; -cmd 'open'; - -does_i3_live; - -done_testing; diff --git a/testcases/t/52-regress-level-up.t b/testcases/t/52-regress-level-up.t deleted file mode 100644 index 678cdd9c..00000000 --- a/testcases/t/52-regress-level-up.t +++ /dev/null @@ -1,18 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression test for using level-up to get to the 'content'-container and -# toggle floating -# -use i3test; - -fresh_workspace; - -cmd 'open'; -cmd 'level up'; -cmd 'level up'; -cmd 'mode toggle'; - -does_i3_live; - -done_testing; diff --git a/testcases/t/53-floating-originalsize.t b/testcases/t/53-floating-originalsize.t deleted file mode 100644 index db0b6e9c..00000000 --- a/testcases/t/53-floating-originalsize.t +++ /dev/null @@ -1,40 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Test if the requested width/height is set after making the window floating. -# -use X11::XCB qw(:all); -use i3test; - -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 = open_window($x, { rect => [ 0, 0, 400, 150 ] }); - -my ($absolute, $top) = $window->rect; - -ok($window->mapped, 'Window is mapped'); -cmp_ok($absolute->{width}, '>', 400, 'i3 raised the width'); -cmp_ok($absolute->{height}, '>', 150, 'i3 raised the height'); - -cmd 'floating toggle'; -sync_with_i3($x); - -($absolute, $top) = $window->rect; - -diag('new width: ' . $absolute->{width}); -diag('new height: ' . $absolute->{height}); - -# we compare with a tolerance of ± 20 pixels for borders in each direction -# (overkill, but hey) -cmp_ok($absolute->{width}, '>', 400-20, 'width now > 380'); -cmp_ok($absolute->{width}, '<', 400+20, 'width now < 420'); -cmp_ok($absolute->{height}, '>', 150-20, 'height now > 130'); -cmp_ok($absolute->{height}, '<', 150+20, 'height now < 170'); - -#cmp_ok($absolute->{width}, '>=', 75, 'i3 raised the width to 75'); -#cmp_ok($absolute->{height}, '>=', 50, 'i3 raised the height to 50'); - -done_testing; diff --git a/testcases/t/54-regress-multiple-dock.t b/testcases/t/54-regress-multiple-dock.t deleted file mode 100644 index 21cb9696..00000000 --- a/testcases/t/54-regress-multiple-dock.t +++ /dev/null @@ -1,57 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression test for closing one of multiple dock clients -# -use X11::XCB qw(:all); -use i3test; - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -##################################################################### -# verify that there is no dock window yet -##################################################################### - -# Children of all dockareas -my @docked = get_dock_clients; - -is(@docked, 0, 'no dock clients yet'); - -##################################################################### -# open a dock client -##################################################################### - -my $first = open_window($x, { - background_color => '#FF0000', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), - }); - -##################################################################### -# Open a second dock client -##################################################################### - -my $second = open_window($x, { - background_color => '#FF0000', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), - }); - -##################################################################### -# Kill the second dock client -##################################################################### -cmd "nop destroying dock client"; -$second->destroy; - -##################################################################### -# Now issue a focus command -##################################################################### -cmd 'next v'; - -does_i3_live; - -done_testing; diff --git a/testcases/t/55-floating-split-size.t b/testcases/t/55-floating-split-size.t deleted file mode 100644 index 5de05e8b..00000000 --- a/testcases/t/55-floating-split-size.t +++ /dev/null @@ -1,57 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Test to see if i3 combines the geometry of all children in a split container -# when setting the split container to floating -# -use X11::XCB qw(:all); -use i3test; - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -##################################################################### -# open a window with 200x80 -##################################################################### - -my $first = open_window($x, { - rect => [ 0, 0, 200, 80], - background_color => '#FF0000', - }); - -##################################################################### -# Open a second window with 300x90 -##################################################################### - -my $second = open_window($x, { - rect => [ 0, 0, 300, 90], - background_color => '#00FF00', - }); - -##################################################################### -# Set the parent to floating -##################################################################### -cmd 'nop setting floating'; -cmd 'focus parent'; -cmd 'floating enable'; - -##################################################################### -# Get geometry of the first floating node (the split container) -##################################################################### - -my @nodes = @{get_ws($tmp)->{floating_nodes}}; -my $rect = $nodes[0]->{rect}; - -# we compare the width with ± 20 pixels for borders -cmp_ok($rect->{width}, '>', 500-20, 'width now > 480'); -cmp_ok($rect->{width}, '<', 500+20, 'width now < 520'); -# we compare the height with ± 40 pixels for decorations -cmp_ok($rect->{height}, '>', 90-40, 'width now > 50'); -cmp_ok($rect->{height}, '<', 90+40, 'width now < 130'); - -done_testing; diff --git a/testcases/t/56-fullscreen-focus.t b/testcases/t/56-fullscreen-focus.t deleted file mode 100644 index a559b5a5..00000000 --- a/testcases/t/56-fullscreen-focus.t +++ /dev/null @@ -1,71 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Test if new containers get focused when there is a fullscreen container at -# the time of launching the new one. -# -use X11::XCB qw(:all); -use i3test; - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -##################################################################### -# open the left window -##################################################################### - -my $left = open_window($x, { background_color => '#ff0000' }); - -is($x->input_focus, $left->id, 'left window focused'); - -diag("left = " . $left->id); - -##################################################################### -# Open the right window -##################################################################### - -my $right = open_window($x, { background_color => '#00ff00' }); - -diag("right = " . $right->id); - -##################################################################### -# Set the right window to fullscreen -##################################################################### -cmd 'nop setting fullscreen'; -cmd 'fullscreen'; - -##################################################################### -# Open a third window -##################################################################### - -my $third = open_window($x, { - background_color => '#0000ff', - name => 'Third window', - dont_map => 1, - }); - -$third->map; - -sync_with_i3 $x; - -diag("third = " . $third->id); - -# move the fullscreen window to a different ws - -my $tmp2 = get_unused_workspace; - -cmd "move workspace $tmp2"; - -# verify that the third window has the focus - -sync_with_i3($x); - -is($x->input_focus, $third->id, 'third window focused'); - -done_testing; diff --git a/testcases/t/57-regress-fullscreen-level-up.t b/testcases/t/57-regress-fullscreen-level-up.t deleted file mode 100644 index 7a101dbc..00000000 --- a/testcases/t/57-regress-fullscreen-level-up.t +++ /dev/null @@ -1,48 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression test: level up should be a noop during fullscreen mode -# -use X11::XCB qw(:all); -use i3test; - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; - -my $tmp = fresh_workspace; - -##################################################################### -# open a window, verify it’s not in fullscreen mode -##################################################################### - -my $win = open_window($x); - -my $nodes = get_ws_content $tmp; -is(@$nodes, 1, 'exactly one client'); -is($nodes->[0]->{fullscreen_mode}, 0, 'client not fullscreen'); - -##################################################################### -# make it fullscreen -##################################################################### - -cmd 'nop making fullscreen'; -cmd 'fullscreen'; - -my $nodes = get_ws_content $tmp; -is($nodes->[0]->{fullscreen_mode}, 1, 'client fullscreen now'); - -##################################################################### -# send level up, try to un-fullscreen -##################################################################### -cmd 'level up'; -cmd 'fullscreen'; - -my $nodes = get_ws_content $tmp; -is($nodes->[0]->{fullscreen_mode}, 0, 'client not fullscreen any longer'); - -does_i3_live; - -done_testing; diff --git a/testcases/t/58-wm_take_focus.t b/testcases/t/58-wm_take_focus.t deleted file mode 100644 index a90ce1c3..00000000 --- a/testcases/t/58-wm_take_focus.t +++ /dev/null @@ -1,44 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests if the WM_TAKE_FOCUS protocol is correctly handled by i3 -# -use X11::XCB qw(:all); -use i3test; -use v5.10; - -my $x = X11::XCB::Connection->new; - -subtest 'Window without WM_TAKE_FOCUS', sub { - fresh_workspace; - - my $window = open_window($x); - - ok(!wait_for_event($x, 1, sub { $_[0]->{response_type} == 161 }), 'did not receive ClientMessage'); - - done_testing; -}; - -subtest 'Window with WM_TAKE_FOCUS', sub { - fresh_workspace; - - my $take_focus = $x->atom(name => 'WM_TAKE_FOCUS'); - - my $window = open_window($x, { - dont_map => 1, - protocols => [ $take_focus ], - }); - - $window->map; - - ok(wait_for_event($x, 1, sub { - return 0 unless $_[0]->{response_type} == 161; - my ($data, $time) = unpack("L2", $_[0]->{data}); - return ($data == $take_focus->id); - }), 'got ClientMessage with WM_TAKE_FOCUS atom'); - - done_testing; -}; - - -done_testing; diff --git a/testcases/t/59-socketpaths.t b/testcases/t/59-socketpaths.t deleted file mode 100644 index eb6bd79f..00000000 --- a/testcases/t/59-socketpaths.t +++ /dev/null @@ -1,70 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 -# -# Tests if the various ipc_socket_path options are correctly handled -# -use i3test; -use File::Temp qw(tempfile tempdir); -use POSIX qw(getuid); -use v5.10; - -##################################################################### -# default case: socket will be created in /tmp/i3-/ipc-socket. -##################################################################### - -my $config = < -##################################################################### - -my $rtdir = tempdir(CLEANUP => 1); - -ok(! -e "$rtdir/i3", "$rtdir/i3 does not exist yet"); - -$ENV{XDG_RUNTIME_DIR} = $rtdir; - -$pid = launch_with_config($config, 1); - -ok(-d "$rtdir/i3", "$rtdir/i3 exists and is a directory"); -$socketpath = "$rtdir/i3/ipc-socket." . $pid; -ok(-S $socketpath, "file $socketpath exists and is a socket"); - -exit_gracefully($pid); - -##################################################################### -# configuration file case: socket gets placed whereever we specify -##################################################################### - -my $tmpdir = tempdir(CLEANUP => 1); -$socketpath = $tmpdir . "/config.sock"; -ok(! -e $socketpath, "$socketpath does not exist yet"); - -$config = <new; -my $i3 = i3(get_socket_path()); -my $tmp = fresh_workspace; -my $window = open_window($x); - -sub get_border_style { - my @content = @{get_ws_content($tmp)}; - my $wininfo = first { $_->{window} == $window->id } @content; - - return $wininfo->{border}; -} - -is(get_border_style(), 'normal', 'border style normal'); - -cmd 'border 1pixel'; - -is(get_border_style(), '1pixel', 'border style 1pixel after changing'); - -# perform an inplace-restart -cmd 'restart'; - -sleep 0.25; - -does_i3_live; - -is(get_border_style(), '1pixel', 'border style still 1pixel after restart'); - -done_testing; diff --git a/testcases/t/62-regress-dock-urgent.t b/testcases/t/62-regress-dock-urgent.t deleted file mode 100644 index 5fb88129..00000000 --- a/testcases/t/62-regress-dock-urgent.t +++ /dev/null @@ -1,59 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression test for setting the urgent hint on dock clients. -# found in 4be3178d4d360c2996217d811e61161c84d25898 -# -use X11::XCB qw(:all); -use i3test; - -BEGIN { - use_ok('X11::XCB::Window'); -} - -my $x = X11::XCB::Connection->new; -my $i3 = i3(get_socket_path()); - -my $tmp = fresh_workspace; - -##################################################################### -# verify that there is no dock window yet -##################################################################### - -# Children of all dockareas -my @docked = get_dock_clients; - -is(@docked, 0, 'no dock clients yet'); - -# open a dock client - -my $window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30], - background_color => '#FF0000', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), -); - -$window->map; - -sleep 0.25; - -##################################################################### -# check that we can find it in the layout tree at the expected position -##################################################################### - -@docked = get_dock_clients; -is(@docked, 1, 'one dock client found'); - -# verify the height -my $docknode = $docked[0]; - -is($docknode->{rect}->{height}, 30, 'dock node has unchanged height'); - -$window->add_hint('urgency'); - -sync_with_i3($x); - -does_i3_live; - -done_testing; diff --git a/testcases/t/63-wm-state.t b/testcases/t/63-wm-state.t deleted file mode 100644 index e55d8682..00000000 --- a/testcases/t/63-wm-state.t +++ /dev/null @@ -1,24 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests if WM_STATE is WM_STATE_NORMAL when mapped and WM_STATE_WITHDRAWN when -# unmapped. -# -use X11::XCB qw(:all); -use i3test; - -my $x = X11::XCB::Connection->new; - -my $window = open_window($x); - -sync_with_i3($x); - -is($window->state, ICCCM_WM_STATE_NORMAL, 'WM_STATE normal'); - -$window->unmap; - -wait_for_unmap $x; - -is($window->state, ICCCM_WM_STATE_WITHDRAWN, 'WM_STATE withdrawn'); - -done_testing; diff --git a/testcases/t/64-kill-win-vs-client.t b/testcases/t/64-kill-win-vs-client.t deleted file mode 100644 index ef45a789..00000000 --- a/testcases/t/64-kill-win-vs-client.t +++ /dev/null @@ -1,66 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests if WM_STATE is WM_STATE_NORMAL when mapped and WM_STATE_WITHDRAWN when -# unmapped. -# -use i3test; - -my $x = X11::XCB::Connection->new; - -sub two_windows { - my $tmp = fresh_workspace; - - ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); - - my $first = open_window($x); - my $second = open_window($x); - - sync_with_i3 $x; - - is($x->input_focus, $second->id, 'second window focused'); - ok(@{get_ws_content($tmp)} == 2, 'two containers opened'); - - return $tmp; -} - -############################################################## -# 1: open two windows (in the same client), kill one and see if -# the other one is still there -############################################################## - -my $tmp = two_windows; - -cmd 'kill'; - -sleep 0.25; - -ok(@{get_ws_content($tmp)} == 1, 'one container left after killing'); - -############################################################## -# 2: same test case as test 1, but with the explicit variant -# 'kill window' -############################################################## - -my $tmp = two_windows; - -cmd 'kill window'; - -sleep 0.25; - -ok(@{get_ws_content($tmp)} == 1, 'one container left after killing'); - -############################################################## -# 3: open two windows (in the same client), use 'kill client' -# and check if both are gone -############################################################## - -my $tmp = two_windows; - -cmd 'kill client'; - -sleep 0.25; - -ok(@{get_ws_content($tmp)} == 0, 'no containers left after killing'); - -done_testing; diff --git a/testcases/t/65-for_window.t b/testcases/t/65-for_window.t deleted file mode 100644 index cc100132..00000000 --- a/testcases/t/65-for_window.t +++ /dev/null @@ -1,469 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 -# -# -use X11::XCB qw(:all); -use X11::XCB::Connection; -use i3test; - -my $x = X11::XCB::Connection->new; - -############################################################## -# 1: test the following directive: -# for_window [class="borderless"] border none -# by first creating a window with a different class (should get -# the normal border), then creating a window with the class -# "borderless" (should get no border) -############################################################## - -my $config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#00ff00', - event_mask => [ 'structure_notify' ], -); - -$window->name('Border window'); -$window->map; -wait_for_map $x; - -my @content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'normal', 'normal border'); - -$window->unmap; -wait_for_unmap $x; - -my @content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 0, 'no more nodes'); -diag('content = '. Dumper(\@content)); - -$window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#00ff00', - event_mask => [ 'structure_notify' ], -); - -$window->_create; - -# TODO: move this to X11::XCB::Window -sub set_wm_class { - my ($id, $class, $instance) = @_; - - # Add a _NET_WM_STRUT_PARTIAL hint - my $atomname = $x->atom(name => 'WM_CLASS'); - my $atomtype = $x->atom(name => 'STRING'); - - $x->change_property( - PROP_MODE_REPLACE, - $id, - $atomname->id, - $atomtype->id, - 8, - length($class) + length($instance) + 2, - "$instance\x00$class\x00" - ); -} - -set_wm_class($window->id, 'borderless', 'borderless'); -$window->name('Borderless window'); -$window->map; -wait_for_map $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'none', 'no border'); - -$window->unmap; -wait_for_unmap $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 0, 'no more nodes'); - -exit_gracefully($pid); - -############################################################## -# 2: match on the title, check if for_window is really executed -# only once -############################################################## - -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#00ff00', - event_mask => [ 'structure_notify' ], -); - -$window->name('special title'); -$window->map; -wait_for_map $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'normal', 'normal border'); - -$window->name('special borderless title'); -sync_with_i3 $x; - -@content = @{get_ws_content($tmp)}; -is($content[0]->{border}, 'none', 'no border'); - -$window->name('special title'); -sync_with_i3 $x; - -cmd 'border normal'; - -@content = @{get_ws_content($tmp)}; -is($content[0]->{border}, 'normal', 'border reset to normal'); - -$window->name('special borderless title'); -sync_with_i3 $x; - -@content = @{get_ws_content($tmp)}; -is($content[0]->{border}, 'normal', 'still normal border'); - -$window->unmap; -wait_for_unmap $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 0, 'no more nodes'); - -exit_gracefully($pid); - -############################################################## -# 3: match on the title, set border style *and* a mark -############################################################## - -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#00ff00', - event_mask => [ 'structure_notify' ], -); - -$window->name('special mark title'); -$window->map; -wait_for_map $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'none', 'no border'); - -my $other = open_window($x); - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 2, 'two nodes'); -is($content[0]->{border}, 'none', 'no border'); -is($content[1]->{border}, 'normal', 'normal border'); -ok(!$content[0]->{focused}, 'first one not focused'); - -cmd qq|[con_mark="bleh"] focus|; - -@content = @{get_ws_content($tmp)}; -ok($content[0]->{focused}, 'first node focused'); - -exit_gracefully($pid); - -############################################################## -# 4: multiple criteria for the for_window command -############################################################## - -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#00ff00', - event_mask => [ 'structure_notify' ], -); - -$window->_create; - -set_wm_class($window->id, 'borderless', 'borderless'); -$window->name('usethis'); -$window->map; -wait_for_map $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'none', 'no border'); - -cmd 'kill'; -wait_for_unmap $x; -$window->destroy; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 0, 'no nodes on this workspace now'); - -$window->_create; - -set_wm_class($window->id, 'borderless', 'borderless'); -$window->name('notthis'); -$window->map; -wait_for_map $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'normal', 'no border'); - - -exit_gracefully($pid); - -############################################################## -# 5: check that a class criterion does not match the instance -############################################################## - -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#00ff00', - event_mask => [ 'structure_notify' ], -); - -$window->_create; - -set_wm_class($window->id, 'bar', 'foo'); -$window->name('usethis'); -$window->map; -wait_for_map $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'normal', 'normal border, not matched'); - -exit_gracefully($pid); - -############################################################## -# 6: check that the 'instance' criterion works -############################################################## - -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#00ff00', - event_mask => [ 'structure_notify' ], -); - -$window->_create; - -set_wm_class($window->id, 'bar', 'foo'); -$window->name('usethis'); -$window->map; -wait_for_map $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'none', 'no border'); - -exit_gracefully($pid); - -############################################################## -# 7: check that invalid criteria don’t end up matching all windows -############################################################## - -# this configuration is broken because "asdf" is not a valid integer -# the for_window should therefore recognize this error and don’t add the -# assignment -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#00ff00', - event_mask => [ 'structure_notify' ], -); - -$window->_create; - -set_wm_class($window->id, 'bar', 'foo'); -$window->name('usethis'); -$window->map; -wait_for_map $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'normal', 'normal border'); - -exit_gracefully($pid); - -############################################################## -# 8: check that the role criterion works properly -############################################################## - -# this configuration is broken because "asdf" is not a valid integer -# the for_window should therefore recognize this error and don’t add the -# assignment -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#00ff00', - event_mask => [ 'structure_notify' ], -); - -$window->_create; - -my $atomname = $x->atom(name => 'WM_WINDOW_ROLE'); -my $atomtype = $x->atom(name => 'STRING'); -$x->change_property( - PROP_MODE_REPLACE, - $window->id, - $atomname->id, - $atomtype->id, - 8, - length("i3test") + 1, - "i3test\x00" -); - -$window->name('usethis'); -$window->map; -wait_for_map $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'none', 'no border (window_role)'); - -exit_gracefully($pid); - -############################################################## -# 9: another test for the window_role, but this time it changes -# *after* the window has been mapped -############################################################## - -# this configuration is broken because "asdf" is not a valid integer -# the for_window should therefore recognize this error and don’t add the -# assignment -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#00ff00', - event_mask => [ 'structure_notify' ], -); - -$window->_create; - -$window->name('usethis'); -$window->map; -wait_for_map $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'normal', 'normal border (window_role 2)'); - -$atomname = $x->atom(name => 'WM_WINDOW_ROLE'); -$atomtype = $x->atom(name => 'STRING'); -$x->change_property( - PROP_MODE_REPLACE, - $window->id, - $atomname->id, - $atomtype->id, - 8, - length("i3test") + 1, - "i3test\x00" -); - -$x->flush; - -sync_with_i3 $x; - -@content = @{get_ws_content($tmp)}; -cmp_ok(@content, '==', 1, 'one node on this workspace now'); -is($content[0]->{border}, 'none', 'no border (window_role 2)'); - -exit_gracefully($pid); - - -done_testing; diff --git a/testcases/t/66-assign.t b/testcases/t/66-assign.t deleted file mode 100644 index 4844f5b5..00000000 --- a/testcases/t/66-assign.t +++ /dev/null @@ -1,286 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 -# -# Tests if assignments work -# -use i3test; -use X11::XCB qw(:all); -use X11::XCB::Connection; -use v5.10; - -my $x = X11::XCB::Connection->new; - -# TODO: move to X11::XCB -sub set_wm_class { - my ($id, $class, $instance) = @_; - - # Add a _NET_WM_STRUT_PARTIAL hint - my $atomname = $x->atom(name => 'WM_CLASS'); - my $atomtype = $x->atom(name => 'STRING'); - - $x->change_property( - PROP_MODE_REPLACE, - $id, - $atomname->id, - $atomtype->id, - 8, - length($class) + length($instance) + 2, - "$instance\x00$class\x00" - ); -} - - -##################################################################### -# start a window and see that it does not get assigned with an empty config -##################################################################### - -my $config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - event_mask => [ 'structure_notify' ], -); - -$window->_create; -set_wm_class($window->id, 'special', 'special'); -$window->name('special window'); -$window->map; -wait_for_map $x; - -ok(@{get_ws_content($tmp)} == 1, 'special window got managed to current (random) workspace'); - -exit_gracefully($pid); - -$window->destroy; - -##################################################################### -# start a window and see that it gets assigned to a formerly unused -# workspace -##################################################################### - -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - event_mask => [ 'structure_notify' ], -); - -$window->_create; -set_wm_class($window->id, 'special', 'special'); -$window->name('special window'); -$window->map; -wait_for_map $x; - -ok(@{get_ws_content($tmp)} == 0, 'still no containers'); -ok("targetws" ~~ @{get_workspace_names()}, 'targetws exists'); - -$window->destroy; - -exit_gracefully($pid); - -sleep 0.25; - -##################################################################### -# start a window and see that it gets assigned to a workspace which has content -# already, next to the existing node. -##################################################################### - -$pid = launch_with_config($config); - -# initialize the target workspace, then go to a fresh one -ok(!("targetws" ~~ @{get_workspace_names()}), 'targetws does not exist yet'); -cmd 'workspace targetws'; -cmp_ok(@{get_ws_content('targetws')}, '==', 0, 'no containers on targetws yet'); -cmd 'open'; -cmp_ok(@{get_ws_content('targetws')}, '==', 1, 'one container on targetws'); -$tmp = fresh_workspace; - -ok(@{get_ws_content($tmp)} == 0, 'no containers yet'); -ok("targetws" ~~ @{get_workspace_names()}, 'targetws does not exist yet'); - -my $window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - event_mask => [ 'structure_notify' ], -); - -$window->_create; -set_wm_class($window->id, 'special', 'special'); -$window->name('special window'); -$window->map; - -# We use sync_with_i3 instead of wait_for_map here because i3 will not actually -# map the window -- it will be assigned to a different workspace and will only -# be mapped once you switch to that workspace -sync_with_i3 $x; - -ok(@{get_ws_content($tmp)} == 0, 'still no containers'); -ok(@{get_ws_content('targetws')} == 2, 'two containers on targetws'); - -exit_gracefully($pid); - -##################################################################### -# start a window and see that it gets assigned to a workspace which has content -# already, next to the existing node. -##################################################################### - -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - event_mask => [ 'structure_notify' ], -); - -$window->_create; -set_wm_class($window->id, 'special', 'special'); -$window->name('special window'); -$window->map; -wait_for_map $x; - -my $content = get_ws($tmp); -ok(@{$content->{nodes}} == 0, 'no tiling cons'); -ok(@{$content->{floating_nodes}} == 1, 'one floating con'); - -$window->destroy; - -exit_gracefully($pid); - -sleep 0.25; - -##################################################################### -# make sure that assignments are case-insensitive in the old syntax. -##################################################################### - -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - event_mask => [ 'structure_notify' ], -); - -$window->_create; -set_wm_class($window->id, 'SPEcial', 'SPEcial'); -$window->name('special window'); -$window->map; -wait_for_map $x; - -my $content = get_ws($tmp); -ok(@{$content->{nodes}} == 0, 'no tiling cons'); -ok(@{$content->{floating_nodes}} == 1, 'one floating con'); - -$window->destroy; - -exit_gracefully($pid); - -sleep 0.25; - -##################################################################### -# regression test: dock clients with floating assignments should not crash -# (instead, nothing should happen - dock clients can’t float) -# ticket #501 -##################################################################### - -$config = <root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK'), - event_mask => [ 'structure_notify' ], -); - -$window->_create; -set_wm_class($window->id, 'special', 'special'); -$window->name('special window'); -$window->map; -wait_for_map $x; - -my $content = get_ws($tmp); -ok(@{$content->{nodes}} == 0, 'no tiling cons'); -ok(@{$content->{floating_nodes}} == 0, 'one floating con'); -@docked = get_dock_clients; -is(@docked, 2, 'two dock clients now'); - -$window->destroy; - -does_i3_live; - -exit_gracefully($pid); - -sleep 0.25; - -done_testing; diff --git a/testcases/t/67-workspace_layout.t b/testcases/t/67-workspace_layout.t deleted file mode 100644 index e4b18adf..00000000 --- a/testcases/t/67-workspace_layout.t +++ /dev/null @@ -1,127 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 -# -# Tests the workspace_layout config option. -# - -use i3test; -use X11::XCB qw(:all); -use X11::XCB::Connection; - -my $x = X11::XCB::Connection->new; - -##################################################################### -# 1: check that with an empty config, cons are place next to each -# other and no split containers are created -##################################################################### - -my $config = <input_focus, $second->id, 'second window focused'); -ok(@{get_ws_content($tmp)} == 2, 'two containers opened'); -isnt($content[0]->{layout}, 'stacked', 'layout not stacked'); -isnt($content[1]->{layout}, 'stacked', 'layout not stacked'); - -exit_gracefully($pid); - -##################################################################### -# 2: set workspace_layout stacked, check that when opening two cons, -# they end up in a stacked con -##################################################################### - -$config = <input_focus, $second->id, 'second window focused'); -my @content = @{get_ws_content($tmp)}; -ok(@content == 1, 'one con at workspace level'); -is($content[0]->{layout}, 'stacked', 'layout stacked'); - -##################################################################### -# 3: focus parent, open two new cons, check that they end up in a stacked -# con -##################################################################### - -cmd 'focus parent'; -my $right_top = open_window($x); -my $right_bot = open_window($x); - -@content = @{get_ws_content($tmp)}; -is(@content, 2, 'two cons at workspace level after focus parent'); -is($content[0]->{layout}, 'stacked', 'layout stacked'); -is($content[1]->{layout}, 'stacked', 'layout stacked'); - -##################################################################### -# 4: move one of the cons to the right, check that it will end up in -# a stacked con -##################################################################### - -cmd 'move right'; - -@content = @{get_ws_content($tmp)}; -is(@content, 3, 'three cons at workspace level after move'); -is($content[0]->{layout}, 'stacked', 'layout stacked'); -is($content[1]->{layout}, 'stacked', 'layout stacked'); -is($content[2]->{layout}, 'stacked', 'layout stacked'); - -##################################################################### -# 5: move it to the left again, check that the stacked con is deleted -##################################################################### - -cmd 'move left'; - -@content = @{get_ws_content($tmp)}; -is(@content, 2, 'two cons at workspace level after moving back'); -is($content[0]->{layout}, 'stacked', 'layout stacked'); -is($content[1]->{layout}, 'stacked', 'layout stacked'); - -##################################################################### -# 6: move it to a different workspace, check that it ends up in a -# stacked con -##################################################################### - -my $otmp = get_unused_workspace; - -cmd "move workspace $otmp"; - -@content = @{get_ws_content($tmp)}; -is(@content, 2, 'still two cons on this workspace'); -is($content[0]->{layout}, 'stacked', 'layout stacked'); -is($content[1]->{layout}, 'stacked', 'layout stacked'); - -@content = @{get_ws_content($otmp)}; -is(@content, 1, 'one con on target workspace'); -is($content[0]->{layout}, 'stacked', 'layout stacked'); - -exit_gracefully($pid); - -done_testing; diff --git a/testcases/t/68-regress-fullscreen-restart.t b/testcases/t/68-regress-fullscreen-restart.t deleted file mode 100644 index 1418b402..00000000 --- a/testcases/t/68-regress-fullscreen-restart.t +++ /dev/null @@ -1,28 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Verifies that i3 survives inplace restarts with fullscreen containers -# -use i3test; -use X11::XCB qw(:all); -use X11::XCB::Connection; - -my $x = X11::XCB::Connection->new; - -fresh_workspace; - -open_window($x); -open_window($x); - -cmd 'layout stacking'; -sleep 1; - -cmd 'fullscreen'; -sleep 1; - -cmd 'restart'; -sleep 1; - -does_i3_live; - -done_testing; diff --git a/testcases/t/69-border-toggle.t b/testcases/t/69-border-toggle.t deleted file mode 100644 index aec8df6c..00000000 --- a/testcases/t/69-border-toggle.t +++ /dev/null @@ -1,40 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Tests if the 'border toggle' command works correctly -# -use i3test; - -my $tmp = fresh_workspace; - -cmd 'open'; - -my @nodes = @{get_ws_content($tmp)}; -is(@nodes, 1, 'one container on this workspace'); -is($nodes[0]->{border}, 'normal', 'border style normal'); - -cmd 'border 1pixel'; -@nodes = @{get_ws_content($tmp)}; -is($nodes[0]->{border}, '1pixel', 'border style 1pixel'); - -cmd 'border none'; -@nodes = @{get_ws_content($tmp)}; -is($nodes[0]->{border}, 'none', 'border style none'); - -cmd 'border normal'; -@nodes = @{get_ws_content($tmp)}; -is($nodes[0]->{border}, 'normal', 'border style back to normal'); - -cmd 'border toggle'; -@nodes = @{get_ws_content($tmp)}; -is($nodes[0]->{border}, 'none', 'border style none'); - -cmd 'border toggle'; -@nodes = @{get_ws_content($tmp)}; -is($nodes[0]->{border}, '1pixel', 'border style 1pixel'); - -cmd 'border toggle'; -@nodes = @{get_ws_content($tmp)}; -is($nodes[0]->{border}, 'normal', 'border style back to normal'); - -done_testing; diff --git a/testcases/t/70-force_focus_wrapping.t b/testcases/t/70-force_focus_wrapping.t deleted file mode 100644 index 8a990f23..00000000 --- a/testcases/t/70-force_focus_wrapping.t +++ /dev/null @@ -1,97 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 -# -# Tests if the 'force_focus_wrapping' config directive works correctly. -# -use i3test; -use X11::XCB qw(:all); -use X11::XCB::Connection; - -my $x = X11::XCB::Connection->new; - -##################################################################### -# 1: test the wrapping behaviour without force_focus_wrapping -##################################################################### - -my $config = <input_focus, $third->id, 'third window focused'); - -cmd 'focus left'; -is($x->input_focus, $second->id, 'second window focused'); - -cmd 'focus left'; -is($x->input_focus, $first->id, 'first window focused'); - -# now test the wrapping -cmd 'focus left'; -is($x->input_focus, $second->id, 'second window focused'); - -# but focusing right should not wrap now, but instead focus the third window -cmd 'focus right'; -is($x->input_focus, $third->id, 'third window focused'); - -exit_gracefully($pid); - -##################################################################### -# 2: test the wrapping behaviour with force_focus_wrapping -##################################################################### - -$config = <input_focus, $third->id, 'third window focused'); - -cmd 'focus left'; -is($x->input_focus, $second->id, 'second window focused'); - -cmd 'focus left'; -is($x->input_focus, $first->id, 'first window focused'); - -# now test the wrapping -cmd 'focus left'; -is($x->input_focus, $second->id, 'second window focused'); - -# focusing right should now be forced to wrap -cmd 'focus right'; -is($x->input_focus, $first->id, 'first window focused'); - -exit_gracefully($pid); - -done_testing; diff --git a/testcases/t/71-config-migrate.t b/testcases/t/71-config-migrate.t deleted file mode 100644 index 7948db6c..00000000 --- a/testcases/t/71-config-migrate.t +++ /dev/null @@ -1,349 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 -# -# Tests if i3-migrate-config-to-v4 correctly migrates all config file -# directives and commands -# -use i3test; -use Cwd qw(abs_path); -use File::Temp qw(tempfile tempdir); -use v5.10; - -# reads in a whole file -sub slurp { - open my $fh, '<', shift; - local $/; - <$fh>; -} - -sub migrate_config { - my ($config) = @_; - - my ($fh, $tmpfile) = tempfile('/tmp/i3-migrate-cfg.XXXXXX', UNLINK => 1); - print $fh $config; - close($fh); - - my $cmd = "sh -c 'exec " . abs_path("../i3-migrate-config-to-v4") . " --v3 <$tmpfile'"; - return [ split /\n/, qx($cmd) ]; -} - -sub line_exists { - my ($lines, $pattern) = @_; - - for my $line (@$lines) { - return 1 if $line =~ $pattern; - } - - return 0 -} - -##################################################################### -# check that some directives remain untouched -##################################################################### - -my $input = <new; - -############################################################## -# 1: i3 should start with workspace '1' -############################################################## - -my $config = <get_marks->recv; -} - -############################################################## -# 1: check that get_marks returns no marks yet -############################################################## - -my $tmp = fresh_workspace; - -my $marks = get_marks(); -cmp_deeply($marks, [], 'no marks set so far'); - -############################################################## -# 2: check that setting a mark is reflected in the get_marks reply -############################################################## - -cmd 'open'; -cmd 'mark foo'; - -cmp_deeply(get_marks(), [ 'foo' ], 'mark foo set'); - -############################################################## -# 3: check that the mark is gone after killing the container -############################################################## - -cmd 'kill'; - -cmp_deeply(get_marks(), [ ], 'mark gone'); - -############################################################## -# 4: check that duplicate marks are included twice in the get_marks reply -############################################################## - -cmd 'open'; -cmd 'mark bar'; - -cmd 'open'; -cmd 'mark bar'; - -cmp_deeply(get_marks(), [ 'bar', 'bar' ], 'duplicate mark found twice'); - -done_testing; diff --git a/testcases/t/73-regress-focus-assign.t b/testcases/t/73-regress-focus-assign.t deleted file mode 100644 index 70414af3..00000000 --- a/testcases/t/73-regress-focus-assign.t +++ /dev/null @@ -1,95 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 -# -# Regression: Checks if focus is stolen when a window is managed which is -# assigned to an invisible workspace -# -use i3test; -use X11::XCB qw(:all); -use X11::XCB::Connection; -use v5.10; - -my $x = X11::XCB::Connection->new; - -# TODO: move to X11::XCB -sub set_wm_class { - my ($id, $class, $instance) = @_; - - # Add a _NET_WM_STRUT_PARTIAL hint - my $atomname = $x->atom(name => 'WM_CLASS'); - my $atomtype = $x->atom(name => 'STRING'); - - $x->change_property( - PROP_MODE_REPLACE, - $id, - $atomname->id, - $atomtype->id, - 8, - length($class) + length($instance) + 2, - "$instance\x00$class\x00" - ); -} - - -##################################################################### -# start a window and see that it does not get assigned with an empty config -##################################################################### - -my $config = <{focused}, 'current workspace focused'); - -my $window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', -); - -$window->_create; -set_wm_class($window->id, 'special', 'special'); -$window->name('special window'); -$window->map; -sleep 0.25; - - -ok(@{get_ws_content($tmp)} == 0, 'special window not on current workspace'); -ok(@{get_ws_content('targetws')} == 1, 'special window on targetws'); -ok(get_ws($tmp)->{focused}, 'current workspace still focused'); - -##################################################################### -# the same test, but with a floating window -##################################################################### - -$window = $x->root->create_child( - class => WINDOW_CLASS_INPUT_OUTPUT, - rect => [ 0, 0, 30, 30 ], - background_color => '#0000ff', - window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'), -); - -$window->_create; -set_wm_class($window->id, 'special', 'special'); -$window->name('special window'); -$window->map; -sleep 0.25; - - -ok(@{get_ws_content($tmp)} == 0, 'special window not on current workspace'); -ok(@{get_ws_content('targetws')} == 1, 'special window on targetws'); -ok(get_ws($tmp)->{focused}, 'current workspace still focused'); - -exit_gracefully($pid); - -$window->destroy; - -done_testing; diff --git a/testcases/t/74-border-config.t b/testcases/t/74-border-config.t deleted file mode 100644 index cc1f5c90..00000000 --- a/testcases/t/74-border-config.t +++ /dev/null @@ -1,116 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3 -# -# Tests the new_window and new_float config option. -# - -use i3test; - -my $x = X11::XCB::Connection->new; - -##################################################################### -# 1: check that new windows start with 'normal' border unless configured -# otherwise -##################################################################### - -my $config = <{border}, 'normal', 'border normal by default'); - -exit_gracefully($pid); - -##################################################################### -# 2: check that new tiling windows start with '1pixel' border when -# configured -##################################################################### - -$config = <{border}, '1pixel', 'border normal by default'); - -exit_gracefully($pid); - -##################################################################### -# 3: check that new floating windows start with 'normal' border unless -# configured otherwise -##################################################################### - -$config = <{floating_nodes}}; -ok(@floating == 1, 'one floating container opened'); -my $floatingcon = $floating[0]; -is($floatingcon->{nodes}->[0]->{border}, 'normal', 'border normal by default'); - -exit_gracefully($pid); - -##################################################################### -# 4: check that new floating windows start with '1pixel' border when -# configured -##################################################################### - -$config = <{floating_nodes}}; -ok(@floating == 1, 'one floating container opened'); -$floatingcon = $floating[0]; -is($floatingcon->{nodes}->[0]->{border}, '1pixel', 'border normal by default'); - -exit_gracefully($pid); - -done_testing; diff --git a/testcases/t/74-regress-focus-toggle.t b/testcases/t/74-regress-focus-toggle.t deleted file mode 100644 index 469d1be8..00000000 --- a/testcases/t/74-regress-focus-toggle.t +++ /dev/null @@ -1,17 +0,0 @@ -#!perl -# vim:ts=4:sw=4:expandtab -# -# Regression: Checks if i3 still lives after using 'focus mode_toggle' on an -# empty workspace. This regression was fixed in -# 0848844f2d41055f6ffc69af1149d7a873460976. -# -use i3test; -use v5.10; - -my $tmp = fresh_workspace; - -cmd 'focus mode_toggle'; - -does_i3_live; - -done_testing;