wait_for_map
wait_for_unmap
$x
+ kill_all_windows
);
=head1 NAME
return slurp($logfile);
}
+=head2 kill_all_windows
+
+Kills all windows to clean up between tests.
+
+=cut
+sub kill_all_windows {
+ # Sync in case not all windows are managed by i3 just yet.
+ sync_with_i3;
+ cmd '[title=".*"] kill';
+}
+
=head1 AUTHOR
Michael Stapelberg <michael@i3wm.org>
my (@nodes);
+my $config = <<'EOT';
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+# test 1, test 2
+for_window [class="borderless$"] border none
+for_window [title="special borderless title"] border none
+
+# test 3
+for_window [class="borderless3$" title="usethis"] border none
+for_window [class="borderless3$"] border none
+for_window [title="special borderless title"] border none
+for_window [title="special mark title"] border none, mark bleh
+
+# test 4
+for_window [class="borderless4$" title="usethis"] border none
+
+# test 5, test 6
+for_window [class="foo$"] border 1pixel
+
+# test 6
+for_window [instance="foo6"] border none
+
+# test 7
+for_window [id="asdf"] border none
+
+# test 8, test 9
+for_window [window_role="i3test"] border none
+
+# test 12
+for_window [workspace="trigger"] floating enable, mark triggered
+EOT
+
+# 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',
+ 'notification' => '_NET_WM_WINDOW_TYPE_NOTIFICATION'
+);
+
+for my $window_type (keys %window_types) {
+ $config .= <<EOT;
+for_window [window_type="$window_type"] floating enable, mark branded-$window_type
+EOT
+}
+
+my $pid = launch_with_config($config);
+
##############################################################
# 1: test the following directive:
# for_window [class="borderless"] border none
# "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 = open_window(name => 'Border window');
@content = @{get_ws_content($tmp)};
cmp_ok(@content, '==', 0, 'no more nodes');
-exit_gracefully($pid);
+kill_all_windows;
##############################################################
# 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 = open_window(name => 'special title');
@content = @{get_ws_content($tmp)};
cmp_ok(@content, '==', 0, 'no more nodes');
-exit_gracefully($pid);
+kill_all_windows;
##############################################################
# 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 = open_window(name => 'special mark title');
@content = @{get_ws_content($tmp)};
ok($content[0]->{focused}, 'first node focused');
-exit_gracefully($pid);
+kill_all_windows;
##############################################################
# 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 = open_window(
name => 'usethis',
- wm_class => 'borderless',
+ wm_class => 'borderless4',
);
@content = @{get_ws_content($tmp)};
cmp_ok(@content, '==', 0, 'no nodes on this workspace now');
$window->_create;
-$window->wm_class('borderless');
+$window->wm_class('borderless4');
$window->name('notthis');
$window->map;
wait_for_map $window;
cmp_ok(@content, '==', 1, 'one node on this workspace now');
is($content[0]->{border}, 'normal', 'no border');
-
-exit_gracefully($pid);
+kill_all_windows;
##############################################################
# 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 = open_window(
name => 'usethis',
wm_class => 'bar',
cmp_ok(@content, '==', 1, 'one node on this workspace now');
is($content[0]->{border}, 'normal', 'normal border, not matched');
-exit_gracefully($pid);
+kill_all_windows;
##############################################################
# 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 = open_window(
name => 'usethis',
wm_class => 'bar',
- instance => 'foo',
+ instance => 'foo6',
);
@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);
+kill_all_windows;
##############################################################
# 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 = open_window(
cmp_ok(@content, '==', 1, 'one node on this workspace now');
is($content[0]->{border}, 'normal', 'normal border');
-exit_gracefully($pid);
+kill_all_windows;
##############################################################
# 8: check that the role criterion works properly
##############################################################
-$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 = open_window(
cmp_ok(@content, '==', 1, 'one node on this workspace now');
is($content[0]->{border}, 'none', 'no border (window_role)');
-exit_gracefully($pid);
+kill_all_windows;
##############################################################
# 9: another test for the window_role, but this time it changes
# *after* the window has been mapped
##############################################################
-$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 = open_window(name => 'usethis');
cmp_ok(@content, '==', 1, 'one node on this workspace now');
is($content[0]->{border}, 'none', 'no border (window_role 2)');
-exit_gracefully($pid);
+kill_all_windows;
##############################################################
# 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',
- 'notification' => '_NET_WM_WINDOW_TYPE_NOTIFICATION'
-);
-
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_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'branded' ], "mark set (window_type = $atom)");
-
- exit_gracefully($pid);
+ is_deeply($nodes[0]->{nodes}[0]->{marks}, [ "branded-$window_type" ], "mark set (window_type = $atom)");
+ kill_all_windows;
}
##############################################################
##############################################################
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 @nodes = @{get_ws($tmp)->{floating_nodes}};
cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
- is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'branded' ], "mark set (window_type = $atom)");
-
- exit_gracefully($pid);
+ is_deeply($nodes[0]->{nodes}[0]->{marks}, [ "branded-$window_type" ], "mark set (window_type = $atom)");
+ kill_all_windows;
}
##############################################################
# 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;
cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'triggered' ], "mark set for workspace criterion");
-exit_gracefully($pid);
+kill_all_windows;
##############################################################
-# 13: check that the tiling / floating criteria work.
-##############################################################
-
-$config = <<"EOT";
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-for_window [tiling] mark tiled
-for_window [floating] mark floated
-EOT
-
-$pid = launch_with_config($config);
-$tmp = fresh_workspace;
-
-open_window;
-open_floating_window;
-
-@nodes = @{get_ws($tmp)->{nodes}};
-cmp_ok(@nodes, '==', 1, 'one tiling container on this workspace');
-is_deeply($nodes[0]->{marks}, [ 'tiled' ], "mark set for 'tiling' criterion");
-
-@nodes = @{get_ws($tmp)->{floating_nodes}};
-cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
-is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'floated' ], "mark set for 'floating' criterion");
exit_gracefully($pid);
-##############################################################
-
done_testing;
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • 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);
+
+##############################################################
+# 13: check that the tiling / floating criteria work.
+##############################################################
+
+my $config = <<"EOT";
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [tiling] mark tiled
+for_window [floating] mark floated
+EOT
+
+my $pid = launch_with_config($config);
+my $tmp = fresh_workspace;
+
+open_window;
+open_floating_window;
+
+my @nodes = @{get_ws($tmp)->{nodes}};
+cmp_ok(@nodes, '==', 1, 'one tiling container on this workspace');
+is_deeply($nodes[0]->{marks}, [ 'tiled' ], "mark set for 'tiling' criterion");
+
+@nodes = @{get_ws($tmp)->{floating_nodes}};
+cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
+is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'floated' ], "mark set for 'floating' criterion");
+
+exit_gracefully($pid);
+
+##############################################################
+
+done_testing;
my ($result);
my @urgent;
+$pid = launch_with_config($config);
+
###############################################################################
# Invalid con_id should not crash i3
# See issue #2895.
###############################################################################
-$pid = launch_with_config($config);
$ws = fresh_workspace;
open_window;
cmd "swap container with con_id 1";
does_i3_live;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swap 2 windows in different workspaces using con_id
###############################################################################
-$pid = launch_with_config($config);
-
$ws = fresh_workspace;
open_window;
$A = get_focused($ws);
cmd "swap container with con_id $A";
is(get_focused($ws), $A, 'A is now focused');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swap two containers next to each other.
# | A | B | Focus Stacks:
# +---+---+ H1: B, A
###############################################################################
-$pid = launch_with_config($config);
$ws = fresh_workspace;
$A = open_window(wm_class => 'mark_A');
is($nodes->[1]->{window}, $A->{id}, 'A is on the right');
is(get_focused($ws), $expected_focus, 'B is still focused');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swap two containers with different parents.
# | Y | B | V1: A, Y
# +---+---+ V2: B, X
###############################################################################
-$pid = launch_with_config($config);
$ws = fresh_workspace;
$A = open_window(wm_class => 'mark_A');
is($nodes->[1]->{nodes}->[1]->{window}, $A->{id}, 'A is on the bottom right');
is(get_focused($ws), $expected_focus, 'B is still focused');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swap two containers with different parents.
# | Y | B | V1: Y, A
# +---+---+ V2: B, X
###############################################################################
-$pid = launch_with_config($config);
$ws = fresh_workspace;
$A = open_window(wm_class => 'mark_A');
is($nodes->[1]->{nodes}->[1]->{window}, $A->{id}, 'A is on the bottom right');
is(get_focused($ws), $expected_focus, 'B is still focused');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swap two containers with one being on a different workspace.
# | Y | B | Focus Stacks:
# +---+---+ H2: B, Y
###############################################################################
-$pid = launch_with_config($config);
-
$ws1 = fresh_workspace;
$A = open_window(wm_class => 'mark_A');
$expected_focus = get_focused($ws1);
is($nodes->[1]->{window}, $A->{id}, 'A is on ws2:right');
is(get_focused($ws2), $expected_focus, 'A is focused');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swap two non-focused containers within the same workspace.
# | X | B | V1: A, X
# +---+---+ V2: F, B
###############################################################################
-$pid = launch_with_config($config);
$ws = fresh_workspace;
$A = open_window(wm_class => 'mark_A');
is($nodes->[1]->{nodes}->[1]->{window}, $A->{id}, 'A is on the bottom right');
is(get_focused($ws), $expected_focus, 'F is still focused');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swap two non-focused containers which are both on different workspaces.
# | F |
# +---+
###############################################################################
-$pid = launch_with_config($config);
-
$ws1 = fresh_workspace;
$A = open_window(wm_class => 'mark_A');
is(get_focused($ws3), $expected_focus, 'F is still focused');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swap two non-focused containers with one being on a different workspace.
# | B | F | Focus Stacks:
# +---+---+ H2: F, B
###############################################################################
-$pid = launch_with_config($config);
$ws1 = fresh_workspace;
$A = open_window(wm_class => 'mark_A');
is($nodes->[0]->{window}, $A->{id}, 'A is on the left of the second workspace');
is(get_focused($ws2), $expected_focus, 'F is still focused');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# 1. A container cannot be swapped with its parent.
# | | B |
# +---+---+
###############################################################################
-$pid = launch_with_config($config);
-
$ws = fresh_workspace;
open_window;
open_window;
$result = cmd '[con_mark=A] swap container with mark B';
is($result->[0]->{success}, 0, 'A cannot be swappd with one of its children');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swapping two containers preserves the geometry of the container they are
# | B | A |
# +---+-------+
###############################################################################
-$pid = launch_with_config($config);
-
$ws = fresh_workspace;
$A = open_window(wm_class => 'mark_A');
$B = open_window(wm_class => 'mark_B');
cmp_float($nodes->[0]->{percent}, 0.25, 'B has 25% width');
cmp_float($nodes->[1]->{percent}, 0.75, 'A has 75% width');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swapping containers not sharing the same parent preserves the geometry of
# | | X |
# +---+-----+
###############################################################################
-$pid = launch_with_config($config);
$ws = fresh_workspace;
$A = open_window(wm_class => 'mark_A');
cmp_float($nodes->[0]->{nodes}->[0]->{percent}, 0.25, 'B has 25% height');
cmp_float($nodes->[1]->{nodes}->[0]->{percent}, 0.75, 'A has 75% height');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Swapping containers moves the urgency hint correctly.
###############################################################################
-$pid = launch_with_config($config);
$ws1 = fresh_workspace;
$A = open_window(wm_class => 'mark_A');
is(@urgent, 0, 'A is not marked urgent');
is(get_ws($ws2)->{urgent}, 0, 'the second workspace is not marked urgent');
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
+exit_gracefully($pid);
+
done_testing;
pack('L', $idx),
);
},
+ dont_map => 1,
);
- return $window;
-}
-
-# We need to kill all windows in between tests since they survive the i3 restart
-# and will interfere with the following tests.
-sub kill_windows {
+ # We don’t wait for MapNotify and instead sync with i3 so that we don’t need
+ # to encounter the full timeout of 4s when opening a window on a non-visible
+ # workspace.
+ $window->map;
sync_with_i3;
- cmd '[title="Window.*"] kill';
+
+ return $window;
}
###############################################################################
-my ($config, $config_mm, $pid, $con);
-
-$config = <<EOT;
+my $config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
}
EOT
-$config_mm = <<EOT;
-# i3 config file (v4)
-font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
-
-workspace "0" output "fake-0"
-workspace "1" output "fake-0"
-workspace "2" output "fake-0"
-workspace "10" output "fake-1"
-workspace "11" output "fake-1"
-workspace "12" output "fake-1"
-
-fake-outputs 1024x768+0+0,1024x768+1024+0
-EOT
+my $pid = launch_with_config($config);
###############################################################################
# Upon managing a window which does not set _NET_WM_DESKTOP, the property is
# set on the window.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 1';
-$con = open_window;
+my $con = open_window;
is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set upon managing a window');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Upon managing a window which sets _NET_WM_DESKTOP, the window is moved to
# the specified desktop.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 0';
open_window;
cmd 'workspace 1';
is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP still has the correct value');
is_num_children('1', 2, 'The window was moved to workspace 1');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# Upon managing a window which sets _NET_WM_DESKTOP to the appropriate value,
# the window is made sticky and floating.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 0';
$con = open_window_with_net_wm_desktop(0xFFFFFFFF);
is(@{get_ws('0')->{floating_nodes}}, 1, 'The window is floating');
ok(get_ws('0')->{floating_nodes}->[0]->{nodes}->[0]->{sticky}, 'The window is sticky');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# _NET_WM_DESKTOP is updated when the window is moved to another workspace
# on the same output.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 0';
open_window;
cmd 'workspace 1';
is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# _NET_WM_DESKTOP is updated when the floating window is moved to another
# workspace on the same output.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 0';
open_window;
cmd 'workspace 1';
is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
-kill_windows;
-exit_gracefully($pid);
-
-###############################################################################
-# _NET_WM_DESKTOP is updated when the window is moved to another workspace
-# on another output.
-###############################################################################
-
-$pid = launch_with_config($config_mm);
-
-cmd 'workspace 0';
-open_window;
-cmd 'workspace 10';
-open_window;
-cmd 'workspace 0';
-$con = open_window;
-
-cmd 'move window to workspace 10';
-
-is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
-
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# _NET_WM_DESKTOP is removed when the window is withdrawn.
###############################################################################
-$pid = launch_with_config($config);
-
$con = open_window;
is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set (sanity check)');
is(get_net_wm_desktop($con), undef, '_NET_WM_DESKTOP is removed');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# A _NET_WM_DESKTOP client message sent to the root window moves a window
# to the correct workspace.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 0';
open_window;
cmd 'workspace 1';
is_num_children('1', 2, 'The window is now on workspace 1');
is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# A _NET_WM_DESKTOP client message sent to the root window can make a window
# sticky.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 0';
$con = open_window;
is(@{get_ws('0')->{floating_nodes}}, 1, 'The window is floating');
ok(get_ws('0')->{floating_nodes}->[0]->{nodes}->[0]->{sticky}, 'The window is sticky');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# _NET_WM_DESKTOP is updated when a new workspace with a lower number is
# opened and closed.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 1';
$con = open_window;
is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
cmd 'workspace 0';
is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# _NET_WM_DESKTOP is updated when a window is made sticky by command.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 0';
$con = open_window;
cmd 'floating enable';
cmd 'sticky enable';
is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# _NET_WM_DESKTOP is updated when a window is made sticky by client message.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 0';
$con = open_window;
cmd 'floating enable';
is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
# _NET_WM_DESKTOP is updated when a window is moved to the scratchpad.
###############################################################################
-$pid = launch_with_config($config);
-
cmd 'workspace 0';
$con = open_window;
cmd 'floating enable';
cmd 'scratchpad show';
is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
-kill_windows;
-exit_gracefully($pid);
+kill_all_windows;
###############################################################################
+exit_gracefully($pid);
+
done_testing;
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • 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)
+#
+# Tests for _NET_WM_DESKTOP.
+# Ticket: #2153
+use i3test i3_autostart => 0;
+use X11::XCB qw(:all);
+
+sub get_net_wm_desktop {
+ sync_with_i3;
+
+ my ($con) = @_;
+ my $cookie = $x->get_property(
+ 0,
+ $con->{id},
+ $x->atom(name => '_NET_WM_DESKTOP')->id,
+ $x->atom(name => 'CARDINAL')->id,
+ 0,
+ 1
+ );
+
+ my $reply = $x->get_property_reply($cookie->{sequence});
+ return undef if $reply->{length} != 1;
+
+ return unpack("L", $reply->{value});
+}
+
+my $config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+workspace "0" output "fake-0"
+workspace "1" output "fake-0"
+workspace "2" output "fake-0"
+workspace "10" output "fake-1"
+workspace "11" output "fake-1"
+workspace "12" output "fake-1"
+
+fake-outputs 1024x768+0+0,1024x768+1024+0
+EOT
+
+###############################################################################
+# _NET_WM_DESKTOP is updated when the window is moved to another workspace
+# on another output.
+###############################################################################
+
+my $pid = launch_with_config($config);
+
+cmd 'workspace 0';
+open_window;
+cmd 'workspace 10';
+open_window;
+cmd 'workspace 0';
+my $con = open_window;
+
+cmd 'move window to workspace 10';
+
+is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
+
+exit_gracefully($pid);
+
+done_testing;