]> git.sur5r.net Git - i3/i3/blob - testcases/t/156-fullscreen-focus.t
9c396f40fadfc0a438e5a9c13f3978bb77d0bb8f
[i3/i3] / testcases / t / 156-fullscreen-focus.t
1 #!perl
2 # vim:ts=4:sw=4:expandtab
3 #
4 # Please read the following documents before working on tests:
5 # • https://build.i3wm.org/docs/testsuite.html
6 #   (or docs/testsuite)
7 #
8 # • https://build.i3wm.org/docs/lib-i3test.html
9 #   (alternatively: perldoc ./testcases/lib/i3test.pm)
10 #
11 # • https://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 # Test if new containers get focused when there is a fullscreen container at
18 # the time of launching the new one. Also make sure that focusing containers
19 # in other workspaces work even when there is a fullscreen container.
20 #
21 use i3test i3_config => <<EOT;
22 # i3 config file (v4)
23 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
24
25 fake-outputs 1024x768+0+0,1024x768+1024+0
26 EOT
27 # Screen setup looks like this:
28 # +----+----+
29 # | S1 | S2 |
30 # +----+----+
31
32 my $tmp = fresh_workspace;
33
34 ################################################################################
35 # Open the left window.
36 ################################################################################
37
38 my $left = open_window({ background_color => '#ff0000' });
39
40 is($x->input_focus, $left->id, 'left window focused');
41
42 diag("left = " . $left->id);
43
44 ################################################################################
45 # Open the right window.
46 ################################################################################
47
48 my $right = open_window({ background_color => '#00ff00' });
49
50 diag("right = " . $right->id);
51
52 ################################################################################
53 # Set the right window to fullscreen.
54 ################################################################################
55
56 cmd 'nop setting fullscreen';
57 cmd 'fullscreen';
58
59 ################################################################################
60 # Open a third window. Since we're fullscreen, the window won't be # mapped, so
61 # don't wait for it to be mapped. Instead, just send the map request and sync
62 # with i3 to make sure i3 recognizes it.
63 ################################################################################
64
65 my $third = open_window({
66         background_color => '#0000ff',
67         name => 'Third window',
68         dont_map => 1,
69     });
70
71 $third->map;
72
73 sync_with_i3;
74
75 diag("third = " . $third->id);
76
77 ################################################################################
78 # Move the window to a different workspace, and verify that the third window now
79 # gets focused in the current workspace.
80 ################################################################################
81
82 my $tmp2 = get_unused_workspace;
83
84 cmd "move workspace $tmp2";
85
86 is($x->input_focus, $third->id, 'third window focused');
87
88 ################################################################################
89 # Ensure that moving a window to a workspace which has a fullscreen window does
90 # not focus it (otherwise the user cannot get out of fullscreen mode anymore).
91 ################################################################################
92
93 $tmp = fresh_workspace;
94
95 my $fullscreen_window = open_window;
96 cmd 'fullscreen';
97
98 my $nodes = get_ws_content($tmp);
99 is(scalar @$nodes, 1, 'precisely one window');
100 is($nodes->[0]->{focused}, 1, 'fullscreen window focused');
101 my $old_id = $nodes->[0]->{id};
102
103 $tmp2 = fresh_workspace;
104 my $move_window = open_window;
105 cmd "move workspace $tmp";
106
107 cmd "workspace $tmp";
108
109 $nodes = get_ws_content($tmp);
110 is(scalar @$nodes, 2, 'precisely two windows');
111 is($nodes->[0]->{id}, $old_id, 'id unchanged');
112 is($nodes->[0]->{focused}, 1, 'fullscreen window focused');
113
114 ################################################################################
115 # Ensure it's possible to change focus if it doesn't escape the fullscreen
116 # container with fullscreen global. We can't even focus a container in a
117 # different workspace.
118 ################################################################################
119
120 cmd 'fullscreen';
121
122 # Focus screen 1
123 sync_with_i3;
124 $x->root->warp_pointer(1025, 0);
125 sync_with_i3;
126
127 $tmp = fresh_workspace;
128 cmd "workspace $tmp";
129 my $diff_ws = open_window;
130
131 # Focus screen 0
132 sync_with_i3;
133 $x->root->warp_pointer(0, 0);
134 sync_with_i3;
135
136 $tmp2 = fresh_workspace;
137 cmd "workspace $tmp2";
138 cmd 'split h';
139
140 $left = open_window;
141 my $right1 = open_window;
142 cmd 'split v';
143 my $right2 = open_window;
144
145 cmd 'focus parent';
146 cmd 'fullscreen global';
147
148 cmd '[id="' . $right1->id . '"] focus';
149 is($x->input_focus, $right1->id, 'upper right window focused');
150
151 cmd '[id="' . $right2->id . '"] focus';
152 is($x->input_focus, $right2->id, 'bottom right window focused');
153
154 cmd 'focus parent';
155 isnt($x->input_focus, $right2->id, 'bottom right window no longer focused');
156
157 cmd 'focus child';
158 is($x->input_focus, $right2->id, 'bottom right window focused again');
159
160 cmd 'focus up';
161 is($x->input_focus, $right1->id, 'allowed focus up');
162
163 cmd 'focus down';
164 is($x->input_focus, $right2->id, 'allowed focus down');
165
166 cmd 'focus left';
167 is($x->input_focus, $right2->id, 'prevented focus left');
168
169 cmd 'focus right';
170 is($x->input_focus, $right2->id, 'prevented focus right');
171
172 cmd 'focus down';
173 is($x->input_focus, $right1->id, 'allowed focus wrap (down)');
174
175 cmd 'focus up';
176 is($x->input_focus, $right2->id, 'allowed focus wrap (up)');
177
178 ################################################################################
179 # Same tests when we're in non-global fullscreen mode. It should now be possible
180 # to focus a container in a different workspace.
181 ################################################################################
182
183 cmd 'focus parent';
184 cmd 'fullscreen global';
185 cmd 'fullscreen';
186
187 cmd '[id="' . $right1->id . '"] focus';
188 is($x->input_focus, $right1->id, 'upper right window focused');
189
190 cmd '[id="' . $right2->id . '"] focus';
191 is($x->input_focus, $right2->id, 'bottom right window focused');
192
193 cmd 'focus parent';
194 isnt($x->input_focus, $right2->id, 'bottom right window no longer focused');
195
196 cmd 'focus child';
197 is($x->input_focus, $right2->id, 'bottom right window focused again');
198
199 cmd 'focus up';
200 is($x->input_focus, $right1->id, 'allowed focus up');
201
202 cmd 'focus down';
203 is($x->input_focus, $right2->id, 'allowed focus down');
204
205 cmd 'focus down';
206 is($x->input_focus, $right1->id, 'allowed focus wrap (down)');
207
208 cmd 'focus up';
209 is($x->input_focus, $right2->id, 'allowed focus wrap (up)');
210
211 cmd 'focus left';
212 is($x->input_focus, $right2->id, 'focus left wrapped (no-op)');
213
214 cmd 'focus right';
215 is($x->input_focus, $diff_ws->id, 'allowed focus change to different ws');
216
217 cmd 'focus left';
218 is($x->input_focus, $right2->id, 'focused back into fullscreen container');
219
220 cmd '[id="' . $diff_ws->id . '"] focus';
221 is($x->input_focus, $diff_ws->id, 'allowed focus change to different ws by id');
222
223 ################################################################################
224 # More testing of the interaction between wrapping and the fullscreen focus
225 # restrictions.
226 ################################################################################
227
228 cmd '[id="' . $right1->id . '"] focus';
229 is($x->input_focus, $right1->id, 'upper right window focused');
230
231 cmd 'focus parent';
232 cmd 'fullscreen';
233 cmd 'focus child';
234
235 cmd 'split v';
236 my $right12 = open_window;
237
238 cmd 'focus down';
239 is($x->input_focus, $right2->id, 'bottom right window focused');
240
241 cmd 'split v';
242 my $right22 = open_window;
243
244 cmd 'focus parent';
245 cmd 'fullscreen';
246 cmd 'focus child';
247
248 cmd 'focus down';
249 is($x->input_focus, $right2->id, 'focus did not leave parent container (1)');
250
251 cmd 'focus down';
252 is($x->input_focus, $right22->id, 'focus did not leave parent container (2)');
253
254 cmd 'focus up';
255 is($x->input_focus, $right2->id, 'focus did not leave parent container (3)');
256
257 cmd 'focus up';
258 is($x->input_focus, $right22->id, 'focus did not leave parent container (4)');
259
260 ################################################################################
261 # Ensure that moving in a direction doesn't violate the focus restrictions.
262 ################################################################################
263
264 sub verify_move {
265     my $num = shift;
266     my $msg = shift;
267     my $nodes = get_ws_content($tmp2);
268     my $split = $nodes->[1];
269     my $fs = $split->{nodes}->[1];
270     is(scalar @{$fs->{nodes}}, $num, $msg);
271 }
272
273 cmd 'move left';
274 verify_move(2, 'prevented move left');
275 cmd 'move right';
276 verify_move(2, 'prevented move right');
277 cmd 'move down';
278 verify_move(2, 'prevented move down');
279 cmd 'move up';
280 cmd 'move up';
281 verify_move(2, 'prevented move up');
282
283 ################################################################################
284 # Moving to a different workspace is allowed with per-output fullscreen
285 # containers.
286 ################################################################################
287
288 cmd "move to workspace $tmp";
289 verify_move(1, 'did not prevent move to workspace by name');
290
291 cmd "workspace $tmp";
292 cmd "move to workspace $tmp2";
293 cmd "workspace $tmp2";
294
295 cmd "move to workspace prev";
296 verify_move(1, 'did not prevent move to workspace by position');
297
298 ################################################################################
299 # Ensure that is not allowed with global fullscreen containers.
300 ################################################################################
301
302 cmd "workspace $tmp";
303 cmd "move to workspace $tmp2";
304 cmd "workspace $tmp2";
305
306 cmd 'focus parent';
307 cmd 'fullscreen';
308 cmd 'fullscreen global';
309 cmd 'focus child';
310
311 cmd "move to workspace $tmp";
312 verify_move(2, 'prevented move to workspace by name');
313
314 cmd "move to workspace prev";
315 verify_move(2, 'prevented move to workspace by position');
316
317 ################################################################################
318 # Ensure it's possible to focus a window using the focus command despite
319 # fullscreen window blocking it. Fullscreen window should lose its fullscreen
320 # mode.
321 ################################################################################
322
323 # first & second tiling, focus using id
324 kill_all_windows;
325
326 $tmp = fresh_workspace;
327 my $first = open_window;
328 my $second = open_window;
329 cmd 'fullscreen';
330 is($x->input_focus, $second->id, 'fullscreen window focused');
331 is_num_fullscreen($tmp, 1, '1 fullscreen window');
332
333 cmd '[id="'. $first->id .'"] focus';
334 sync_with_i3;
335
336 is($x->input_focus, $first->id, 'correctly focused using id');
337 is_num_fullscreen($tmp, 0, 'no fullscreen windows');
338
339 # first floating, second tiling, focus using 'focus floating'
340 kill_all_windows;
341
342 $tmp = fresh_workspace;
343 $first = open_floating_window;
344 $second = open_window;
345 cmd 'fullscreen';
346 is($x->input_focus, $second->id, 'fullscreen window focused');
347 is_num_fullscreen($tmp, 1, '1 fullscreen window');
348
349 cmd 'focus floating';
350 sync_with_i3;
351
352 is($x->input_focus, $first->id, 'correctly focused using focus floating');
353 is_num_fullscreen($tmp, 0, 'no fullscreen windows');
354
355 # first tiling, second floating, focus using 'focus tiling'
356 kill_all_windows;
357
358 $tmp = fresh_workspace;
359 $first = open_window;
360 $second = open_floating_window;
361 cmd 'fullscreen';
362 is($x->input_focus, $second->id, 'fullscreen window focused');
363 is_num_fullscreen($tmp, 1, '1 fullscreen window');
364
365 cmd 'focus tiling';
366 sync_with_i3;
367
368 is($x->input_focus, $first->id, 'correctly focused using focus tiling');
369 is_num_fullscreen($tmp, 0, 'no fullscreen windows');
370
371 ################################################################################
372 # When the fullscreen window is in an other workspace it should maintain its
373 # fullscreen mode since it's not blocking the window to be focused.
374 ################################################################################
375
376 kill_all_windows;
377
378 $tmp = fresh_workspace;
379 $first = open_window;
380
381 $tmp2 = fresh_workspace;
382 $second = open_window;
383 cmd 'fullscreen';
384 is($x->input_focus, $second->id, 'fullscreen window focused');
385 is_num_fullscreen($tmp2, 1, '1 fullscreen window');
386
387 cmd '[id="'. $first->id .'"] focus';
388 sync_with_i3;
389
390 is($x->input_focus, $first->id, 'correctly focused using focus id');
391 is_num_fullscreen($tmp, 0, 'no fullscreen windows on first workspace');
392 is_num_fullscreen($tmp2, 1, 'still one fullscreen window on second workspace');
393
394 ################################################################################
395 # But a global window in another workspace is blocking the window to be focused.
396 # Ensure that it loses its fullscreen mode.
397 ################################################################################
398
399 kill_all_windows;
400
401 $tmp = fresh_workspace;
402 $first = open_window;
403
404 $tmp2 = fresh_workspace;
405 $second = open_window;
406 cmd 'fullscreen global';
407 is($x->input_focus, $second->id, 'global window focused');
408 is_num_fullscreen($tmp2, 1, '1 fullscreen window');
409
410 cmd '[id="'. $first->id .'"] focus';
411 sync_with_i3;
412
413 is($x->input_focus, $first->id, 'correctly focused using focus id');
414 is_num_fullscreen($tmp2, 0, 'no fullscreen windows');
415
416
417 # TODO: Tests for "move to output" and "move workspace to output".
418 done_testing;