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 <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2015-09-23 20:48:56 +02:00 committed by Daniel Hahler
parent dd657c0531
commit 2f78ec5b30
3 changed files with 17 additions and 10 deletions

View File

@ -569,23 +569,27 @@ main(int argc, char **argv)
xkb_init(); xkb_init();
/* The default GC is just a newly created associated with a window with /* The default GC is just a newly created associated with a window with
* depth globalconf.default_depth */ * depth globalconf.default_depth.
xcb_window_t tmp_win = xcb_generate_id(globalconf.connection); * 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); globalconf.gc = xcb_generate_id(globalconf.connection);
xcb_create_window(globalconf.connection, globalconf.default_depth, 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, -1, -1, 1, 1, 0,
XCB_COPY_FROM_PARENT, globalconf.visual->visual_id, 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 []) (const uint32_t [])
{ {
globalconf.screen->black_pixel, globalconf.screen->black_pixel,
globalconf.screen->black_pixel, globalconf.screen->black_pixel,
1,
globalconf.default_cmap 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 }); (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 */ /* Get the window tree associated to this screen */
tree_c = xcb_query_tree_unchecked(globalconf.connection, tree_c = xcb_query_tree_unchecked(globalconf.connection,

View File

@ -117,6 +117,8 @@ typedef struct
client_t *client; client_t *client;
/** Is there a focus change pending? */ /** Is there a focus change pending? */
bool need_update; bool need_update;
/** When nothing has the input focus, this window actually is focused */
xcb_window_t window_no_focus;
} focus; } focus;
/** Drawins */ /** Drawins */
drawin_array_t drawins; drawin_array_t drawins;

View File

@ -433,7 +433,7 @@ void
client_focus_refresh(void) client_focus_refresh(void)
{ {
client_t *c = globalconf.focus.client; 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) if(!globalconf.focus.need_update)
return; return;
@ -447,10 +447,11 @@ client_focus_refresh(void)
if(!c->nofocus) if(!c->nofocus)
win = c->window; win = c->window;
else else
/* Focus the root window to make sure the previously focused client /* Move the focus away from whatever has it to make sure the
* doesn't get any input in case WM_TAKE_FOCUS gets ignored. * 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)) if(client_hasproto(c, WM_TAKE_FOCUS))
xwindow_takefocus(c->window); xwindow_takefocus(c->window);