]> git.sur5r.net Git - i3/i3/blob - testcases/t/113-urgent.t
Merge branch 'fix-urgent-crash'
[i3/i3] / testcases / t / 113-urgent.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 use i3test i3_autostart => 0;
18 use List::Util qw(first);
19
20 my $_NET_WM_STATE_REMOVE = 0;
21 my $_NET_WM_STATE_ADD = 1;
22 my $_NET_WM_STATE_TOGGLE = 2;
23
24 sub set_urgency {
25     my ($win, $urgent_flag, $type) = @_;
26     if ($type == 1) {
27         $win->add_hint('urgency') if ($urgent_flag);
28         $win->delete_hint('urgency') if (!$urgent_flag);
29     } elsif ($type == 2) {
30         my $msg = pack "CCSLLLLLL",
31             X11::XCB::CLIENT_MESSAGE, # response_type
32             32, # format
33             0, # sequence
34             $win->id, # window
35             $x->atom(name => '_NET_WM_STATE')->id, # message type
36             ($urgent_flag ? $_NET_WM_STATE_ADD : $_NET_WM_STATE_REMOVE), # data32[0]
37             $x->atom(name => '_NET_WM_STATE_DEMANDS_ATTENTION')->id, # data32[1]
38             0, # data32[2]
39             0, # data32[3]
40             0; # data32[4]
41
42         $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg);
43     }
44 }
45
46 my $config = <<EOT;
47 # i3 config file (v4)
48 font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
49
50 force_display_urgency_hint 0ms
51 EOT
52
53 my $type;
54 for ($type = 1; $type <= 2; $type++) {
55     my $pid = launch_with_config($config);
56     my $tmp = fresh_workspace;
57
58 #####################################################################
59 # Create two windows and put them in stacking mode
60 #####################################################################
61
62     cmd 'split v';
63
64     my $top = open_window;
65     my $bottom = open_window;
66
67     my @urgent = grep { $_->{urgent} } @{get_ws_content($tmp)};
68     is(@urgent, 0, 'no window got the urgent flag');
69
70 # cmd 'layout stacking';
71
72 #####################################################################
73 # Add the urgency hint, switch to a different workspace and back again
74 #####################################################################
75     set_urgency($top, 1, $type);
76     sync_with_i3;
77
78     my @content = @{get_ws_content($tmp)};
79     @urgent = grep { $_->{urgent} } @content;
80     my $top_info = first { $_->{window} == $top->id } @content;
81     my $bottom_info = first { $_->{window} == $bottom->id } @content;
82
83     ok($top_info->{urgent}, 'top window is marked urgent');
84     ok(!$bottom_info->{urgent}, 'bottom window is not marked urgent');
85     is(@urgent, 1, 'exactly one window got the urgent flag');
86
87     cmd '[id="' . $top->id . '"] focus';
88
89     @urgent = grep { $_->{urgent} } @{get_ws_content($tmp)};
90     is(@urgent, 0, 'no window got the urgent flag after focusing');
91
92     set_urgency($top, 1, $type);
93     sync_with_i3;
94
95     @urgent = grep { $_->{urgent} } @{get_ws_content($tmp)};
96     is(@urgent, 0, 'no window got the urgent flag after re-setting urgency hint');
97
98 #####################################################################
99 # Check if the workspace urgency hint gets set/cleared correctly
100 #####################################################################
101
102     my $ws = get_ws($tmp);
103     ok(!$ws->{urgent}, 'urgent flag not set on workspace');
104
105     my $otmp = fresh_workspace;
106
107     set_urgency($top, 1, $type);
108     sync_with_i3;
109
110     $ws = get_ws($tmp);
111     ok($ws->{urgent}, 'urgent flag set on workspace');
112
113     cmd "workspace $tmp";
114
115     $ws = get_ws($tmp);
116     ok(!$ws->{urgent}, 'urgent flag not set on workspace after switching');
117
118 ################################################################################
119 # Use the 'urgent' criteria to switch to windows which have the urgency hint set.
120 ################################################################################
121
122 # Go to a new workspace, open a different window, verify focus is on it.
123     $otmp = fresh_workspace;
124     my $different_window = open_window;
125     is($x->input_focus, $different_window->id, 'new window focused');
126
127 # Add the urgency hint on the other window.
128     set_urgency($top, 1, $type);
129     sync_with_i3;
130
131 # Now try to switch to that window and see if focus changes.
132     cmd '[urgent=latest] focus';
133     isnt($x->input_focus, $different_window->id, 'window no longer focused');
134     is($x->input_focus, $top->id, 'urgent window focused');
135
136 ################################################################################
137 # Same thing, but with multiple windows and using the 'urgency=latest' criteria
138 # (verify that it works in the correct order).
139 ################################################################################
140
141     cmd "workspace $otmp";
142     is($x->input_focus, $different_window->id, 'new window focused again');
143
144     set_urgency($top, 1, $type);
145     sync_with_i3;
146
147     set_urgency($bottom, 1, $type);
148     sync_with_i3;
149
150     cmd '[urgent=latest] focus';
151     is($x->input_focus, $bottom->id, 'latest urgent window focused');
152     set_urgency($bottom, 0, $type);
153     sync_with_i3;
154
155     cmd '[urgent=latest] focus';
156     is($x->input_focus, $top->id, 'second urgent window focused');
157     set_urgency($top, 0, $type);
158     sync_with_i3;
159
160 ################################################################################
161 # Same thing, but with multiple windows and using the 'urgency=oldest' criteria
162 # (verify that it works in the correct order).
163 ################################################################################
164
165     cmd "workspace $otmp";
166     is($x->input_focus, $different_window->id, 'new window focused again');
167
168     set_urgency($top, 1, $type);
169     sync_with_i3;
170
171     set_urgency($bottom, 1, $type);
172     sync_with_i3;
173
174     cmd '[urgent=oldest] focus';
175     is($x->input_focus, $top->id, 'oldest urgent window focused');
176     set_urgency($top, 0, $type);
177     sync_with_i3;
178
179     cmd '[urgent=oldest] focus';
180     is($x->input_focus, $bottom->id, 'oldest urgent window focused');
181     set_urgency($bottom, 0, $type);
182     sync_with_i3;
183
184 ################################################################################
185 # Check if urgent flag gets propagated to parent containers
186 ################################################################################
187
188     cmd 'split v';
189
190
191
192     sub count_urgent {
193         my ($con) = @_;
194
195         my @children = (@{$con->{nodes}}, @{$con->{floating_nodes}});
196         my $urgent = grep { $_->{urgent} } @children;
197         $urgent += count_urgent($_) for @children;
198         return $urgent;
199     }
200
201     $tmp = fresh_workspace;
202
203     my $win1 = open_window;
204     my $win2 = open_window;
205     cmd 'layout stacked';
206     cmd 'split vertical';
207     my $win3 = open_window;
208     my $win4 = open_window;
209     cmd 'split horizontal' ;
210     my $win5 = open_window;
211     my $win6 = open_window;
212
213     sync_with_i3;
214
215
216     my $urgent = count_urgent(get_ws($tmp));
217     is($urgent, 0, 'no window got the urgent flag');
218
219     cmd '[id="' . $win2->id . '"] focus';
220     sync_with_i3;
221     set_urgency($win5, 1, $type);
222     set_urgency($win6, 1, $type);
223     sync_with_i3;
224
225 # we should have 5 urgent cons. win5, win6 and their 3 split parents.
226
227     $urgent = count_urgent(get_ws($tmp));
228     is($urgent, 5, '2 windows and 3 split containers got the urgent flag');
229
230     cmd '[id="' . $win5->id . '"] focus';
231     sync_with_i3;
232
233 # now win5 and still the split parents should be urgent.
234     $urgent = count_urgent(get_ws($tmp));
235     is($urgent, 4, '1 window and 3 split containers got the urgent flag');
236
237     cmd '[id="' . $win6->id . '"] focus';
238     sync_with_i3;
239
240 # now now window should be urgent.
241     $urgent = count_urgent(get_ws($tmp));
242     is($urgent, 0, 'All urgent flags got cleared');
243
244 ################################################################################
245 # Regression test: Check that urgent floating containers work properly (ticket
246 # #821)
247 ################################################################################
248
249     $tmp = fresh_workspace;
250     my $floating_win = open_floating_window;
251
252 # switch away
253     fresh_workspace;
254
255     set_urgency($floating_win, 1, $type);
256     sync_with_i3;
257
258     cmd "workspace $tmp";
259
260     does_i3_live;
261
262 ###############################################################################
263 # Check if the urgency hint is still set when the urgent window is killed
264 ###############################################################################
265
266     my $ws1 = fresh_workspace;
267     my $ws2 = fresh_workspace;
268     cmd "workspace $ws1";
269     my $w1 = open_window;
270     my $w2 = open_window;
271     cmd "workspace $ws2";
272     sync_with_i3;
273     set_urgency($w1, 1, $type);
274     sync_with_i3;
275     cmd '[id="' . $w1->id . '"] kill';
276     sync_with_i3;
277     my $w = get_ws($ws1);
278     is($w->{urgent}, 0, 'Urgent flag no longer set after killing the window ' .
279        'from another workspace');
280
281 ##############################################################################
282 # Check if urgent flag can be unset if we move the window out of the container
283 ##############################################################################
284     my $tmp = fresh_workspace;
285     cmd 'layout tabbed';
286     my $w1 = open_window;
287     my $w2 = open_window;
288     sync_with_i3;
289     cmd '[id="' . $w2->id . '"] focus';
290     sync_with_i3;
291     cmd 'split v';
292     cmd 'layout stacked';
293     my $w3 = open_window;
294     sync_with_i3;
295     cmd '[id="' . $w2->id . '"] focus';
296     sync_with_i3;
297     set_urgency($w3, 1, $type);
298     sync_with_i3;
299     cmd 'focus parent';
300     sync_with_i3;
301     cmd 'move right';
302     cmd '[id="' . $w3->id . '"] focus';
303     sync_with_i3;
304     my $ws = get_ws($tmp);
305     ok(!$ws->{urgent}, 'urgent flag not set on workspace');
306
307     exit_gracefully($pid);
308 }
309
310 done_testing;