From 1a1d42153408822d267d0cb4718b22d8ff116f27 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 24 Sep 2013 07:47:36 +0200 Subject: [PATCH] Bugfix: correctly recognize assigned windows as urgent (Thanks jookia) fixes #1086 --- include/window.h | 2 +- src/handlers.c | 19 ++---- src/manage.c | 9 ++- src/window.c | 8 ++- testcases/t/211-regress-urgency-assign.t | 86 ++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 testcases/t/211-regress-urgency-assign.t diff --git a/include/window.h b/include/window.h index 59d3b1bb..abc27d6a 100644 --- a/include/window.h +++ b/include/window.h @@ -61,6 +61,6 @@ void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool befo * Updates the WM_HINTS (we only care about the input focus handling part). * */ -void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop); +void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop, bool *urgency_hint); #endif diff --git a/src/handlers.c b/src/handlers.c index 931e8634..084a7285 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -883,24 +883,13 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_ return false; } - xcb_icccm_wm_hints_t hints; - + bool urgency_hint; if (reply == NULL) - if (!(reply = xcb_get_property_reply(conn, xcb_icccm_get_wm_hints(conn, window), NULL))) - return false; - - if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply)) - return false; - - /* Update the flag on the client directly */ - bool hint_urgent = (xcb_icccm_wm_hints_get_urgency(&hints) != 0); - con_set_urgency(con, hint_urgent); - + reply = xcb_get_property_reply(conn, xcb_icccm_get_wm_hints(conn, window), NULL); + window_update_hints(con->window, reply, &urgency_hint); + con_set_urgency(con, urgency_hint); tree_render(); - if (con->window) - window_update_hints(con->window, reply); - else free(reply); return true; } diff --git a/src/manage.c b/src/manage.c index f5bd76ea..bb376f60 100644 --- a/src/manage.c +++ b/src/manage.c @@ -220,7 +220,8 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki window_update_transient_for(cwindow, xcb_get_property_reply(conn, transient_cookie, NULL)); window_update_strut_partial(cwindow, xcb_get_property_reply(conn, strut_cookie, NULL)); window_update_role(cwindow, xcb_get_property_reply(conn, role_cookie, NULL), true); - window_update_hints(cwindow, xcb_get_property_reply(conn, wm_hints_cookie, NULL)); + bool urgency_hint; + window_update_hints(cwindow, xcb_get_property_reply(conn, wm_hints_cookie, NULL), &urgency_hint); xcb_get_property_reply_t *startup_id_reply; startup_id_reply = xcb_get_property_reply(conn, startup_id_cookie, NULL); @@ -469,6 +470,12 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki /* Send an event about window creation */ ipc_send_window_new_event(nc); + /* Windows might get managed with the urgency hint already set (Pidgin is + * known to do that), so check for that and handle the hint accordingly. + * This code needs to be in this part of manage_window() because the window + * needs to be on the final workspace first. */ + con_set_urgency(nc, urgency_hint); + geom_out: free(geom); out: diff --git a/src/window.c b/src/window.c index b886c380..b51be53f 100644 --- a/src/window.c +++ b/src/window.c @@ -228,7 +228,10 @@ void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool befo * Updates the WM_HINTS (we only care about the input focus handling part). * */ -void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop) { +void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop, bool *urgency_hint) { + if (urgency_hint != NULL) + *urgency_hint = false; + if (prop == NULL || xcb_get_property_value_length(prop) == 0) { DLOG("WM_HINTS not set.\n"); FREE(prop); @@ -246,5 +249,8 @@ void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop) { win->doesnt_accept_focus = !hints.input; LOG("WM_HINTS.input changed to \"%d\"\n", hints.input); + if (urgency_hint != NULL) + *urgency_hint = (xcb_icccm_wm_hints_get_urgency(&hints) != 0); + free(prop); } diff --git a/testcases/t/211-regress-urgency-assign.t b/testcases/t/211-regress-urgency-assign.t new file mode 100644 index 00000000..a90703ee --- /dev/null +++ b/testcases/t/211-regress-urgency-assign.t @@ -0,0 +1,86 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# Verifies that windows are properly recognized as urgent when they start up +# with the urgency hint already set (and are assigned to a non-visible +# workspace). +# +# Ticket: #1086 +# Bug still in: 4.6-62-g7098ef6 +use i3test i3_autostart => 0; +use X11::XCB qw(:all); + +# TODO: move to X11::XCB +sub set_wm_class { + my ($id, $class, $instance) = @_; + + # Add a _NET_WM_STRUT_PARTIAL hint + my $atomname = $x->atom(name => 'WM_CLASS'); + my $atomtype = $x->atom(name => 'STRING'); + + $x->change_property( + PROP_MODE_REPLACE, + $id, + $atomname->id, + $atomtype->id, + 8, + length($class) + length($instance) + 2, + "$instance\x00$class\x00" + ); +} + +sub open_special { + my %args = @_; + my $wm_class = delete($args{wm_class}) || 'special'; + $args{name} //= 'special window'; + + # We use dont_map because i3 will not map the window on the current + # workspace. Thus, open_window would time out in wait_for_map (2 seconds). + my $window = open_window( + %args, + before_map => sub { set_wm_class($_->id, $wm_class, $wm_class) }, + dont_map => 1, + ); + $window->add_hint('urgency'); + $window->map; + return $window; +} + +my $config = < 0, + 'assignment destination workspace exists'); + +my @urgent = grep { $_->{urgent} } @{get_ws_content('nonvisible')}; +isnt(@urgent, 0, 'urgent window(s) found on destination workspace'); + +exit_gracefully($pid); + +done_testing; -- 2.39.5