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