]> git.sur5r.net Git - i3/i3/blob - testcases/t/132-move-workspace.t
Implement moving workspaces as if they're regular containers
[i3/i3] / testcases / t / 132-move-workspace.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 # Checks if the 'move [window/container] to workspace' command works correctly
18 #
19 use i3test;
20
21 my $i3 = i3(get_socket_path());
22
23 # We move the pointer out of our way to avoid a bug where the focus will
24 # be set to the window under the cursor
25 $x->root->warp_pointer(0, 0);
26
27 sub move_workspace_test {
28     my ($movecmd) = @_;
29
30     my $tmp = get_unused_workspace();
31     my $tmp2 = get_unused_workspace();
32     cmd "workspace $tmp";
33
34     is_num_children($tmp, 0, 'no containers yet');
35
36     my $first = open_empty_con($i3);
37     my $second = open_empty_con($i3);
38     is_num_children($tmp, 2, 'two containers on first ws');
39
40     cmd "workspace $tmp2";
41     is_num_children($tmp2, 0, 'no containers on second ws yet');
42
43     cmd "workspace $tmp";
44
45     cmd "$movecmd $tmp2";
46     is_num_children($tmp, 1, 'one container on first ws anymore');
47     is_num_children($tmp2, 1, 'one container on second ws');
48     my ($nodes, $focus) = get_ws_content($tmp2);
49
50     is($focus->[0], $second, 'same container on different ws');
51
52     ($nodes, $focus) = get_ws_content($tmp);
53     ok($nodes->[0]->{focused}, 'first container focused on first ws');
54 }
55
56 move_workspace_test('move workspace');  # supported for legacy reasons
57 move_workspace_test('move to workspace');
58 # Those are just synonyms and more verbose ways of saying the same thing:
59 move_workspace_test('move window to workspace');
60 move_workspace_test('move container to workspace');
61
62 ################################################################################
63 # Check that 'move to workspace number <number>' works to move a window to
64 # named workspaces which start with <number>.
65 ################################################################################
66
67 cmd 'workspace 13: meh';
68 cmd 'open';
69 is_num_children('13: meh', 1, 'one container on 13: meh');
70
71 ok(!workspace_exists('13'), 'workspace 13 does not exist yet');
72
73 cmd 'workspace 12';
74 cmd 'open';
75
76 cmd 'move to workspace number 13';
77 is_num_children('13: meh', 2, 'one container on 13: meh');
78 is_num_children('12', 0, 'no container on 12 anymore');
79
80 ok(!workspace_exists('13'), 'workspace 13 does still not exist');
81
82 ################################################################################
83 # Check that 'move to workspace number <number><name>' works to move a window to
84 # named workspaces which start with <number>.
85 ################################################################################
86
87 cmd 'workspace 15: meh';
88 cmd 'open';
89 is_num_children('15: meh', 1, 'one container on 15: meh');
90
91 ok(!workspace_exists('15'), 'workspace 15 does not exist yet');
92 ok(!workspace_exists('15: duh'), 'workspace 15: duh does not exist yet');
93
94 cmd 'workspace 14';
95 cmd 'open';
96
97 cmd 'move to workspace number 15: duh';
98 is_num_children('15: meh', 2, 'two containers on 15: meh');
99 is_num_children('14', 0, 'no container on 14 anymore');
100
101 ok(!workspace_exists('15'), 'workspace 15 does still not exist');
102 ok(!workspace_exists('15: duh'), 'workspace 15 does still not exist');
103
104 ###################################################################
105 # check if 'move workspace next' and 'move workspace prev' work
106 ###################################################################
107
108 # Open two containers on the first workspace, one container on the second
109 # workspace. Because the workspaces are named, they will be sorted by order of
110 # creation.
111 my $tmp = get_unused_workspace();
112 my $tmp2 = get_unused_workspace();
113 cmd "workspace $tmp";
114 is_num_children($tmp, 0, 'no containers yet');
115 my $first = open_empty_con($i3);
116 my $second = open_empty_con($i3);
117 is_num_children($tmp, 2, 'two containers');
118
119 cmd "workspace $tmp2";
120 is_num_children($tmp2, 0, 'no containers yet');
121 my $third = open_empty_con($i3);
122 is_num_children($tmp2, 1, 'one container on second ws');
123
124 # go back to the first workspace, move one of the containers to the next one
125 cmd "workspace $tmp";
126 cmd 'move workspace next';
127 is_num_children($tmp, 1, 'one container on first ws');
128 is_num_children($tmp2, 2, 'two containers on second ws');
129
130 # go to the second workspace and move two containers to the first one
131 cmd "workspace $tmp2";
132 cmd 'move workspace prev';
133 cmd 'move workspace prev';
134 is_num_children($tmp, 3, 'three containers on first ws');
135 is_num_children($tmp2, 0, 'no containers on second ws');
136
137 ###################################################################
138 # check if 'move workspace current' works
139 ###################################################################
140
141 $tmp = get_unused_workspace();
142 $tmp2 = get_unused_workspace();
143
144 cmd "workspace $tmp";
145 $first = open_window(name => 'win-name');
146 is_num_children($tmp, 1, 'one container on first ws');
147
148 cmd "workspace $tmp2";
149 is_num_children($tmp2, 0, 'no containers yet');
150
151 cmd qq|[title="win-name"] move workspace $tmp2|;
152 is_num_children($tmp2, 1, 'one container on second ws');
153
154 cmd qq|[title="win-name"] move workspace $tmp|;
155 is_num_children($tmp2, 0, 'no containers on second ws');
156
157 ###################################################################
158 # check if floating cons are moved to new workspaces properly
159 # (that is, if they are floating on the target ws, too)
160 ###################################################################
161
162 $tmp = get_unused_workspace();
163 $tmp2 = get_unused_workspace();
164 cmd "workspace $tmp";
165
166 cmd "open";
167 cmd "floating toggle";
168
169 my $ws = get_ws($tmp);
170 is(@{$ws->{nodes}}, 0, 'no nodes on workspace');
171 is(@{$ws->{floating_nodes}}, 1, 'one floating node on workspace');
172
173 cmd "move workspace $tmp2";
174
175 $ws = get_ws($tmp2);
176 is(@{$ws->{nodes}}, 0, 'no nodes on workspace');
177 is(@{$ws->{floating_nodes}}, 1, 'one floating node on workspace');
178
179 ################################################################################
180 # Check that 'move workspace number' works correctly.
181 ################################################################################
182
183 $tmp = get_unused_workspace();
184 cmd 'open';
185
186 cmd 'workspace 16';
187 cmd 'open';
188 is_num_children('16', 1, 'one node on ws 16');
189
190 cmd "workspace $tmp";
191 cmd 'open';
192 cmd 'move workspace number 16';
193 is_num_children('16', 2, 'two nodes on ws 16');
194
195 ok(!workspace_exists('17'), 'workspace 17 does not exist yet');
196 cmd 'open';
197 cmd 'move workspace number 17';
198 ok(workspace_exists('17'), 'workspace 17 created by moving');
199 is(@{get_ws('17')->{nodes}}, 1, 'one node on ws 16');
200
201 ################################################################################
202 # The following four tests verify the various 'move workspace' commands when
203 # the selection is itself a workspace.
204 ################################################################################
205
206 # borrowed from 122-split.t
207 # recursively sums up all nodes and their children
208 sub sum_nodes {
209     my ($nodes) = @_;
210
211     return 0 if !@{$nodes};
212
213     my @children = (map { @{$_->{nodes}} } @{$nodes},
214                     map { @{$_->{'floating_nodes'}} } @{$nodes});
215
216     return @{$nodes} + sum_nodes(\@children);
217 }
218
219 ############################################################
220 # move workspace 'next|prev'
221 ############################################################
222 $tmp = get_unused_workspace();
223 $tmp2 = get_unused_workspace();
224
225 cmd "workspace $tmp";
226 cmd 'open';
227 is_num_children($tmp, 1, 'one container on first ws');
228
229 cmd "workspace $tmp2";
230 cmd 'open';
231 is_num_children($tmp2, 1, 'one container on second ws');
232 cmd 'open';
233 is_num_children($tmp2, 2, 'two containers on second ws');
234
235 cmd 'focus parent';
236 cmd 'move workspace prev';
237
238 is_num_children($tmp, 2, 'two child containers on first ws');
239 is(sum_nodes(get_ws_content($tmp)), 4, 'four total containers on first ws');
240 is_num_children($tmp2, 0, 'no containers on second ws');
241
242 ############################################################
243 # move workspace current
244 # This is a special case that should be a no-op.
245 ############################################################
246 $tmp = fresh_workspace();
247
248 cmd 'open';
249 is_num_children($tmp, 1, 'one container on first ws');
250 my $tmpcount = sum_nodes(get_ws_content($tmp));
251
252 cmd 'focus parent';
253 cmd "move workspace $tmp";
254
255 is(sum_nodes(get_ws_content($tmp)), $tmpcount, 'number of containers in first ws unchanged');
256
257 ############################################################
258 # move workspace '<name>'
259 ############################################################
260 $tmp2 = get_unused_workspace();
261 $tmp = fresh_workspace();
262
263 cmd 'open';
264 is_num_children($tmp, 1, 'one container on first ws');
265
266 cmd "workspace $tmp2";
267 cmd 'open';
268 is_num_children($tmp2, 1, 'one container on second ws');
269 cmd 'open';
270 is_num_children($tmp2, 2, 'two containers on second ws');
271
272 cmd 'focus parent';
273 cmd "move workspace $tmp";
274
275 is_num_children($tmp, 2, 'two child containers on first ws');
276 is(sum_nodes(get_ws_content($tmp)), 4, 'four total containers on first ws');
277 is_num_children($tmp2, 0, 'no containers on second ws');
278
279 ############################################################
280 # move workspace number '<number>'
281 ############################################################
282 cmd 'workspace 18';
283 cmd 'open';
284 is_num_children('18', 1, 'one container on ws 18');
285
286 cmd 'workspace 19';
287 cmd 'open';
288 is_num_children('19', 1, 'one container on ws 19');
289 cmd 'open';
290 is_num_children('19', 2, 'two containers on ws 19');
291
292 cmd 'focus parent';
293 cmd 'move workspace number 18';
294
295 is_num_children('18', 2, 'two child containers on ws 18');
296 is(sum_nodes(get_ws_content('18')), 4, 'four total containers on ws 18');
297 is_num_children('19', 0, 'no containers on ws 19');
298
299 ###################################################################
300 # move workspace '<name>' with a floating child
301 ###################################################################
302 $tmp2 = get_unused_workspace();
303 $tmp = fresh_workspace();
304 cmd 'open';
305 cmd 'floating toggle';
306 cmd 'open';
307 cmd 'floating toggle';
308 cmd 'open';
309
310 $ws = get_ws($tmp);
311 is_num_children($tmp, 1, 'one container on first workspace');
312 is(@{$ws->{floating_nodes}}, 2, 'two floating nodes on first workspace');
313
314 cmd 'focus parent';
315 cmd "move workspace $tmp2";
316
317 $ws = get_ws($tmp2);
318 is_num_children($tmp2, 1, 'one container on second workspace');
319 is(@{$ws->{floating_nodes}}, 2, 'two floating nodes on second workspace');
320
321 done_testing;