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