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; |