Make client key bindings for e.g. xeyes work again

Instead of focusing the root window, we now create a "focus window" inside of
our frame window. This window is placed so that it is not visible, but we can
grab key bindings on it to simulate the window having the input focus.

Fixes: https://github.com/awesomeWM/awesome/issues/699
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2016-02-28 13:29:25 +01:00
parent f9d15691b8
commit aae960e99e
4 changed files with 35 additions and 6 deletions

View File

@ -673,7 +673,7 @@ event_handle_key(xcb_key_press_event_t *ev)
/* get keysym ignoring all modifiers */ /* get keysym ignoring all modifiers */
xcb_keysym_t keysym = xcb_key_symbols_get_keysym(globalconf.keysyms, ev->detail, 0); xcb_keysym_t keysym = xcb_key_symbols_get_keysym(globalconf.keysyms, ev->detail, 0);
client_t *c; 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); luaA_object_push(L, c);
event_key_callback(ev, &c->keys, L, -1, 1, &keysym); event_key_callback(ev, &c->keys, L, -1, 1, &keysym);

View File

@ -254,6 +254,16 @@ client_getbywin(xcb_window_t w)
return NULL; 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. /** Get a client by its frame window.
* \param w The client window to find. * \param w The client window to find.
* \return A client pointer if found, NULL otherwise. * \return A client pointer if found, NULL otherwise.
@ -416,6 +426,20 @@ client_focus(client_t *c)
globalconf.focus.need_update = true; 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 void
client_focus_refresh(void) client_focus_refresh(void)
{ {
@ -434,11 +458,7 @@ client_focus_refresh(void)
if(!c->nofocus) if(!c->nofocus)
win = c->window; win = c->window;
else else
/* Move the focus away from whatever has it to make sure the win = client_get_nofocus_window(c);
* previously focused client doesn't get any input in case
* WM_TAKE_FOCUS gets ignored.
*/
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);
@ -1360,6 +1380,8 @@ client_unmanage(client_t *c, bool window_valid)
/* Ignore all spurious enter/leave notify events */ /* Ignore all spurious enter/leave notify events */
client_ignore_enterleave_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); xcb_destroy_window(globalconf.connection, c->frame_window);
client_restore_enterleave_events(); client_restore_enterleave_events();
@ -2499,6 +2521,8 @@ luaA_client_keys(lua_State *L)
luaA_key_array_set(L, 1, 2, keys); luaA_key_array_set(L, 1, 2, keys);
luaA_object_emit_signal(L, 1, "property::keys", 0); luaA_object_emit_signal(L, 1, "property::keys", 0);
xwindow_grabkeys(c->window, keys); xwindow_grabkeys(c->window, keys);
if (c->nofocus_window)
xwindow_grabkeys(c->nofocus_window, &c->keys);
} }
return luaA_key_array_get(L, 1, keys); return luaA_key_array_get(L, 1, keys);

View File

@ -51,6 +51,8 @@ typedef enum {
struct client_t struct client_t
{ {
WINDOW_OBJECT_HEADER WINDOW_OBJECT_HEADER
/** Window we use for input focus and no-input clients */
xcb_window_t nofocus_window;
/** Client logical screen */ /** Client logical screen */
screen_t *screen; screen_t *screen;
/** Client name */ /** Client name */
@ -139,6 +141,7 @@ LUA_OBJECT_FUNCS(client_class, client_t, client)
bool client_on_selected_tags(client_t *); bool client_on_selected_tags(client_t *);
client_t * client_getbywin(xcb_window_t); client_t * client_getbywin(xcb_window_t);
client_t * client_getbynofocuswin(xcb_window_t);
client_t * client_getbyframewin(xcb_window_t); client_t * client_getbyframewin(xcb_window_t);
void client_ban(client_t *); void client_ban(client_t *);

2
xkb.c
View File

@ -199,6 +199,8 @@ xkb_reload_keymap(void)
{ {
client_t *c = *_c; client_t *c = *_c;
xwindow_grabkeys(c->window, &c->keys); xwindow_grabkeys(c->window, &c->keys);
if (c->nofocus_window)
xwindow_grabkeys(c->nofocus_window, &c->keys);
} }
} }