]> git.sur5r.net Git - i3/i3/blobdiff - testcases/t/165-for_window.t
Merge pull request #1805 from lasers/next
[i3/i3] / testcases / t / 165-for_window.t
index 6e921cef484339b7d72eb3744e611d6498c8bcfe..985a7bfd687ec5e8d44e99c81d6ef64a1bafaeca 100644 (file)
@@ -1,13 +1,23 @@
 #!perl
 # vim:ts=4:sw=4:expandtab
-# !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3
 #
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+#   (or docs/testsuite)
 #
-use X11::XCB qw(:all);
-use X11::XCB::Connection;
-use i3test;
+# • http://build.i3wm.org/docs/lib-i3test.html
+#   (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • http://build.i3wm.org/docs/ipc.html
+#   (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+#   (unless you are already familiar with Perl)
+#
+use i3test i3_autostart => 0;
+use X11::XCB qw(PROP_MODE_REPLACE);
 
-my $x = X11::XCB::Connection->new;
+my (@nodes);
 
 ##############################################################
 # 1: test the following directive:
@@ -28,67 +38,30 @@ 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 $window = open_window(name => 'Border window');
 
 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;
+wait_for_unmap $window;
 
-my @content = @{get_ws_content($tmp)};
+@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 = open_window(
+    name => 'Borderless window',
+    wm_class => 'borderless',
 );
 
-$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;
+wait_for_unmap $window;
 
 @content = @{get_ws_content($tmp)};
 cmp_ok(@content, '==', 0, 'no more nodes');
@@ -111,29 +84,20 @@ $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;
+$window = open_window(name => 'special title');
 
 @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;
+sync_with_i3;
 
 @content = @{get_ws_content($tmp)};
 is($content[0]->{border}, 'none', 'no border');
 
 $window->name('special title');
-sync_with_i3 $x;
+sync_with_i3;
 
 cmd 'border normal';
 
@@ -141,13 +105,13 @@ cmd 'border normal';
 is($content[0]->{border}, 'normal', 'border reset to normal');
 
 $window->name('special borderless title');
-sync_with_i3 $x;
+sync_with_i3;
 
 @content = @{get_ws_content($tmp)};
 is($content[0]->{border}, 'normal', 'still normal border');
 
 $window->unmap;
-wait_for_unmap $x;
+wait_for_unmap $window;
 
 @content = @{get_ws_content($tmp)};
 cmp_ok(@content, '==', 0, 'no more nodes');
@@ -171,22 +135,13 @@ $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;
+$window = open_window(name => 'special mark title');
 
 @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);
+my $other = open_window;
 
 @content = @{get_ws_content($tmp)};
 cmp_ok(@content, '==', 2, 'two nodes');
@@ -215,40 +170,30 @@ $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 = open_window(
+    name => 'usethis',
+    wm_class => 'borderless',
 );
 
-$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;
+wait_for_unmap $window;
 $window->destroy;
 
 # give i3 a chance to delete the window from its tree
-sync_with_i3 $x;
+sync_with_i3;
 
 @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->wm_class('borderless');
 $window->name('notthis');
 $window->map;
-wait_for_map $x;
+wait_for_map $window;
 
 @content = @{get_ws_content($tmp)};
 cmp_ok(@content, '==', 1, 'one node on this workspace now');
@@ -271,19 +216,12 @@ $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;
+$window = open_window(
+    name => 'usethis',
+    wm_class => 'bar',
+    instance => 'foo',
+);
 
 @content = @{get_ws_content($tmp)};
 cmp_ok(@content, '==', 1, 'one node on this workspace now');
@@ -306,20 +244,12 @@ $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 = open_window(
+    name => 'usethis',
+    wm_class => 'bar',
+    instance => 'foo',
 );
 
-$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');
@@ -343,20 +273,12 @@ $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 = open_window(
+    name => 'usethis',
+    wm_class => 'bar',
+    instance => 'foo',
 );
 
-$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');
@@ -367,9 +289,6 @@ 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
@@ -380,31 +299,24 @@ $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 = open_window(
+    name => 'usethis',
+    before_map => sub {
+        my ($window) = @_;
+        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)');
@@ -416,9 +328,6 @@ exit_gracefully($pid);
 #    *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
@@ -429,25 +338,14 @@ $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;
+$window = open_window(name => 'usethis');
 
 @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');
+my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
+my $atomtype = $x->atom(name => 'STRING');
 $x->change_property(
   PROP_MODE_REPLACE,
   $window->id,
@@ -460,7 +358,7 @@ $x->change_property(
 
 $x->flush;
 
-sync_with_i3 $x;
+sync_with_i3;
 
 @content = @{get_ws_content($tmp)};
 cmp_ok(@content, '==', 1, 'one node on this workspace now');
@@ -468,5 +366,98 @@ is($content[0]->{border}, 'none', 'no border (window_role 2)');
 
 exit_gracefully($pid);
 
+##############################################################
+# 10: check that the criterion 'window_type' works
+##############################################################
+
+# test all window types
+my %window_types = (
+    'normal'        => '_NET_WM_WINDOW_TYPE_NORMAL',
+    'dialog'        => '_NET_WM_WINDOW_TYPE_DIALOG',
+    'utility'       => '_NET_WM_WINDOW_TYPE_UTILITY',
+    'toolbar'       => '_NET_WM_WINDOW_TYPE_TOOLBAR',
+    'splash'        => '_NET_WM_WINDOW_TYPE_SPLASH',
+    'menu'          => '_NET_WM_WINDOW_TYPE_MENU',
+    'dropdown_menu' => '_NET_WM_WINDOW_TYPE_DROPDOWN_MENU',
+    'popup_menu'    => '_NET_WM_WINDOW_TYPE_POPUP_MENU',
+    'tooltip'       => '_NET_WM_WINDOW_TYPE_TOOLTIP'
+);
+
+while (my ($window_type, $atom) = each %window_types) {
+
+    $config = <<"EOT";
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [window_type="$window_type"] floating enable, mark branded
+EOT
+
+    $pid = launch_with_config($config);
+    $tmp = fresh_workspace;
+
+    $window = open_window(window_type => $x->atom(name => $atom));
+
+    my @nodes = @{get_ws($tmp)->{floating_nodes}};
+    cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
+    is($nodes[0]->{nodes}[0]->{mark}, 'branded', "mark set (window_type = $atom)");
+
+    exit_gracefully($pid);
+
+}
+
+##############################################################
+# 11: check that the criterion 'window_type' works if the
+#     _NET_WM_WINDOW_TYPE is changed after managing.
+##############################################################
+
+while (my ($window_type, $atom) = each %window_types) {
+
+    $config = <<"EOT";
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [window_type="$window_type"] floating enable, mark branded
+EOT
+
+    $pid = launch_with_config($config);
+    $tmp = fresh_workspace;
+
+    $window = open_window();
+
+    my $atomname = $x->atom(name => '_NET_WM_WINDOW_TYPE');
+    my $atomtype = $x->atom(name => 'ATOM');
+    $x->change_property(PROP_MODE_REPLACE, $window->id, $atomname->id, $atomtype->id,
+      32, 1, pack('L1', $x->atom(name => $atom)->id));
+    $x->flush;
+    sync_with_i3;
+
+    my @nodes = @{get_ws($tmp)->{floating_nodes}};
+    cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
+    is($nodes[0]->{nodes}[0]->{mark}, 'branded', "mark set (window_type = $atom)");
+
+    exit_gracefully($pid);
+
+}
+
+##############################################################
+# 12: check that the criterion 'workspace' works
+##############################################################
+
+$config = <<"EOT";
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [workspace="trigger"] floating enable, mark triggered
+EOT
+
+$pid = launch_with_config($config);
+
+cmd 'workspace trigger';
+$window = open_window;
+
+@nodes = @{get_ws('trigger')->{floating_nodes}};
+cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
+is($nodes[0]->{nodes}[0]->{mark}, 'triggered', "mark set for workspace criterion");
+
+exit_gracefully($pid);
+
+##############################################################
 
 done_testing;