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));
53 # TODO: move this to X11::XCB::Window
55 my ($id, $class, $instance) = @_;
57 # Add a _NET_WM_STRUT_PARTIAL hint
58 my $atomname = $x->atom(name => 'WM_CLASS');
59 my $atomtype = $x->atom(name => 'STRING');
67 length($class) + length($instance) + 2,
68 "$instance\x00$class\x00"
72 $window = open_window(
73 name => 'Borderless window',
74 before_map => sub { set_wm_class($_->id, 'borderless', 'borderless') },
77 @content = @{get_ws_content($tmp)};
78 cmp_ok(@content, '==', 1, 'one node on this workspace now');
79 is($content[0]->{border}, 'none', 'no border');
82 wait_for_unmap $window;
84 @content = @{get_ws_content($tmp)};
85 cmp_ok(@content, '==', 0, 'no more nodes');
87 exit_gracefully($pid);
89 ##############################################################
90 # 2: match on the title, check if for_window is really executed
92 ##############################################################
96 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
97 for_window [class="borderless"] border none
98 for_window [title="special borderless title"] border none
101 $pid = launch_with_config($config);
103 $tmp = fresh_workspace;
105 $window = open_window(name => 'special title');
107 @content = @{get_ws_content($tmp)};
108 cmp_ok(@content, '==', 1, 'one node on this workspace now');
109 is($content[0]->{border}, 'normal', 'normal border');
111 $window->name('special borderless title');
114 @content = @{get_ws_content($tmp)};
115 is($content[0]->{border}, 'none', 'no border');
117 $window->name('special title');
122 @content = @{get_ws_content($tmp)};
123 is($content[0]->{border}, 'normal', 'border reset to normal');
125 $window->name('special borderless title');
128 @content = @{get_ws_content($tmp)};
129 is($content[0]->{border}, 'normal', 'still normal border');
132 wait_for_unmap $window;
134 @content = @{get_ws_content($tmp)};
135 cmp_ok(@content, '==', 0, 'no more nodes');
137 exit_gracefully($pid);
139 ##############################################################
140 # 3: match on the title, set border style *and* a mark
141 ##############################################################
144 # i3 config file (v4)
145 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
146 for_window [class="borderless" title="usethis"] border none
147 for_window [class="borderless"] border none
148 for_window [title="special borderless title"] border none
149 for_window [title="special mark title"] border none, mark bleh
152 $pid = launch_with_config($config);
154 $tmp = fresh_workspace;
156 $window = open_window(name => 'special mark title');
158 @content = @{get_ws_content($tmp)};
159 cmp_ok(@content, '==', 1, 'one node on this workspace now');
160 is($content[0]->{border}, 'none', 'no border');
162 my $other = open_window;
164 @content = @{get_ws_content($tmp)};
165 cmp_ok(@content, '==', 2, 'two nodes');
166 is($content[0]->{border}, 'none', 'no border');
167 is($content[1]->{border}, 'normal', 'normal border');
168 ok(!$content[0]->{focused}, 'first one not focused');
170 cmd qq|[con_mark="bleh"] focus|;
172 @content = @{get_ws_content($tmp)};
173 ok($content[0]->{focused}, 'first node focused');
175 exit_gracefully($pid);
177 ##############################################################
178 # 4: multiple criteria for the for_window command
179 ##############################################################
182 # i3 config file (v4)
183 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
184 for_window [class="borderless" title="usethis"] border none
187 $pid = launch_with_config($config);
189 $tmp = fresh_workspace;
191 $window = open_window(
193 before_map => sub { set_wm_class($_->id, 'borderless', 'borderless') },
196 @content = @{get_ws_content($tmp)};
197 cmp_ok(@content, '==', 1, 'one node on this workspace now');
198 is($content[0]->{border}, 'none', 'no border');
201 wait_for_unmap $window;
204 # give i3 a chance to delete the window from its tree
207 @content = @{get_ws_content($tmp)};
208 cmp_ok(@content, '==', 0, 'no nodes on this workspace now');
212 set_wm_class($window->id, 'borderless', 'borderless');
213 $window->name('notthis');
215 wait_for_map $window;
217 @content = @{get_ws_content($tmp)};
218 cmp_ok(@content, '==', 1, 'one node on this workspace now');
219 is($content[0]->{border}, 'normal', 'no border');
222 exit_gracefully($pid);
224 ##############################################################
225 # 5: check that a class criterion does not match the instance
226 ##############################################################
229 # i3 config file (v4)
230 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
231 for_window [class="foo"] border 1pixel
234 $pid = launch_with_config($config);
236 $tmp = fresh_workspace;
239 $window = open_window(
241 before_map => sub { set_wm_class($_->id, 'bar', 'foo') },
244 @content = @{get_ws_content($tmp)};
245 cmp_ok(@content, '==', 1, 'one node on this workspace now');
246 is($content[0]->{border}, 'normal', 'normal border, not matched');
248 exit_gracefully($pid);
250 ##############################################################
251 # 6: check that the 'instance' criterion works
252 ##############################################################
255 # i3 config file (v4)
256 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
257 for_window [class="foo"] border 1pixel
258 for_window [instance="foo"] border none
261 $pid = launch_with_config($config);
263 $tmp = fresh_workspace;
265 $window = open_window(
267 before_map => sub { set_wm_class($_->id, 'bar', 'foo') },
270 @content = @{get_ws_content($tmp)};
271 cmp_ok(@content, '==', 1, 'one node on this workspace now');
272 is($content[0]->{border}, 'none', 'no border');
274 exit_gracefully($pid);
276 ##############################################################
277 # 7: check that invalid criteria don’t end up matching all windows
278 ##############################################################
280 # this configuration is broken because "asdf" is not a valid integer
281 # the for_window should therefore recognize this error and don’t add the
284 # i3 config file (v4)
285 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
286 for_window [id="asdf"] border none
289 $pid = launch_with_config($config);
291 $tmp = fresh_workspace;
293 $window = open_window(
295 before_map => sub { set_wm_class($_->id, 'bar', 'foo') },
298 @content = @{get_ws_content($tmp)};
299 cmp_ok(@content, '==', 1, 'one node on this workspace now');
300 is($content[0]->{border}, 'normal', 'normal border');
302 exit_gracefully($pid);
304 ##############################################################
305 # 8: check that the role criterion works properly
306 ##############################################################
308 # this configuration is broken because "asdf" is not a valid integer
309 # the for_window should therefore recognize this error and don’t add the
312 # i3 config file (v4)
313 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
314 for_window [window_role="i3test"] border none
317 $pid = launch_with_config($config);
319 $tmp = fresh_workspace;
321 $window = open_window(
325 my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
326 my $atomtype = $x->atom(name => 'STRING');
333 length("i3test") + 1,
339 @content = @{get_ws_content($tmp)};
340 cmp_ok(@content, '==', 1, 'one node on this workspace now');
341 is($content[0]->{border}, 'none', 'no border (window_role)');
343 exit_gracefully($pid);
345 ##############################################################
346 # 9: another test for the window_role, but this time it changes
347 # *after* the window has been mapped
348 ##############################################################
350 # this configuration is broken because "asdf" is not a valid integer
351 # the for_window should therefore recognize this error and don’t add the
354 # i3 config file (v4)
355 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
356 for_window [window_role="i3test"] border none
359 $pid = launch_with_config($config);
361 $tmp = fresh_workspace;
363 $window = open_window(name => 'usethis');
365 @content = @{get_ws_content($tmp)};
366 cmp_ok(@content, '==', 1, 'one node on this workspace now');
367 is($content[0]->{border}, 'normal', 'normal border (window_role 2)');
369 my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
370 my $atomtype = $x->atom(name => 'STRING');
377 length("i3test") + 1,
385 @content = @{get_ws_content($tmp)};
386 cmp_ok(@content, '==', 1, 'one node on this workspace now');
387 is($content[0]->{border}, 'none', 'no border (window_role 2)');
389 exit_gracefully($pid);