]> git.sur5r.net Git - i3/i3/blob - testcases/t/529-net-wm-desktop.t
ae596203e4ddda18f5b3ffc4f26a0cf889bc37ac
[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 # • https://build.i3wm.org/docs/testsuite.html
6 #   (or docs/testsuite)
7 #
8 # • https://build.i3wm.org/docs/lib-i3test.html
9 #   (alternatively: perldoc ./testcases/lib/i3test.pm)
10 #
11 # • https://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_config => <<EOT;
20 # i3 config file (v4)
21 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
22
23 bar {
24     status_command i3status
25 }
26 EOT
27 use X11::XCB qw(:all);
28
29 ###############################################################################
30
31 sub get_net_wm_desktop {
32     sync_with_i3;
33
34     my ($con) = @_; 
35     my $cookie = $x->get_property(
36         0,  
37         $con->{id},
38         $x->atom(name => '_NET_WM_DESKTOP')->id,
39         $x->atom(name => 'CARDINAL')->id,
40         0,  
41         1
42     );  
43
44     my $reply = $x->get_property_reply($cookie->{sequence});
45     return undef if $reply->{length} != 1;
46
47     return unpack("L", $reply->{value});
48 }
49
50 sub send_net_wm_desktop {
51     my ($con, $idx) = @_;
52     my $msg = pack "CCSLLLLLL",
53         X11::XCB::CLIENT_MESSAGE, 32, 0,
54         $con->{id},
55         $x->atom(name => '_NET_WM_DESKTOP')->id,
56         $idx, 0, 0, 0, 0;
57
58     $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg);
59     sync_with_i3;
60 }
61
62 sub open_window_with_net_wm_desktop {
63     my $idx = shift;
64     my $window = open_window(
65         before_map => sub {
66             my ($window) = @_;
67             $x->change_property(
68                 PROP_MODE_REPLACE,
69                 $window->id,
70                 $x->atom(name => '_NET_WM_DESKTOP')->id,
71                 $x->atom(name => 'CARDINAL')->id,
72                 32, 1,
73                 pack('L', $idx),
74             );
75         },
76         dont_map => 1,
77     );
78
79     # We don’t wait for MapNotify and instead sync with i3 so that we don’t need
80     # to encounter the full timeout of 4s when opening a window on a non-visible
81     # workspace.
82     $window->map;
83     sync_with_i3;
84
85     return $window;
86 }
87
88 ###############################################################################
89 # Upon managing a window which does not set _NET_WM_DESKTOP, the property is
90 # set on the window.
91 ###############################################################################
92
93 cmd 'workspace 1';
94 my $con = open_window;
95
96 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set upon managing a window');
97
98 kill_all_windows;
99
100 ###############################################################################
101 # Upon managing a window which sets _NET_WM_DESKTOP, the window is moved to
102 # the specified desktop.
103 ###############################################################################
104
105 cmd 'workspace 0';
106 open_window;
107 cmd 'workspace 1';
108 open_window;
109 cmd 'workspace 2';
110 open_window;
111
112 $con = open_window_with_net_wm_desktop(1);
113
114 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP still has the correct value');
115 is_num_children('1', 2, 'The window was moved to workspace 1');
116
117 kill_all_windows;
118
119 ###############################################################################
120 # Upon managing a window which sets _NET_WM_DESKTOP to the appropriate value,
121 # the window is made sticky and floating.
122 ###############################################################################
123
124 cmd 'workspace 0';
125 $con = open_window_with_net_wm_desktop(0xFFFFFFFF);
126
127 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP still has the correct value');
128 is(@{get_ws('0')->{floating_nodes}}, 1, 'The window is floating');
129 ok(get_ws('0')->{floating_nodes}->[0]->{nodes}->[0]->{sticky}, 'The window is sticky');
130
131 kill_all_windows;
132
133 ###############################################################################
134 # _NET_WM_DESKTOP is updated when the window is moved to another workspace
135 # on the same output.
136 ###############################################################################
137
138 cmd 'workspace 0';
139 open_window;
140 cmd 'workspace 1';
141 open_window;
142 cmd 'workspace 0';
143 $con = open_window;
144
145 cmd 'move window to workspace 1';
146
147 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
148
149 kill_all_windows;
150
151 ###############################################################################
152 # _NET_WM_DESKTOP is updated when the floating window is moved to another
153 # workspace on the same output.
154 ###############################################################################
155
156 cmd 'workspace 0';
157 open_window;
158 cmd 'workspace 1';
159 open_window;
160 cmd 'workspace 0';
161 $con = open_window;
162 cmd 'floating enable';
163
164 cmd 'move window to workspace 1';
165
166 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated when moving the window');
167
168 kill_all_windows;
169
170 ###############################################################################
171 # _NET_WM_DESKTOP is removed when the window is withdrawn.
172 ###############################################################################
173
174 $con = open_window;
175 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set (sanity check)');
176
177 $con->unmap;
178 wait_for_unmap($con);
179
180 is(get_net_wm_desktop($con), undef, '_NET_WM_DESKTOP is removed');
181
182 kill_all_windows;
183
184 ###############################################################################
185 # A _NET_WM_DESKTOP client message sent to the root window moves a window
186 # to the correct workspace.
187 ###############################################################################
188
189 cmd 'workspace 0';
190 open_window;
191 cmd 'workspace 1';
192 open_window;
193 cmd 'workspace 0';
194
195 $con = open_window;
196 is_num_children('0', 2, 'The window is on workspace 0');
197
198 send_net_wm_desktop($con, 1);
199
200 is_num_children('0', 1, 'The window is no longer on workspace 0');
201 is_num_children('1', 2, 'The window is now on workspace 1');
202 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated');
203
204 kill_all_windows;
205
206 ###############################################################################
207 # A _NET_WM_DESKTOP client message sent to the root window can make a window
208 # sticky.
209 ###############################################################################
210
211 cmd 'workspace 0';
212 $con = open_window;
213
214 send_net_wm_desktop($con, 0xFFFFFFFF);
215
216 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
217 is(@{get_ws('0')->{floating_nodes}}, 1, 'The window is floating');
218 ok(get_ws('0')->{floating_nodes}->[0]->{nodes}->[0]->{sticky}, 'The window is sticky');
219
220 kill_all_windows;
221
222 ###############################################################################
223 # _NET_WM_DESKTOP is updated when a new workspace with a lower number is
224 # opened and closed.
225 ###############################################################################
226
227 cmd 'workspace 1';
228 $con = open_window;
229 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
230
231 cmd 'workspace 0';
232 is(get_net_wm_desktop($con), 1, '_NET_WM_DESKTOP is updated');
233
234 kill_all_windows;
235
236 ###############################################################################
237 # _NET_WM_DESKTOP is updated when a window is made sticky by command.
238 ###############################################################################
239
240 cmd 'workspace 0';
241 $con = open_window;
242 cmd 'floating enable';
243 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
244
245 cmd 'sticky enable';
246 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
247
248 kill_all_windows;
249
250 ###############################################################################
251 # _NET_WM_DESKTOP is updated when a window is made sticky by client message.
252 ###############################################################################
253
254 cmd 'workspace 0';
255 $con = open_window;
256 cmd 'floating enable';
257 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
258
259 my $msg = pack "CCSLLLLLL",
260     X11::XCB::CLIENT_MESSAGE, 32, 0,
261     $con->{id},
262     $x->atom(name => '_NET_WM_STATE')->id,
263     1,
264     $x->atom(name => '_NET_WM_STATE_STICKY')->id,
265     0, 0, 0;
266
267 $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg);
268 sync_with_i3;
269
270 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
271
272 kill_all_windows;
273
274 ###############################################################################
275 # _NET_WM_DESKTOP is updated when a window is moved to the scratchpad.
276 ###############################################################################
277
278 cmd 'workspace 0';
279 $con = open_window;
280 cmd 'floating enable';
281 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
282
283 cmd 'move scratchpad';
284 is(get_net_wm_desktop($con), 0xFFFFFFFF, '_NET_WM_DESKTOP is updated');
285
286 cmd 'scratchpad show';
287 is(get_net_wm_desktop($con), 0, '_NET_WM_DESKTOP is set sanity check)');
288
289 kill_all_windows;
290
291 ###############################################################################
292
293 done_testing;