2 # vim:ts=4:sw=4:expandtab
4 # Please read the following documents before working on tests:
5 # • http://build.i3wm.org/docs/testsuite.html
8 # • http://build.i3wm.org/docs/lib-i3test.html
9 # (alternatively: perldoc ./testcases/lib/i3test.pm)
11 # • http://build.i3wm.org/docs/ipc.html
14 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
15 # (unless you are already familiar with Perl)
17 use i3test i3_autostart => 0;
18 use X11::XCB qw(PROP_MODE_REPLACE);
20 ##############################################################
21 # 1: test the following directive:
22 # for_window [class="borderless"] border none
23 # by first creating a window with a different class (should get
24 # the normal border), then creating a window with the class
25 # "borderless" (should get no border)
26 ##############################################################
30 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
31 for_window [class="borderless"] border none
32 for_window [title="special borderless title"] border none
35 my $pid = launch_with_config($config);
37 my $tmp = fresh_workspace;
39 my $window = open_window(name => 'Border window');
41 my @content = @{get_ws_content($tmp)};
42 cmp_ok(@content, '==', 1, 'one node on this workspace now');
43 is($content[0]->{border}, 'normal', 'normal border');
46 wait_for_unmap $window;
48 @content = @{get_ws_content($tmp)};
49 cmp_ok(@content, '==', 0, 'no more nodes');
50 diag('content = '. Dumper(\@content));
52 $window = open_window(
53 name => 'Borderless window',
54 wm_class => 'borderless',
57 @content = @{get_ws_content($tmp)};
58 cmp_ok(@content, '==', 1, 'one node on this workspace now');
59 is($content[0]->{border}, 'none', 'no border');
62 wait_for_unmap $window;
64 @content = @{get_ws_content($tmp)};
65 cmp_ok(@content, '==', 0, 'no more nodes');
67 exit_gracefully($pid);
69 ##############################################################
70 # 2: match on the title, check if for_window is really executed
72 ##############################################################
76 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
77 for_window [class="borderless"] border none
78 for_window [title="special borderless title"] border none
81 $pid = launch_with_config($config);
83 $tmp = fresh_workspace;
85 $window = open_window(name => 'special title');
87 @content = @{get_ws_content($tmp)};
88 cmp_ok(@content, '==', 1, 'one node on this workspace now');
89 is($content[0]->{border}, 'normal', 'normal border');
91 $window->name('special borderless title');
94 @content = @{get_ws_content($tmp)};
95 is($content[0]->{border}, 'none', 'no border');
97 $window->name('special title');
102 @content = @{get_ws_content($tmp)};
103 is($content[0]->{border}, 'normal', 'border reset to normal');
105 $window->name('special borderless title');
108 @content = @{get_ws_content($tmp)};
109 is($content[0]->{border}, 'normal', 'still normal border');
112 wait_for_unmap $window;
114 @content = @{get_ws_content($tmp)};
115 cmp_ok(@content, '==', 0, 'no more nodes');
117 exit_gracefully($pid);
119 ##############################################################
120 # 3: match on the title, set border style *and* a mark
121 ##############################################################
124 # i3 config file (v4)
125 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
126 for_window [class="borderless" title="usethis"] border none
127 for_window [class="borderless"] border none
128 for_window [title="special borderless title"] border none
129 for_window [title="special mark title"] border none, mark bleh
132 $pid = launch_with_config($config);
134 $tmp = fresh_workspace;
136 $window = open_window(name => 'special mark title');
138 @content = @{get_ws_content($tmp)};
139 cmp_ok(@content, '==', 1, 'one node on this workspace now');
140 is($content[0]->{border}, 'none', 'no border');
142 my $other = open_window;
144 @content = @{get_ws_content($tmp)};
145 cmp_ok(@content, '==', 2, 'two nodes');
146 is($content[0]->{border}, 'none', 'no border');
147 is($content[1]->{border}, 'normal', 'normal border');
148 ok(!$content[0]->{focused}, 'first one not focused');
150 cmd qq|[con_mark="bleh"] focus|;
152 @content = @{get_ws_content($tmp)};
153 ok($content[0]->{focused}, 'first node focused');
155 exit_gracefully($pid);
157 ##############################################################
158 # 4: multiple criteria for the for_window command
159 ##############################################################
162 # i3 config file (v4)
163 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
164 for_window [class="borderless" title="usethis"] border none
167 $pid = launch_with_config($config);
169 $tmp = fresh_workspace;
171 $window = open_window(
173 wm_class => 'borderless',
176 @content = @{get_ws_content($tmp)};
177 cmp_ok(@content, '==', 1, 'one node on this workspace now');
178 is($content[0]->{border}, 'none', 'no border');
181 wait_for_unmap $window;
184 # give i3 a chance to delete the window from its tree
187 @content = @{get_ws_content($tmp)};
188 cmp_ok(@content, '==', 0, 'no nodes on this workspace now');
191 $window->wm_class('borderless');
192 $window->name('notthis');
194 wait_for_map $window;
196 @content = @{get_ws_content($tmp)};
197 cmp_ok(@content, '==', 1, 'one node on this workspace now');
198 is($content[0]->{border}, 'normal', 'no border');
201 exit_gracefully($pid);
203 ##############################################################
204 # 5: check that a class criterion does not match the instance
205 ##############################################################
208 # i3 config file (v4)
209 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
210 for_window [class="foo"] border 1pixel
213 $pid = launch_with_config($config);
215 $tmp = fresh_workspace;
218 $window = open_window(
224 @content = @{get_ws_content($tmp)};
225 cmp_ok(@content, '==', 1, 'one node on this workspace now');
226 is($content[0]->{border}, 'normal', 'normal border, not matched');
228 exit_gracefully($pid);
230 ##############################################################
231 # 6: check that the 'instance' criterion works
232 ##############################################################
235 # i3 config file (v4)
236 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
237 for_window [class="foo"] border 1pixel
238 for_window [instance="foo"] border none
241 $pid = launch_with_config($config);
243 $tmp = fresh_workspace;
245 $window = open_window(
251 @content = @{get_ws_content($tmp)};
252 cmp_ok(@content, '==', 1, 'one node on this workspace now');
253 is($content[0]->{border}, 'none', 'no border');
255 exit_gracefully($pid);
257 ##############################################################
258 # 7: check that invalid criteria don’t end up matching all windows
259 ##############################################################
261 # this configuration is broken because "asdf" is not a valid integer
262 # the for_window should therefore recognize this error and don’t add the
265 # i3 config file (v4)
266 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
267 for_window [id="asdf"] border none
270 $pid = launch_with_config($config);
272 $tmp = fresh_workspace;
274 $window = open_window(
280 @content = @{get_ws_content($tmp)};
281 cmp_ok(@content, '==', 1, 'one node on this workspace now');
282 is($content[0]->{border}, 'normal', 'normal border');
284 exit_gracefully($pid);
286 ##############################################################
287 # 8: check that the role criterion works properly
288 ##############################################################
291 # i3 config file (v4)
292 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
293 for_window [window_role="i3test"] border none
296 $pid = launch_with_config($config);
298 $tmp = fresh_workspace;
300 $window = open_window(
304 my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
305 my $atomtype = $x->atom(name => 'STRING');
312 length("i3test") + 1,
318 @content = @{get_ws_content($tmp)};
319 cmp_ok(@content, '==', 1, 'one node on this workspace now');
320 is($content[0]->{border}, 'none', 'no border (window_role)');
322 exit_gracefully($pid);
324 ##############################################################
325 # 9: another test for the window_role, but this time it changes
326 # *after* the window has been mapped
327 ##############################################################
330 # i3 config file (v4)
331 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
332 for_window [window_role="i3test"] border none
335 $pid = launch_with_config($config);
337 $tmp = fresh_workspace;
339 $window = open_window(name => 'usethis');
341 @content = @{get_ws_content($tmp)};
342 cmp_ok(@content, '==', 1, 'one node on this workspace now');
343 is($content[0]->{border}, 'normal', 'normal border (window_role 2)');
345 my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
346 my $atomtype = $x->atom(name => 'STRING');
353 length("i3test") + 1,
361 @content = @{get_ws_content($tmp)};
362 cmp_ok(@content, '==', 1, 'one node on this workspace now');
363 is($content[0]->{border}, 'none', 'no border (window_role 2)');
365 exit_gracefully($pid);
367 ##############################################################
368 # 10: check that the criterion 'window_type' works
369 ##############################################################
371 # test all window types
373 'normal' => '_NET_WM_WINDOW_TYPE_NORMAL',
374 'dialog' => '_NET_WM_WINDOW_TYPE_DIALOG',
375 'utility' => '_NET_WM_WINDOW_TYPE_UTILITY',
376 'toolbar' => '_NET_WM_WINDOW_TYPE_TOOLBAR',
377 'splash' => '_NET_WM_WINDOW_TYPE_SPLASH',
378 'menu' => '_NET_WM_WINDOW_TYPE_MENU',
379 'dropdown_menu' => '_NET_WM_WINDOW_TYPE_DROPDOWN_MENU',
380 'popup_menu' => '_NET_WM_WINDOW_TYPE_POPUP_MENU',
381 'tooltip' => '_NET_WM_WINDOW_TYPE_TOOLTIP'
384 while (my ($window_type, $atom) = each %window_types) {
387 # i3 config file (v4)
388 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
389 for_window [window_type="$window_type"] floating enable, mark branded
392 $pid = launch_with_config($config);
393 $tmp = fresh_workspace;
395 $window = open_window(window_type => $x->atom(name => $atom));
397 my @nodes = @{get_ws($tmp)->{floating_nodes}};
398 cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
399 is($nodes[0]->{nodes}[0]->{mark}, 'branded', "mark set (window_type = $atom)");
401 exit_gracefully($pid);
405 ##############################################################
406 # 11: check that the criterion 'window_type' works if the
407 # _NET_WM_WINDOW_TYPE is changed after managing.
408 ##############################################################
410 while (my ($window_type, $atom) = each %window_types) {
413 # i3 config file (v4)
414 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
415 for_window [window_type="$window_type"] floating enable, mark branded
418 $pid = launch_with_config($config);
419 $tmp = fresh_workspace;
421 $window = open_window();
423 my $atomname = $x->atom(name => '_NET_WM_WINDOW_TYPE');
424 my $atomtype = $x->atom(name => 'ATOM');
425 $x->change_property(PROP_MODE_REPLACE, $window->id, $atomname->id, $atomtype->id,
426 32, 1, pack('L1', $x->atom(name => $atom)->id));
430 my @nodes = @{get_ws($tmp)->{floating_nodes}};
431 cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
432 is($nodes[0]->{nodes}[0]->{mark}, 'branded', "mark set (window_type = $atom)");
434 exit_gracefully($pid);
438 ##############################################################