]> git.sur5r.net Git - i3/i3/blob - testcases/t/135-floating-focus.t
168151f4c0191018883f4e741248116614f6efb6
[i3/i3] / testcases / t / 135-floating-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 use i3test;
18
19 my $tmp = fresh_workspace;
20
21 #############################################################################
22 # 1: see if focus stays the same when toggling tiling/floating mode
23 #############################################################################
24
25 my $first = open_window;
26 my $second = open_window;
27
28 is($x->input_focus, $second->id, 'second window focused');
29
30 cmd 'floating enable';
31 cmd 'floating disable';
32
33 is($x->input_focus, $second->id, 'second window still focused after mode toggle');
34
35 #############################################################################
36 # 2: see if focus stays on the current floating window if killing another
37 # floating window
38 #############################################################################
39
40 $tmp = fresh_workspace;
41
42 $first = open_window;    # window 2
43 $second = open_window;   # window 3
44 my $third = open_window; # window 4
45
46 is($x->input_focus, $third->id, 'last container focused');
47
48 cmd 'floating enable';
49
50 cmd '[id="' . $second->id . '"] focus';
51
52 is($x->input_focus, $second->id, 'second con focused');
53
54 cmd 'floating enable';
55
56 # now kill the third one (it's floating). focus should stay unchanged
57 cmd '[id="' . $third->id . '"] kill';
58
59 wait_for_unmap($third);
60
61 is($x->input_focus, $second->id, 'second con still focused after killing third');
62
63
64 #############################################################################
65 # 3: see if the focus gets reverted correctly when closing floating clients
66 # (first to the next floating client, then to the last focused tiling client)
67 #############################################################################
68
69 $tmp = fresh_workspace;
70
71 $first = open_window({ background_color => '#ff0000' });    # window 5
72 $second = open_window({ background_color => '#00ff00' });   # window 6
73 $third = open_window({ background_color => '#0000ff' }); # window 7
74
75 is($x->input_focus, $third->id, 'last container focused');
76
77 cmd 'floating enable';
78
79 cmd '[id="' . $second->id . '"] focus';
80
81 is($x->input_focus, $second->id, 'second con focused');
82
83 cmd 'floating enable';
84
85 # now kill the second one. focus should fall back to the third one, which is
86 # also floating
87 cmd 'kill';
88 wait_for_unmap($second);
89
90 is($x->input_focus, $third->id, 'third con focused');
91
92 cmd 'kill';
93 wait_for_unmap($third);
94
95 is($x->input_focus, $first->id, 'first con focused after killing all floating cons');
96
97 #############################################################################
98 # 4: same test as 3, but with another split con
99 #############################################################################
100
101 $tmp = fresh_workspace;
102
103 $first = open_window({ background_color => '#ff0000' });    # window 5
104 cmd 'split v';
105 cmd 'layout stacked';
106 $second = open_window({ background_color => '#00ff00' });   # window 6
107 $third = open_window({ background_color => '#0000ff' }); # window 7
108 is($x->input_focus, $third->id, 'last container focused');
109
110 cmd '[id="' . $second->id . '"] focus';
111 cmd 'floating enable';
112 cmd '[id="' . $third->id . '"] floating enable';
113
114 sync_with_i3;
115 is($x->input_focus, $second->id, 'second con focused');
116
117 # now kill the second one. focus should fall back to the third one, which is
118 # also floating
119 cmd 'kill';
120 wait_for_unmap($second);
121
122 is($x->input_focus, $third->id, 'third con focused');
123
124 cmd 'kill';
125 wait_for_unmap($third);
126
127 is($x->input_focus, $first->id, 'first con focused after killing all floating cons');
128
129 #############################################################################
130 # 5: see if the 'focus tiling' and 'focus floating' commands work
131 #############################################################################
132
133 $tmp = fresh_workspace;
134
135 $first = open_window({ background_color => '#ff0000' });    # window 8
136 $second = open_window({ background_color => '#00ff00' });   # window 9
137
138 is($x->input_focus, $second->id, 'second container focused');
139
140 cmd 'floating enable';
141
142 is($x->input_focus, $second->id, 'second container focused');
143
144 cmd 'focus tiling';
145
146 is($x->input_focus, $first->id, 'first (tiling) container focused');
147
148 cmd 'focus floating';
149
150 is($x->input_focus, $second->id, 'second (floating) container focused');
151
152 cmd 'focus floating';
153
154 is($x->input_focus, $second->id, 'second (floating) container still focused');
155
156 cmd 'focus mode_toggle';
157
158 is($x->input_focus, $first->id, 'first (tiling) container focused');
159
160 cmd 'focus mode_toggle';
161
162 is($x->input_focus, $second->id, 'second (floating) container focused');
163
164 #############################################################################
165 # 6: see if switching floating focus using the focus left/right command works
166 #############################################################################
167
168 $tmp = fresh_workspace;
169
170 $first = open_floating_window({ background_color => '#ff0000' });# window 10
171 $second = open_floating_window({ background_color => '#00ff00' }); # window 11
172 $third = open_floating_window({ background_color => '#0000ff' }); # window 12
173
174 is($x->input_focus, $third->id, 'third container focused');
175
176 cmd 'focus left';
177
178 is($x->input_focus, $second->id, 'second container focused');
179
180 cmd 'focus left';
181
182 is($x->input_focus, $first->id, 'first container focused');
183
184 cmd 'focus left';
185
186 is($x->input_focus, $third->id, 'focus wrapped to third container');
187
188 cmd 'focus right';
189
190 is($x->input_focus, $first->id, 'focus wrapped to first container');
191
192 cmd 'focus right';
193
194 is($x->input_focus, $second->id, 'focus on second container');
195
196 #############################################################################
197 # 7: verify that focusing the parent of a window inside a floating con goes
198 # up to the grandparent (workspace) and that focusing child from the ws
199 # goes back down to the child of the floating con
200 #############################################################################
201
202 $tmp = fresh_workspace;
203
204 my $tiled = open_window;
205 my $floating = open_floating_window;
206 is($x->input_focus, $floating->id, 'floating window focused');
207
208 cmd 'focus parent';
209
210 is(get_ws($tmp)->{focused}, 1, 'workspace is focused');
211 cmd 'focus child';
212
213 is($x->input_focus, $floating->id, 'floating window focused');
214
215 #############################################################################
216 # 8: verify that focusing a floating window raises it to the top.
217 # This test can't verify that the floating container is visually on top, just
218 # that it is placed on the tail of the floating_head.
219 # See issue: 2572
220 #############################################################################
221
222 $tmp = fresh_workspace;
223
224 $first = open_floating_window;
225 $second = open_floating_window;
226
227 is($x->input_focus, $second->id, 'second floating window focused');
228 my $ws = get_ws($tmp);
229 is($ws->{floating_nodes}->[1]->{nodes}->[0]->{window}, $second->id, 'second on top');
230 is($ws->{floating_nodes}->[0]->{nodes}->[0]->{window}, $first->id, 'first behind');
231
232 cmd '[id=' . $first->id . '] focus';
233
234 is($x->input_focus, $first->id, 'first floating window focused');
235 $ws = get_ws($tmp);
236 is($ws->{floating_nodes}->[1]->{nodes}->[0]->{window}, $first->id, 'first on top');
237 is($ws->{floating_nodes}->[0]->{nodes}->[0]->{window}, $second->id, 'second behind');
238
239 #############################################################################
240 # 9: verify that disabling / enabling floating for a window from a different
241 # workspace maintains the correct focus order.
242 #############################################################################
243
244 sub open_window_helper {
245     my $floating = shift if @_;
246     if ($floating){
247         return open_floating_window;
248     }
249     else {
250         return open_window;
251     }
252 }
253
254 for my $floating (0, 1){
255     $tmp = fresh_workspace;
256     $first = open_window;
257     $second = open_window_helper($floating);
258     is($x->input_focus, $second->id, "second window focused");
259
260     fresh_workspace;
261     cmd "[id=" . $second->id . "] floating toggle";
262     cmd "workspace $tmp";
263     sync_with_i3;
264
265     my $workspace = get_ws($tmp);
266     is($workspace->{floating_nodes}->[0]->{nodes}->[0]->{window}, $second->id, 'second window on first workspace, floating') unless $floating;
267     is($workspace->{nodes}->[1]->{window}, $second->id, 'second window on first workspace, right') unless !$floating;
268     is($x->input_focus, $second->id, 'second window still focused');
269 }
270
271 #############################################################################
272 # 10: verify that toggling floating for an unfocused window on another
273 # workspace doesn't make it focused.
274 #############################################################################
275
276 for my $floating (0, 1){
277     $tmp = fresh_workspace;
278     $first = open_window_helper($floating);
279     $second = open_window;
280     is($x->input_focus, $second->id, 'second (tiling) window focused');
281
282     fresh_workspace;
283     cmd "[id=" . $first->id . "] floating toggle";
284     cmd "workspace $tmp";
285     sync_with_i3;
286
287     my $workspace = get_ws($tmp);
288     is($workspace->{floating_nodes}->[0]->{nodes}->[0]->{window}, $first->id, 'first window on first workspace, floating') unless $floating;
289     is($workspace->{nodes}->[1]->{window}, $first->id, 'first window on first workspace, right') unless !$floating;
290     is($x->input_focus, $second->id, 'second window still focused');
291 }
292
293 #############################################################################
294 # 11: verify that toggling floating for a focused window on another workspace
295 # which has another, unfocused floating window maintains the focus of the
296 # first window.
297 #############################################################################
298 for my $floating (0, 1){
299     $tmp = fresh_workspace;
300     $first = open_window;
301     $second = open_floating_window;
302     is($x->input_focus, $second->id, 'second (floating) window focused');
303     $third = open_window_helper($floating);
304     is($x->input_focus, $third->id, "third (floating = $floating) window focused");
305
306     fresh_workspace;
307     cmd "[id=" . $third->id . "] floating toggle";
308     cmd "workspace $tmp";
309     sync_with_i3;
310
311     my $workspace = get_ws($tmp);
312     is($workspace->{floating_nodes}->[0]->{nodes}->[0]->{window}, $third->id, 'third window on first workspace, floating') unless $floating;
313     is($workspace->{nodes}->[1]->{window}, $third->id, 'third window on first workspace, right') unless !$floating;
314     is($x->input_focus, $third->id, 'third window still focused');
315 }
316
317 #############################################################################
318 # 12: verify that toggling floating for an unfocused window on another
319 # workspace which has another, focused floating window doesn't change focus.
320 #############################################################################
321
322 for my $floating (0, 1){
323     $tmp = fresh_workspace;
324     $first = open_window;
325     $second = open_window_helper($floating);
326     is($x->input_focus, $second->id, "second (floating = $floating) window focused");
327     $third = open_floating_window;
328     is($x->input_focus, $third->id, 'third (floating) window focused');
329
330     fresh_workspace;
331     cmd "[id=" . $second->id . "] floating toggle";
332     cmd "workspace $tmp";
333     sync_with_i3;
334
335     my $workspace = get_ws($tmp);
336     is($workspace->{floating_nodes}->[0]->{nodes}->[0]->{window}, $second->id, 'second window on first workspace, floating') unless $floating;
337     is($workspace->{nodes}->[1]->{window}, $second->id, 'second window on first workspace, right') unless !$floating;
338     is($x->input_focus, $third->id, 'third window still focused');
339 }
340
341 #############################################################################
342 # 13: For layout [H1 [A V1[ B F ] ] ] verify that toggling F's floating
343 # mode maintains its focus.
344 #############################################################################
345
346 for my $floating (0, 1){
347     $tmp = fresh_workspace;
348     $first = open_window;
349     $second = open_window;
350     cmd "split v";
351     sync_with_i3;
352     is($x->input_focus, $second->id, "second (floating = $floating) window focused");
353     $third = open_window_helper($floating);
354     is($x->input_focus, $third->id, 'third (floating) window focused');
355
356     fresh_workspace;
357     cmd "[id=" . $third->id . "] floating toggle";
358     cmd "workspace $tmp";
359     sync_with_i3;
360
361     my $workspace = get_ws($tmp);
362     is($workspace->{floating_nodes}->[0]->{nodes}->[0]->{window}, $third->id, 'third window on first workspace, floating') unless $floating;
363     is($workspace->{nodes}->[1]->{nodes}->[1]->{window}, $third->id, 'third window on first workspace') unless !$floating;
364     is($x->input_focus, $third->id, 'third window still focused');
365 }
366
367 #############################################################################
368 # 14: For layout [H1 [A V1[ H2 [B H2 [ C V2 [ F D ] ] ] ] ] ] verify that
369 # toggling F's floating mode maintains its focus.
370 #############################################################################
371
372 sub kill_and_confirm_focus {
373     my $focus = shift;
374     my $msg = shift;
375     cmd "kill";
376     sync_with_i3;
377     is($x->input_focus, $focus, $msg);
378 }
379
380 $tmp = fresh_workspace;
381 my $A = open_window;
382 my $B = open_window;
383 cmd "split v";
384 my $C = open_window;
385 cmd "split h";
386 my $F = open_window;
387 cmd "split v";
388 my $D = open_window;
389 is($x->input_focus, $D->id, "D is focused");
390
391 sync_with_i3;
392 my $workspace = get_ws($tmp);
393 is($workspace->{nodes}->[1]->{nodes}->[1]->{nodes}->[1]->{nodes}->[0]->{window}, $F->id, 'F opened in its expected position');
394
395 fresh_workspace;
396 cmd "[id=" . $F->id . "] floating enable";
397 cmd "workspace $tmp";
398 sync_with_i3;
399
400 $workspace = get_ws($tmp);
401 is($workspace->{floating_nodes}->[0]->{nodes}->[0]->{window}, $F->id, 'F on first workspace, floating');
402 is($workspace->{nodes}->[1]->{nodes}->[1]->{nodes}->[1]->{nodes}->[0]->{window}, $D->id, 'D where F used to be');
403 is($x->input_focus, $D->id, 'D still focused');
404
405 fresh_workspace;
406 cmd "[id=" . $F->id . "] floating disable";
407 cmd "workspace $tmp";
408 sync_with_i3;
409
410 $workspace = get_ws($tmp);
411 is($workspace->{nodes}->[1]->{nodes}->[1]->{nodes}->[1]->{nodes}->[1]->{window}, $F->id, 'F where D used to be');
412 is($x->input_focus, $D->id, 'D still focused');
413
414 kill_and_confirm_focus($F->id, 'F focused after D is killed');
415 kill_and_confirm_focus($C->id, 'C focused after F is killed');
416 kill_and_confirm_focus($B->id, 'B focused after C is killed');
417 kill_and_confirm_focus($A->id, 'A focused after B is killed');
418
419 done_testing;