]> git.sur5r.net Git - i3/i3/blob - testcases/t/165-for_window.t
Merge branch 'fix-urgent-crash'
[i3/i3] / testcases / t / 165-for_window.t
1 #!perl
2 # vim:ts=4:sw=4:expandtab
3 #
4 # Please read the following documents before working on tests:
5 # • http://build.i3wm.org/docs/testsuite.html
6 #   (or docs/testsuite)
7 #
8 # • http://build.i3wm.org/docs/lib-i3test.html
9 #   (alternatively: perldoc ./testcases/lib/i3test.pm)
10 #
11 # • http://build.i3wm.org/docs/ipc.html
12 #   (or docs/ipc)
13 #
14 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
15 #   (unless you are already familiar with Perl)
16 #
17 use i3test i3_autostart => 0;
18 use X11::XCB qw(PROP_MODE_REPLACE);
19
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 ##############################################################
27
28 my $config = <<EOT;
29 # i3 config file (v4)
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
33 EOT
34
35 my $pid = launch_with_config($config);
36
37 my $tmp = fresh_workspace;
38
39 my $window = open_window(name => 'Border window');
40
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');
44
45 $window->unmap;
46 wait_for_unmap $window;
47
48 @content = @{get_ws_content($tmp)};
49 cmp_ok(@content, '==', 0, 'no more nodes');
50 diag('content = '. Dumper(\@content));
51
52
53 # TODO: move this to X11::XCB::Window
54 sub set_wm_class {
55     my ($id, $class, $instance) = @_;
56
57     # Add a _NET_WM_STRUT_PARTIAL hint
58     my $atomname = $x->atom(name => 'WM_CLASS');
59     my $atomtype = $x->atom(name => 'STRING');
60
61     $x->change_property(
62         PROP_MODE_REPLACE,
63         $id,
64         $atomname->id,
65         $atomtype->id,
66         8,
67         length($class) + length($instance) + 2,
68         "$instance\x00$class\x00"
69     );
70 }
71
72 $window = open_window(
73     name => 'Borderless window',
74     before_map => sub { set_wm_class($_->id, 'borderless', 'borderless') },
75 );
76
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');
80
81 $window->unmap;
82 wait_for_unmap $window;
83
84 @content = @{get_ws_content($tmp)};
85 cmp_ok(@content, '==', 0, 'no more nodes');
86
87 exit_gracefully($pid);
88
89 ##############################################################
90 # 2: match on the title, check if for_window is really executed
91 # only once
92 ##############################################################
93
94 $config = <<EOT;
95 # i3 config file (v4)
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
99 EOT
100
101 $pid = launch_with_config($config);
102
103 $tmp = fresh_workspace;
104
105 $window = open_window(name => 'special title');
106
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');
110
111 $window->name('special borderless title');
112 sync_with_i3;
113
114 @content = @{get_ws_content($tmp)};
115 is($content[0]->{border}, 'none', 'no border');
116
117 $window->name('special title');
118 sync_with_i3;
119
120 cmd 'border normal';
121
122 @content = @{get_ws_content($tmp)};
123 is($content[0]->{border}, 'normal', 'border reset to normal');
124
125 $window->name('special borderless title');
126 sync_with_i3;
127
128 @content = @{get_ws_content($tmp)};
129 is($content[0]->{border}, 'normal', 'still normal border');
130
131 $window->unmap;
132 wait_for_unmap $window;
133
134 @content = @{get_ws_content($tmp)};
135 cmp_ok(@content, '==', 0, 'no more nodes');
136
137 exit_gracefully($pid);
138
139 ##############################################################
140 # 3: match on the title, set border style *and* a mark
141 ##############################################################
142
143 $config = <<EOT;
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
150 EOT
151
152 $pid = launch_with_config($config);
153
154 $tmp = fresh_workspace;
155
156 $window = open_window(name => 'special mark title');
157
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');
161
162 my $other = open_window;
163
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');
169
170 cmd qq|[con_mark="bleh"] focus|;
171
172 @content = @{get_ws_content($tmp)};
173 ok($content[0]->{focused}, 'first node focused');
174
175 exit_gracefully($pid);
176
177 ##############################################################
178 # 4: multiple criteria for the for_window command
179 ##############################################################
180
181 $config = <<EOT;
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
185 EOT
186
187 $pid = launch_with_config($config);
188
189 $tmp = fresh_workspace;
190
191 $window = open_window(
192     name => 'usethis',
193     before_map => sub { set_wm_class($_->id, 'borderless', 'borderless') },
194 );
195
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');
199
200 cmd 'kill';
201 wait_for_unmap $window;
202 $window->destroy;
203
204 # give i3 a chance to delete the window from its tree
205 sync_with_i3;
206
207 @content = @{get_ws_content($tmp)};
208 cmp_ok(@content, '==', 0, 'no nodes on this workspace now');
209
210 $window->_create;
211
212 set_wm_class($window->id, 'borderless', 'borderless');
213 $window->name('notthis');
214 $window->map;
215 wait_for_map $window;
216
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');
220
221
222 exit_gracefully($pid);
223
224 ##############################################################
225 # 5: check that a class criterion does not match the instance
226 ##############################################################
227
228 $config = <<EOT;
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
232 EOT
233
234 $pid = launch_with_config($config);
235
236 $tmp = fresh_workspace;
237
238
239 $window = open_window(
240     name => 'usethis',
241     before_map => sub { set_wm_class($_->id, 'bar', 'foo') },
242 );
243
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');
247
248 exit_gracefully($pid);
249
250 ##############################################################
251 # 6: check that the 'instance' criterion works
252 ##############################################################
253
254 $config = <<EOT;
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
259 EOT
260
261 $pid = launch_with_config($config);
262
263 $tmp = fresh_workspace;
264
265 $window = open_window(
266     name => 'usethis',
267     before_map => sub { set_wm_class($_->id, 'bar', 'foo') },
268 );
269
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');
273
274 exit_gracefully($pid);
275
276 ##############################################################
277 # 7: check that invalid criteria don’t end up matching all windows
278 ##############################################################
279
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
282 # assignment
283 $config = <<EOT;
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
287 EOT
288
289 $pid = launch_with_config($config);
290
291 $tmp = fresh_workspace;
292
293 $window = open_window(
294     name => 'usethis',
295     before_map => sub { set_wm_class($_->id, 'bar', 'foo') },
296 );
297
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');
301
302 exit_gracefully($pid);
303
304 ##############################################################
305 # 8: check that the role criterion works properly
306 ##############################################################
307
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
310 # assignment
311 $config = <<EOT;
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
315 EOT
316
317 $pid = launch_with_config($config);
318
319 $tmp = fresh_workspace;
320
321 $window = open_window(
322     name => 'usethis',
323     before_map => sub {
324         my ($window) = @_;
325         my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
326         my $atomtype = $x->atom(name => 'STRING');
327         $x->change_property(
328             PROP_MODE_REPLACE,
329             $window->id,
330             $atomname->id,
331             $atomtype->id,
332             8,
333             length("i3test") + 1,
334             "i3test\x00"
335         );
336     },
337 );
338
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)');
342
343 exit_gracefully($pid);
344
345 ##############################################################
346 # 9: another test for the window_role, but this time it changes
347 #    *after* the window has been mapped
348 ##############################################################
349
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
352 # assignment
353 $config = <<EOT;
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
357 EOT
358
359 $pid = launch_with_config($config);
360
361 $tmp = fresh_workspace;
362
363 $window = open_window(name => 'usethis');
364
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)');
368
369 my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
370 my $atomtype = $x->atom(name => 'STRING');
371 $x->change_property(
372   PROP_MODE_REPLACE,
373   $window->id,
374   $atomname->id,
375   $atomtype->id,
376   8,
377   length("i3test") + 1,
378   "i3test\x00"
379 );
380
381 $x->flush;
382
383 sync_with_i3;
384
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)');
388
389 exit_gracefully($pid);
390
391
392 done_testing;