]> git.sur5r.net Git - i3/i3/blob - testcases/t/165-for_window.t
testcases: drop sync_with_i3()s $x parameter, use global
[i3/i3] / testcases / t / 165-for_window.t
1 #!perl
2 # vim:ts=4:sw=4:expandtab
3 # !NO_I3_INSTANCE! will prevent complete-run.pl from starting i3
4 #
5 #
6 use i3test;
7 use X11::XCB qw(PROP_MODE_REPLACE WINDOW_CLASS_INPUT_OUTPUT);
8
9 ##############################################################
10 # 1: test the following directive:
11 #    for_window [class="borderless"] border none
12 # by first creating a window with a different class (should get
13 # the normal border), then creating a window with the class
14 # "borderless" (should get no border)
15 ##############################################################
16
17 my $config = <<EOT;
18 # i3 config file (v4)
19 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
20 for_window [class="borderless"] border none
21 for_window [title="special borderless title"] border none
22 EOT
23
24 my $pid = launch_with_config($config);
25
26 my $tmp = fresh_workspace;
27
28 my $window = $x->root->create_child(
29     class => WINDOW_CLASS_INPUT_OUTPUT,
30     rect => [ 0, 0, 30, 30 ],
31     background_color => '#00ff00',
32     event_mask => [ 'structure_notify' ],
33 );
34
35 $window->name('Border window');
36 $window->map;
37 wait_for_map $window;
38
39 my @content = @{get_ws_content($tmp)};
40 cmp_ok(@content, '==', 1, 'one node on this workspace now');
41 is($content[0]->{border}, 'normal', 'normal border');
42
43 $window->unmap;
44 wait_for_unmap $window;
45
46 @content = @{get_ws_content($tmp)};
47 cmp_ok(@content, '==', 0, 'no more nodes');
48 diag('content = '. Dumper(\@content));
49
50 $window = $x->root->create_child(
51     class => WINDOW_CLASS_INPUT_OUTPUT,
52     rect => [ 0, 0, 30, 30 ],
53     background_color => '#00ff00',
54     event_mask => [ 'structure_notify' ],
55 );
56
57 $window->_create;
58
59 # TODO: move this to X11::XCB::Window
60 sub set_wm_class {
61     my ($id, $class, $instance) = @_;
62
63     # Add a _NET_WM_STRUT_PARTIAL hint
64     my $atomname = $x->atom(name => 'WM_CLASS');
65     my $atomtype = $x->atom(name => 'STRING');
66
67     $x->change_property(
68         PROP_MODE_REPLACE,
69         $id,
70         $atomname->id,
71         $atomtype->id,
72         8,
73         length($class) + length($instance) + 2,
74         "$instance\x00$class\x00"
75     );
76 }
77
78 set_wm_class($window->id, 'borderless', 'borderless');
79 $window->name('Borderless window');
80 $window->map;
81 wait_for_map $window;
82
83 @content = @{get_ws_content($tmp)};
84 cmp_ok(@content, '==', 1, 'one node on this workspace now');
85 is($content[0]->{border}, 'none', 'no border');
86
87 $window->unmap;
88 wait_for_unmap $window;
89
90 @content = @{get_ws_content($tmp)};
91 cmp_ok(@content, '==', 0, 'no more nodes');
92
93 exit_gracefully($pid);
94
95 ##############################################################
96 # 2: match on the title, check if for_window is really executed
97 # only once
98 ##############################################################
99
100 $config = <<EOT;
101 # i3 config file (v4)
102 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
103 for_window [class="borderless"] border none
104 for_window [title="special borderless title"] border none
105 EOT
106
107 $pid = launch_with_config($config);
108
109 $tmp = fresh_workspace;
110
111 $window = $x->root->create_child(
112     class => WINDOW_CLASS_INPUT_OUTPUT,
113     rect => [ 0, 0, 30, 30 ],
114     background_color => '#00ff00',
115     event_mask => [ 'structure_notify' ],
116 );
117
118 $window->name('special title');
119 $window->map;
120 wait_for_map $window;
121
122 @content = @{get_ws_content($tmp)};
123 cmp_ok(@content, '==', 1, 'one node on this workspace now');
124 is($content[0]->{border}, 'normal', 'normal border');
125
126 $window->name('special borderless title');
127 sync_with_i3;
128
129 @content = @{get_ws_content($tmp)};
130 is($content[0]->{border}, 'none', 'no border');
131
132 $window->name('special title');
133 sync_with_i3;
134
135 cmd 'border normal';
136
137 @content = @{get_ws_content($tmp)};
138 is($content[0]->{border}, 'normal', 'border reset to normal');
139
140 $window->name('special borderless title');
141 sync_with_i3;
142
143 @content = @{get_ws_content($tmp)};
144 is($content[0]->{border}, 'normal', 'still normal border');
145
146 $window->unmap;
147 wait_for_unmap $window;
148
149 @content = @{get_ws_content($tmp)};
150 cmp_ok(@content, '==', 0, 'no more nodes');
151
152 exit_gracefully($pid);
153
154 ##############################################################
155 # 3: match on the title, set border style *and* a mark
156 ##############################################################
157
158 $config = <<EOT;
159 # i3 config file (v4)
160 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
161 for_window [class="borderless" title="usethis"] border none
162 for_window [class="borderless"] border none
163 for_window [title="special borderless title"] border none
164 for_window [title="special mark title"] border none, mark bleh
165 EOT
166
167 $pid = launch_with_config($config);
168
169 $tmp = fresh_workspace;
170
171 $window = $x->root->create_child(
172     class => WINDOW_CLASS_INPUT_OUTPUT,
173     rect => [ 0, 0, 30, 30 ],
174     background_color => '#00ff00',
175     event_mask => [ 'structure_notify' ],
176 );
177
178 $window->name('special mark title');
179 $window->map;
180 wait_for_map $window;
181
182 @content = @{get_ws_content($tmp)};
183 cmp_ok(@content, '==', 1, 'one node on this workspace now');
184 is($content[0]->{border}, 'none', 'no border');
185
186 my $other = open_window;
187
188 @content = @{get_ws_content($tmp)};
189 cmp_ok(@content, '==', 2, 'two nodes');
190 is($content[0]->{border}, 'none', 'no border');
191 is($content[1]->{border}, 'normal', 'normal border');
192 ok(!$content[0]->{focused}, 'first one not focused');
193
194 cmd qq|[con_mark="bleh"] focus|;
195
196 @content = @{get_ws_content($tmp)};
197 ok($content[0]->{focused}, 'first node focused');
198
199 exit_gracefully($pid);
200
201 ##############################################################
202 # 4: multiple criteria for the for_window command
203 ##############################################################
204
205 $config = <<EOT;
206 # i3 config file (v4)
207 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
208 for_window [class="borderless" title="usethis"] border none
209 EOT
210
211 $pid = launch_with_config($config);
212
213 $tmp = fresh_workspace;
214
215 $window = $x->root->create_child(
216     class => WINDOW_CLASS_INPUT_OUTPUT,
217     rect => [ 0, 0, 30, 30 ],
218     background_color => '#00ff00',
219     event_mask => [ 'structure_notify' ],
220 );
221
222 $window->_create;
223
224 set_wm_class($window->id, 'borderless', 'borderless');
225 $window->name('usethis');
226 $window->map;
227 wait_for_map $window;
228
229 @content = @{get_ws_content($tmp)};
230 cmp_ok(@content, '==', 1, 'one node on this workspace now');
231 is($content[0]->{border}, 'none', 'no border');
232
233 cmd 'kill';
234 wait_for_unmap $window;
235 $window->destroy;
236
237 # give i3 a chance to delete the window from its tree
238 sync_with_i3;
239
240 @content = @{get_ws_content($tmp)};
241 cmp_ok(@content, '==', 0, 'no nodes on this workspace now');
242
243 $window->_create;
244
245 set_wm_class($window->id, 'borderless', 'borderless');
246 $window->name('notthis');
247 $window->map;
248 wait_for_map $window;
249
250 @content = @{get_ws_content($tmp)};
251 cmp_ok(@content, '==', 1, 'one node on this workspace now');
252 is($content[0]->{border}, 'normal', 'no border');
253
254
255 exit_gracefully($pid);
256
257 ##############################################################
258 # 5: check that a class criterion does not match the instance
259 ##############################################################
260
261 $config = <<EOT;
262 # i3 config file (v4)
263 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
264 for_window [class="foo"] border 1pixel
265 EOT
266
267 $pid = launch_with_config($config);
268
269 $tmp = fresh_workspace;
270
271 $window = $x->root->create_child(
272     class => WINDOW_CLASS_INPUT_OUTPUT,
273     rect => [ 0, 0, 30, 30 ],
274     background_color => '#00ff00',
275     event_mask => [ 'structure_notify' ],
276 );
277
278 $window->_create;
279
280 set_wm_class($window->id, 'bar', 'foo');
281 $window->name('usethis');
282 $window->map;
283 wait_for_map $window;
284
285 @content = @{get_ws_content($tmp)};
286 cmp_ok(@content, '==', 1, 'one node on this workspace now');
287 is($content[0]->{border}, 'normal', 'normal border, not matched');
288
289 exit_gracefully($pid);
290
291 ##############################################################
292 # 6: check that the 'instance' criterion works
293 ##############################################################
294
295 $config = <<EOT;
296 # i3 config file (v4)
297 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
298 for_window [class="foo"] border 1pixel
299 for_window [instance="foo"] border none
300 EOT
301
302 $pid = launch_with_config($config);
303
304 $tmp = fresh_workspace;
305
306 $window = $x->root->create_child(
307     class => WINDOW_CLASS_INPUT_OUTPUT,
308     rect => [ 0, 0, 30, 30 ],
309     background_color => '#00ff00',
310     event_mask => [ 'structure_notify' ],
311 );
312
313 $window->_create;
314
315 set_wm_class($window->id, 'bar', 'foo');
316 $window->name('usethis');
317 $window->map;
318 wait_for_map $window;
319
320 @content = @{get_ws_content($tmp)};
321 cmp_ok(@content, '==', 1, 'one node on this workspace now');
322 is($content[0]->{border}, 'none', 'no border');
323
324 exit_gracefully($pid);
325
326 ##############################################################
327 # 7: check that invalid criteria don’t end up matching all windows
328 ##############################################################
329
330 # this configuration is broken because "asdf" is not a valid integer
331 # the for_window should therefore recognize this error and don’t add the
332 # assignment
333 $config = <<EOT;
334 # i3 config file (v4)
335 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
336 for_window [id="asdf"] border none
337 EOT
338
339 $pid = launch_with_config($config);
340
341 $tmp = fresh_workspace;
342
343 $window = $x->root->create_child(
344     class => WINDOW_CLASS_INPUT_OUTPUT,
345     rect => [ 0, 0, 30, 30 ],
346     background_color => '#00ff00',
347     event_mask => [ 'structure_notify' ],
348 );
349
350 $window->_create;
351
352 set_wm_class($window->id, 'bar', 'foo');
353 $window->name('usethis');
354 $window->map;
355 wait_for_map $window;
356
357 @content = @{get_ws_content($tmp)};
358 cmp_ok(@content, '==', 1, 'one node on this workspace now');
359 is($content[0]->{border}, 'normal', 'normal border');
360
361 exit_gracefully($pid);
362
363 ##############################################################
364 # 8: check that the role criterion works properly
365 ##############################################################
366
367 # this configuration is broken because "asdf" is not a valid integer
368 # the for_window should therefore recognize this error and don’t add the
369 # assignment
370 $config = <<EOT;
371 # i3 config file (v4)
372 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
373 for_window [window_role="i3test"] border none
374 EOT
375
376 $pid = launch_with_config($config);
377
378 $tmp = fresh_workspace;
379
380 $window = $x->root->create_child(
381     class => WINDOW_CLASS_INPUT_OUTPUT,
382     rect => [ 0, 0, 30, 30 ],
383     background_color => '#00ff00',
384     event_mask => [ 'structure_notify' ],
385 );
386
387 $window->_create;
388
389 my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
390 my $atomtype = $x->atom(name => 'STRING');
391 $x->change_property(
392   PROP_MODE_REPLACE,
393   $window->id,
394   $atomname->id,
395   $atomtype->id,
396   8,
397   length("i3test") + 1,
398   "i3test\x00"
399 );
400
401 $window->name('usethis');
402 $window->map;
403 wait_for_map $window;
404
405 @content = @{get_ws_content($tmp)};
406 cmp_ok(@content, '==', 1, 'one node on this workspace now');
407 is($content[0]->{border}, 'none', 'no border (window_role)');
408
409 exit_gracefully($pid);
410
411 ##############################################################
412 # 9: another test for the window_role, but this time it changes
413 #    *after* the window has been mapped
414 ##############################################################
415
416 # this configuration is broken because "asdf" is not a valid integer
417 # the for_window should therefore recognize this error and don’t add the
418 # assignment
419 $config = <<EOT;
420 # i3 config file (v4)
421 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
422 for_window [window_role="i3test"] border none
423 EOT
424
425 $pid = launch_with_config($config);
426
427 $tmp = fresh_workspace;
428
429 $window = $x->root->create_child(
430     class => WINDOW_CLASS_INPUT_OUTPUT,
431     rect => [ 0, 0, 30, 30 ],
432     background_color => '#00ff00',
433     event_mask => [ 'structure_notify' ],
434 );
435
436 $window->_create;
437
438 $window->name('usethis');
439 $window->map;
440 wait_for_map $window;
441
442 @content = @{get_ws_content($tmp)};
443 cmp_ok(@content, '==', 1, 'one node on this workspace now');
444 is($content[0]->{border}, 'normal', 'normal border (window_role 2)');
445
446 $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
447 $atomtype = $x->atom(name => 'STRING');
448 $x->change_property(
449   PROP_MODE_REPLACE,
450   $window->id,
451   $atomname->id,
452   $atomtype->id,
453   8,
454   length("i3test") + 1,
455   "i3test\x00"
456 );
457
458 $x->flush;
459
460 sync_with_i3;
461
462 @content = @{get_ws_content($tmp)};
463 cmp_ok(@content, '==', 1, 'one node on this workspace now');
464 is($content[0]->{border}, 'none', 'no border (window_role 2)');
465
466 exit_gracefully($pid);
467
468
469 done_testing;