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
parent abf7d1546c
commit 9b5ab994b0
3 changed files with 17 additions and 10 deletions

View File

@ -558,23 +558,27 @@ main(int argc, char **argv)
spawn_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,

View File

@ -112,6 +112,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;

View File

@ -343,7 +343,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;
@ -357,10 +357,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);