From 2f78ec5b30b71fc7e793f2fe6bf117485dc1a3c8 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Wed, 23 Sep 2015 20:48:56 +0200 Subject: [PATCH] Never explicitly focus the root window Whenever client.focus == nil, we set the input focus to the root window to express "nothing has the input focus". However, thanks to the way X11 input works, this means that whatever is under the mouse cursor gets keyboard input events. This can easily be reproduced with urxvt and some small addition to the config to unfocus things. This commit changes things. Instead of focusing the root window, we create a special "no focus" window that gets focused if we want nothing to have the focus. Closes https://github.com/awesomeWM/awesome/pull/470. Signed-off-by: Uli Schlachter --- awesome.c | 16 ++++++++++------ globalconf.h | 2 ++ objects/client.c | 9 +++++---- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/awesome.c b/awesome.c index fc102800b..952b1939e 100644 --- a/awesome.c +++ b/awesome.c @@ -569,23 +569,27 @@ main(int argc, char **argv) xkb_init(); /* The default GC is just a newly created associated with a window with - * depth globalconf.default_depth */ - xcb_window_t tmp_win = xcb_generate_id(globalconf.connection); + * depth globalconf.default_depth. + * The window_no_focus is used for "nothing has the input focus". */ + globalconf.focus.window_no_focus = xcb_generate_id(globalconf.connection); globalconf.gc = xcb_generate_id(globalconf.connection); xcb_create_window(globalconf.connection, globalconf.default_depth, - tmp_win, globalconf.screen->root, + globalconf.focus.window_no_focus, globalconf.screen->root, -1, -1, 1, 1, 0, XCB_COPY_FROM_PARENT, globalconf.visual->visual_id, - XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP, + XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | + XCB_CW_OVERRIDE_REDIRECT | XCB_CW_COLORMAP, (const uint32_t []) { globalconf.screen->black_pixel, globalconf.screen->black_pixel, + 1, globalconf.default_cmap }); - xcb_create_gc(globalconf.connection, globalconf.gc, tmp_win, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, + xcb_map_window(globalconf.connection, globalconf.focus.window_no_focus); + xcb_create_gc(globalconf.connection, globalconf.gc, globalconf.focus.window_no_focus, + XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, (const uint32_t[]) { globalconf.screen->black_pixel, globalconf.screen->white_pixel }); - xcb_destroy_window(globalconf.connection, tmp_win); /* Get the window tree associated to this screen */ tree_c = xcb_query_tree_unchecked(globalconf.connection, diff --git a/globalconf.h b/globalconf.h index 29a9d6a52..0f1b84848 100644 --- a/globalconf.h +++ b/globalconf.h @@ -117,6 +117,8 @@ typedef struct client_t *client; /** Is there a focus change pending? */ bool need_update; + /** When nothing has the input focus, this window actually is focused */ + xcb_window_t window_no_focus; } focus; /** Drawins */ drawin_array_t drawins; diff --git a/objects/client.c b/objects/client.c index 504425a72..821273764 100644 --- a/objects/client.c +++ b/objects/client.c @@ -433,7 +433,7 @@ void client_focus_refresh(void) { client_t *c = globalconf.focus.client; - xcb_window_t win = globalconf.screen->root; + xcb_window_t win = globalconf.focus.window_no_focus; if(!globalconf.focus.need_update) return; @@ -447,10 +447,11 @@ client_focus_refresh(void) if(!c->nofocus) win = c->window; else - /* Focus the root window to make sure the previously focused client - * doesn't get any input in case WM_TAKE_FOCUS gets ignored. + /* Move the focus away from whatever has it to make sure the + * previously focused client doesn't get any input in case + * WM_TAKE_FOCUS gets ignored. */ - win = globalconf.screen->root; + win = globalconf.focus.window_no_focus; if(client_hasproto(c, WM_TAKE_FOCUS)) xwindow_takefocus(c->window);