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 $pid = launch_with_config($config);
37 ###############################################################################
38 # Invalid con_id should not crash i3
40 ###############################################################################
42 $ws = fresh_workspace;
45 cmd "swap container with con_id 1";
49 ###############################################################################
50 # Swap 2 windows in different workspaces using con_id
51 ###############################################################################
53 $ws = fresh_workspace;
55 $A = get_focused($ws);
57 $ws = fresh_workspace;
60 cmd "swap container with con_id $A";
61 is(get_focused($ws), $A, 'A is now focused');
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.
68 # +---+---+ Layout: H1[ A B ]
69 # | A | B | Focus Stacks:
71 ###############################################################################
72 $ws = fresh_workspace;
74 $A = open_window(wm_class => 'mark_A');
75 $B = open_window(wm_class => 'mark_B');
76 $expected_focus = get_focused($ws);
78 cmd '[con_mark=B] swap container with mark A';
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');
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.
90 # +---+---+ Layout: H1[ V1[ A Y ] V2[ X B ] ]
91 # | A | X | Focus Stacks:
92 # +---+---+ H1: V2, V1
95 ###############################################################################
96 $ws = fresh_workspace;
98 $A = open_window(wm_class => 'mark_A');
99 $B = open_window(wm_class => 'mark_B');
102 cmd 'move up, focus left';
105 cmd 'focus up, focus right, focus down';
106 $expected_focus = get_focused($ws);
108 cmd '[con_mark=B] swap container with mark A';
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');
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.
120 # +---+---+ Layout: H1[ V1[ A Y ] V2[ X B ] ]
121 # | A | X | Focus Stacks:
122 # +---+---+ H1: V2, V1
125 ###############################################################################
126 $ws = fresh_workspace;
128 $A = open_window(wm_class => 'mark_A');
129 $B = open_window(wm_class => 'mark_B');
132 cmd 'move up, focus left';
135 cmd 'focus right, focus down';
136 $expected_focus = get_focused($ws);
138 cmd '[con_mark=B] swap container with mark A';
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');
145 ###############################################################################
146 # Swap two containers with one being on a different workspace.
147 # The focused container is B.
149 # Layout: O1[ W1[ H1 ] W2[ H2 ] ]
153 # +---+---+ Layout: H1[ A X ]
154 # | A | X | Focus Stacks:
157 # +---+---+ Layout: H2[ Y, B ]
158 # | Y | B | Focus Stacks:
160 ###############################################################################
161 $ws1 = fresh_workspace;
162 $A = open_window(wm_class => 'mark_A');
163 $expected_focus = get_focused($ws1);
167 $ws2 = fresh_workspace;
169 $B = open_window(wm_class => 'mark_B');
171 cmd '[con_mark=B] swap container with mark A';
173 $nodes = get_ws_content($ws1);
174 is($nodes->[0]->{window}, $B->{id}, 'B is on ws1:left');
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');
180 ###############################################################################
181 # Swap two non-focused containers within the same workspace.
183 # +---+---+ Layout: H1[ V1[ A X ] V2[ F B ] ]
184 # | A | F | Focus Stacks:
185 # +---+---+ H1: V2, V1
188 ###############################################################################
189 $ws = fresh_workspace;
191 $A = open_window(wm_class => 'mark_A');
192 $B = open_window(wm_class => 'mark_B');
195 cmd 'move up, focus left';
198 cmd 'focus up, focus right';
199 $expected_focus = get_focused($ws);
201 cmd '[con_mark=B] swap container with mark A';
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');
208 ###############################################################################
209 # Swap two non-focused containers which are both on different workspaces.
211 # Layout: O1[ W1[ A ] W2[ B ] W3[ F ] ]
226 ###############################################################################
227 $ws1 = fresh_workspace;
228 $A = open_window(wm_class => 'mark_A');
230 $ws2 = fresh_workspace;
231 $B = open_window(wm_class => 'mark_B');
233 $ws3 = fresh_workspace;
235 $expected_focus = get_focused($ws3);
237 cmd '[con_mark=B] swap container with mark A';
239 $nodes = get_ws_content($ws1);
240 is($nodes->[0]->{window}, $B->{id}, 'B is on the first workspace');
242 $nodes = get_ws_content($ws2);
243 is($nodes->[0]->{window}, $A->{id}, 'A is on the second workspace');
245 is(get_focused($ws3), $expected_focus, 'F is still focused');
247 ###############################################################################
248 # Swap two non-focused containers with one being on a different workspace.
250 # Layout: O1[ W1[ A ] W2[ H2 ] ]
258 # +---+---+ Layout: H2[ B, F ]
259 # | B | F | Focus Stacks:
261 ###############################################################################
263 $ws1 = fresh_workspace;
264 $A = open_window(wm_class => 'mark_A');
266 $ws2 = fresh_workspace;
267 $B = open_window(wm_class => 'mark_B');
269 $expected_focus = get_focused($ws2);
271 cmd '[con_mark=B] swap container with mark A';
273 $nodes = get_ws_content($ws1);
274 is($nodes->[0]->{window}, $B->{id}, 'B is on the first workspace');
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');
280 ###############################################################################
281 # 1. A container cannot be swapped with its parent.
282 # 2. A container cannot be swapped with one of its children.
285 # +---+---+ Layout: H1[ X V1[ Y B ] ]
286 # | | Y | (with A := V1)
290 ###############################################################################
291 $ws = fresh_workspace;
295 $B = open_window(wm_class => 'mark_B');
296 cmd 'focus parent, mark A, focus child';
298 $result = cmd '[con_mark=B] swap container with mark A';
299 is($result->[0]->{success}, 0, 'B cannot be swappd with its parent');
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');
304 ###############################################################################
305 # Swapping two containers preserves the geometry of the container they are
306 # being swapped with.
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';
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');
328 cmd '[con_mark=B] swap container with mark A';
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');
334 ###############################################################################
335 # Swapping containers not sharing the same parent preserves the geometry of
336 # the container they are swapped with.
355 ###############################################################################
356 $ws = fresh_workspace;
358 $A = open_window(wm_class => 'mark_A');
359 $B = open_window(wm_class => 'mark_B');
362 cmd 'focus up, resize grow height 0 or 25 ppt';
363 cmd 'focus left, split v';
365 cmd 'resize grow height 0 or 25 ppt';
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');
372 cmd '[con_mark=B] swap container with mark A';
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');
378 ###############################################################################
379 # Swapping containers moves the urgency hint correctly.
380 ###############################################################################
382 $ws1 = fresh_workspace;
383 $A = open_window(wm_class => 'mark_A');
384 $ws2 = fresh_workspace;
385 $B = open_window(wm_class => 'mark_B');
388 $B->add_hint('urgency');
391 cmd '[con_mark=B] swap container with mark A';
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');
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');
401 ###############################################################################
403 exit_gracefully($pid);