]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: correctly recognize assigned windows as urgent (Thanks jookia)
authorMichael Stapelberg <michael@stapelberg.de>
Tue, 24 Sep 2013 05:47:36 +0000 (07:47 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Tue, 24 Sep 2013 05:47:36 +0000 (07:47 +0200)
fixes #1086

include/window.h
src/handlers.c
src/manage.c
src/window.c
testcases/t/211-regress-urgency-assign.t [new file with mode: 0644]

index 59d3b1bbd97a3bc1401b6bda614bb23c89b6b11b..abc27d6aaf69e1ecf10abfdb9b3cda59fac80448 100644 (file)
@@ -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
index 931e863456ab07bd9a1d917fb9031262a02a9f98..084a728561ae1db27e0be907ec8f68141fccb9f5 100644 (file)
@@ -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;
 }
 
index f5bd76ea39bc61595d8d4321b12a5f2c89144489..bb376f60bfaa16497e097effd7d5cb9615e946cf 100644 (file)
@@ -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:
index b886c380880e865dd913340840420ab2e1cd0cbc..b51be53f9f4e86db4f99692e8a75f6072a5884e6 100644 (file)
@@ -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 (file)
index 0000000..a90703e
--- /dev/null
@@ -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 = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+assign [class="special"] nonvisible
+EOT
+my $pid = launch_with_config($config);
+
+my $tmp = fresh_workspace;
+
+ok((scalar grep { $_ eq 'nonvisible' } @{get_workspace_names()}) == 0,
+   'assignment destination workspace does not exist yet');
+
+my $window = open_special;
+sync_with_i3;
+
+ok((scalar grep { $_ eq 'nonvisible' } @{get_workspace_names()}) > 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;