From 3dbf89c990d4796c6a8170bb3eb10e74890b3233 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 10 Oct 2010 14:50:35 +0200 Subject: [PATCH] Lazyle set the input focus (FS#804) Instead of immediately setting the X11 input focus when client.focus is assigned something, we now just remember that we'll have to do something later. The focus is then set in the next prepare call by libev (= after the current main loop run is done). Signed-off-by: Uli Schlachter --- event.h | 1 + globalconf.h | 2 ++ objects/client.c | 46 ++++++++++++++++++++++++++-------------------- objects/client.h | 1 + 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/event.h b/event.h index 447394a9b..66b25f638 100644 --- a/event.h +++ b/event.h @@ -29,6 +29,7 @@ awesome_refresh(void) { banning_refresh(); stack_refresh(); + client_focus_refresh(); return xcb_flush(globalconf.connection); } diff --git a/globalconf.h b/globalconf.h index 2027ea763..88272d28a 100644 --- a/globalconf.h +++ b/globalconf.h @@ -85,6 +85,8 @@ typedef struct { /** Focused client */ client_t *client; + /** Is there a focus change pending? */ + bool need_update; } focus; /** Drawins */ drawin_array_t drawins; diff --git a/objects/client.c b/objects/client.c index 2a05f66d1..6e1dd4d6f 100644 --- a/objects/client.c +++ b/objects/client.c @@ -188,6 +188,7 @@ static void client_unfocus_update(client_t *c) { globalconf.focus.client = NULL; + globalconf.focus.need_update = true; luaA_object_push(globalconf.L, c); luaA_object_emit_signal(globalconf.L, -1, "unfocus", 0); @@ -200,15 +201,6 @@ client_unfocus_update(client_t *c) static void client_unfocus(client_t *c) { - - xcb_window_t root_win = globalconf.screen->root; - /* Set focus on root window, so no events leak to the current window. - * This kind of inlines client_set_focus(), but a root window will never have - * the WM_TAKE_FOCUS protocol. - */ - xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_PARENT, - root_win, globalconf.timestamp); - client_unfocus_update(c); } @@ -329,19 +321,33 @@ client_focus(client_t *c) if(!client_maybevisible(c, c->screen)) return; - /* X11 doesn't let you focus a window that isn't viewable */ - client_unban(c); + client_focus_update(c); + globalconf.focus.need_update = true; +} - /* Sets focus on window - using xcb_set_input_focus or WM_TAKE_FOCUS */ - if(!c->nofocus) +void +client_focus_refresh(void) +{ + client_t *c = globalconf.focus.client; + + if(!globalconf.focus.need_update) + return; + globalconf.focus.need_update = false; + + if(c) + { + /* Sets focus on window - using xcb_set_input_focus or WM_TAKE_FOCUS */ + if(!c->nofocus) + xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_PARENT, + c->window, globalconf.timestamp); + + if(client_hasproto(c, WM_TAKE_FOCUS)) + xwindow_takefocus(c->window); + } + else + /* Nothing has the focus, set the focus to the root window */ xcb_set_input_focus(globalconf.connection, XCB_INPUT_FOCUS_PARENT, - c->window, globalconf.timestamp); - - if(client_hasproto(c, WM_TAKE_FOCUS)) - xwindow_takefocus(c->window); - - if (!c->nofocus) - client_focus_update(c); + globalconf.screen->root, globalconf.timestamp); } static void diff --git a/objects/client.h b/objects/client.h index 3a24e00ad..ec63537b8 100644 --- a/objects/client.h +++ b/objects/client.h @@ -145,6 +145,7 @@ void client_set_icon(lua_State *, int, int); void client_set_skip_taskbar(lua_State *, int, bool); void client_focus(client_t *); void client_focus_update(client_t *); +void client_focus_refresh(void); bool client_hasproto(client_t *, xcb_atom_t); void client_ignore_enterleave_events(void); void client_restore_enterleave_events(void);