We don't need to unfocus currently selected client.
Added WM_TAKE_FOCUS atom, so we can implement correct ICCCM,
focus behavior, in relation to Input Models ( sections 4.1.7 [1],
4.2.7 [2] ).
Currently correctly implemented are, "No Input", and "Passive"
models, and additionally works "Locally Active".
To test focus-in and focus-out events I used program from [3].

[1] http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.7
[2] http://tronche.com/gui/x/icccm/sec-4.html#s-4.2.7
[3] http://mail.gnome.org/archives/gtk-devel-list/2001-November/msg00334.html

Signed-off-by: Mariusz Ceier <[email protected]>
---
 client.c          |   53 ++++++++++++++++++++++++++++++++++++++---------------
 common/atoms.list |    1 +
 2 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/client.c b/client.c
index ea107f6..0b1d688 100644
--- a/client.c
+++ b/client.c
@@ -179,6 +179,20 @@ client_getbywin(xcb_window_t w)
     return c;
 }
 
+/** Call unfocus hook.
+ * \param c Client being unfocused
+ */
+static void
+client_unfocus_hook(client_t *c)
+{
+    /* Call hook */
+    if(globalconf.hooks.unfocus != LUA_REFNIL)
+    {
+        luaA_client_userdata_new(globalconf.L, c);
+        luaA_dofunction(globalconf.L, globalconf.hooks.unfocus, 1, 0);
+    }
+}
+
 /** Unfocus a client.
  * \param c The client.
  */
@@ -189,16 +203,10 @@ client_unfocus(client_t *c)
     globalconf.screens[c->phys_screen].client_focus = NULL;
 
     /* Set focus on root window, so no events leak to the current window. */
-    if (!c->nofocus)
-        xcb_set_input_focus(globalconf.connection, 
XCB_INPUT_FOCUS_POINTER_ROOT,
+    xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_POINTER_ROOT,
             root_win, XCB_CURRENT_TIME);
 
-    /* Call hook */
-    if(globalconf.hooks.unfocus != LUA_REFNIL)
-    {
-        luaA_client_userdata_new(globalconf.L, c);
-        luaA_dofunction(globalconf.L, globalconf.hooks.unfocus, 1, 0);
-    }
+    client_unfocus_hook(c);
 
     ewmh_update_net_active_window(c->phys_screen);
 }
@@ -244,10 +252,21 @@ client_focus(client_t *c)
     if(!client_maybevisible(c, c->screen))
         return;
 
-    /* unfocus current selected client */
+    bool takefocus = window_hasproto(c->win, WM_TAKE_FOCUS);
+
+    /* Input Model: No Input */
+    if ((!takefocus)&&(c->nofocus))
+        return;
+
+    /* unfocus current selected client
+     * We don't really need to unfocus here,
+     * because client already received FocusOut event.
+     * What we need to do is call unfocus hook, to
+     * inform lua script, about this event.
+     */
     if(globalconf.screen_focus->client_focus
        && c != globalconf.screen_focus->client_focus)
-        client_unfocus(globalconf.screen_focus->client_focus);
+        client_unfocus_hook(globalconf.screen_focus->client_focus);
 
     /* stop hiding c */
     c->ishidden = false;
@@ -259,9 +278,14 @@ client_focus(client_t *c)
     globalconf.screen_focus = &globalconf.screens[c->phys_screen];
     globalconf.screen_focus->client_focus = c;
 
-    if (!c->nofocus)
-        xcb_set_input_focus(globalconf.connection, 
XCB_INPUT_FOCUS_POINTER_ROOT,
-                            c->win, XCB_CURRENT_TIME);
+    /* Input Models: Passive, Locally Active */
+    xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_POINTER_ROOT,
+                        c->win, XCB_CURRENT_TIME);
+
+    /* TODO: Currently we don't handle correctly globally active input model 
+     * One fix I know of, is we should handle FocusIn and FocusOut events for 
windows,
+     * and use WM_TAKE_FOCUS client message.
+     */
 
     /* Some layouts use focused client differently, so call them back.
      * And anyway, we have maybe unhidden */
@@ -1349,8 +1373,7 @@ luaA_client_redraw(lua_State *L)
        performed on the window where the pointer is currently on
        because after the unmapping/mapping, the focus is lost */
     if(globalconf.screen_focus->client_focus == *c)
-        xcb_set_input_focus(globalconf.connection, 
XCB_INPUT_FOCUS_POINTER_ROOT,
-                            (*c)->win, XCB_CURRENT_TIME);
+        client_focus(*c);
 
     return 0;
 }
diff --git a/common/atoms.list b/common/atoms.list
index f426fad..dd4c7c9 100644
--- a/common/atoms.list
+++ b/common/atoms.list
@@ -55,3 +55,4 @@ WM_CHANGE_STATE
 WM_WINDOW_ROLE
 WM_CLIENT_LEADER
 XSEL_DATA
+WM_TAKE_FOCUS
-- 
1.6.1.1


-- 
To unsubscribe, send mail to [email protected].

Reply via email to