]> git.sur5r.net Git - i3/i3/blob - testcases/t/529-net-wm-desktop.t
Handle the EWMH atom _NET_WM_DESKTOP.
[i3/i3] / testcases / t / 529-net-wm-desktop.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 for _NET_WM_DESKTOP.
18 # Ticket: #2153
19 use i3test i3_autostart => 0;
20 use X11::XCB qw(:all);
21
22 ###############################################################################
23
24 sub get_net_wm_desktop {
25     sync_with_i3;
26
27     my ($con) = @_; 
28     my $cookie = $x->get_property(
29         0,  
30         $con->{id},
31         $x->atom(name => '_NET_WM_DESKTOP')->id,
32         $x->atom(name => 'CARDINAL')->id,
33         0,  
34         1
35     );  
36
37     my $reply = $x->get_property_reply($cookie->{sequence});
38     return undef if $reply->{length} != 1;
39
40     return unpack("L", $reply->{value});
41 }
42
43 sub send_net_wm_desktop {
44     my ($con, $idx) = @_;
45     my $msg = pack "CCSLLLLLL",
46         X11::XCB::CLIENT_MESSAGE, 32, 0,
47         $con->{id},
48         $x->atom(name => '_NET_WM_DESKTOP')->id,
49         $idx, 0, 0, 0, 0;
50
51     $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg);
52     sync_with_i3;
53 }
54
55 sub open_window_with_net_wm_desktop {
56     my $idx = shift;
57     my $window = open_window(
58         before_map => sub {
59             my ($window) = @_;
60             $x->change_property(
61                 PROP_MODE_REPLACE,
62                 $window->id,
63                 $x->atom(name => '_NET_WM_DESKTOP')->id,
64                 $x->atom(name => 'CARDINAL')->id,
65                 32, 1,
66                 pack('L', $idx),
67             );
68         },
69     );
70
71     return $window;
72 }
73
74 # We need to kill all windows in between tests since they survive the i3 restart
75 # and will interfere with the following tests.
76 sub kill_windows {
77     sync_with_i3;
78     cmd '[title="Window.*"] kill';
79 }
80
81 ###############################################################################
82
83 my ($config, $config_mm, $pid, $con);
84
85 $config = <<EOT;
86 # i3 config file (v4)
87 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
88
89 bar {
90     status_command i3status
91 }
92 EOT
93
94 $config_mm = <<EOT;
95 # i3 config file (v4)
96 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
97
98 workspace "0" output "fake-0"
99 workspace "1" output "fake-0"
100 workspace "2" output "fake-0"
101 workspace "10" output "fake-1"
102 workspace "11" output "fake-1"
103 workspace "12" output "fake-1"
104
105 fake-outputs 1024x768+0+0,1024x768+1024+0
106 EOT
107
108 ###############################################################################
109 # Upon managing a window which does not set _NET_WM_DESKTOP, the property is
110 # set on the window.
111 ###############################################################################
112
113 $pid = launch_with_config($config);
114
115 cmd 'workspace 1';
116 $con = open_window;
117
118 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set upon managing a window');
119
120 kill_windows;
121 exit_gracefully($pid);
122
123 ###############################################################################
124 # Upon managing a window which sets _NET_WM_DESKTOP, the window is moved to
125 # the specified desktop.
126 ###############################################################################
127
128 $pid = launch_with_config($config);
129
130 cmd 'workspace 0';
131 open_window;
132 cmd 'workspace 1';
133 open_window;
134 cmd 'workspace 2';
135 open_window;
136
137 $con = open_window_with_net_wm_desktop(1);
138
139 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP still has the correct value');
140 is_num_children('1', 2, 'The window was moved to workspace 1');
141
142 kill_windows;
143 exit_gracefully($pid);
144
145 ###############################################################################
146 # Upon managing a window which sets _NET_WM_DESKTOP to the appropriate value,
147 # the window is made sticky and floating.
148 ###############################################################################
149
150 $pid = launch_with_config($config);
151
152 cmd 'workspace 0';
153 $con = open_window_with_net_wm_desktop(0xFFFFFFFF);
154
155 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP still has the correct value');
156 is(@{get_ws('0')->{floating_nodes}}, 1, 'The window is floating');
157 ok(get_ws('0')->{floating_nodes}->[0]->{nodes}->[0]->{sticky}, 'The window is sticky');
158
159 kill_windows;
160 exit_gracefully($pid);
161
162 ###############################################################################
163 # _NET_WM_DESKTOP is updated when the window is moved to another workspace
164 # on the same output.
165 ###############################################################################
166
167 $pid = launch_with_config($config);
168
169 cmd 'workspace 0';
170 open_window;
171 cmd 'workspace 1';
172 open_window;
173 cmd 'workspace 0';
174 $con = open_window;
175
176 cmd 'move window to workspace 1';
177
178 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
179
180 kill_windows;
181 exit_gracefully($pid);
182
183 ###############################################################################
184 # _NET_WM_DESKTOP is updated when the floating window is moved to another
185 # workspace on the same output.
186 ###############################################################################
187
188 $pid = launch_with_config($config);
189
190 cmd 'workspace 0';
191 open_window;
192 cmd 'workspace 1';
193 open_window;
194 cmd 'workspace 0';
195 $con = open_window;
196 cmd 'floating enable';
197
198 cmd 'move window to workspace 1';
199
200 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
201
202 kill_windows;
203 exit_gracefully($pid);
204
205 ###############################################################################
206 # _NET_WM_DESKTOP is updated when the window is moved to another workspace
207 # on another output.
208 ###############################################################################
209
210 $pid = launch_with_config($config_mm);
211
212 cmd 'workspace 0';
213 open_window;
214 cmd 'workspace 10';
215 open_window;
216 cmd 'workspace 0';
217 $con = open_window;
218
219 cmd 'move window to workspace 10';
220
221 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
222
223 kill_windows;
224 exit_gracefully($pid);
225
226 ###############################################################################
227 # _NET_WM_DESKTOP is removed when the window is withdrawn.
228 ###############################################################################
229
230 $pid = launch_with_config($config);
231
232 $con = open_window;
233 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set (sanity check)');
234
235 $con->unmap;
236 wait_for_unmap($con);
237
238 is(get_net_wm_desktop($con), undef, '_NET_WM_DESKTOP is removed');
239
240 kill_windows;
241 exit_gracefully($pid);
242
243 ###############################################################################
244 # A _NET_WM_DESKTOP client message sent to the root window moves a window
245 # to the correct workspace.
246 ###############################################################################
247
248 $pid = launch_with_config($config);
249
250 cmd 'workspace 0';
251 open_window;
252 cmd 'workspace 1';
253 open_window;
254 cmd 'workspace 0';
255
256 $con = open_window;
257 is_num_children('0', 2, 'The window is on workspace 0');
258
259 send_net_wm_desktop($con, 1);
260
261 is_num_children('0', 1, 'The window is no longer on workspace 0');
262 is_num_children('1', 2, 'The window is now on workspace 1');
263 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated');
264
265 kill_windows;
266 exit_gracefully($pid);
267
268 ###############################################################################
269 # A _NET_WM_DESKTOP client message sent to the root window can make a window
270 # sticky.
271 ###############################################################################
272
273 $pid = launch_with_config($config);
274
275 cmd 'workspace 0';
276 $con = open_window;
277
278 send_net_wm_desktop($con, 0xFFFFFFFF);
279
280 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
281 is(@{get_ws('0')->{floating_nodes}}, 1, 'The window is floating');
282 ok(get_ws('0')->{floating_nodes}->[0]->{nodes}->[0]->{sticky}, 'The window is sticky');
283
284 kill_windows;
285 exit_gracefully($pid);
286
287 ###############################################################################
288 # _NET_WM_DESKTOP is updated when a new workspace with a lower number is
289 # opened and closed.
290 ###############################################################################
291
292 $pid = launch_with_config($config);
293
294 cmd 'workspace 1';
295 $con = open_window;
296 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
297
298 cmd 'workspace 0';
299 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated');
300
301 kill_windows;
302 exit_gracefully($pid);
303
304 ###############################################################################
305 # _NET_WM_DESKTOP is updated when a window is made sticky by command.
306 ###############################################################################
307
308 $pid = launch_with_config($config);
309
310 cmd 'workspace 0';
311 $con = open_window;
312 cmd 'floating enable';
313 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
314
315 cmd 'sticky enable';
316 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
317
318 kill_windows;
319 exit_gracefully($pid);
320
321 ###############################################################################
322 # _NET_WM_DESKTOP is updated when a window is made sticky by client message.
323 ###############################################################################
324
325 $pid = launch_with_config($config);
326
327 cmd 'workspace 0';
328 $con = open_window;
329 cmd 'floating enable';
330 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
331
332 my $msg = pack "CCSLLLLLL",
333     X11::XCB::CLIENT_MESSAGE, 32, 0,
334     $con->{id},
335     $x->atom(name => '_NET_WM_STATE')->id,
336     1,
337     $x->atom(name => '_NET_WM_STATE_STICKY')->id,
338     0, 0, 0;
339
340 $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg);
341 sync_with_i3;
342
343 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
344
345 kill_windows;
346 exit_gracefully($pid);
347
348 ###############################################################################
349
350 done_testing;