2 # vim:ts=4:sw=4:expandtab
4 # Please read the following documents before working on tests:
5 # • http://build.i3wm.org/docs/testsuite.html
8 # • http://build.i3wm.org/docs/lib-i3test.html
9 # (alternatively: perldoc ./testcases/lib/i3test.pm)
11 # • http://build.i3wm.org/docs/ipc.html
14 # • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
15 # (unless you are already familiar with Perl)
17 # Tests the swap command.
19 use i3test i3_autostart => 0;
23 font font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
25 for_window[class="mark_A"] mark A
26 for_window[class="mark_B"] mark B
30 my ($ws, $ws1, $ws2, $ws3);
31 my ($nodes, $expected_focus, $A, $B, $F);
35 ###############################################################################
36 # Invalid con_id should not crash i3
38 ###############################################################################
40 $pid = launch_with_config($config);
41 $ws = fresh_workspace;
44 cmd "swap container with con_id 1";
47 exit_gracefully($pid);
49 ###############################################################################
50 # Swap 2 windows in different workspaces using con_id
51 ###############################################################################
53 $pid = launch_with_config($config);
55 $ws = fresh_workspace;
57 $A = get_focused($ws);
59 $ws = fresh_workspace;
62 cmd "swap container with con_id $A";
63 is(get_focused($ws), $A, 'A is now focused');
65 exit_gracefully($pid);
67 ###############################################################################
68 # Swap two containers next to each other.
69 # Focus should stay on B because both windows are on the focused workspace.
70 # The focused container is B.
72 # +---+---+ Layout: H1[ A B ]
73 # | A | B | Focus Stacks:
75 ###############################################################################
76 $pid = launch_with_config($config);
77 $ws = fresh_workspace;
79 $A = open_window(wm_class => 'mark_A');
80 $B = open_window(wm_class => 'mark_B');
81 $expected_focus = get_focused($ws);
83 cmd '[con_mark=B] swap container with mark A';
85 $nodes = get_ws_content($ws);
86 is($nodes->[0]->{window}, $B->{id}, 'B is on the left');
87 is($nodes->[1]->{window}, $A->{id}, 'A is on the right');
88 is(get_focused($ws), $expected_focus, 'B is still focused');
90 exit_gracefully($pid);
92 ###############################################################################
93 # Swap two containers with different parents.
94 # In this test, the focus head of the left v-split container is A.
95 # The focused container is B.
97 # +---+---+ Layout: H1[ V1[ A Y ] V2[ X B ] ]
98 # | A | X | Focus Stacks:
99 # +---+---+ H1: V2, V1
102 ###############################################################################
103 $pid = launch_with_config($config);
104 $ws = fresh_workspace;
106 $A = open_window(wm_class => 'mark_A');
107 $B = open_window(wm_class => 'mark_B');
110 cmd 'move up, focus left';
113 cmd 'focus up, focus right, focus down';
114 $expected_focus = get_focused($ws);
116 cmd '[con_mark=B] swap container with mark A';
118 $nodes = get_ws_content($ws);
119 is($nodes->[0]->{nodes}->[0]->{window}, $B->{id}, 'B is on the top left');
120 is($nodes->[1]->{nodes}->[1]->{window}, $A->{id}, 'A is on the bottom right');
121 is(get_focused($ws), $expected_focus, 'B is still focused');
123 exit_gracefully($pid);
125 ###############################################################################
126 # Swap two containers with different parents.
127 # In this test, the focus head of the left v-split container is _not_ A.
128 # The focused container is B.
130 # +---+---+ Layout: H1[ V1[ A Y ] V2[ X B ] ]
131 # | A | X | Focus Stacks:
132 # +---+---+ H1: V2, V1
135 ###############################################################################
136 $pid = launch_with_config($config);
137 $ws = fresh_workspace;
139 $A = open_window(wm_class => 'mark_A');
140 $B = open_window(wm_class => 'mark_B');
143 cmd 'move up, focus left';
146 cmd 'focus right, focus down';
147 $expected_focus = get_focused($ws);
149 cmd '[con_mark=B] swap container with mark A';
151 $nodes = get_ws_content($ws);
152 is($nodes->[0]->{nodes}->[0]->{window}, $B->{id}, 'B is on the top left');
153 is($nodes->[1]->{nodes}->[1]->{window}, $A->{id}, 'A is on the bottom right');
154 is(get_focused($ws), $expected_focus, 'B is still focused');
156 exit_gracefully($pid);
158 ###############################################################################
159 # Swap two containers with one being on a different workspace.
160 # The focused container is B.
162 # Layout: O1[ W1[ H1 ] W2[ H2 ] ]
166 # +---+---+ Layout: H1[ A X ]
167 # | A | X | Focus Stacks:
170 # +---+---+ Layout: H2[ Y, B ]
171 # | Y | B | Focus Stacks:
173 ###############################################################################
174 $pid = launch_with_config($config);
176 $ws1 = fresh_workspace;
177 $A = open_window(wm_class => 'mark_A');
178 $expected_focus = get_focused($ws1);
182 $ws2 = fresh_workspace;
184 $B = open_window(wm_class => 'mark_B');
186 cmd '[con_mark=B] swap container with mark A';
188 $nodes = get_ws_content($ws1);
189 is($nodes->[0]->{window}, $B->{id}, 'B is on ws1:left');
191 $nodes = get_ws_content($ws2);
192 is($nodes->[1]->{window}, $A->{id}, 'A is on ws2:right');
193 is(get_focused($ws2), $expected_focus, 'A is focused');
195 exit_gracefully($pid);
197 ###############################################################################
198 # Swap two non-focused containers within the same workspace.
200 # +---+---+ Layout: H1[ V1[ A X ] V2[ F B ] ]
201 # | A | F | Focus Stacks:
202 # +---+---+ H1: V2, V1
205 ###############################################################################
206 $pid = launch_with_config($config);
207 $ws = fresh_workspace;
209 $A = open_window(wm_class => 'mark_A');
210 $B = open_window(wm_class => 'mark_B');
213 cmd 'move up, focus left';
216 cmd 'focus up, focus right';
217 $expected_focus = get_focused($ws);
219 cmd '[con_mark=B] swap container with mark A';
221 $nodes = get_ws_content($ws);
222 is($nodes->[0]->{nodes}->[0]->{window}, $B->{id}, 'B is on the top left');
223 is($nodes->[1]->{nodes}->[1]->{window}, $A->{id}, 'A is on the bottom right');
224 is(get_focused($ws), $expected_focus, 'F is still focused');
226 exit_gracefully($pid);
228 ###############################################################################
229 # Swap two non-focused containers which are both on different workspaces.
231 # Layout: O1[ W1[ A ] W2[ B ] W3[ F ] ]
246 ###############################################################################
247 $pid = launch_with_config($config);
249 $ws1 = fresh_workspace;
250 $A = open_window(wm_class => 'mark_A');
252 $ws2 = fresh_workspace;
253 $B = open_window(wm_class => 'mark_B');
255 $ws3 = fresh_workspace;
257 $expected_focus = get_focused($ws3);
259 cmd '[con_mark=B] swap container with mark A';
261 $nodes = get_ws_content($ws1);
262 is($nodes->[0]->{window}, $B->{id}, 'B is on the first workspace');
264 $nodes = get_ws_content($ws2);
265 is($nodes->[0]->{window}, $A->{id}, 'A is on the second workspace');
267 is(get_focused($ws3), $expected_focus, 'F is still focused');
269 exit_gracefully($pid);
271 ###############################################################################
272 # Swap two non-focused containers with one being on a different workspace.
274 # Layout: O1[ W1[ A ] W2[ H2 ] ]
282 # +---+---+ Layout: H2[ B, F ]
283 # | B | F | Focus Stacks:
285 ###############################################################################
286 $pid = launch_with_config($config);
288 $ws1 = fresh_workspace;
289 $A = open_window(wm_class => 'mark_A');
291 $ws2 = fresh_workspace;
292 $B = open_window(wm_class => 'mark_B');
294 $expected_focus = get_focused($ws2);
296 cmd '[con_mark=B] swap container with mark A';
298 $nodes = get_ws_content($ws1);
299 is($nodes->[0]->{window}, $B->{id}, 'B is on the first workspace');
301 $nodes = get_ws_content($ws2);
302 is($nodes->[0]->{window}, $A->{id}, 'A is on the left of the second workspace');
303 is(get_focused($ws2), $expected_focus, 'F is still focused');
305 exit_gracefully($pid);
307 ###############################################################################
308 # 1. A container cannot be swapped with its parent.
309 # 2. A container cannot be swapped with one of its children.
312 # +---+---+ Layout: H1[ X V1[ Y B ] ]
313 # | | Y | (with A := V1)
317 ###############################################################################
318 $pid = launch_with_config($config);
320 $ws = fresh_workspace;
324 $B = open_window(wm_class => 'mark_B');
325 cmd 'focus parent, mark A, focus child';
327 $result = cmd '[con_mark=B] swap container with mark A';
328 is($result->[0]->{success}, 0, 'B cannot be swappd with its parent');
330 $result = cmd '[con_mark=A] swap container with mark B';
331 is($result->[0]->{success}, 0, 'A cannot be swappd with one of its children');
333 exit_gracefully($pid);
335 ###############################################################################
336 # Swapping two containers preserves the geometry of the container they are
337 # being swapped with.
348 ###############################################################################
349 $pid = launch_with_config($config);
351 $ws = fresh_workspace;
352 $A = open_window(wm_class => 'mark_A');
353 $B = open_window(wm_class => 'mark_B');
354 cmd 'resize grow width 0 or 25 ppt';
357 $nodes = get_ws_content($ws);
358 cmp_float($nodes->[0]->{percent}, 0.25, 'A has 25% width');
359 cmp_float($nodes->[1]->{percent}, 0.75, 'B has 75% width');
361 cmd '[con_mark=B] swap container with mark A';
363 $nodes = get_ws_content($ws);
364 cmp_float($nodes->[0]->{percent}, 0.25, 'B has 25% width');
365 cmp_float($nodes->[1]->{percent}, 0.75, 'A has 75% width');
367 exit_gracefully($pid);
369 ###############################################################################
370 # Swapping containers not sharing the same parent preserves the geometry of
371 # the container they are swapped with.
390 ###############################################################################
391 $pid = launch_with_config($config);
392 $ws = fresh_workspace;
394 $A = open_window(wm_class => 'mark_A');
395 $B = open_window(wm_class => 'mark_B');
398 cmd 'focus up, resize grow height 0 or 25 ppt';
399 cmd 'focus left, split v';
401 cmd 'resize grow height 0 or 25 ppt';
404 $nodes = get_ws_content($ws);
405 cmp_float($nodes->[0]->{nodes}->[0]->{percent}, 0.25, 'A has 25% height');
406 cmp_float($nodes->[1]->{nodes}->[0]->{percent}, 0.75, 'B has 75% height');
408 cmd '[con_mark=B] swap container with mark A';
410 $nodes = get_ws_content($ws);
411 cmp_float($nodes->[0]->{nodes}->[0]->{percent}, 0.25, 'B has 25% height');
412 cmp_float($nodes->[1]->{nodes}->[0]->{percent}, 0.75, 'A has 75% height');
414 exit_gracefully($pid);
416 ###############################################################################
417 # Swapping containers moves the urgency hint correctly.
418 ###############################################################################
419 $pid = launch_with_config($config);
421 $ws1 = fresh_workspace;
422 $A = open_window(wm_class => 'mark_A');
423 $ws2 = fresh_workspace;
424 $B = open_window(wm_class => 'mark_B');
427 $B->add_hint('urgency');
430 cmd '[con_mark=B] swap container with mark A';
432 @urgent = grep { $_->{urgent} } @{get_ws_content($ws1)};
433 is(@urgent, 1, 'B is marked urgent');
434 is(get_ws($ws1)->{urgent}, 1, 'the first workspace is marked urgent');
436 @urgent = grep { $_->{urgent} } @{get_ws_content($ws2)};
437 is(@urgent, 0, 'A is not marked urgent');
438 is(get_ws($ws2)->{urgent}, 0, 'the second workspace is not marked urgent');
440 exit_gracefully($pid);
442 ###############################################################################