]> git.sur5r.net Git - i3/i3/blob - testcases/t/165-for_window.t
Merge pull request #1731 from Airblader/feature-indicator-pango
[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 $window = open_window(
53     name => 'Borderless window',
54     wm_class => 'borderless',
55 );
56
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');
60
61 $window->unmap;
62 wait_for_unmap $window;
63
64 @content = @{get_ws_content($tmp)};
65 cmp_ok(@content, '==', 0, 'no more nodes');
66
67 exit_gracefully($pid);
68
69 ##############################################################
70 # 2: match on the title, check if for_window is really executed
71 # only once
72 ##############################################################
73
74 $config = <<EOT;
75 # i3 config file (v4)
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
79 EOT
80
81 $pid = launch_with_config($config);
82
83 $tmp = fresh_workspace;
84
85 $window = open_window(name => 'special title');
86
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');
90
91 $window->name('special borderless title');
92 sync_with_i3;
93
94 @content = @{get_ws_content($tmp)};
95 is($content[0]->{border}, 'none', 'no border');
96
97 $window->name('special title');
98 sync_with_i3;
99
100 cmd 'border normal';
101
102 @content = @{get_ws_content($tmp)};
103 is($content[0]->{border}, 'normal', 'border reset to normal');
104
105 $window->name('special borderless title');
106 sync_with_i3;
107
108 @content = @{get_ws_content($tmp)};
109 is($content[0]->{border}, 'normal', 'still normal border');
110
111 $window->unmap;
112 wait_for_unmap $window;
113
114 @content = @{get_ws_content($tmp)};
115 cmp_ok(@content, '==', 0, 'no more nodes');
116
117 exit_gracefully($pid);
118
119 ##############################################################
120 # 3: match on the title, set border style *and* a mark
121 ##############################################################
122
123 $config = <<EOT;
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
130 EOT
131
132 $pid = launch_with_config($config);
133
134 $tmp = fresh_workspace;
135
136 $window = open_window(name => 'special mark title');
137
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');
141
142 my $other = open_window;
143
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');
149
150 cmd qq|[con_mark="bleh"] focus|;
151
152 @content = @{get_ws_content($tmp)};
153 ok($content[0]->{focused}, 'first node focused');
154
155 exit_gracefully($pid);
156
157 ##############################################################
158 # 4: multiple criteria for the for_window command
159 ##############################################################
160
161 $config = <<EOT;
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
165 EOT
166
167 $pid = launch_with_config($config);
168
169 $tmp = fresh_workspace;
170
171 $window = open_window(
172     name => 'usethis',
173     wm_class => 'borderless',
174 );
175
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');
179
180 cmd 'kill';
181 wait_for_unmap $window;
182 $window->destroy;
183
184 # give i3 a chance to delete the window from its tree
185 sync_with_i3;
186
187 @content = @{get_ws_content($tmp)};
188 cmp_ok(@content, '==', 0, 'no nodes on this workspace now');
189
190 $window->_create;
191 $window->wm_class('borderless');
192 $window->name('notthis');
193 $window->map;
194 wait_for_map $window;
195
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');
199
200
201 exit_gracefully($pid);
202
203 ##############################################################
204 # 5: check that a class criterion does not match the instance
205 ##############################################################
206
207 $config = <<EOT;
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
211 EOT
212
213 $pid = launch_with_config($config);
214
215 $tmp = fresh_workspace;
216
217
218 $window = open_window(
219     name => 'usethis',
220     wm_class => 'bar',
221     instance => 'foo',
222 );
223
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');
227
228 exit_gracefully($pid);
229
230 ##############################################################
231 # 6: check that the 'instance' criterion works
232 ##############################################################
233
234 $config = <<EOT;
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
239 EOT
240
241 $pid = launch_with_config($config);
242
243 $tmp = fresh_workspace;
244
245 $window = open_window(
246     name => 'usethis',
247     wm_class => 'bar',
248     instance => 'foo',
249 );
250
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');
254
255 exit_gracefully($pid);
256
257 ##############################################################
258 # 7: check that invalid criteria don’t end up matching all windows
259 ##############################################################
260
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
263 # assignment
264 $config = <<EOT;
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
268 EOT
269
270 $pid = launch_with_config($config);
271
272 $tmp = fresh_workspace;
273
274 $window = open_window(
275     name => 'usethis',
276     wm_class => 'bar',
277     instance => 'foo',
278 );
279
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');
283
284 exit_gracefully($pid);
285
286 ##############################################################
287 # 8: check that the role criterion works properly
288 ##############################################################
289
290 $config = <<EOT;
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
294 EOT
295
296 $pid = launch_with_config($config);
297
298 $tmp = fresh_workspace;
299
300 $window = open_window(
301     name => 'usethis',
302     before_map => sub {
303         my ($window) = @_;
304         my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
305         my $atomtype = $x->atom(name => 'STRING');
306         $x->change_property(
307             PROP_MODE_REPLACE,
308             $window->id,
309             $atomname->id,
310             $atomtype->id,
311             8,
312             length("i3test") + 1,
313             "i3test\x00"
314         );
315     },
316 );
317
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)');
321
322 exit_gracefully($pid);
323
324 ##############################################################
325 # 9: another test for the window_role, but this time it changes
326 #    *after* the window has been mapped
327 ##############################################################
328
329 $config = <<EOT;
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
333 EOT
334
335 $pid = launch_with_config($config);
336
337 $tmp = fresh_workspace;
338
339 $window = open_window(name => 'usethis');
340
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)');
344
345 my $atomname = $x->atom(name => 'WM_WINDOW_ROLE');
346 my $atomtype = $x->atom(name => 'STRING');
347 $x->change_property(
348   PROP_MODE_REPLACE,
349   $window->id,
350   $atomname->id,
351   $atomtype->id,
352   8,
353   length("i3test") + 1,
354   "i3test\x00"
355 );
356
357 $x->flush;
358
359 sync_with_i3;
360
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)');
364
365 exit_gracefully($pid);
366
367 ##############################################################
368 # 10: check that the criterion 'window_type' works
369 ##############################################################
370
371 # test all window types
372 my %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'
382 );
383
384 while (my ($window_type, $atom) = each %window_types) {
385
386     $config = <<"EOT";
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
390 EOT
391
392     $pid = launch_with_config($config);
393     $tmp = fresh_workspace;
394
395     $window = open_window(window_type => $x->atom(name => $atom));
396
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)");
400
401     exit_gracefully($pid);
402
403 }
404
405 ##############################################################
406 # 11: check that the criterion 'window_type' works if the
407 #     _NET_WM_WINDOW_TYPE is changed after managing.
408 ##############################################################
409
410 while (my ($window_type, $atom) = each %window_types) {
411
412     $config = <<"EOT";
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
416 EOT
417
418     $pid = launch_with_config($config);
419     $tmp = fresh_workspace;
420
421     $window = open_window();
422
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));
427     $x->flush;
428     sync_with_i3;
429
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)");
433
434     exit_gracefully($pid);
435
436 }
437
438 ##############################################################
439
440 done_testing;