Add support for _NET_WM_STATE_DEMANDS_ATTENTION.
Patch status: merged
Patch by oblique
Long description:
_NET_WM_STATE_DEMANDS_ATTENTION indicates that some action in or with the window happened. It's a weaker hint than urgency flag of WM_HINTS, but some applications and almost all Qt applications use it instead of WM_HINTS' urgency flag (one example is Skype).
To apply this patch, use:
curl http://cr.i3wm.org/patch/65/raw.patch | git am
b/docs/hacking-howto
23 |
@@ -28,7 +28,8 @@ In the case of i3, the tasks (and order of them) are the following: |
24 |
the first client of X) and manage them (reparent them, create window |
25 |
decorations, etc.) |
26 |
. When new windows are created, manage them |
27 |
-. Handle the client’s `_WM_STATE` property, but only the `_WM_STATE_FULLSCREEN` |
28 |
+. Handle the client’s `_WM_STATE` property, but only `_WM_STATE_FULLSCREEN` and |
29 |
+ `_NET_WM_STATE_DEMANDS_ATTENTION` |
30 |
. Handle the client’s `WM_NAME` property |
31 |
. Handle the client’s size hints to display them proportionally |
32 |
. Handle the client’s urgency hint |
b/include/atoms.xmacro
37 |
@@ -2,6 +2,7 @@ xmacro(_NET_SUPPORTED) |
38 |
xmacro(_NET_SUPPORTING_WM_CHECK) |
39 |
xmacro(_NET_WM_NAME) |
40 |
xmacro(_NET_WM_STATE_FULLSCREEN) |
41 |
+xmacro(_NET_WM_STATE_DEMANDS_ATTENTION) |
42 |
xmacro(_NET_WM_STATE) |
43 |
xmacro(_NET_WM_WINDOW_TYPE) |
44 |
xmacro(_NET_WM_WINDOW_TYPE_DOCK) |
b/include/con.h
49 |
@@ -325,6 +325,12 @@ bool con_has_urgent_child(Con *con); |
50 |
void con_update_parents_urgency(Con *con); |
51 |
|
52 |
/** |
53 |
+ * Set urgency flag to the container, all the parent containers and the workspace. |
54 |
+ * |
55 |
+ */ |
56 |
+void con_set_urgency(Con *con, bool urgent); |
57 |
+ |
58 |
+/** |
59 |
* Create a string representing the subtree under con. |
60 |
* |
61 |
*/ |
b/src/con.c
66 |
@@ -1531,6 +1531,45 @@ void con_update_parents_urgency(Con *con) { |
67 |
} |
68 |
|
69 |
/* |
70 |
+ * Set urgency flag to the container, all the parent containers and the workspace. |
71 |
+ * |
72 |
+ */ |
73 |
+void con_set_urgency(Con *con, bool urgent) { |
74 |
+ if (focused == con) { |
75 |
+ DLOG("Ignoring urgency flag for current client\n"); |
76 |
+ con->window->urgent.tv_sec = 0; |
77 |
+ con->window->urgent.tv_usec = 0; |
78 |
+ return; |
79 |
+ } |
80 |
+ |
81 |
+ if (con->urgency_timer == NULL) { |
82 |
+ con->urgent = urgent; |
83 |
+ } else |
84 |
+ DLOG("Discarding urgency WM_HINT because timer is running\n"); |
85 |
+ |
86 |
+ //CLIENT_LOG(con); |
87 |
+ if (con->window) { |
88 |
+ if (con->urgent) { |
89 |
+ gettimeofday(&con->window->urgent, NULL); |
90 |
+ } else { |
91 |
+ con->window->urgent.tv_sec = 0; |
92 |
+ con->window->urgent.tv_usec = 0; |
93 |
+ } |
94 |
+ } |
95 |
+ |
96 |
+ con_update_parents_urgency(con); |
97 |
+ |
98 |
+ if (con->urgent == urgent) |
99 |
+ LOG("Urgency flag changed to %d\n", con->urgent); |
100 |
+ |
101 |
+ Con *ws; |
102 |
+ /* Set the urgency flag on the workspace, if a workspace could be found |
103 |
+ * (for dock clients, that is not the case). */ |
104 |
+ if ((ws = con_get_workspace(con)) != NULL) |
105 |
+ workspace_update_urgent_flag(ws); |
106 |
+} |
107 |
+ |
108 |
+/* |
109 |
* Create a string representing the subtree under con. |
110 |
* |
111 |
*/ |
b/src/ewmh.c
116 |
@@ -164,5 +164,5 @@ void ewmh_setup_hints(void) { |
117 |
/* I’m not entirely sure if we need to keep _NET_WM_NAME on root. */ |
118 |
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3"); |
119 |
|
120 |
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 16, supported_atoms); |
121 |
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 19, supported_atoms); |
122 |
} |
b/src/handlers.c
127 |
@@ -619,10 +619,10 @@ static void handle_client_message(xcb_client_message_event_t *event) { |
128 |
|
129 |
LOG("ClientMessage for window 0x%08x\n", event->window); |
130 |
if (event->type == A__NET_WM_STATE) { |
131 |
- if (event->format != 32 || event->data.data32[1] != A__NET_WM_STATE_FULLSCREEN) { |
132 |
- DLOG("atom in clientmessage is %d, fullscreen is %d\n", |
133 |
- event->data.data32[1], A__NET_WM_STATE_FULLSCREEN); |
134 |
- DLOG("not about fullscreen atom\n"); |
135 |
+ if (event->format != 32 || |
136 |
+ (event->data.data32[1] != A__NET_WM_STATE_FULLSCREEN && |
137 |
+ event->data.data32[1] != A__NET_WM_STATE_DEMANDS_ATTENTION)) { |
138 |
+ DLOG("Unknown atom in clientmessage of type %d\n", event->data.data32[1]); |
139 |
return; |
140 |
} |
141 |
|
142 |
@@ -632,15 +632,25 @@ static void handle_client_message(xcb_client_message_event_t *event) { |
143 |
return; |
144 |
} |
145 |
|
146 |
- /* Check if the fullscreen state should be toggled */ |
147 |
- if ((con->fullscreen_mode != CF_NONE && |
148 |
- (event->data.data32[0] == _NET_WM_STATE_REMOVE || |
149 |
- event->data.data32[0] == _NET_WM_STATE_TOGGLE)) || |
150 |
- (con->fullscreen_mode == CF_NONE && |
151 |
- (event->data.data32[0] == _NET_WM_STATE_ADD || |
152 |
- event->data.data32[0] == _NET_WM_STATE_TOGGLE))) { |
153 |
- DLOG("toggling fullscreen\n"); |
154 |
- con_toggle_fullscreen(con, CF_OUTPUT); |
155 |
+ if (event->data.data32[1] == A__NET_WM_STATE_FULLSCREEN) { |
156 |
+ /* Check if the fullscreen state should be toggled */ |
157 |
+ if ((con->fullscreen_mode != CF_NONE && |
158 |
+ (event->data.data32[0] == _NET_WM_STATE_REMOVE || |
159 |
+ event->data.data32[0] == _NET_WM_STATE_TOGGLE)) || |
160 |
+ (con->fullscreen_mode == CF_NONE && |
161 |
+ (event->data.data32[0] == _NET_WM_STATE_ADD || |
162 |
+ event->data.data32[0] == _NET_WM_STATE_TOGGLE))) { |
163 |
+ DLOG("toggling fullscreen\n"); |
164 |
+ con_toggle_fullscreen(con, CF_OUTPUT); |
165 |
+ } |
166 |
+ } else if (event->data.data32[1] == A__NET_WM_STATE_DEMANDS_ATTENTION) { |
167 |
+ /* Check if the urgent flag must be set or not */ |
168 |
+ if (event->data.data32[0] == _NET_WM_STATE_ADD) |
169 |
+ con_set_urgency(con, true); |
170 |
+ else if (event->data.data32[0] == _NET_WM_STATE_REMOVE) |
171 |
+ con_set_urgency(con, false); |
172 |
+ else if (event->data.data32[0] == _NET_WM_STATE_TOGGLE) |
173 |
+ con_set_urgency(con, !con->urgent); |
174 |
} |
175 |
|
176 |
tree_render(); |
177 |
@@ -833,44 +843,12 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_ |
178 |
if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply)) |
179 |
return false; |
180 |
|
181 |
- if (!con->urgent && focused == con) { |
182 |
- DLOG("Ignoring urgency flag for current client\n"); |
183 |
- con->window->urgent.tv_sec = 0; |
184 |
- con->window->urgent.tv_usec = 0; |
185 |
- goto end; |
186 |
- } |
187 |
- |
188 |
/* Update the flag on the client directly */ |
189 |
bool hint_urgent = (xcb_icccm_wm_hints_get_urgency(&hints) != 0); |
190 |
- |
191 |
- if (con->urgency_timer == NULL) { |
192 |
- con->urgent = hint_urgent; |
193 |
- } else |
194 |
- DLOG("Discarding urgency WM_HINT because timer is running\n"); |
195 |
- |
196 |
- //CLIENT_LOG(con); |
197 |
- if (con->window) { |
198 |
- if (con->urgent) { |
199 |
- gettimeofday(&con->window->urgent, NULL); |
200 |
- } else { |
201 |
- con->window->urgent.tv_sec = 0; |
202 |
- con->window->urgent.tv_usec = 0; |
203 |
- } |
204 |
- } |
205 |
- |
206 |
- con_update_parents_urgency(con); |
207 |
- |
208 |
- LOG("Urgency flag changed to %d\n", con->urgent); |
209 |
- |
210 |
- Con *ws; |
211 |
- /* Set the urgency flag on the workspace, if a workspace could be found |
212 |
- * (for dock clients, that is not the case). */ |
213 |
- if ((ws = con_get_workspace(con)) != NULL) |
214 |
- workspace_update_urgent_flag(ws); |
215 |
+ con_set_urgency(con, hint_urgent); |
216 |
|
217 |
tree_render(); |
218 |
|
219 |
-end: |
220 |
if (con->window) |
221 |
window_update_hints(con->window, reply); |
222 |
else free(reply); |
223 |
@@ -1094,7 +1072,7 @@ void handle_event(int type, xcb_generic_event_t *event) { |
224 |
|
225 |
/* Client message are sent to the root window. The only interesting |
226 |
* client message for us is _NET_WM_STATE, we honour |
227 |
- * _NET_WM_STATE_FULLSCREEN */ |
228 |
+ * _NET_WM_STATE_FULLSCREEN and _NET_WM_STATE_DEMANDS_ATTENTION */ |
229 |
case XCB_CLIENT_MESSAGE: |
230 |
handle_client_message((xcb_client_message_event_t*)event); |
231 |
break; |
b/testcases/t/113-urgent.t
236 |
@@ -17,239 +17,268 @@ |
237 |
use i3test i3_autostart => 0; |
238 |
use List::Util qw(first); |
239 |
|
240 |
+my $_NET_WM_STATE_REMOVE = 0; |
241 |
+my $_NET_WM_STATE_ADD = 1; |
242 |
+my $_NET_WM_STATE_TOGGLE = 2; |
243 |
+ |
244 |
+sub set_urgency { |
245 |
+ my ($win, $urgent_flag, $type) = @_; |
246 |
+ if ($type == 1) { |
247 |
+ $win->add_hint('urgency') if ($urgent_flag); |
248 |
+ $win->delete_hint('urgency') if (!$urgent_flag); |
249 |
+ } elsif ($type == 2) { |
250 |
+ my $msg = pack "CCSLLLLLL", |
251 |
+ X11::XCB::CLIENT_MESSAGE, # response_type |
252 |
+ 32, # format |
253 |
+ 0, # sequence |
254 |
+ $win->id, # window |
255 |
+ $x->atom(name => '_NET_WM_STATE')->id, # message type |
256 |
+ ($urgent_flag ? $_NET_WM_STATE_ADD : $_NET_WM_STATE_REMOVE), # data32[0] |
257 |
+ $x->atom(name => '_NET_WM_STATE_DEMANDS_ATTENTION')->id, # data32[1] |
258 |
+ 0, # data32[2] |
259 |
+ 0, # data32[3] |
260 |
+ 0; # data32[4] |
261 |
+ |
262 |
+ $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg); |
263 |
+ } |
264 |
+} |
265 |
+ |
266 |
my $config = <<EOT; |
267 |
# i3 config file (v4) |
268 |
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 |
269 |
|
270 |
force_display_urgency_hint 0ms |
271 |
EOT |
272 |
-my $pid = launch_with_config($config); |
273 |
|
274 |
-my $tmp = fresh_workspace; |
275 |
+my $type; |
276 |
+for ($type = 1; $type <= 2; $type++) { |
277 |
+ my $pid = launch_with_config($config); |
278 |
+ my $tmp = fresh_workspace; |
279 |
|
280 |
##################################################################### |
281 |
# Create two windows and put them in stacking mode |
282 |
##################################################################### |
283 |
|
284 |
-cmd 'split v'; |
285 |
+ cmd 'split v'; |
286 |
|
287 |
-my $top = open_window; |
288 |
-my $bottom = open_window; |
289 |
+ my $top = open_window; |
290 |
+ my $bottom = open_window; |
291 |
|
292 |
-my @urgent = grep { $_->{urgent} } @{get_ws_content($tmp)}; |
293 |
-is(@urgent, 0, 'no window got the urgent flag'); |
294 |
+ my @urgent = grep { $_->{urgent} } @{get_ws_content($tmp)}; |
295 |
+ is(@urgent, 0, 'no window got the urgent flag'); |
296 |
|
297 |
# cmd 'layout stacking'; |
298 |
|
299 |
##################################################################### |
300 |
# Add the urgency hint, switch to a different workspace and back again |
301 |
##################################################################### |
302 |
-$top->add_hint('urgency'); |
303 |
-sync_with_i3; |
304 |
+ set_urgency($top, 1, $type); |
305 |
+ sync_with_i3; |
306 |
|
307 |
-my @content = @{get_ws_content($tmp)}; |
308 |
-@urgent = grep { $_->{urgent} } @content; |
309 |
-my $top_info = first { $_->{window} == $top->id } @content; |
310 |
-my $bottom_info = first { $_->{window} == $bottom->id } @content; |
311 |
+ my @content = @{get_ws_content($tmp)}; |
312 |
+ @urgent = grep { $_->{urgent} } @content; |
313 |
+ my $top_info = first { $_->{window} == $top->id } @content; |
314 |
+ my $bottom_info = first { $_->{window} == $bottom->id } @content; |
315 |
|
316 |
-ok($top_info->{urgent}, 'top window is marked urgent'); |
317 |
-ok(!$bottom_info->{urgent}, 'bottom window is not marked urgent'); |
318 |
-is(@urgent, 1, 'exactly one window got the urgent flag'); |
319 |
+ ok($top_info->{urgent}, 'top window is marked urgent'); |
320 |
+ ok(!$bottom_info->{urgent}, 'bottom window is not marked urgent'); |
321 |
+ is(@urgent, 1, 'exactly one window got the urgent flag'); |
322 |
|
323 |
-cmd '[id="' . $top->id . '"] focus'; |
324 |
+ cmd '[id="' . $top->id . '"] focus'; |
325 |
|
326 |
-@urgent = grep { $_->{urgent} } @{get_ws_content($tmp)}; |
327 |
-is(@urgent, 0, 'no window got the urgent flag after focusing'); |
328 |
+ @urgent = grep { $_->{urgent} } @{get_ws_content($tmp)}; |
329 |
+ is(@urgent, 0, 'no window got the urgent flag after focusing'); |
330 |
|
331 |
-$top->add_hint('urgency'); |
332 |
-sync_with_i3; |
333 |
+ set_urgency($top, 1, $type); |
334 |
+ sync_with_i3; |
335 |
|
336 |
-@urgent = grep { $_->{urgent} } @{get_ws_content($tmp)}; |
337 |
-is(@urgent, 0, 'no window got the urgent flag after re-setting urgency hint'); |
338 |
+ @urgent = grep { $_->{urgent} } @{get_ws_content($tmp)}; |
339 |
+ is(@urgent, 0, 'no window got the urgent flag after re-setting urgency hint'); |
340 |
|
341 |
##################################################################### |
342 |
# Check if the workspace urgency hint gets set/cleared correctly |
343 |
##################################################################### |
344 |
|
345 |
-my $ws = get_ws($tmp); |
346 |
-ok(!$ws->{urgent}, 'urgent flag not set on workspace'); |
347 |
+ my $ws = get_ws($tmp); |
348 |
+ ok(!$ws->{urgent}, 'urgent flag not set on workspace'); |
349 |
|
350 |
-my $otmp = fresh_workspace; |
351 |
+ my $otmp = fresh_workspace; |
352 |
|
353 |
-$top->add_hint('urgency'); |
354 |
-sync_with_i3; |
355 |
+ set_urgency($top, 1, $type); |
356 |
+ sync_with_i3; |
357 |
|
358 |
-$ws = get_ws($tmp); |
359 |
-ok($ws->{urgent}, 'urgent flag set on workspace'); |
360 |
+ $ws = get_ws($tmp); |
361 |
+ ok($ws->{urgent}, 'urgent flag set on workspace'); |
362 |
|
363 |
-cmd "workspace $tmp"; |
364 |
+ cmd "workspace $tmp"; |
365 |
|
366 |
-$ws = get_ws($tmp); |
367 |
-ok(!$ws->{urgent}, 'urgent flag not set on workspace after switching'); |
368 |
+ $ws = get_ws($tmp); |
369 |
+ ok(!$ws->{urgent}, 'urgent flag not set on workspace after switching'); |
370 |
|
371 |
################################################################################ |
372 |
# Use the 'urgent' criteria to switch to windows which have the urgency hint set. |
373 |
################################################################################ |
374 |
|
375 |
# Go to a new workspace, open a different window, verify focus is on it. |
376 |
-$otmp = fresh_workspace; |
377 |
-my $different_window = open_window; |
378 |
-is($x->input_focus, $different_window->id, 'new window focused'); |
379 |
+ $otmp = fresh_workspace; |
380 |
+ my $different_window = open_window; |
381 |
+ is($x->input_focus, $different_window->id, 'new window focused'); |
382 |
|
383 |
# Add the urgency hint on the other window. |
384 |
-$top->add_hint('urgency'); |
385 |
-sync_with_i3; |
386 |
+ set_urgency($top, 1, $type); |
387 |
+ sync_with_i3; |
388 |
|
389 |
# Now try to switch to that window and see if focus changes. |
390 |
-cmd '[urgent=latest] focus'; |
391 |
-isnt($x->input_focus, $different_window->id, 'window no longer focused'); |
392 |
-is($x->input_focus, $top->id, 'urgent window focused'); |
393 |
+ cmd '[urgent=latest] focus'; |
394 |
+ isnt($x->input_focus, $different_window->id, 'window no longer focused'); |
395 |
+ is($x->input_focus, $top->id, 'urgent window focused'); |
396 |
|
397 |
################################################################################ |
398 |
# Same thing, but with multiple windows and using the 'urgency=latest' criteria |
399 |
# (verify that it works in the correct order). |
400 |
################################################################################ |
401 |
|
402 |
-cmd "workspace $otmp"; |
403 |
-is($x->input_focus, $different_window->id, 'new window focused again'); |
404 |
+ cmd "workspace $otmp"; |
405 |
+ is($x->input_focus, $different_window->id, 'new window focused again'); |
406 |
|
407 |
-$top->add_hint('urgency'); |
408 |
-sync_with_i3; |
409 |
+ set_urgency($top, 1, $type); |
410 |
+ sync_with_i3; |
411 |
|
412 |
-$bottom->add_hint('urgency'); |
413 |
-sync_with_i3; |
414 |
+ set_urgency($bottom, 1, $type); |
415 |
+ sync_with_i3; |
416 |
|
417 |
-cmd '[urgent=latest] focus'; |
418 |
-is($x->input_focus, $bottom->id, 'latest urgent window focused'); |
419 |
-$bottom->delete_hint('urgency'); |
420 |
-sync_with_i3; |
421 |
+ cmd '[urgent=latest] focus'; |
422 |
+ is($x->input_focus, $bottom->id, 'latest urgent window focused'); |
423 |
+ set_urgency($bottom, 0, $type); |
424 |
+ sync_with_i3; |
425 |
|
426 |
-cmd '[urgent=latest] focus'; |
427 |
-is($x->input_focus, $top->id, 'second urgent window focused'); |
428 |
-$top->delete_hint('urgency'); |
429 |
-sync_with_i3; |
430 |
+ cmd '[urgent=latest] focus'; |
431 |
+ is($x->input_focus, $top->id, 'second urgent window focused'); |
432 |
+ set_urgency($top, 0, $type); |
433 |
+ sync_with_i3; |
434 |
|
435 |
################################################################################ |
436 |
# Same thing, but with multiple windows and using the 'urgency=oldest' criteria |
437 |
# (verify that it works in the correct order). |
438 |
################################################################################ |
439 |
|
440 |
-cmd "workspace $otmp"; |
441 |
-is($x->input_focus, $different_window->id, 'new window focused again'); |
442 |
+ cmd "workspace $otmp"; |
443 |
+ is($x->input_focus, $different_window->id, 'new window focused again'); |
444 |
|
445 |
-$top->add_hint('urgency'); |
446 |
-sync_with_i3; |
447 |
+ set_urgency($top, 1, $type); |
448 |
+ sync_with_i3; |
449 |
|
450 |
-$bottom->add_hint('urgency'); |
451 |
-sync_with_i3; |
452 |
+ set_urgency($bottom, 1, $type); |
453 |
+ sync_with_i3; |
454 |
|
455 |
-cmd '[urgent=oldest] focus'; |
456 |
-is($x->input_focus, $top->id, 'oldest urgent window focused'); |
457 |
-$top->delete_hint('urgency'); |
458 |
-sync_with_i3; |
459 |
+ cmd '[urgent=oldest] focus'; |
460 |
+ is($x->input_focus, $top->id, 'oldest urgent window focused'); |
461 |
+ set_urgency($top, 0, $type); |
462 |
+ sync_with_i3; |
463 |
|
464 |
-cmd '[urgent=oldest] focus'; |
465 |
-is($x->input_focus, $bottom->id, 'oldest urgent window focused'); |
466 |
-$bottom->delete_hint('urgency'); |
467 |
-sync_with_i3; |
468 |
+ cmd '[urgent=oldest] focus'; |
469 |
+ is($x->input_focus, $bottom->id, 'oldest urgent window focused'); |
470 |
+ set_urgency($bottom, 0, $type); |
471 |
+ sync_with_i3; |
472 |
|
473 |
################################################################################ |
474 |
# Check if urgent flag gets propagated to parent containers |
475 |
################################################################################ |
476 |
|
477 |
-cmd 'split v'; |
478 |
+ cmd 'split v'; |
479 |
|
480 |
|
481 |
|
482 |
-sub count_urgent { |
483 |
- my ($con) = @_; |
484 |
+ sub count_urgent { |
485 |
+ my ($con) = @_; |
486 |
|
487 |
- my @children = (@{$con->{nodes}}, @{$con->{floating_nodes}}); |
488 |
- my $urgent = grep { $_->{urgent} } @children; |
489 |
- $urgent += count_urgent($_) for @children; |
490 |
- return $urgent; |
491 |
-} |
492 |
+ my @children = (@{$con->{nodes}}, @{$con->{floating_nodes}}); |
493 |
+ my $urgent = grep { $_->{urgent} } @children; |
494 |
+ $urgent += count_urgent($_) for @children; |
495 |
+ return $urgent; |
496 |
+ } |
497 |
|
498 |
-$tmp = fresh_workspace; |
499 |
+ $tmp = fresh_workspace; |
500 |
|
501 |
-my $win1 = open_window; |
502 |
-my $win2 = open_window; |
503 |
-cmd 'layout stacked'; |
504 |
-cmd 'split vertical'; |
505 |
-my $win3 = open_window; |
506 |
-my $win4 = open_window; |
507 |
-cmd 'split horizontal' ; |
508 |
-my $win5 = open_window; |
509 |
-my $win6 = open_window; |
510 |
+ my $win1 = open_window; |
511 |
+ my $win2 = open_window; |
512 |
+ cmd 'layout stacked'; |
513 |
+ cmd 'split vertical'; |
514 |
+ my $win3 = open_window; |
515 |
+ my $win4 = open_window; |
516 |
+ cmd 'split horizontal' ; |
517 |
+ my $win5 = open_window; |
518 |
+ my $win6 = open_window; |
519 |
|
520 |
-sync_with_i3; |
521 |
+ sync_with_i3; |
522 |
|
523 |
|
524 |
-my $urgent = count_urgent(get_ws($tmp)); |
525 |
-is($urgent, 0, 'no window got the urgent flag'); |
526 |
+ my $urgent = count_urgent(get_ws($tmp)); |
527 |
+ is($urgent, 0, 'no window got the urgent flag'); |
528 |
|
529 |
-cmd '[id="' . $win2->id . '"] focus'; |
530 |
-sync_with_i3; |
531 |
-$win5->add_hint('urgency'); |
532 |
-$win6->add_hint('urgency'); |
533 |
-sync_with_i3; |
534 |
+ cmd '[id="' . $win2->id . '"] focus'; |
535 |
+ sync_with_i3; |
536 |
+ set_urgency($win5, 1, $type); |
537 |
+ set_urgency($win6, 1, $type); |
538 |
+ sync_with_i3; |
539 |
|
540 |
# we should have 5 urgent cons. win5, win6 and their 3 split parents. |
541 |
|
542 |
-$urgent = count_urgent(get_ws($tmp)); |
543 |
-is($urgent, 5, '2 windows and 3 split containers got the urgent flag'); |
544 |
+ $urgent = count_urgent(get_ws($tmp)); |
545 |
+ is($urgent, 5, '2 windows and 3 split containers got the urgent flag'); |
546 |
|
547 |
-cmd '[id="' . $win5->id . '"] focus'; |
548 |
-sync_with_i3; |
549 |
+ cmd '[id="' . $win5->id . '"] focus'; |
550 |
+ sync_with_i3; |
551 |
|
552 |
# now win5 and still the split parents should be urgent. |
553 |
-$urgent = count_urgent(get_ws($tmp)); |
554 |
-is($urgent, 4, '1 window and 3 split containers got the urgent flag'); |
555 |
+ $urgent = count_urgent(get_ws($tmp)); |
556 |
+ is($urgent, 4, '1 window and 3 split containers got the urgent flag'); |
557 |
|
558 |
-cmd '[id="' . $win6->id . '"] focus'; |
559 |
-sync_with_i3; |
560 |
+ cmd '[id="' . $win6->id . '"] focus'; |
561 |
+ sync_with_i3; |
562 |
|
563 |
# now now window should be urgent. |
564 |
-$urgent = count_urgent(get_ws($tmp)); |
565 |
-is($urgent, 0, 'All urgent flags got cleared'); |
566 |
+ $urgent = count_urgent(get_ws($tmp)); |
567 |
+ is($urgent, 0, 'All urgent flags got cleared'); |
568 |
|
569 |
################################################################################ |
570 |
# Regression test: Check that urgent floating containers work properly (ticket |
571 |
# #821) |
572 |
################################################################################ |
573 |
|
574 |
-$tmp = fresh_workspace; |
575 |
-my $floating_win = open_floating_window; |
576 |
+ $tmp = fresh_workspace; |
577 |
+ my $floating_win = open_floating_window; |
578 |
|
579 |
# switch away |
580 |
-fresh_workspace; |
581 |
+ fresh_workspace; |
582 |
|
583 |
-$floating_win->add_hint('urgency'); |
584 |
-sync_with_i3; |
585 |
+ set_urgency($floating_win, 1, $type); |
586 |
+ sync_with_i3; |
587 |
|
588 |
-cmd "workspace $tmp"; |
589 |
+ cmd "workspace $tmp"; |
590 |
|
591 |
-does_i3_live; |
592 |
+ does_i3_live; |
593 |
|
594 |
############################################################################### |
595 |
# Check if the urgency hint is still set when the urgent window is killed |
596 |
############################################################################### |
597 |
|
598 |
-my $ws1 = fresh_workspace; |
599 |
-my $ws2 = fresh_workspace; |
600 |
-cmd "workspace $ws1"; |
601 |
-my $w1 = open_window; |
602 |
-my $w2 = open_window; |
603 |
-cmd "workspace $ws2"; |
604 |
-sync_with_i3; |
605 |
-$w1->add_hint('urgency'); |
606 |
-sync_with_i3; |
607 |
-cmd '[id="' . $w1->id . '"] kill'; |
608 |
-sync_with_i3; |
609 |
-my $w = get_ws($ws1); |
610 |
-is($w->{urgent}, 0, 'Urgent flag no longer set after killing the window ' . |
611 |
- 'from another workspace'); |
612 |
- |
613 |
- |
614 |
-exit_gracefully($pid); |
615 |
+ my $ws1 = fresh_workspace; |
616 |
+ my $ws2 = fresh_workspace; |
617 |
+ cmd "workspace $ws1"; |
618 |
+ my $w1 = open_window; |
619 |
+ my $w2 = open_window; |
620 |
+ cmd "workspace $ws2"; |
621 |
+ sync_with_i3; |
622 |
+ set_urgency($w1, 1, $type); |
623 |
+ sync_with_i3; |
624 |
+ cmd '[id="' . $w1->id . '"] kill'; |
625 |
+ sync_with_i3; |
626 |
+ my $w = get_ws($ws1); |
627 |
+ is($w->{urgent}, 0, 'Urgent flag no longer set after killing the window ' . |
628 |
+ 'from another workspace'); |
629 |
+ |
630 |
+ exit_gracefully($pid); |
631 |
+} |
632 |
+ |
633 |
done_testing; |