diff --git a/awesome.c b/awesome.c index 156d61f4c..2ce1bb514 100644 --- a/awesome.c +++ b/awesome.c @@ -527,8 +527,6 @@ main(int argc, char **argv) | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE - | XCB_EVENT_MASK_KEY_PRESS - | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_FOCUS_CHANGE }; diff --git a/client.c b/client.c index e0fa8dbc2..5a8df3f76 100644 --- a/client.c +++ b/client.c @@ -597,17 +597,6 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen, */ window_state_set(c->win, XCB_WM_STATE_NORMAL); - /* Grab everything */ - xcb_grab_key(globalconf.connection, true, w, - XCB_MOD_MASK_ANY, XCB_GRAB_ANY, - XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC); - - xcb_grab_button(globalconf.connection, false, w, - XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, - XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, - XCB_GRAB_ANY, XCB_MOD_MASK_ANY); - - if(!startup) spawn_start_notify(c); @@ -1923,6 +1912,8 @@ luaA_client_buttons(lua_State *L) if(lua_gettop(L) == 2) luaA_button_array_set(L, 1, 2, buttons); + window_buttons_grab(client->win, &client->buttons); + return luaA_button_array_get(L, 1, buttons); } @@ -1941,7 +1932,11 @@ luaA_client_keys(lua_State *L) key_array_t *keys = &c->keys; if(lua_gettop(L) == 2) + { luaA_key_array_set(L, 1, 2, keys); + xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->win, XCB_BUTTON_MASK_ANY); + window_grabkeys(c->win, keys); + } return luaA_key_array_get(L, 1, keys); } diff --git a/event.c b/event.c index f21dd527c..f7df3d4aa 100644 --- a/event.c +++ b/event.c @@ -43,7 +43,7 @@ #include "common/xutil.h" #define DO_EVENT_HOOK_CALLBACK(type, prefix, xcbtype, xcbeventprefix, arraytype, match) \ - static int \ + static void \ event_##xcbtype##_callback(xcb_##xcbtype##_press_event_t *ev, \ arraytype *arr, \ int oud, \ @@ -51,7 +51,7 @@ void *data) \ { \ int abs_oud = oud < 0 ? ((lua_gettop(globalconf.L) + 1) + oud) : oud; \ - int item_matching = 0, item_matched = 0; \ + int item_matching = 0; \ foreach(item, *arr) \ if(match(ev, *item, data)) \ { \ @@ -61,7 +61,7 @@ prefix##_push(globalconf.L, *item); \ item_matching++; \ } \ - for(item_matched = item_matching; item_matching > 0; item_matching--) \ + for(; item_matching > 0; item_matching--) \ { \ type *item = luaL_checkudata(globalconf.L, -1, #prefix); \ switch(ev->response_type) \ @@ -102,7 +102,6 @@ lua_pop(globalconf.L, 1); \ } \ lua_pop(globalconf.L, nargs); \ - return item_matched; \ } static bool @@ -603,19 +602,10 @@ event_handle_key(void *data __attribute__ ((unused)), if((c = client_getbywin(ev->event))) { client_push(globalconf.L, c); - if(!event_key_callback(ev, &c->keys, -1, 1, &keysym)) - if(!event_key_callback(ev, &globalconf.keys, 0, 0, &keysym)) - xcb_allow_events(globalconf.connection, - XCB_ALLOW_REPLAY_KEYBOARD, - XCB_CURRENT_TIME); - + event_key_callback(ev, &c->keys, -1, 1, &keysym); } else event_key_callback(ev, &globalconf.keys, 0, 0, &keysym); - - xcb_allow_events(globalconf.connection, - XCB_ALLOW_SYNC_KEYBOARD, - XCB_CURRENT_TIME); } return 0; @@ -797,6 +787,24 @@ event_handle_mappingnotify(void *data, globalconf.keysyms, &globalconf.numlockmask, &globalconf.shiftlockmask, &globalconf.capslockmask, &globalconf.modeswitchmask); + + int nscreen = xcb_setup_roots_length(xcb_get_setup(connection)); + + /* regrab everything */ + for(int phys_screen = 0; phys_screen < nscreen; phys_screen++) + { + xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen); + /* yes XCB_BUTTON_MASK_ANY is also for grab_key even if it's look weird */ + xcb_ungrab_key(connection, XCB_GRAB_ANY, s->root, XCB_BUTTON_MASK_ANY); + window_grabkeys(s->root, &globalconf.keys); + } + + foreach(_c, globalconf.clients) + { + client_t *c = *_c; + xcb_ungrab_key(connection, XCB_GRAB_ANY, c->win, XCB_BUTTON_MASK_ANY); + window_grabkeys(c->win, &c->keys); + } } return 0; diff --git a/key.c b/key.c index feddeba6b..322a409fe 100644 --- a/key.c +++ b/key.c @@ -31,6 +31,36 @@ #include "common/xutil.h" #include "common/tokenize.h" +/** Grab key on a window. + * \param win The window. + * \param k The key. + */ +static void +window_grabkey(xcb_window_t win, keyb_t *k) +{ + if(k->keycode) + xcb_grab_key(globalconf.connection, true, win, + k->mod, k->keycode, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); + else if(k->keysym) + { + xcb_keycode_t *keycodes = xcb_key_symbols_get_keycode(globalconf.keysyms, k->keysym); + if(keycodes) + { + for(xcb_keycode_t *kc = keycodes; *kc; kc++) + xcb_grab_key(globalconf.connection, true, win, + k->mod, *kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); + p_delete(&keycodes); + } + } +} + +void +window_grabkeys(xcb_window_t win, key_array_t *keys) +{ + foreach(k, *keys) + window_grabkey(win, *k); +} + /** XCB equivalent of XLookupString which translate the keycode given * by PressEvent to a KeySym and a string * \todo use XKB! diff --git a/key.h b/key.h index afb070489..aabd1cfb9 100644 --- a/key.h +++ b/key.h @@ -49,6 +49,7 @@ xcb_keysym_t key_getkeysym(xcb_keycode_t, uint16_t); void luaA_key_array_set(lua_State *, int, int, key_array_t *); int luaA_key_array_get(lua_State *, int, key_array_t *); +void window_grabkeys(xcb_window_t, key_array_t *); int luaA_pushmodifiers(lua_State *, uint16_t); uint16_t luaA_tomodifiers(lua_State *L, int ud); diff --git a/root.c b/root.c index e3c79f38e..cd0249b48 100644 --- a/root.c +++ b/root.c @@ -126,6 +126,15 @@ luaA_root_keys(lua_State *L) while(lua_next(L, 1)) key_array_append(&globalconf.keys, key_ref(L, -1)); + int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); + + for(int phys_screen = 0; phys_screen < nscreen; phys_screen++) + { + xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen); + xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, s->root, XCB_BUTTON_MASK_ANY); + window_grabkeys(s->root, &globalconf.keys); + } + return 1; } diff --git a/window.c b/window.c index 3d0bdbcaf..a8c48396b 100644 --- a/window.c +++ b/window.c @@ -23,8 +23,12 @@ #include #include "window.h" +#include "button.h" #include "common/atoms.h" +/** Mask shorthands */ +#define BUTTONMASK (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE) + /** Set client state (WM_STATE) property. * \param win The window to set state. * \param state The state to set. @@ -92,6 +96,19 @@ window_configure(xcb_window_t win, area_t geometry, int border) xcb_send_event(globalconf.connection, false, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char *) &ce); } +/** Grab or ungrab buttons on a window. + * \param win The window. + * \param buttons The buttons to grab. + */ +void +window_buttons_grab(xcb_window_t win, button_array_t *buttons) +{ + foreach(b, *buttons) + xcb_grab_button(globalconf.connection, false, win, BUTTONMASK, + XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, + (*b)->button, (*b)->mod); +} + /** Get the opacity of a window. * \param win The window. * \return The opacity, between 0 and 1 or -1 or no opacity set. diff --git a/window.h b/window.h index 321074b26..d606736d1 100644 --- a/window.h +++ b/window.h @@ -28,9 +28,11 @@ void window_state_set(xcb_window_t, long); xcb_get_property_cookie_t window_state_get_unchecked(xcb_window_t); uint32_t window_state_get_reply(xcb_get_property_cookie_t); void window_configure(xcb_window_t, area_t, int); +void window_buttons_grab(xcb_window_t, button_array_t *); double window_opacity_get(xcb_window_t); double window_opacity_get_from_reply(xcb_get_property_reply_t *); void window_opacity_set(xcb_window_t, double); +void window_grabbuttons(xcb_window_t, xcb_window_t, button_array_t *); void window_takefocus(xcb_window_t); void window_set_cursor(xcb_window_t, xcb_cursor_t);