diff --git a/event.c b/event.c index f52723330..bfaae46c5 100644 --- a/event.c +++ b/event.c @@ -673,7 +673,7 @@ event_handle_key(xcb_key_press_event_t *ev) /* get keysym ignoring all modifiers */ xcb_keysym_t keysym = xcb_key_symbols_get_keysym(globalconf.keysyms, ev->detail, 0); client_t *c; - if((c = client_getbywin(ev->event))) + if((c = client_getbywin(ev->event)) || (c = client_getbynofocuswin(ev->event))) { luaA_object_push(L, c); event_key_callback(ev, &c->keys, L, -1, 1, &keysym); diff --git a/objects/client.c b/objects/client.c index 5a61869a3..bffc44d5f 100644 --- a/objects/client.c +++ b/objects/client.c @@ -254,6 +254,16 @@ client_getbywin(xcb_window_t w) return NULL; } +client_t * +client_getbynofocuswin(xcb_window_t w) +{ + foreach(c, globalconf.clients) + if((*c)->nofocus_window == w) + return *c; + + return NULL; +} + /** Get a client by its frame window. * \param w The client window to find. * \return A client pointer if found, NULL otherwise. @@ -416,6 +426,20 @@ client_focus(client_t *c) globalconf.focus.need_update = true; } +static xcb_window_t +client_get_nofocus_window(client_t *c) +{ + if (c->nofocus_window == XCB_NONE) { + c->nofocus_window = xcb_generate_id(globalconf.connection); + xcb_create_window(globalconf.connection, globalconf.default_depth, c->nofocus_window, c->frame_window, + -2, -2, 1, 1, 0, XCB_COPY_FROM_PARENT, globalconf.visual->visual_id, + 0, NULL); + xcb_map_window(globalconf.connection, c->nofocus_window); + xwindow_grabkeys(c->nofocus_window, &c->keys); + } + return c->nofocus_window; +} + void client_focus_refresh(void) { @@ -434,11 +458,7 @@ client_focus_refresh(void) if(!c->nofocus) win = c->window; else - /* 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.focus.window_no_focus; + win = client_get_nofocus_window(c); if(client_hasproto(c, WM_TAKE_FOCUS)) xwindow_takefocus(c->window); @@ -1360,6 +1380,8 @@ client_unmanage(client_t *c, bool window_valid) /* Ignore all spurious enter/leave notify events */ client_ignore_enterleave_events(); + if (c->nofocus_window != XCB_NONE) + xcb_destroy_window(globalconf.connection, c->nofocus_window); xcb_destroy_window(globalconf.connection, c->frame_window); client_restore_enterleave_events(); @@ -2499,6 +2521,8 @@ luaA_client_keys(lua_State *L) luaA_key_array_set(L, 1, 2, keys); luaA_object_emit_signal(L, 1, "property::keys", 0); xwindow_grabkeys(c->window, keys); + if (c->nofocus_window) + xwindow_grabkeys(c->nofocus_window, &c->keys); } return luaA_key_array_get(L, 1, keys); diff --git a/objects/client.h b/objects/client.h index 86a28c9c2..2468fb89e 100644 --- a/objects/client.h +++ b/objects/client.h @@ -51,6 +51,8 @@ typedef enum { struct client_t { WINDOW_OBJECT_HEADER + /** Window we use for input focus and no-input clients */ + xcb_window_t nofocus_window; /** Client logical screen */ screen_t *screen; /** Client name */ @@ -139,6 +141,7 @@ LUA_OBJECT_FUNCS(client_class, client_t, client) bool client_on_selected_tags(client_t *); client_t * client_getbywin(xcb_window_t); +client_t * client_getbynofocuswin(xcb_window_t); client_t * client_getbyframewin(xcb_window_t); void client_ban(client_t *); diff --git a/xkb.c b/xkb.c index c206e44ff..f96944457 100644 --- a/xkb.c +++ b/xkb.c @@ -199,6 +199,8 @@ xkb_reload_keymap(void) { client_t *c = *_c; xwindow_grabkeys(c->window, &c->keys); + if (c->nofocus_window) + xwindow_grabkeys(c->nofocus_window, &c->keys); } }