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