]> git.sur5r.net Git - i3/i3/blob - testcases/t/529-net-wm-desktop.t
42b488d952efc886b89c9cfb20741846d66848bb
[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         dont_map => 1,
70     );
71
72     # We don’t wait for MapNotify and instead sync with i3 so that we don’t need
73     # to encounter the full timeout of 4s when opening a window on a non-visible
74     # workspace.
75     $window->map;
76     sync_with_i3;
77
78     return $window;
79 }
80
81 # We need to kill all windows in between tests since they survive the i3 restart
82 # and will interfere with the following tests.
83 sub kill_windows {
84     sync_with_i3;
85     cmd '[title="Window.*"] kill';
86 }
87
88 ###############################################################################
89
90 my $config = <<EOT;
91 # i3 config file (v4)
92 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
93
94 bar {
95     status_command i3status
96 }
97 EOT
98
99 my $pid = launch_with_config($config);
100
101 ###############################################################################
102 # Upon managing a window which does not set _NET_WM_DESKTOP, the property is
103 # set on the window.
104 ###############################################################################
105
106 cmd 'workspace 1';
107 my $con = open_window;
108
109 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set upon managing a window');
110
111 kill_windows;
112
113 ###############################################################################
114 # Upon managing a window which sets _NET_WM_DESKTOP, the window is moved to
115 # the specified desktop.
116 ###############################################################################
117
118 cmd 'workspace 0';
119 open_window;
120 cmd 'workspace 1';
121 open_window;
122 cmd 'workspace 2';
123 open_window;
124
125 $con = open_window_with_net_wm_desktop(1);
126
127 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP still has the correct value');
128 is_num_children('1', 2, 'The window was moved to workspace 1');
129
130 kill_windows;
131
132 ###############################################################################
133 # Upon managing a window which sets _NET_WM_DESKTOP to the appropriate value,
134 # the window is made sticky and floating.
135 ###############################################################################
136
137 cmd 'workspace 0';
138 $con = open_window_with_net_wm_desktop(0xFFFFFFFF);
139
140 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP still has the correct value');
141 is(@{get_ws('0')->{floating_nodes}}, 1, 'The window is floating');
142 ok(get_ws('0')->{floating_nodes}->[0]->{nodes}->[0]->{sticky}, 'The window is sticky');
143
144 kill_windows;
145
146 ###############################################################################
147 # _NET_WM_DESKTOP is updated when the window is moved to another workspace
148 # on the same output.
149 ###############################################################################
150
151 cmd 'workspace 0';
152 open_window;
153 cmd 'workspace 1';
154 open_window;
155 cmd 'workspace 0';
156 $con = open_window;
157
158 cmd 'move window to workspace 1';
159
160 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
161
162 kill_windows;
163
164 ###############################################################################
165 # _NET_WM_DESKTOP is updated when the floating window is moved to another
166 # workspace on the same output.
167 ###############################################################################
168
169 cmd 'workspace 0';
170 open_window;
171 cmd 'workspace 1';
172 open_window;
173 cmd 'workspace 0';
174 $con = open_window;
175 cmd 'floating enable';
176
177 cmd 'move window to workspace 1';
178
179 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
180
181 kill_windows;
182
183 ###############################################################################
184 # _NET_WM_DESKTOP is removed when the window is withdrawn.
185 ###############################################################################
186
187 $con = open_window;
188 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set (sanity check)');
189
190 $con->unmap;
191 wait_for_unmap($con);
192
193 is(get_net_wm_desktop($con), undef, '_NET_WM_DESKTOP is removed');
194
195 kill_windows;
196
197 ###############################################################################
198 # A _NET_WM_DESKTOP client message sent to the root window moves a window
199 # to the correct workspace.
200 ###############################################################################
201
202 cmd 'workspace 0';
203 open_window;
204 cmd 'workspace 1';
205 open_window;
206 cmd 'workspace 0';
207
208 $con = open_window;
209 is_num_children('0', 2, 'The window is on workspace 0');
210
211 send_net_wm_desktop($con, 1);
212
213 is_num_children('0', 1, 'The window is no longer on workspace 0');
214 is_num_children('1', 2, 'The window is now on workspace 1');
215 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated');
216
217 kill_windows;
218
219 ###############################################################################
220 # A _NET_WM_DESKTOP client message sent to the root window can make a window
221 # sticky.
222 ###############################################################################
223
224 cmd 'workspace 0';
225 $con = open_window;
226
227 send_net_wm_desktop($con, 0xFFFFFFFF);
228
229 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
230 is(@{get_ws('0')->{floating_nodes}}, 1, 'The window is floating');
231 ok(get_ws('0')->{floating_nodes}->[0]->{nodes}->[0]->{sticky}, 'The window is sticky');
232
233 kill_windows;
234
235 ###############################################################################
236 # _NET_WM_DESKTOP is updated when a new workspace with a lower number is
237 # opened and closed.
238 ###############################################################################
239
240 cmd 'workspace 1';
241 $con = open_window;
242 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
243
244 cmd 'workspace 0';
245 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated');
246
247 kill_windows;
248
249 ###############################################################################
250 # _NET_WM_DESKTOP is updated when a window is made sticky by command.
251 ###############################################################################
252
253 cmd 'workspace 0';
254 $con = open_window;
255 cmd 'floating enable';
256 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
257
258 cmd 'sticky enable';
259 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
260
261 kill_windows;
262
263 ###############################################################################
264 # _NET_WM_DESKTOP is updated when a window is made sticky by client message.
265 ###############################################################################
266
267 cmd 'workspace 0';
268 $con = open_window;
269 cmd 'floating enable';
270 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
271
272 my $msg = pack "CCSLLLLLL",
273     X11::XCB::CLIENT_MESSAGE, 32, 0,
274     $con->{id},
275     $x->atom(name => '_NET_WM_STATE')->id,
276     1,
277     $x->atom(name => '_NET_WM_STATE_STICKY')->id,
278     0, 0, 0;
279
280 $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg);
281 sync_with_i3;
282
283 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
284
285 kill_windows;
286
287 ###############################################################################
288 # _NET_WM_DESKTOP is updated when a window is moved to the scratchpad.
289 ###############################################################################
290
291 cmd 'workspace 0';
292 $con = open_window;
293 cmd 'floating enable';
294 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
295
296 cmd 'move scratchpad';
297 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
298
299 cmd 'scratchpad show';
300 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
301
302 kill_windows;
303
304 ###############################################################################
305
306 exit_gracefully($pid);
307
308 done_testing;