]> git.sur5r.net Git - i3/i3/commitdiff
tests: rename files (00x-*.t is basic stuff, >=100-*.t are tests using IPC)
authorMichael Stapelberg <michael@stapelberg.de>
Sat, 8 Oct 2011 13:38:50 +0000 (14:38 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Sat, 8 Oct 2011 13:38:50 +0000 (14:38 +0100)
147 files changed:
testcases/t/00-load.t [deleted file]
testcases/t/000-load-deps.t [new file with mode: 0644]
testcases/t/001-tile.t [new file with mode: 0644]
testcases/t/002-i3-sync.t [new file with mode: 0644]
testcases/t/003-ipc.t [new file with mode: 0644]
testcases/t/004-unmanaged.t [new file with mode: 0644]
testcases/t/005-floating.t [new file with mode: 0644]
testcases/t/01-tile.t [deleted file]
testcases/t/02-fullscreen.t [deleted file]
testcases/t/03-unmanaged.t [deleted file]
testcases/t/04-floating.t [deleted file]
testcases/t/05-ipc.t [deleted file]
testcases/t/06-focus.t [deleted file]
testcases/t/07-move.t [deleted file]
testcases/t/08-focus-stack.t [deleted file]
testcases/t/09-stacking.t [deleted file]
testcases/t/10-dock.t [deleted file]
testcases/t/100-fullscreen.t [new file with mode: 0644]
testcases/t/101-focus.t [new file with mode: 0644]
testcases/t/102-dock.t [new file with mode: 0644]
testcases/t/103-move.t [new file with mode: 0644]
testcases/t/104-focus-stack.t [new file with mode: 0644]
testcases/t/105-stacking.t [new file with mode: 0644]
testcases/t/11-goto.t [deleted file]
testcases/t/111-goto.t [new file with mode: 0644]
testcases/t/112-floating-resize.t [new file with mode: 0644]
testcases/t/113-urgent.t [new file with mode: 0644]
testcases/t/114-client-leader.t [new file with mode: 0644]
testcases/t/115-ipc-workspaces.t [new file with mode: 0644]
testcases/t/116-nestedcons.t [new file with mode: 0644]
testcases/t/117-workspace.t [new file with mode: 0644]
testcases/t/118-openkill.t [new file with mode: 0644]
testcases/t/119-match.t [new file with mode: 0644]
testcases/t/12-floating-resize.t [deleted file]
testcases/t/120-multiple-cmds.t [new file with mode: 0644]
testcases/t/121-next-prev.t [new file with mode: 0644]
testcases/t/122-split.t [new file with mode: 0644]
testcases/t/124-move.t [new file with mode: 0644]
testcases/t/126-regress-close.t [new file with mode: 0644]
testcases/t/127-regress-floating-parent.t [new file with mode: 0644]
testcases/t/128-open-order.t [new file with mode: 0644]
testcases/t/129-focus-after-close.t [new file with mode: 0644]
testcases/t/13-urgent.t [deleted file]
testcases/t/130-close-empty-split.t [new file with mode: 0644]
testcases/t/131-stacking-order.t [new file with mode: 0644]
testcases/t/132-move-workspace.t [new file with mode: 0644]
testcases/t/133-size-hints.t [new file with mode: 0644]
testcases/t/134-invalid-command.t [new file with mode: 0644]
testcases/t/135-floating-focus.t [new file with mode: 0644]
testcases/t/136-floating-ws-empty.t [new file with mode: 0644]
testcases/t/137-floating-unmap.t [new file with mode: 0644]
testcases/t/138-floating-attach.t [new file with mode: 0644]
testcases/t/139-ws-numbers.t [new file with mode: 0644]
testcases/t/14-client-leader.t [deleted file]
testcases/t/140-focus-lost.t [new file with mode: 0644]
testcases/t/141-resize.t [new file with mode: 0644]
testcases/t/142-regress-move-floating.t [new file with mode: 0644]
testcases/t/143-regress-floating-restart.t [new file with mode: 0644]
testcases/t/144-regress-floating-resize.t [new file with mode: 0644]
testcases/t/145-flattening.t [new file with mode: 0644]
testcases/t/146-floating-reinsert.t [new file with mode: 0644]
testcases/t/147-regress-floatingmove.t [new file with mode: 0644]
testcases/t/148-regress-floatingmovews.t [new file with mode: 0644]
testcases/t/15-ipc-workspaces.t [deleted file]
testcases/t/150-regress-dock-restart.t [new file with mode: 0644]
testcases/t/151-regress-float-size.t [new file with mode: 0644]
testcases/t/152-regress-level-up.t [new file with mode: 0644]
testcases/t/153-floating-originalsize.t [new file with mode: 0644]
testcases/t/154-regress-multiple-dock.t [new file with mode: 0644]
testcases/t/155-floating-split-size.t [new file with mode: 0644]
testcases/t/156-fullscreen-focus.t [new file with mode: 0644]
testcases/t/157-regress-fullscreen-level-up.t [new file with mode: 0644]
testcases/t/158-wm_take_focus.t [new file with mode: 0644]
testcases/t/159-socketpaths.t [new file with mode: 0644]
testcases/t/16-nestedcons.t [deleted file]
testcases/t/161-regress-borders-restart.t [new file with mode: 0644]
testcases/t/162-regress-dock-urgent.t [new file with mode: 0644]
testcases/t/163-wm-state.t [new file with mode: 0644]
testcases/t/164-kill-win-vs-client.t [new file with mode: 0644]
testcases/t/165-for_window.t [new file with mode: 0644]
testcases/t/166-assign.t [new file with mode: 0644]
testcases/t/167-workspace_layout.t [new file with mode: 0644]
testcases/t/168-regress-fullscreen-restart.t [new file with mode: 0644]
testcases/t/169-border-toggle.t [new file with mode: 0644]
testcases/t/17-workspace.t [deleted file]
testcases/t/170-force_focus_wrapping.t [new file with mode: 0644]
testcases/t/171-config-migrate.t [new file with mode: 0644]
testcases/t/172-start-on-named-ws.t [new file with mode: 0644]
testcases/t/173-get-marks.t [new file with mode: 0644]
testcases/t/173-regress-focus-assign.t [new file with mode: 0644]
testcases/t/174-border-config.t [new file with mode: 0644]
testcases/t/174-regress-focus-toggle.t [new file with mode: 0644]
testcases/t/18-openkill.t [deleted file]
testcases/t/19-match.t [deleted file]
testcases/t/20-multiple-cmds.t [deleted file]
testcases/t/21-next-prev.t [deleted file]
testcases/t/22-split.t [deleted file]
testcases/t/24-move.t [deleted file]
testcases/t/26-regress-close.t [deleted file]
testcases/t/27-regress-floating-parent.t [deleted file]
testcases/t/28-open-order.t [deleted file]
testcases/t/29-focus-after-close.t [deleted file]
testcases/t/30-close-empty-split.t [deleted file]
testcases/t/31-stacking-order.t [deleted file]
testcases/t/32-move-workspace.t [deleted file]
testcases/t/33-size-hints.t [deleted file]
testcases/t/34-invalid-command.t [deleted file]
testcases/t/35-floating-focus.t [deleted file]
testcases/t/36-floating-ws-empty.t [deleted file]
testcases/t/37-floating-unmap.t [deleted file]
testcases/t/38-floating-attach.t [deleted file]
testcases/t/39-ws-numbers.t [deleted file]
testcases/t/40-focus-lost.t [deleted file]
testcases/t/41-resize.t [deleted file]
testcases/t/42-regress-move-floating.t [deleted file]
testcases/t/43-regress-floating-restart.t [deleted file]
testcases/t/44-regress-floating-resize.t [deleted file]
testcases/t/45-flattening.t [deleted file]
testcases/t/46-floating-reinsert.t [deleted file]
testcases/t/47-regress-floatingmove.t [deleted file]
testcases/t/48-regress-floatingmovews.t [deleted file]
testcases/t/50-regress-dock-restart.t [deleted file]
testcases/t/51-regress-float-size.t [deleted file]
testcases/t/52-regress-level-up.t [deleted file]
testcases/t/53-floating-originalsize.t [deleted file]
testcases/t/54-regress-multiple-dock.t [deleted file]
testcases/t/55-floating-split-size.t [deleted file]
testcases/t/56-fullscreen-focus.t [deleted file]
testcases/t/57-regress-fullscreen-level-up.t [deleted file]
testcases/t/58-wm_take_focus.t [deleted file]
testcases/t/59-socketpaths.t [deleted file]
testcases/t/61-regress-borders-restart.t [deleted file]
testcases/t/62-regress-dock-urgent.t [deleted file]
testcases/t/63-wm-state.t [deleted file]
testcases/t/64-kill-win-vs-client.t [deleted file]
testcases/t/65-for_window.t [deleted file]
testcases/t/66-assign.t [deleted file]
testcases/t/67-workspace_layout.t [deleted file]
testcases/t/68-regress-fullscreen-restart.t [deleted file]
testcases/t/69-border-toggle.t [deleted file]
testcases/t/70-force_focus_wrapping.t [deleted file]
testcases/t/71-config-migrate.t [deleted file]
testcases/t/72-start-on-named-ws.t [deleted file]
testcases/t/73-get-marks.t [deleted file]
testcases/t/73-regress-focus-assign.t [deleted file]
testcases/t/74-border-config.t [deleted file]
testcases/t/74-regress-focus-toggle.t [deleted file]

diff --git a/testcases/t/00-load.t b/testcases/t/00-load.t
deleted file mode 100644 (file)
index 5dfc5c6..0000000
+++ /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 (file)
index 0000000..5dfc5c6
--- /dev/null
@@ -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 (file)
index 0000000..0db3b83
--- /dev/null
@@ -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 (file)
index 0000000..7518c94
--- /dev/null
@@ -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 (file)
index 0000000..982ece7
--- /dev/null
@@ -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 (file)
index 0000000..1ef934e
--- /dev/null
@@ -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 (file)
index 0000000..d605328
--- /dev/null
@@ -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 (file)
index 0db3b83..0000000
+++ /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 (file)
index ae8c63f..0000000
+++ /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 (file)
index 1ef934e..0000000
+++ /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 (file)
index d605328..0000000
+++ /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 (file)
index 982ece7..0000000
+++ /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 (file)
index 5ded494..0000000
+++ /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 (file)
index 6e35ebe..0000000
+++ /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 (file)
index b5be284..0000000
+++ /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 (file)
index cc285f3..0000000
+++ /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 (file)
index cad54c2..0000000
+++ /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 (file)
index 0000000..ae8c63f
--- /dev/null
@@ -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 (file)
index 0000000..5ded494
--- /dev/null
@@ -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 (file)
index 0000000..cad54c2
--- /dev/null
@@ -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 (file)
index 0000000..6e35ebe
--- /dev/null
@@ -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 (file)
index 0000000..b5be284
--- /dev/null
@@ -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 (file)
index 0000000..cc285f3
--- /dev/null
@@ -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 (file)
index 903fa0c..0000000
+++ /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 (file)
index 0000000..903fa0c
--- /dev/null
@@ -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 (file)
index 0000000..ac3387a
--- /dev/null
@@ -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 (file)
index 0000000..7954408
--- /dev/null
@@ -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 (file)
index 0000000..6f7ffce
--- /dev/null
@@ -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 (file)
index 0000000..4d9a029
--- /dev/null
@@ -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 (file)
index 0000000..4b3958a
--- /dev/null
@@ -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 (file)
index 0000000..3c3b6cc
--- /dev/null
@@ -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 (file)
index 0000000..e2a729c
--- /dev/null
@@ -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 (file)
index 0000000..8b9d21d
--- /dev/null
@@ -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 (file)
index ac3387a..0000000
+++ /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 (file)
index 0000000..784329f
--- /dev/null
@@ -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 (file)
index 0000000..447be31
--- /dev/null
@@ -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 (file)
index 0000000..3484c7f
--- /dev/null
@@ -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 (file)
index 0000000..4df3a2a
--- /dev/null
@@ -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 (file)
index 0000000..8aec87d
--- /dev/null
@@ -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 (file)
index 0000000..52b8b9c
--- /dev/null
@@ -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 (file)
index 0000000..b638e70
--- /dev/null
@@ -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 (file)
index 0000000..8d22561
--- /dev/null
@@ -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 (file)
index 7954408..0000000
+++ /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 (file)
index 0000000..57855cd
--- /dev/null
@@ -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 (file)
index 0000000..9c1e74c
--- /dev/null
@@ -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 (file)
index 0000000..82e59dd
--- /dev/null
@@ -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 (file)
index 0000000..d2d77e8
--- /dev/null
@@ -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 (file)
index 0000000..d58985e
--- /dev/null
@@ -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 (file)
index 0000000..4c5b562
--- /dev/null
@@ -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 (file)
index 0000000..a6e0e40
--- /dev/null
@@ -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 (file)
index 0000000..ab1a33d
--- /dev/null
@@ -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 (file)
index 0000000..b08190a
--- /dev/null
@@ -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 (file)
index 0000000..31f013e
--- /dev/null
@@ -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 (file)
index 6f7ffce..0000000
+++ /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 (file)
index 0000000..fb77f01
--- /dev/null
@@ -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 (file)
index 0000000..8691a04
--- /dev/null
@@ -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 (file)
index 0000000..6b2df80
--- /dev/null
@@ -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 (file)
index 0000000..babbb57
--- /dev/null
@@ -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 (file)
index 0000000..de33eeb
--- /dev/null
@@ -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 (file)
index 0000000..904252e
--- /dev/null
@@ -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 (file)
index 0000000..bc1302b
--- /dev/null
@@ -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 (file)
index 0000000..771ace3
--- /dev/null
@@ -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 (file)
index 0000000..6f9dfc4
--- /dev/null
@@ -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 (file)
index 4d9a029..0000000
+++ /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 (file)
index 0000000..e294e6b
--- /dev/null
@@ -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 (file)
index 0000000..881ef8c
--- /dev/null
@@ -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 (file)
index 0000000..678cdd9
--- /dev/null
@@ -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 (file)
index 0000000..db0b6e9
--- /dev/null
@@ -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 (file)
index 0000000..21cb969
--- /dev/null
@@ -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 (file)
index 0000000..5de05e8
--- /dev/null
@@ -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 (file)
index 0000000..a559b5a
--- /dev/null
@@ -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 (file)
index 0000000..7a101db
--- /dev/null
@@ -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 (file)
index 0000000..a90ce1c
--- /dev/null
@@ -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 (file)
index 0000000..eb6bd79
--- /dev/null
@@ -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-<username>/ipc-socket.<pid>
+#####################################################################
+
+my $config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+EOT
+
+# ensure XDG_RUNTIME_DIR is not set
+delete $ENV{XDG_RUNTIME_DIR};
+my $pid = launch_with_config($config, 1);
+
+my $folder = "/tmp/i3-" . getpwuid(getuid());
+ok(-d $folder, "folder $folder exists");
+my $socketpath = "$folder/ipc-socket." . $pid;
+ok(-S $socketpath, "file $socketpath exists and is a socket");
+
+exit_gracefully($pid);
+
+#####################################################################
+# XDG_RUNTIME_DIR case: socket gets created in $XDG_RUNTIME_DIR/i3/ipc-socket.<pid>
+#####################################################################
+
+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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+ipc-socket $socketpath
+EOT
+
+$pid = launch_with_config($config, 1);
+
+ok(-S $socketpath, "file $socketpath exists and is a socket");
+
+exit_gracefully($pid);
+
+done_testing;
diff --git a/testcases/t/16-nestedcons.t b/testcases/t/16-nestedcons.t
deleted file mode 100644 (file)
index 4b3958a..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#!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/161-regress-borders-restart.t b/testcases/t/161-regress-borders-restart.t
new file mode 100644 (file)
index 0000000..c5e3ef8
--- /dev/null
@@ -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 (file)
index 0000000..5fb8812
--- /dev/null
@@ -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 (file)
index 0000000..e55d868
--- /dev/null
@@ -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 (file)
index 0000000..ef45a78
--- /dev/null
@@ -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 (file)
index 0000000..cc10013
--- /dev/null
@@ -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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [class="borderless"] border none
+for_window [title="special borderless title"] border none
+EOT
+
+my $pid = launch_with_config($config);
+
+my $tmp = fresh_workspace;
+
+my $window = $x->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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [class="borderless"] border none
+for_window [title="special borderless title"] border none
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+$window = $x->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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [class="borderless" title="usethis"] border none
+for_window [class="borderless"] border none
+for_window [title="special borderless title"] border none
+for_window [title="special mark title"] border none, mark bleh
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+$window = $x->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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [class="borderless" title="usethis"] border none
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+$window = $x->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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [class="foo"] border 1pixel
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+$window = $x->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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [class="foo"] border 1pixel
+for_window [instance="foo"] border none
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+$window = $x->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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [id="asdf"] border none
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+$window = $x->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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [window_role="i3test"] border none
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+$window = $x->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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [window_role="i3test"] border none
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+$window = $x->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 (file)
index 0000000..4844f5b
--- /dev/null
@@ -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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+EOT
+
+my $pid = launch_with_config($config);
+
+my $tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers 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;
+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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+assign "special" → targetws
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+my $workspaces = get_workspace_names;
+ok(!("targetws" ~~ @{$workspaces}), '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;
+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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+assign "special" → ~
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+my $workspaces = get_workspace_names;
+ok(!("targetws" ~~ @{$workspaces}), '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;
+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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+assign "special" → ~
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+my $workspaces = get_workspace_names;
+ok(!("targetws" ~~ @{$workspaces}), '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;
+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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+assign "special" → ~
+EOT
+
+$pid = launch_with_config($config);
+
+# TODO: replace this with checking the process hierarchy
+# XXX: give i3-nagbar some time to start up
+sleep 1;
+
+$tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+my @docked = get_dock_clients;
+# We expect i3-nagbar as the first dock client due to using the old assign
+# syntax
+is(@docked, 1, 'one dock client yet');
+
+my $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_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 (file)
index 0000000..e4b18ad
--- /dev/null
@@ -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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+EOT
+
+my $pid = launch_with_config($config);
+
+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');
+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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+workspace_layout stacked
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+
+$first = open_window($x);
+$second = open_window($x);
+
+sync_with_i3($x);
+
+is($x->input_focus, $second->id, 'second window focused');
+my @content = @{get_ws_content($tmp)};
+ok(@content == 1, 'one con at workspace level');
+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 (file)
index 0000000..1418b40
--- /dev/null
@@ -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 (file)
index 0000000..aec8df6
--- /dev/null
@@ -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 (file)
index 3c3b6cc..0000000
+++ /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 (file)
index 0000000..8a990f2
--- /dev/null
@@ -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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+EOT
+
+my $pid = launch_with_config($config);
+
+my $tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+
+my $first = open_window($x);
+my $second = open_window($x);
+
+cmd 'layout tabbed';
+cmd 'focus parent';
+
+my $third = open_window($x);
+is($x->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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+force_focus_wrapping true
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+
+$first = open_window($x);
+$second = open_window($x);
+
+cmd 'layout tabbed';
+cmd 'focus parent';
+
+$third = open_window($x);
+
+sync_with_i3($x);
+
+is($x->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 (file)
index 0000000..7948db6
--- /dev/null
@@ -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 = <<EOT;
+    font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+EOT
+
+my $output = migrate_config($input);
+ok(line_exists($output, qr|font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1|), 'font directive unchanged');
+
+$input = <<EOT;
+    floating_Modifier Mod1
+    focus_follows_mouse true
+    ipc-socket /tmp/i3-ipc.sock
+    ipc_socket /tmp/i3-ipc.sock
+    exec /usr/bin/i3
+    set stuff Mod1
+    assign "XTerm" → 3
+    assign "XTerm" → ~5
+    client.focused #2F343A #900000 #FFFFFF
+    client.focused_inactive #FF0000 #FF0000 #FF0000
+    client.unfocused #00FF00 #00FF00 #00FF00
+    client.urgent #0000FF #0000FF #0000FF
+    client.background #000000
+EOT
+
+$output = migrate_config($input);
+ok(line_exists($output, qr|^floating_Modifier Mod1$|), 'floating_modifier unchanged');
+ok(line_exists($output, qr|^focus_follows_mouse true$|), 'focus_follows_mouse unchanged');
+ok(line_exists($output, qr|^ipc-socket /tmp/i3-ipc.sock$|), 'ipc-socket unchanged');
+ok(line_exists($output, qr|^ipc_socket /tmp/i3-ipc.sock$|), 'ipc_socket unchanged');
+ok(line_exists($output, qr|^exec /usr/bin/i3|), 'exec unchanged');
+ok(line_exists($output, qr|^set stuff Mod1|), 'set unchanged');
+ok(line_exists($output, qr|^assign "XTerm" → 3|), 'assign unchanged');
+ok(line_exists($output, qr|^assign "XTerm" → ~5|), 'assign unchanged');
+ok(line_exists($output, qr|^client\.focused #2F343A #900000 #FFFFFF$|), 'client.focused unchanged');
+ok(line_exists($output, qr|^client\.focused_inactive #FF0000 #FF0000 #FF0000$|), 'client.focused_inactive unchanged');
+ok(line_exists($output, qr|^client\.unfocused #00FF00 #00FF00 #00FF00$|), 'client.unfocused unchanged');
+ok(line_exists($output, qr|^client\.urgent #0000FF #0000FF #0000FF$|), 'client.urgent unchanged');
+ok(line_exists($output, qr|^client\.background #000000$|), 'client.background unchanged');
+
+#####################################################################
+# check whether the bar colors get removed properly
+#####################################################################
+
+$input = <<EOT;
+    bar.focused #FFFF00 #FFFF00 #FFFF00
+    bar.unfocused #FFFF00 #FFFF00 #FFFF00
+    bar.urgent #FFFF00 #FFFF00 #FFFF00
+EOT
+
+$output = migrate_config($input);
+ok(!line_exists($output, qr|^bar\.|), 'no bar. lines');
+ok(line_exists($output, qr|^#.*REMOVED bar|), 'note bar. removed');
+
+
+#####################################################################
+# check whether the other directives get converted correctly
+#####################################################################
+
+$input = <<EOT;
+    new_container stacking
+    workspace_bar no
+    new_window bb
+EOT
+
+$output = migrate_config($input);
+ok(line_exists($output, qr|^workspace_layout stacking$|), 'new_container changed');
+ok(line_exists($output, qr|REMOVED workspace_bar|), 'workspace_bar removed');
+ok(!line_exists($output, qr|^workspace_bar|), 'no workspace_bar in the output');
+ok(line_exists($output, qr|^new_window none$|), 'new_window changed');
+
+#####################################################################
+# check whether new_window's parameters get changed correctly
+#####################################################################
+
+$output = migrate_config('new_window bb');
+ok(line_exists($output, qr|^new_window none$|), 'new_window bb changed');
+
+$output = migrate_config('new_window bn');
+ok(line_exists($output, qr|^new_window normal$|), 'new_window bn changed');
+
+$output = migrate_config('new_window bp');
+ok(line_exists($output, qr|^new_window 1pixel$|), 'new_window bp changed');
+
+#####################################################################
+# check that some commands remain untouched
+#####################################################################
+
+$input = <<EOT;
+    bindsym Mod1+s exec /usr/bin/urxvt
+    bindsym Mod1+s mark foo
+    bindsym Mod1+s restart
+    bindsym Mod1+s reload
+    bindsym Mod1+s exit
+    bindsym Mod1+s stack-limit cols 2
+    bindsym Mod1+s stack-limit rows 3
+    bind Mod1+c exec /usr/bin/urxvt
+    mode "asdf" {
+        bind 36 mode default
+    }
+EOT
+
+$output = migrate_config($input);
+ok(line_exists($output, qr|^bindsym Mod1\+s exec /usr/bin/urxvt$|), 'exec unchanged');
+ok(line_exists($output, qr|^bindsym Mod1\+s mark foo$|), 'mark unchanged');
+ok(line_exists($output, qr|^bindsym Mod1\+s restart$|), 'restart unchanged');
+ok(line_exists($output, qr|^bindsym Mod1\+s reload$|), 'reload unchanged');
+ok(line_exists($output, qr|^bindsym Mod1\+s exit$|), 'exit unchanged');
+ok(line_exists($output, qr|^bindsym Mod1\+s stack-limit cols 2$|), 'stack-limit unchanged');
+ok(line_exists($output, qr|^bindsym Mod1\+s stack-limit rows 3$|), 'stack-limit unchanged');
+ok(line_exists($output, qr|^bindcode Mod1\+c exec /usr/bin/urxvt$|), 'bind changed to bindcode');
+ok(line_exists($output, qr|^mode "asdf" {$|), 'mode asdf unchanged');
+ok(line_exists($output, qr|^bindcode 36 mode \"default\"$|), 'mode default unchanged');
+ok(line_exists($output, qr|^}$|), 'closing mode bracket still there');
+
+#####################################################################
+# check the simple command replacements
+#####################################################################
+
+$input = <<EOT;
+    bindsym Mod1+s s
+    bindsym Mod1+s d
+    bindsym Mod1+s T
+
+    bindsym Mod1+s f
+    bindsym Mod1+s fg
+
+    bindsym Mod1+s t
+
+    bindsym Mod1+s h
+    bindsym Mod1+s j
+    bindsym Mod1+s k
+    bindsym Mod1+s l
+
+    bindsym Mod1+s mh
+    bindsym Mod1+s mj
+    bindsym Mod1+s mk
+    bindsym Mod1+s ml
+
+    bindsym Mod1+s bn
+    bindsym Mod1+s bp
+    bindsym Mod1+s bb
+    bindsym Mod1+s bt
+
+    bindsym Mod1+j wch
+    bindsym Mod1+j wcml
+
+    bindsym Mod1+k kill
+
+    bindsym Mod1+n nw
+    bindsym Mod1+p pw
+EOT
+
+$output = migrate_config($input);
+ok(line_exists($output, qr|^bindsym Mod1\+s layout stacking$|), 's replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s layout default$|), 'd replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s layout tabbed$|), 'T replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s fullscreen$|), 'f replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s fullscreen global$|), 'fg replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s floating toggle$|), 't replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s focus left$|), 'h replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s focus down$|), 'j replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s focus up$|), 'k replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s focus right$|), 'l replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s move left$|), 'mh replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s move down$|), 'mj replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s move up$|), 'mk replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s move right$|), 'ml replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s border normal$|), 'bn replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s border 1pixel$|), 'bp replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s border none$|), 'bb replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+s border toggle$|), 'bt replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+j focus parent; focus left$|), 'with container replaced with focus parent; focus left');
+ok(line_exists($output, qr|^bindsym Mod1\+j focus parent; move right$|), 'with container replaced with focus parent; move right');
+ok(line_exists($output, qr|^bindsym Mod1\+k kill$|), 'kill unchanged');
+ok(line_exists($output, qr|^bindsym Mod1\+n workspace next$|), 'nw replaced');
+ok(line_exists($output, qr|^bindsym Mod1\+p workspace prev$|), 'pw replaced');
+
+#####################################################################
+# check more advanced replacements
+#####################################################################
+
+$input = <<EOT;
+    bindsym Mod1+s goto foo
+EOT
+
+$output = migrate_config($input);
+ok(line_exists($output, qr|^bindsym Mod1\+s \[con_mark="foo"\] focus$|), 'goto replaced');
+
+#####################################################################
+# check whether focus's parameters get changed correctly
+#####################################################################
+
+$output = migrate_config('bindsym Mod1+f focus 3');
+ok(line_exists($output, qr|^#.*focus.*obsolete.*focus 3$|), 'focus [number] gone');
+
+$output = migrate_config('bindsym Mod1+f focus floating');
+ok(line_exists($output, qr|^bindsym Mod1\+f focus floating$|), 'focus floating unchanged');
+
+$output = migrate_config('bindsym Mod1+f focus tiling');
+ok(line_exists($output, qr|^bindsym Mod1\+f focus tiling$|), 'focus tiling unchanged');
+
+$output = migrate_config('bindsym Mod1+f focus ft');
+ok(line_exists($output, qr|^bindsym Mod1\+f focus mode_toggle$|), 'focus ft changed');
+
+#####################################################################
+# check whether resize's parameters get changed correctly
+#####################################################################
+
+$output = migrate_config('bindsym Mod1+f resize left +10');
+ok(line_exists($output, qr|^bindsym Mod1\+f resize grow left 10 px$|), 'resize left changed');
+
+$output = migrate_config('bindsym Mod1+f resize top -20');
+ok(line_exists($output, qr|^bindsym Mod1\+f resize shrink up 20 px$|), 'resize top changed');
+
+$output = migrate_config('bindsym Mod1+f resize right -20');
+ok(line_exists($output, qr|^bindsym Mod1\+f resize shrink right 20 px$|), 'resize right changed');
+
+$output = migrate_config('bindsym Mod1+f resize bottom +23');
+ok(line_exists($output, qr|^bindsym Mod1\+f resize grow down 23 px$|), 'resize bottom changed');
+
+#####################################################################
+# also resizing, but with indention this time
+#####################################################################
+
+$output = migrate_config("bindsym Mod1+f resize          left    \t +10");
+ok(line_exists($output, qr|^bindsym Mod1\+f resize grow left 10 px$|), 'resize left changed');
+
+#####################################################################
+# check whether jump's parameters get changed correctly
+#####################################################################
+
+$output = migrate_config('bindsym Mod1+f jump 3');
+ok(line_exists($output, qr|^#.*obsolete.*jump 3$|), 'jump to workspace removed');
+
+$output = migrate_config('bindsym Mod1+f jump 3 4 5');
+ok(line_exists($output, qr|^#.*obsolete.*jump 3 4 5$|), 'jump to workspace + col/row removed');
+
+$output = migrate_config('bindsym Mod1+f jump "XTerm"');
+ok(line_exists($output, qr|^bindsym Mod1\+f \[class="XTerm"\] focus$|), 'jump changed');
+
+$output = migrate_config('bindsym Mod1+f jump "XTerm/irssi"');
+ok(line_exists($output, qr|^bindsym Mod1\+f \[class="XTerm" title="irssi"\] focus$|), 'jump changed');
+
+#####################################################################
+# check whether workspace commands are handled correctly
+#####################################################################
+
+$output = migrate_config('workspace 3 output VGA-1');
+ok(line_exists($output, qr|^workspace 3 output VGA-1$|), 'workspace assignment unchanged');
+
+$output = migrate_config('workspace 3 work');
+ok(!line_exists($output, qr|^workspace|), 'workspace name not present');
+ok(line_exists($output, qr|#.*workspace name.*bindings|), 'note present');
+
+$input = <<EOT;
+    workspace 3 work
+    bindsym Mod1+3 3
+EOT
+$output = migrate_config($input);
+ok(!line_exists($output, qr|^workspace|), 'workspace name not present');
+ok(line_exists($output, qr|^bindsym Mod1\+3 workspace work|), 'named workspace in bindings');
+
+# The same, but in reverse order
+$input = <<EOT;
+    bindsym Mod1+3 3
+    workspace 3 work
+EOT
+$output = migrate_config($input);
+ok(!line_exists($output, qr|^workspace|), 'workspace name not present');
+ok(line_exists($output, qr|^bindsym Mod1\+3 workspace work|), 'named workspace in bindings');
+
+$output = migrate_config('bindsym Mod1+3 3');
+ok(line_exists($output, qr|^bindsym Mod1\+3 workspace 3|), 'workspace changed');
+
+$output = migrate_config('bindsym Mod1+3 m3');
+ok(line_exists($output, qr|^bindsym Mod1\+3 move workspace 3|), 'move workspace changed');
+
+$input = <<EOT;
+    workspace 3 work
+    bindsym Mod1+3 m3
+EOT
+$output = migrate_config($input);
+ok(!line_exists($output, qr|^workspace|), 'workspace name not present');
+ok(line_exists($output, qr|^bindsym Mod1\+3 move workspace work|), 'move to named workspace in bindings');
+
+#####################################################################
+# check whether an i3bar call is added if the workspace bar bar was enabled
+#####################################################################
+
+$output = migrate_config('');
+ok(line_exists($output, qr|i3bar|), 'i3bar added');
+
+$output = migrate_config('workspace_bar enable');
+ok(line_exists($output, qr|i3bar|), 'i3bar added');
+
+$output = migrate_config('workspace_bar no');
+ok(!line_exists($output, qr|i3bar|), 'no i3bar added');
+
+#####################################################################
+# check whether the mode command gets quotes
+#####################################################################
+
+$output = migrate_config('bindsym Mod1+m mode foobar');
+ok(line_exists($output, qr|^bindsym Mod1\+m mode "foobar"|), 'mode got quotes');
+
+done_testing();
diff --git a/testcases/t/172-start-on-named-ws.t b/testcases/t/172-start-on-named-ws.t
new file mode 100644 (file)
index 0000000..4493bf8
--- /dev/null
@@ -0,0 +1,65 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3
+#
+# checks if i3 starts up on workspace '1' or the first configured named workspace
+#
+use X11::XCB qw(:all);
+use X11::XCB::Connection;
+use i3test;
+
+my $x = X11::XCB::Connection->new;
+
+##############################################################
+# 1: i3 should start with workspace '1'
+##############################################################
+
+my $config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+EOT
+
+my $pid = launch_with_config($config);
+
+my @names = @{get_workspace_names()};
+cmp_deeply(\@names, [ '1' ], 'i3 starts on workspace 1 without any configuration');
+
+exit_gracefully($pid);
+
+##############################################################
+# 2: with named workspaces, i3 should start on the first named one
+##############################################################
+
+$config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+bindsym Mod1+1 workspace foobar
+EOT
+
+$pid = launch_with_config($config);
+
+my @names = @{get_workspace_names()};
+cmp_deeply(\@names, [ 'foobar' ], 'i3 starts on named workspace foobar');
+
+exit_gracefully($pid);
+
+##############################################################
+# 3: the same test as 2, but with a quoted workspace name
+##############################################################
+
+$config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+bindsym Mod1+1 workspace "foobar"
+EOT
+
+$pid = launch_with_config($config);
+
+my @names = @{get_workspace_names()};
+cmp_deeply(\@names, [ 'foobar' ], 'i3 starts on named workspace foobar');
+
+exit_gracefully($pid);
+
+done_testing;
diff --git a/testcases/t/173-get-marks.t b/testcases/t/173-get-marks.t
new file mode 100644 (file)
index 0000000..e74c233
--- /dev/null
@@ -0,0 +1,50 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# checks if the IPC message type get_marks works correctly
+#
+use i3test;
+
+sub get_marks {
+    return i3(get_socket_path())->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 (file)
index 0000000..70414af
--- /dev/null
@@ -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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+assign "special" → targetws
+EOT
+
+my $pid = launch_with_config($config);
+
+my $tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+ok(get_ws($tmp)->{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 (file)
index 0000000..cc1f5c9
--- /dev/null
@@ -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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+EOT
+
+my $pid = launch_with_config($config);
+
+my $tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+
+my $first = open_window($x);
+
+my @content = @{get_ws_content($tmp)};
+ok(@content == 1, 'one container opened');
+is($content[0]->{border}, 'normal', 'border normal by default');
+
+exit_gracefully($pid);
+
+#####################################################################
+# 2: check that new tiling windows start with '1pixel' border when
+# configured
+#####################################################################
+
+$config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+new_window 1pixel
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+
+$first = open_window($x);
+
+@content = @{get_ws_content($tmp)};
+ok(@content == 1, 'one container opened');
+is($content[0]->{border}, '1pixel', 'border normal by default');
+
+exit_gracefully($pid);
+
+#####################################################################
+# 3: check that new floating windows start with 'normal' border unless
+# configured otherwise
+#####################################################################
+
+$config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+
+$first = open_floating_window($x);
+
+my $wscontent = get_ws($tmp);
+my @floating = @{$wscontent->{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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+new_float 1pixel
+EOT
+
+$pid = launch_with_config($config);
+
+$tmp = fresh_workspace;
+
+ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
+
+$first = open_floating_window($x);
+
+$wscontent = get_ws($tmp);
+@floating = @{$wscontent->{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 (file)
index 0000000..469d1be
--- /dev/null
@@ -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 (file)
index e2a729c..0000000
+++ /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 (file)
index 8b9d21d..0000000
+++ /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 (file)
index 784329f..0000000
+++ /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 (file)
index 447be31..0000000
+++ /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 (file)
index 3484c7f..0000000
+++ /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 (file)
index 4df3a2a..0000000
+++ /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 (file)
index 8aec87d..0000000
+++ /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 (file)
index 52b8b9c..0000000
+++ /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 (file)
index b638e70..0000000
+++ /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 (file)
index 8d22561..0000000
+++ /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 (file)
index 57855cd..0000000
+++ /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 (file)
index 9c1e74c..0000000
+++ /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 (file)
index 82e59dd..0000000
+++ /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 (file)
index d2d77e8..0000000
+++ /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 (file)
index d58985e..0000000
+++ /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 (file)
index 4c5b562..0000000
+++ /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 (file)
index a6e0e40..0000000
+++ /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 (file)
index ab1a33d..0000000
+++ /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 (file)
index b08190a..0000000
+++ /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 (file)
index 31f013e..0000000
+++ /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 (file)
index fb77f01..0000000
+++ /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 (file)
index 8691a04..0000000
+++ /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 (file)
index 6b2df80..0000000
+++ /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 (file)
index babbb57..0000000
+++ /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 (file)
index de33eeb..0000000
+++ /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 (file)
index 904252e..0000000
+++ /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 (file)
index bc1302b..0000000
+++ /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 (file)
index 771ace3..0000000
+++ /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 (file)
index 6f9dfc4..0000000
+++ /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 (file)
index e294e6b..0000000
+++ /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 (file)
index 881ef8c..0000000
+++ /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 (file)
index 678cdd9..0000000
+++ /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 (file)
index db0b6e9..0000000
+++ /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 (file)
index 21cb969..0000000
+++ /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 (file)
index 5de05e8..0000000
+++ /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 (file)
index a559b5a..0000000
+++ /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 (file)
index 7a101db..0000000
+++ /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 (file)
index a90ce1c..0000000
+++ /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 (file)
index eb6bd79..0000000
+++ /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-<username>/ipc-socket.<pid>
-#####################################################################
-
-my $config = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-EOT
-
-# ensure XDG_RUNTIME_DIR is not set
-delete $ENV{XDG_RUNTIME_DIR};
-my $pid = launch_with_config($config, 1);
-
-my $folder = "/tmp/i3-" . getpwuid(getuid());
-ok(-d $folder, "folder $folder exists");
-my $socketpath = "$folder/ipc-socket." . $pid;
-ok(-S $socketpath, "file $socketpath exists and is a socket");
-
-exit_gracefully($pid);
-
-#####################################################################
-# XDG_RUNTIME_DIR case: socket gets created in $XDG_RUNTIME_DIR/i3/ipc-socket.<pid>
-#####################################################################
-
-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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-ipc-socket $socketpath
-EOT
-
-$pid = launch_with_config($config, 1);
-
-ok(-S $socketpath, "file $socketpath exists and is a socket");
-
-exit_gracefully($pid);
-
-done_testing;
diff --git a/testcases/t/61-regress-borders-restart.t b/testcases/t/61-regress-borders-restart.t
deleted file mode 100644 (file)
index c5e3ef8..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#!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/62-regress-dock-urgent.t b/testcases/t/62-regress-dock-urgent.t
deleted file mode 100644 (file)
index 5fb8812..0000000
+++ /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 (file)
index e55d868..0000000
+++ /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 (file)
index ef45a78..0000000
+++ /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 (file)
index cc10013..0000000
+++ /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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [class="borderless"] border none
-for_window [title="special borderless title"] border none
-EOT
-
-my $pid = launch_with_config($config);
-
-my $tmp = fresh_workspace;
-
-my $window = $x->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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [class="borderless"] border none
-for_window [title="special borderless title"] border none
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-$window = $x->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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [class="borderless" title="usethis"] border none
-for_window [class="borderless"] border none
-for_window [title="special borderless title"] border none
-for_window [title="special mark title"] border none, mark bleh
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-$window = $x->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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [class="borderless" title="usethis"] border none
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-$window = $x->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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [class="foo"] border 1pixel
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-$window = $x->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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [class="foo"] border 1pixel
-for_window [instance="foo"] border none
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-$window = $x->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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [id="asdf"] border none
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-$window = $x->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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [window_role="i3test"] border none
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-$window = $x->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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [window_role="i3test"] border none
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-$window = $x->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 (file)
index 4844f5b..0000000
+++ /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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-EOT
-
-my $pid = launch_with_config($config);
-
-my $tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers 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;
-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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-assign "special" → targetws
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-my $workspaces = get_workspace_names;
-ok(!("targetws" ~~ @{$workspaces}), '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;
-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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-assign "special" → ~
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-my $workspaces = get_workspace_names;
-ok(!("targetws" ~~ @{$workspaces}), '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;
-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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-assign "special" → ~
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-my $workspaces = get_workspace_names;
-ok(!("targetws" ~~ @{$workspaces}), '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;
-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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-assign "special" → ~
-EOT
-
-$pid = launch_with_config($config);
-
-# TODO: replace this with checking the process hierarchy
-# XXX: give i3-nagbar some time to start up
-sleep 1;
-
-$tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-my @docked = get_dock_clients;
-# We expect i3-nagbar as the first dock client due to using the old assign
-# syntax
-is(@docked, 1, 'one dock client yet');
-
-my $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_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 (file)
index e4b18ad..0000000
+++ /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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-EOT
-
-my $pid = launch_with_config($config);
-
-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');
-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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-workspace_layout stacked
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-
-$first = open_window($x);
-$second = open_window($x);
-
-sync_with_i3($x);
-
-is($x->input_focus, $second->id, 'second window focused');
-my @content = @{get_ws_content($tmp)};
-ok(@content == 1, 'one con at workspace level');
-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 (file)
index 1418b40..0000000
+++ /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 (file)
index aec8df6..0000000
+++ /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 (file)
index 8a990f2..0000000
+++ /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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-EOT
-
-my $pid = launch_with_config($config);
-
-my $tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-
-my $first = open_window($x);
-my $second = open_window($x);
-
-cmd 'layout tabbed';
-cmd 'focus parent';
-
-my $third = open_window($x);
-is($x->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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-force_focus_wrapping true
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-
-$first = open_window($x);
-$second = open_window($x);
-
-cmd 'layout tabbed';
-cmd 'focus parent';
-
-$third = open_window($x);
-
-sync_with_i3($x);
-
-is($x->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 (file)
index 7948db6..0000000
+++ /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 = <<EOT;
-    font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-EOT
-
-my $output = migrate_config($input);
-ok(line_exists($output, qr|font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1|), 'font directive unchanged');
-
-$input = <<EOT;
-    floating_Modifier Mod1
-    focus_follows_mouse true
-    ipc-socket /tmp/i3-ipc.sock
-    ipc_socket /tmp/i3-ipc.sock
-    exec /usr/bin/i3
-    set stuff Mod1
-    assign "XTerm" → 3
-    assign "XTerm" → ~5
-    client.focused #2F343A #900000 #FFFFFF
-    client.focused_inactive #FF0000 #FF0000 #FF0000
-    client.unfocused #00FF00 #00FF00 #00FF00
-    client.urgent #0000FF #0000FF #0000FF
-    client.background #000000
-EOT
-
-$output = migrate_config($input);
-ok(line_exists($output, qr|^floating_Modifier Mod1$|), 'floating_modifier unchanged');
-ok(line_exists($output, qr|^focus_follows_mouse true$|), 'focus_follows_mouse unchanged');
-ok(line_exists($output, qr|^ipc-socket /tmp/i3-ipc.sock$|), 'ipc-socket unchanged');
-ok(line_exists($output, qr|^ipc_socket /tmp/i3-ipc.sock$|), 'ipc_socket unchanged');
-ok(line_exists($output, qr|^exec /usr/bin/i3|), 'exec unchanged');
-ok(line_exists($output, qr|^set stuff Mod1|), 'set unchanged');
-ok(line_exists($output, qr|^assign "XTerm" → 3|), 'assign unchanged');
-ok(line_exists($output, qr|^assign "XTerm" → ~5|), 'assign unchanged');
-ok(line_exists($output, qr|^client\.focused #2F343A #900000 #FFFFFF$|), 'client.focused unchanged');
-ok(line_exists($output, qr|^client\.focused_inactive #FF0000 #FF0000 #FF0000$|), 'client.focused_inactive unchanged');
-ok(line_exists($output, qr|^client\.unfocused #00FF00 #00FF00 #00FF00$|), 'client.unfocused unchanged');
-ok(line_exists($output, qr|^client\.urgent #0000FF #0000FF #0000FF$|), 'client.urgent unchanged');
-ok(line_exists($output, qr|^client\.background #000000$|), 'client.background unchanged');
-
-#####################################################################
-# check whether the bar colors get removed properly
-#####################################################################
-
-$input = <<EOT;
-    bar.focused #FFFF00 #FFFF00 #FFFF00
-    bar.unfocused #FFFF00 #FFFF00 #FFFF00
-    bar.urgent #FFFF00 #FFFF00 #FFFF00
-EOT
-
-$output = migrate_config($input);
-ok(!line_exists($output, qr|^bar\.|), 'no bar. lines');
-ok(line_exists($output, qr|^#.*REMOVED bar|), 'note bar. removed');
-
-
-#####################################################################
-# check whether the other directives get converted correctly
-#####################################################################
-
-$input = <<EOT;
-    new_container stacking
-    workspace_bar no
-    new_window bb
-EOT
-
-$output = migrate_config($input);
-ok(line_exists($output, qr|^workspace_layout stacking$|), 'new_container changed');
-ok(line_exists($output, qr|REMOVED workspace_bar|), 'workspace_bar removed');
-ok(!line_exists($output, qr|^workspace_bar|), 'no workspace_bar in the output');
-ok(line_exists($output, qr|^new_window none$|), 'new_window changed');
-
-#####################################################################
-# check whether new_window's parameters get changed correctly
-#####################################################################
-
-$output = migrate_config('new_window bb');
-ok(line_exists($output, qr|^new_window none$|), 'new_window bb changed');
-
-$output = migrate_config('new_window bn');
-ok(line_exists($output, qr|^new_window normal$|), 'new_window bn changed');
-
-$output = migrate_config('new_window bp');
-ok(line_exists($output, qr|^new_window 1pixel$|), 'new_window bp changed');
-
-#####################################################################
-# check that some commands remain untouched
-#####################################################################
-
-$input = <<EOT;
-    bindsym Mod1+s exec /usr/bin/urxvt
-    bindsym Mod1+s mark foo
-    bindsym Mod1+s restart
-    bindsym Mod1+s reload
-    bindsym Mod1+s exit
-    bindsym Mod1+s stack-limit cols 2
-    bindsym Mod1+s stack-limit rows 3
-    bind Mod1+c exec /usr/bin/urxvt
-    mode "asdf" {
-        bind 36 mode default
-    }
-EOT
-
-$output = migrate_config($input);
-ok(line_exists($output, qr|^bindsym Mod1\+s exec /usr/bin/urxvt$|), 'exec unchanged');
-ok(line_exists($output, qr|^bindsym Mod1\+s mark foo$|), 'mark unchanged');
-ok(line_exists($output, qr|^bindsym Mod1\+s restart$|), 'restart unchanged');
-ok(line_exists($output, qr|^bindsym Mod1\+s reload$|), 'reload unchanged');
-ok(line_exists($output, qr|^bindsym Mod1\+s exit$|), 'exit unchanged');
-ok(line_exists($output, qr|^bindsym Mod1\+s stack-limit cols 2$|), 'stack-limit unchanged');
-ok(line_exists($output, qr|^bindsym Mod1\+s stack-limit rows 3$|), 'stack-limit unchanged');
-ok(line_exists($output, qr|^bindcode Mod1\+c exec /usr/bin/urxvt$|), 'bind changed to bindcode');
-ok(line_exists($output, qr|^mode "asdf" {$|), 'mode asdf unchanged');
-ok(line_exists($output, qr|^bindcode 36 mode \"default\"$|), 'mode default unchanged');
-ok(line_exists($output, qr|^}$|), 'closing mode bracket still there');
-
-#####################################################################
-# check the simple command replacements
-#####################################################################
-
-$input = <<EOT;
-    bindsym Mod1+s s
-    bindsym Mod1+s d
-    bindsym Mod1+s T
-
-    bindsym Mod1+s f
-    bindsym Mod1+s fg
-
-    bindsym Mod1+s t
-
-    bindsym Mod1+s h
-    bindsym Mod1+s j
-    bindsym Mod1+s k
-    bindsym Mod1+s l
-
-    bindsym Mod1+s mh
-    bindsym Mod1+s mj
-    bindsym Mod1+s mk
-    bindsym Mod1+s ml
-
-    bindsym Mod1+s bn
-    bindsym Mod1+s bp
-    bindsym Mod1+s bb
-    bindsym Mod1+s bt
-
-    bindsym Mod1+j wch
-    bindsym Mod1+j wcml
-
-    bindsym Mod1+k kill
-
-    bindsym Mod1+n nw
-    bindsym Mod1+p pw
-EOT
-
-$output = migrate_config($input);
-ok(line_exists($output, qr|^bindsym Mod1\+s layout stacking$|), 's replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s layout default$|), 'd replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s layout tabbed$|), 'T replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s fullscreen$|), 'f replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s fullscreen global$|), 'fg replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s floating toggle$|), 't replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s focus left$|), 'h replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s focus down$|), 'j replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s focus up$|), 'k replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s focus right$|), 'l replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s move left$|), 'mh replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s move down$|), 'mj replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s move up$|), 'mk replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s move right$|), 'ml replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s border normal$|), 'bn replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s border 1pixel$|), 'bp replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s border none$|), 'bb replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+s border toggle$|), 'bt replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+j focus parent; focus left$|), 'with container replaced with focus parent; focus left');
-ok(line_exists($output, qr|^bindsym Mod1\+j focus parent; move right$|), 'with container replaced with focus parent; move right');
-ok(line_exists($output, qr|^bindsym Mod1\+k kill$|), 'kill unchanged');
-ok(line_exists($output, qr|^bindsym Mod1\+n workspace next$|), 'nw replaced');
-ok(line_exists($output, qr|^bindsym Mod1\+p workspace prev$|), 'pw replaced');
-
-#####################################################################
-# check more advanced replacements
-#####################################################################
-
-$input = <<EOT;
-    bindsym Mod1+s goto foo
-EOT
-
-$output = migrate_config($input);
-ok(line_exists($output, qr|^bindsym Mod1\+s \[con_mark="foo"\] focus$|), 'goto replaced');
-
-#####################################################################
-# check whether focus's parameters get changed correctly
-#####################################################################
-
-$output = migrate_config('bindsym Mod1+f focus 3');
-ok(line_exists($output, qr|^#.*focus.*obsolete.*focus 3$|), 'focus [number] gone');
-
-$output = migrate_config('bindsym Mod1+f focus floating');
-ok(line_exists($output, qr|^bindsym Mod1\+f focus floating$|), 'focus floating unchanged');
-
-$output = migrate_config('bindsym Mod1+f focus tiling');
-ok(line_exists($output, qr|^bindsym Mod1\+f focus tiling$|), 'focus tiling unchanged');
-
-$output = migrate_config('bindsym Mod1+f focus ft');
-ok(line_exists($output, qr|^bindsym Mod1\+f focus mode_toggle$|), 'focus ft changed');
-
-#####################################################################
-# check whether resize's parameters get changed correctly
-#####################################################################
-
-$output = migrate_config('bindsym Mod1+f resize left +10');
-ok(line_exists($output, qr|^bindsym Mod1\+f resize grow left 10 px$|), 'resize left changed');
-
-$output = migrate_config('bindsym Mod1+f resize top -20');
-ok(line_exists($output, qr|^bindsym Mod1\+f resize shrink up 20 px$|), 'resize top changed');
-
-$output = migrate_config('bindsym Mod1+f resize right -20');
-ok(line_exists($output, qr|^bindsym Mod1\+f resize shrink right 20 px$|), 'resize right changed');
-
-$output = migrate_config('bindsym Mod1+f resize bottom +23');
-ok(line_exists($output, qr|^bindsym Mod1\+f resize grow down 23 px$|), 'resize bottom changed');
-
-#####################################################################
-# also resizing, but with indention this time
-#####################################################################
-
-$output = migrate_config("bindsym Mod1+f resize          left    \t +10");
-ok(line_exists($output, qr|^bindsym Mod1\+f resize grow left 10 px$|), 'resize left changed');
-
-#####################################################################
-# check whether jump's parameters get changed correctly
-#####################################################################
-
-$output = migrate_config('bindsym Mod1+f jump 3');
-ok(line_exists($output, qr|^#.*obsolete.*jump 3$|), 'jump to workspace removed');
-
-$output = migrate_config('bindsym Mod1+f jump 3 4 5');
-ok(line_exists($output, qr|^#.*obsolete.*jump 3 4 5$|), 'jump to workspace + col/row removed');
-
-$output = migrate_config('bindsym Mod1+f jump "XTerm"');
-ok(line_exists($output, qr|^bindsym Mod1\+f \[class="XTerm"\] focus$|), 'jump changed');
-
-$output = migrate_config('bindsym Mod1+f jump "XTerm/irssi"');
-ok(line_exists($output, qr|^bindsym Mod1\+f \[class="XTerm" title="irssi"\] focus$|), 'jump changed');
-
-#####################################################################
-# check whether workspace commands are handled correctly
-#####################################################################
-
-$output = migrate_config('workspace 3 output VGA-1');
-ok(line_exists($output, qr|^workspace 3 output VGA-1$|), 'workspace assignment unchanged');
-
-$output = migrate_config('workspace 3 work');
-ok(!line_exists($output, qr|^workspace|), 'workspace name not present');
-ok(line_exists($output, qr|#.*workspace name.*bindings|), 'note present');
-
-$input = <<EOT;
-    workspace 3 work
-    bindsym Mod1+3 3
-EOT
-$output = migrate_config($input);
-ok(!line_exists($output, qr|^workspace|), 'workspace name not present');
-ok(line_exists($output, qr|^bindsym Mod1\+3 workspace work|), 'named workspace in bindings');
-
-# The same, but in reverse order
-$input = <<EOT;
-    bindsym Mod1+3 3
-    workspace 3 work
-EOT
-$output = migrate_config($input);
-ok(!line_exists($output, qr|^workspace|), 'workspace name not present');
-ok(line_exists($output, qr|^bindsym Mod1\+3 workspace work|), 'named workspace in bindings');
-
-$output = migrate_config('bindsym Mod1+3 3');
-ok(line_exists($output, qr|^bindsym Mod1\+3 workspace 3|), 'workspace changed');
-
-$output = migrate_config('bindsym Mod1+3 m3');
-ok(line_exists($output, qr|^bindsym Mod1\+3 move workspace 3|), 'move workspace changed');
-
-$input = <<EOT;
-    workspace 3 work
-    bindsym Mod1+3 m3
-EOT
-$output = migrate_config($input);
-ok(!line_exists($output, qr|^workspace|), 'workspace name not present');
-ok(line_exists($output, qr|^bindsym Mod1\+3 move workspace work|), 'move to named workspace in bindings');
-
-#####################################################################
-# check whether an i3bar call is added if the workspace bar bar was enabled
-#####################################################################
-
-$output = migrate_config('');
-ok(line_exists($output, qr|i3bar|), 'i3bar added');
-
-$output = migrate_config('workspace_bar enable');
-ok(line_exists($output, qr|i3bar|), 'i3bar added');
-
-$output = migrate_config('workspace_bar no');
-ok(!line_exists($output, qr|i3bar|), 'no i3bar added');
-
-#####################################################################
-# check whether the mode command gets quotes
-#####################################################################
-
-$output = migrate_config('bindsym Mod1+m mode foobar');
-ok(line_exists($output, qr|^bindsym Mod1\+m mode "foobar"|), 'mode got quotes');
-
-done_testing();
diff --git a/testcases/t/72-start-on-named-ws.t b/testcases/t/72-start-on-named-ws.t
deleted file mode 100644 (file)
index 4493bf8..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#!perl
-# vim:ts=4:sw=4:expandtab
-# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3
-#
-# checks if i3 starts up on workspace '1' or the first configured named workspace
-#
-use X11::XCB qw(:all);
-use X11::XCB::Connection;
-use i3test;
-
-my $x = X11::XCB::Connection->new;
-
-##############################################################
-# 1: i3 should start with workspace '1'
-##############################################################
-
-my $config = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-EOT
-
-my $pid = launch_with_config($config);
-
-my @names = @{get_workspace_names()};
-cmp_deeply(\@names, [ '1' ], 'i3 starts on workspace 1 without any configuration');
-
-exit_gracefully($pid);
-
-##############################################################
-# 2: with named workspaces, i3 should start on the first named one
-##############################################################
-
-$config = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-
-bindsym Mod1+1 workspace foobar
-EOT
-
-$pid = launch_with_config($config);
-
-my @names = @{get_workspace_names()};
-cmp_deeply(\@names, [ 'foobar' ], 'i3 starts on named workspace foobar');
-
-exit_gracefully($pid);
-
-##############################################################
-# 3: the same test as 2, but with a quoted workspace name
-##############################################################
-
-$config = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-
-bindsym Mod1+1 workspace "foobar"
-EOT
-
-$pid = launch_with_config($config);
-
-my @names = @{get_workspace_names()};
-cmp_deeply(\@names, [ 'foobar' ], 'i3 starts on named workspace foobar');
-
-exit_gracefully($pid);
-
-done_testing;
diff --git a/testcases/t/73-get-marks.t b/testcases/t/73-get-marks.t
deleted file mode 100644 (file)
index e74c233..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#!perl
-# vim:ts=4:sw=4:expandtab
-#
-# checks if the IPC message type get_marks works correctly
-#
-use i3test;
-
-sub get_marks {
-    return i3(get_socket_path())->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 (file)
index 70414af..0000000
+++ /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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-assign "special" → targetws
-EOT
-
-my $pid = launch_with_config($config);
-
-my $tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-ok(get_ws($tmp)->{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 (file)
index cc1f5c9..0000000
+++ /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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-EOT
-
-my $pid = launch_with_config($config);
-
-my $tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-
-my $first = open_window($x);
-
-my @content = @{get_ws_content($tmp)};
-ok(@content == 1, 'one container opened');
-is($content[0]->{border}, 'normal', 'border normal by default');
-
-exit_gracefully($pid);
-
-#####################################################################
-# 2: check that new tiling windows start with '1pixel' border when
-# configured
-#####################################################################
-
-$config = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-
-new_window 1pixel
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-
-$first = open_window($x);
-
-@content = @{get_ws_content($tmp)};
-ok(@content == 1, 'one container opened');
-is($content[0]->{border}, '1pixel', 'border normal by default');
-
-exit_gracefully($pid);
-
-#####################################################################
-# 3: check that new floating windows start with 'normal' border unless
-# configured otherwise
-#####################################################################
-
-$config = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-
-$first = open_floating_window($x);
-
-my $wscontent = get_ws($tmp);
-my @floating = @{$wscontent->{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 = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-
-new_float 1pixel
-EOT
-
-$pid = launch_with_config($config);
-
-$tmp = fresh_workspace;
-
-ok(@{get_ws_content($tmp)} == 0, 'no containers yet');
-
-$first = open_floating_window($x);
-
-$wscontent = get_ws($tmp);
-@floating = @{$wscontent->{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 (file)
index 469d1be..0000000
+++ /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;