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:
parent
89a29b5404
commit
e54d911a94
4
event.c
4
event.c
|
@ -645,7 +645,7 @@ event_handle_key(xcb_key_press_event_t *ev)
|
||||||
/* get keysym ignoring all modifiers */
|
/* get keysym ignoring all modifiers */
|
||||||
xcb_keysym_t keysym = keyresolv_get_keysym(ev->detail, 0);
|
xcb_keysym_t keysym = keyresolv_get_keysym(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(globalconf.L, c);
|
luaA_object_push(globalconf.L, c);
|
||||||
event_key_callback(ev, &c->keys, -1, 1, &keysym);
|
event_key_callback(ev, &c->keys, -1, 1, &keysym);
|
||||||
|
@ -836,6 +836,8 @@ event_handle_mappingnotify(xcb_mapping_notify_event_t *ev)
|
||||||
client_t *c = *_c;
|
client_t *c = *_c;
|
||||||
xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->window, XCB_BUTTON_MASK_ANY);
|
xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->window, XCB_BUTTON_MASK_ANY);
|
||||||
xwindow_grabkeys(c->window, &c->keys);
|
xwindow_grabkeys(c->window, &c->keys);
|
||||||
|
if (c->nofocus_window)
|
||||||
|
xwindow_grabkeys(c->nofocus_window, &c->keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,6 +164,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.
|
||||||
|
@ -326,6 +336,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)
|
||||||
{
|
{
|
||||||
|
@ -344,11 +368,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);
|
||||||
|
@ -1226,6 +1246,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();
|
||||||
|
|
||||||
|
@ -2275,6 +2297,8 @@ luaA_client_keys(lua_State *L)
|
||||||
luaA_object_emit_signal(L, 1, "property::keys", 0);
|
luaA_object_emit_signal(L, 1, "property::keys", 0);
|
||||||
xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->window, XCB_BUTTON_MASK_ANY);
|
xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->window, XCB_BUTTON_MASK_ANY);
|
||||||
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);
|
||||||
|
|
|
@ -56,6 +56,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 */
|
||||||
|
@ -137,6 +139,7 @@ LUA_OBJECT_FUNCS(client_class, client_t, client)
|
||||||
|
|
||||||
bool client_maybevisible(client_t *);
|
bool client_maybevisible(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 *);
|
||||||
|
|
Loading…
Reference in New Issue