diff --git a/client.c b/client.c index a195d9fe6..8afc0a23d 100644 --- a/client.c +++ b/client.c @@ -202,7 +202,7 @@ client_unfocus_hook(client_t *c) /** Unfocus a client. * \param c The client. */ -static void +void client_unfocus(client_t *c) { xcb_window_t root_win = xutil_screen_get(globalconf.connection, c->phys_screen)->root; @@ -293,6 +293,10 @@ client_focus(client_t *c, bool sendmessage) if(c == focused_before) return; + /* If we recieved a FocusOut event, this condition won't be hit. */ + if(focused_before) + client_unfocus(focused_before); + /* stop hiding c */ c->ishidden = false; client_setminimized(c, false); @@ -319,15 +323,6 @@ client_focus(client_t *c, bool sendmessage) * And anyway, we have maybe unhidden */ client_need_arrange(c); - /* 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(focused_before) - client_unfocus_hook(focused_before); - client_focus_hook(c); /* according to EWMH, we have to remove the urgent state from a client */ diff --git a/client.h b/client.h index b1d107786..160cf3de4 100644 --- a/client.h +++ b/client.h @@ -76,6 +76,7 @@ void client_setminimized(client_t *, bool); void client_setborder(client_t *, int); void client_seturgent(client_t *, bool); void client_focus(client_t *, bool); +void client_unfocus(client_t *); int luaA_client_newindex(lua_State *); diff --git a/event.c b/event.c index 6d7fe0c6a..ae9078350 100644 --- a/event.c +++ b/event.c @@ -548,6 +548,29 @@ event_handle_focusin(void *data __attribute__ ((unused)), return 0; } +/** The focus out event handler. + * \param data currently unused. + * \param connection The connection to the X server. + * \param ev The event. + */ +static int +event_handle_focusout(void *data __attribute__ ((unused)), + xcb_connection_t *connection, + xcb_focus_out_event_t *ev) +{ + /* filter focus-out events */ + if (ev->detail != XCB_NOTIFY_DETAIL_NONLINEAR) + return 0; + + client_t *c; + + if((c = client_getbytitlebarwin(ev->event)) + || (c = client_getbywin(ev->event))) + client_unfocus(c); + + return 0; +} + /** The expose event handler. * \param data currently unused. * \param connection The connection to the X server. @@ -865,6 +888,7 @@ void a_xcb_set_event_handlers(void) xcb_event_set_enter_notify_handler(&globalconf.evenths, event_handle_enternotify, NULL); xcb_event_set_leave_notify_handler(&globalconf.evenths, event_handle_leavenotify, NULL); xcb_event_set_focus_in_handler(&globalconf.evenths, event_handle_focusin, NULL); + xcb_event_set_focus_out_handler(&globalconf.evenths, event_handle_focusout, NULL); xcb_event_set_motion_notify_handler(&globalconf.evenths, event_handle_motionnotify, NULL); xcb_event_set_expose_handler(&globalconf.evenths, event_handle_expose, NULL); xcb_event_set_key_press_handler(&globalconf.evenths, event_handle_key, NULL);