]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: Respect WM_HINTS.input for WM_TAKE_FOCUS clients
authorMichael Stapelberg <michael@stapelberg.de>
Wed, 18 Jan 2012 19:16:57 +0000 (19:16 +0000)
committerMichael Stapelberg <michael@stapelberg.de>
Wed, 18 Jan 2012 19:16:57 +0000 (19:16 +0000)
This fixes problems with Qt apps (like Quassel) and apparently Eclipse since
the last commit.

include/data.h
include/window.h
src/handlers.c
src/manage.c
src/window.c
src/x.c

index 740278aecd12eb4bae72c0848d5ec25c474bf28d..10fc16d25aba594f1a22d932b5a841575062c8d2 100644 (file)
@@ -2,7 +2,7 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
  *
  * include/data.h: This file defines all data structures used by i3
  *
@@ -293,6 +293,10 @@ struct Window {
     /** Whether the application needs to receive WM_TAKE_FOCUS */
     bool needs_take_focus;
 
+    /** Whether this window accepts focus. We store this inverted so that the
+     * default will be 'accepts focus'. */
+    bool doesnt_accept_focus;
+
     /** Whether the window says it is a dock window */
     enum { W_NODOCK = 0, W_DOCK_TOP = 1, W_DOCK_BOTTOM = 2 } dock;
 
index 61ec8614b52ef783d4df6fc46d670934ed7ae0fa..60198b878f3517e04addc9c33744d4e06ef16d49 100644 (file)
@@ -57,4 +57,10 @@ void window_update_strut_partial(i3Window *win, xcb_get_property_reply_t *prop);
  */
 void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt);
 
+/**
+ * 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);
+
 #endif
index 69c1831d1326ce5617308f72215068ea5e7f9eb9..d835d367e5afb5bfcf5441120f10c989690430a7 100644 (file)
@@ -855,18 +855,16 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_
 
     xcb_icccm_wm_hints_t hints;
 
-    if (reply != NULL) {
-        if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply))
+    if (reply == NULL)
+        if (!(reply = xcb_get_property_reply(conn, xcb_icccm_get_wm_hints(conn, window), NULL)))
             return false;
-    } else {
-        if (!xcb_icccm_get_wm_hints_reply(conn, xcb_icccm_get_wm_hints_unchecked(conn, con->window->id), &hints, NULL))
-            return false;
-    }
+
+    if (!xcb_icccm_get_wm_hints_from_reply(&hints, reply))
+        return false;
 
     if (!con->urgent && focused == con) {
         DLOG("Ignoring urgency flag for current client\n");
-        FREE(reply);
-        return true;
+        goto end;
     }
 
     /* Update the flag on the client directly */
@@ -882,17 +880,10 @@ static bool handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_
 
     tree_render();
 
-#if 0
-    /* If the workspace this client is on is not visible, we need to redraw
-     * the workspace bar */
-    if (!workspace_is_visible(client->workspace)) {
-            Output *output = client->workspace->output;
-            render_workspace(conn, output, output->current_workspace);
-            xcb_flush(conn);
-    }
-#endif
-
-    FREE(reply);
+end:
+    if (con->window)
+        window_update_hints(con->window, reply);
+    else free(reply);
     return true;
 }
 
index ee1b3d6c30bd77ad147014877655ba7af9afebd0..a87807b429914db043143485b0d8f7a203a44047 100644 (file)
@@ -80,7 +80,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
     xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
                               utf8_title_cookie, title_cookie,
                               class_cookie, leader_cookie, transient_cookie,
-                              role_cookie, startup_id_cookie;
+                              role_cookie, startup_id_cookie, wm_hints_cookie;
 
 
     geomc = xcb_get_geometry(conn, d);
@@ -142,6 +142,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
     class_cookie = GET_PROPERTY(XCB_ATOM_WM_CLASS, 128);
     role_cookie = GET_PROPERTY(A_WM_WINDOW_ROLE, 128);
     startup_id_cookie = GET_PROPERTY(A__NET_STARTUP_ID, 512);
+    wm_hints_cookie = xcb_icccm_get_wm_hints(conn, window);
     /* TODO: also get wm_normal_hints here. implement after we got rid of xcb-event */
 
     DLOG("Managing window 0x%08x\n", window);
@@ -169,6 +170,7 @@ 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));
 
     xcb_get_property_reply_t *startup_id_reply;
     startup_id_reply = xcb_get_property_reply(conn, startup_id_cookie, NULL);
index 30957a4b81678e3f629d12acb6303b17812fa8f2..e630e776c001d061a255e7f1b6b8011949929d68 100644 (file)
@@ -2,7 +2,7 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
  *
  * window.c: Updates window attributes (X11 hints/properties).
  *
@@ -251,3 +251,28 @@ void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool befo
 
     free(prop);
 }
+
+/*
+ * 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) {
+    if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
+        DLOG("WM_HINTS not set.\n");
+        FREE(prop);
+        return;
+    }
+
+    xcb_icccm_wm_hints_t hints;
+
+    if (!xcb_icccm_get_wm_hints_from_reply(&hints, prop)) {
+        DLOG("Could not get WM_HINTS\n");
+        free(prop);
+        return;
+    }
+
+    win->doesnt_accept_focus = !hints.input;
+    LOG("WM_HINTS.input changed to \"%d\"\n", hints.input);
+
+    free(prop);
+}
diff --git a/src/x.c b/src/x.c
index 42bb744d1c3a7382dd98829e935be3fd65b30238..557a49d915d6f6e8e74f602e1a822a496576ebb7 100644 (file)
--- a/src/x.c
+++ b/src/x.c
@@ -2,7 +2,7 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
  *
  * x.c: Interface to X11, transfers our in-memory state to X11 (see also
  *      render.c). Basically a big state machine.
@@ -849,12 +849,17 @@ void x_push_changes(Con *con) {
             /* Invalidate focused_id to correctly focus new windows with the same ID */
             focused_id = XCB_NONE;
         } else {
+            bool set_focus = true;
             if (focused->window != NULL &&
                 focused->window->needs_take_focus) {
-                DLOG("Updating focus by sending WM_TAKE_FOCUS to window 0x%08x only (focused: %p / %s)\n",
+                DLOG("Updating focus by sending WM_TAKE_FOCUS to window 0x%08x (focused: %p / %s)\n",
                      to_focus, focused, focused->name);
                 send_take_focus(to_focus);
-            } else {
+                set_focus = !focused->window->doesnt_accept_focus;
+                DLOG("set_focus = %d\n", set_focus);
+            }
+
+            if (set_focus) {
                 DLOG("Updating focus (focused: %p / %s)\n", focused, focused->name);
                 /* We remove XCB_EVENT_MASK_FOCUS_CHANGE from the event mask to get
                  * no focus change events for our own focus changes. We only want