]> git.sur5r.net Git - i3/i3/blob - testcases/t/291-swap.t
tests: use i3_config arg instead of precisely one launch_with_config
[i3/i3] / testcases / t / 291-swap.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 # Tests the swap command.
18 # Ticket: #917
19 use i3test i3_config => <<EOT;
20 # i3 config file (v4)
21 font font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
22
23 for_window[class="mark_A"] mark A
24 for_window[class="mark_B"] mark B
25 EOT
26
27 my ($ws, $ws1, $ws2, $ws3);
28 my ($nodes, $expected_focus, $A, $B, $F);
29 my ($result);
30 my @urgent;
31
32 ###############################################################################
33 # Invalid con_id should not crash i3
34 # See issue #2895.
35 ###############################################################################
36
37 $ws = fresh_workspace;
38
39 open_window;
40 cmd "swap container with con_id 1";
41
42 does_i3_live;
43 kill_all_windows;
44
45 ###############################################################################
46 # Swap 2 windows in different workspaces using con_id
47 ###############################################################################
48
49 $ws = fresh_workspace;
50 open_window;
51 $A = get_focused($ws);
52
53 $ws = fresh_workspace;
54 open_window;
55
56 cmd "swap container with con_id $A";
57 is(get_focused($ws), $A, 'A is now focused');
58
59 kill_all_windows;
60
61 ###############################################################################
62 # Swap two containers next to each other.
63 # Focus should stay on B because both windows are on the focused workspace.
64 # The focused container is B.
65 #
66 # +---+---+    Layout: H1[ A B ]
67 # | A | B |    Focus Stacks:
68 # +---+---+        H1: B, A
69 ###############################################################################
70 $ws = fresh_workspace;
71
72 $A = open_window(wm_class => 'mark_A');
73 $B = open_window(wm_class => 'mark_B');
74 $expected_focus = get_focused($ws);
75
76 cmd '[con_mark=B] swap container with mark A';
77
78 $nodes = get_ws_content($ws);
79 is($nodes->[0]->{window}, $B->{id}, 'B is on the left');
80 is($nodes->[1]->{window}, $A->{id}, 'A is on the right');
81 is(get_focused($ws), $expected_focus, 'B is still focused');
82
83 kill_all_windows;
84
85 ###############################################################################
86 # Swap two containers with different parents.
87 # In this test, the focus head of the left v-split container is A.
88 # The focused container is B.
89 #
90 # +---+---+    Layout: H1[ V1[ A Y ] V2[ X B ] ]
91 # | A | X |    Focus Stacks:
92 # +---+---+        H1: V2, V1
93 # | Y | B |        V1: A, Y
94 # +---+---+        V2: B, X
95 ###############################################################################
96 $ws = fresh_workspace;
97
98 $A = open_window(wm_class => 'mark_A');
99 $B = open_window(wm_class => 'mark_B');
100 cmd 'split v';
101 open_window;
102 cmd 'move up, focus left';
103 cmd 'split v';
104 open_window;
105 cmd 'focus up, focus right, focus down';
106 $expected_focus = get_focused($ws);
107
108 cmd '[con_mark=B] swap container with mark A';
109
110 $nodes = get_ws_content($ws);
111 is($nodes->[0]->{nodes}->[0]->{window}, $B->{id}, 'B is on the top left');
112 is($nodes->[1]->{nodes}->[1]->{window}, $A->{id}, 'A is on the bottom right');
113 is(get_focused($ws), $expected_focus, 'B is still focused');
114
115 kill_all_windows;
116
117 ###############################################################################
118 # Swap two containers with different parents.
119 # In this test, the focus head of the left v-split container is _not_ A.
120 # The focused container is B.
121 #
122 # +---+---+    Layout: H1[ V1[ A Y ] V2[ X B ] ]
123 # | A | X |    Focus Stacks:
124 # +---+---+        H1: V2, V1
125 # | Y | B |        V1: Y, A
126 # +---+---+        V2: B, X
127 ###############################################################################
128 $ws = fresh_workspace;
129
130 $A = open_window(wm_class => 'mark_A');
131 $B = open_window(wm_class => 'mark_B');
132 cmd 'split v';
133 open_window;
134 cmd 'move up, focus left';
135 cmd 'split v';
136 open_window;
137 cmd 'focus right, focus down';
138 $expected_focus = get_focused($ws);
139
140 cmd '[con_mark=B] swap container with mark A';
141
142 $nodes = get_ws_content($ws);
143 is($nodes->[0]->{nodes}->[0]->{window}, $B->{id}, 'B is on the top left');
144 is($nodes->[1]->{nodes}->[1]->{window}, $A->{id}, 'A is on the bottom right');
145 is(get_focused($ws), $expected_focus, 'B is still focused');
146
147 kill_all_windows;
148
149 ###############################################################################
150 # Swap two containers with one being on a different workspace.
151 # The focused container is B.
152 #
153 # Layout: O1[ W1[ H1 ] W2[ H2 ] ]
154 # Focus Stacks:
155 #     O1: W2, W1
156 #
157 # +---+---+    Layout: H1[ A X ]
158 # | A | X |    Focus Stacks:
159 # +---+---+        H1: A, X
160 #
161 # +---+---+    Layout: H2[ Y, B ]
162 # | Y | B |    Focus Stacks:
163 # +---+---+        H2: B, Y
164 ###############################################################################
165 $ws1 = fresh_workspace;
166 $A = open_window(wm_class => 'mark_A');
167 $expected_focus = get_focused($ws1);
168 open_window;
169 cmd 'focus left';
170
171 $ws2 = fresh_workspace;
172 open_window;
173 $B = open_window(wm_class => 'mark_B');
174
175 cmd '[con_mark=B] swap container with mark A';
176
177 $nodes = get_ws_content($ws1);
178 is($nodes->[0]->{window}, $B->{id}, 'B is on ws1:left');
179
180 $nodes = get_ws_content($ws2);
181 is($nodes->[1]->{window}, $A->{id}, 'A is on ws2:right');
182 is(get_focused($ws2), $expected_focus, 'A is focused');
183
184 kill_all_windows;
185
186 ###############################################################################
187 # Swap two non-focused containers within the same workspace.
188 #
189 # +---+---+    Layout: H1[ V1[ A X ] V2[ F B ] ]
190 # | A | F |    Focus Stacks:
191 # +---+---+        H1: V2, V1
192 # | X | B |        V1: A, X
193 # +---+---+        V2: F, B
194 ###############################################################################
195 $ws = fresh_workspace;
196
197 $A = open_window(wm_class => 'mark_A');
198 $B = open_window(wm_class => 'mark_B');
199 cmd 'split v';
200 open_window;
201 cmd 'move up, focus left';
202 cmd 'split v';
203 open_window;
204 cmd 'focus up, focus right';
205 $expected_focus = get_focused($ws);
206
207 cmd '[con_mark=B] swap container with mark A';
208
209 $nodes = get_ws_content($ws);
210 is($nodes->[0]->{nodes}->[0]->{window}, $B->{id}, 'B is on the top left');
211 is($nodes->[1]->{nodes}->[1]->{window}, $A->{id}, 'A is on the bottom right');
212 is(get_focused($ws), $expected_focus, 'F is still focused');
213
214 kill_all_windows;
215
216 ###############################################################################
217 # Swap two non-focused containers which are both on different workspaces.
218 #
219 # Layout: O1[ W1[ A ] W2[ B ] W3[ F ] ]
220 # Focus Stacks:
221 #     O1: W3, W2, W1
222 #
223 # +---+
224 # | A |
225 # +---+
226 #
227 # +---+
228 # | B |
229 # +---+
230 #
231 # +---+
232 # | F |
233 # +---+
234 ###############################################################################
235 $ws1 = fresh_workspace;
236 $A = open_window(wm_class => 'mark_A');
237
238 $ws2 = fresh_workspace;
239 $B = open_window(wm_class => 'mark_B');
240
241 $ws3 = fresh_workspace;
242 open_window;
243 $expected_focus = get_focused($ws3);
244
245 cmd '[con_mark=B] swap container with mark A';
246
247 $nodes = get_ws_content($ws1);
248 is($nodes->[0]->{window}, $B->{id}, 'B is on the first workspace');
249
250 $nodes = get_ws_content($ws2);
251 is($nodes->[0]->{window}, $A->{id}, 'A is on the second workspace');
252
253 is(get_focused($ws3), $expected_focus, 'F is still focused');
254
255 kill_all_windows;
256
257 ###############################################################################
258 # Swap two non-focused containers with one being on a different workspace.
259 #
260 # Layout: O1[ W1[ A ] W2[ H2 ] ]
261 # Focus Stacks:
262 #     O1: W2, W1
263 #
264 # +---+
265 # | A |
266 # +---+
267 #
268 # +---+---+    Layout: H2[ B, F ]
269 # | B | F |    Focus Stacks:
270 # +---+---+        H2: F, B
271 ###############################################################################
272
273 $ws1 = fresh_workspace;
274 $A = open_window(wm_class => 'mark_A');
275
276 $ws2 = fresh_workspace;
277 $B = open_window(wm_class => 'mark_B');
278 open_window;
279 $expected_focus = get_focused($ws2);
280
281 cmd '[con_mark=B] swap container with mark A';
282
283 $nodes = get_ws_content($ws1);
284 is($nodes->[0]->{window}, $B->{id}, 'B is on the first workspace');
285
286 $nodes = get_ws_content($ws2);
287 is($nodes->[0]->{window}, $A->{id}, 'A is on the left of the second workspace');
288 is(get_focused($ws2), $expected_focus, 'F is still focused');
289
290 kill_all_windows;
291
292 ###############################################################################
293 # 1. A container cannot be swapped with its parent.
294 # 2. A container cannot be swapped with one of its children.
295 #
296 #      ↓A↓
297 # +---+---+    Layout: H1[ X V1[ Y B ] ]
298 # |   | Y |        (with A := V1)
299 # | X +---+
300 # |   | B |
301 # +---+---+
302 ###############################################################################
303 $ws = fresh_workspace;
304 open_window;
305 open_window;
306 cmd 'split v';
307 $B = open_window(wm_class => 'mark_B');
308 cmd 'focus parent, mark A, focus child';
309
310 $result = cmd '[con_mark=B] swap container with mark A';
311 is($result->[0]->{success}, 0, 'B cannot be swappd with its parent');
312
313 $result = cmd '[con_mark=A] swap container with mark B';
314 is($result->[0]->{success}, 0, 'A cannot be swappd with one of its children');
315
316 kill_all_windows;
317
318 ###############################################################################
319 # Swapping two containers preserves the geometry of the container they are
320 # being swapped with.
321 #
322 # Before:
323 # +---+-------+
324 # | A |   B   |
325 # +---+-------+
326 #
327 # After:
328 # +---+-------+
329 # | B |   A   |
330 # +---+-------+
331 ###############################################################################
332 $ws = fresh_workspace;
333 $A = open_window(wm_class => 'mark_A');
334 $B = open_window(wm_class => 'mark_B');
335 cmd 'resize grow width 0 or 25 ppt';
336
337 # sanity checks
338 $nodes = get_ws_content($ws);
339 cmp_float($nodes->[0]->{percent}, 0.25, 'A has 25% width');
340 cmp_float($nodes->[1]->{percent}, 0.75, 'B has 75% width');
341
342 cmd '[con_mark=B] swap container with mark A';
343
344 $nodes = get_ws_content($ws);
345 cmp_float($nodes->[0]->{percent}, 0.25, 'B has 25% width');
346 cmp_float($nodes->[1]->{percent}, 0.75, 'A has 75% width');
347
348 kill_all_windows;
349
350 ###############################################################################
351 # Swapping containers not sharing the same parent preserves the geometry of
352 # the container they are swapped with.
353 #
354 # Before:
355 # +---+-----+
356 # | A |     |
357 # +---+  B  |
358 # |   |     |
359 # | Y +-----+
360 # |   |  X  |
361 # +---+-----+
362 #
363 # After:
364 # +---+-----+
365 # | B |     |
366 # +---+  A  |
367 # |   |     |
368 # | Y +-----+
369 # |   |  X  |
370 # +---+-----+
371 ###############################################################################
372 $ws = fresh_workspace;
373
374 $A = open_window(wm_class => 'mark_A');
375 $B = open_window(wm_class => 'mark_B');
376 cmd 'split v';
377 open_window;
378 cmd 'focus up, resize grow height 0 or 25 ppt';
379 cmd 'focus left, split v';
380 open_window;
381 cmd 'resize grow height 0 or 25 ppt';
382
383 # sanity checks
384 $nodes = get_ws_content($ws);
385 cmp_float($nodes->[0]->{nodes}->[0]->{percent}, 0.25, 'A has 25% height');
386 cmp_float($nodes->[1]->{nodes}->[0]->{percent}, 0.75, 'B has 75% height');
387
388 cmd '[con_mark=B] swap container with mark A';
389
390 $nodes = get_ws_content($ws);
391 cmp_float($nodes->[0]->{nodes}->[0]->{percent}, 0.25, 'B has 25% height');
392 cmp_float($nodes->[1]->{nodes}->[0]->{percent}, 0.75, 'A has 75% height');
393
394 kill_all_windows;
395
396 ###############################################################################
397 # Swapping containers moves the urgency hint correctly.
398 ###############################################################################
399
400 $ws1 = fresh_workspace;
401 $A = open_window(wm_class => 'mark_A');
402 $ws2 = fresh_workspace;
403 $B = open_window(wm_class => 'mark_B');
404 open_window;
405
406 $B->add_hint('urgency');
407 sync_with_i3;
408
409 cmd '[con_mark=B] swap container with mark A';
410
411 @urgent = grep { $_->{urgent} } @{get_ws_content($ws1)};
412 is(@urgent, 1, 'B is marked urgent');
413 is(get_ws($ws1)->{urgent}, 1, 'the first workspace is marked urgent');
414
415 @urgent = grep { $_->{urgent} } @{get_ws_content($ws2)};
416 is(@urgent, 0, 'A is not marked urgent');
417 is(get_ws($ws2)->{urgent}, 0, 'the second workspace is not marked urgent');
418
419 kill_all_windows;
420
421 ###############################################################################
422
423 done_testing;