button, key: grab all keys by default, and check for match.

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2009-07-28 10:42:31 +02:00
parent f4579d1dc1
commit f6d2aa3064
8 changed files with 27 additions and 95 deletions

View File

@ -527,6 +527,8 @@ main(int argc, char **argv)
| XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE
| XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_PRESS
| XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_RELEASE
| XCB_EVENT_MASK_KEY_PRESS
| XCB_EVENT_MASK_KEY_RELEASE
| XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE
}; };

View File

@ -576,6 +576,17 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen,
*/ */
window_state_set(c->win, XCB_WM_STATE_NORMAL); 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) if(!startup)
spawn_start_notify(c); spawn_start_notify(c);
@ -1061,16 +1072,8 @@ client_unmanage(client_t *c)
if(globalconf.hooks.clients != LUA_REFNIL) if(globalconf.hooks.clients != LUA_REFNIL)
luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.clients, 0, 0); luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.clients, 0, 0);
/* The server grab construct avoids race conditions. */
xcb_grab_server(globalconf.connection);
xcb_ungrab_button(globalconf.connection, XCB_BUTTON_INDEX_ANY, c->win,
XCB_BUTTON_MASK_ANY);
window_state_set(c->win, XCB_WM_STATE_WITHDRAWN); window_state_set(c->win, XCB_WM_STATE_WITHDRAWN);
xcb_flush(globalconf.connection);
xcb_ungrab_server(globalconf.connection);
titlebar_client_detach(c); titlebar_client_detach(c);
ewmh_update_net_client_list(c->phys_screen); ewmh_update_net_client_list(c->phys_screen);
@ -1914,8 +1917,6 @@ luaA_client_buttons(lua_State *L)
if(lua_gettop(L) == 2) if(lua_gettop(L) == 2)
luaA_button_array_set(L, 1, 2, buttons); luaA_button_array_set(L, 1, 2, buttons);
window_buttons_grab(client->win, &client->buttons);
return luaA_button_array_get(L, 1, buttons); return luaA_button_array_get(L, 1, buttons);
} }
@ -1934,11 +1935,7 @@ luaA_client_keys(lua_State *L)
key_array_t *keys = &c->keys; key_array_t *keys = &c->keys;
if(lua_gettop(L) == 2) if(lua_gettop(L) == 2)
{
luaA_key_array_set(L, 1, 2, keys); 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); return luaA_key_array_get(L, 1, keys);
} }

36
event.c
View File

@ -43,7 +43,7 @@
#include "common/xutil.h" #include "common/xutil.h"
#define DO_EVENT_HOOK_CALLBACK(type, prefix, xcbtype, xcbeventprefix, arraytype, match) \ #define DO_EVENT_HOOK_CALLBACK(type, prefix, xcbtype, xcbeventprefix, arraytype, match) \
static void \ static int \
event_##xcbtype##_callback(xcb_##xcbtype##_press_event_t *ev, \ event_##xcbtype##_callback(xcb_##xcbtype##_press_event_t *ev, \
arraytype *arr, \ arraytype *arr, \
int oud, \ int oud, \
@ -51,7 +51,7 @@
void *data) \ void *data) \
{ \ { \
int abs_oud = oud < 0 ? ((lua_gettop(globalconf.L) + 1) + oud) : oud; \ int abs_oud = oud < 0 ? ((lua_gettop(globalconf.L) + 1) + oud) : oud; \
int item_matching = 0; \ int item_matching = 0, item_matched = 0; \
foreach(item, *arr) \ foreach(item, *arr) \
if(match(ev, *item, data)) \ if(match(ev, *item, data)) \
{ \ { \
@ -61,7 +61,7 @@
prefix##_push(globalconf.L, *item); \ prefix##_push(globalconf.L, *item); \
item_matching++; \ item_matching++; \
} \ } \
for(; item_matching > 0; item_matching--) \ for(item_matched = item_matching; item_matching > 0; item_matching--) \
{ \ { \
type *item = luaL_checkudata(globalconf.L, -1, #prefix); \ type *item = luaL_checkudata(globalconf.L, -1, #prefix); \
switch(ev->response_type) \ switch(ev->response_type) \
@ -102,6 +102,7 @@
lua_pop(globalconf.L, 1); \ lua_pop(globalconf.L, 1); \
} \ } \
lua_pop(globalconf.L, nargs); \ lua_pop(globalconf.L, nargs); \
return item_matched; \
} }
static bool static bool
@ -602,10 +603,19 @@ event_handle_key(void *data __attribute__ ((unused)),
if((c = client_getbywin(ev->event))) if((c = client_getbywin(ev->event)))
{ {
client_push(globalconf.L, c); client_push(globalconf.L, c);
event_key_callback(ev, &c->keys, -1, 1, &keysym); 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);
} }
else else
event_key_callback(ev, &globalconf.keys, 0, 0, &keysym); event_key_callback(ev, &globalconf.keys, 0, 0, &keysym);
xcb_allow_events(globalconf.connection,
XCB_ALLOW_SYNC_KEYBOARD,
XCB_CURRENT_TIME);
} }
return 0; return 0;
@ -787,24 +797,6 @@ event_handle_mappingnotify(void *data,
globalconf.keysyms, &globalconf.numlockmask, globalconf.keysyms, &globalconf.numlockmask,
&globalconf.shiftlockmask, &globalconf.capslockmask, &globalconf.shiftlockmask, &globalconf.capslockmask,
&globalconf.modeswitchmask); &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; return 0;

30
key.c
View File

@ -33,36 +33,6 @@
DO_LUA_TOSTRING(keyb_t, key, "key") DO_LUA_TOSTRING(keyb_t, key, "key")
/** 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 /** XCB equivalent of XLookupString which translate the keycode given
* by PressEvent to a KeySym and a string * by PressEvent to a KeySym and a string
* \todo use XKB! * \todo use XKB!

1
key.h
View File

@ -48,7 +48,6 @@ xcb_keysym_t key_getkeysym(xcb_keycode_t, uint16_t);
void luaA_key_array_set(lua_State *, int, int, key_array_t *); void luaA_key_array_set(lua_State *, int, int, key_array_t *);
int luaA_key_array_get(lua_State *, 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); int luaA_pushmodifiers(lua_State *, uint16_t);
uint16_t luaA_tomodifiers(lua_State *L, int ud); uint16_t luaA_tomodifiers(lua_State *L, int ud);

9
root.c
View File

@ -126,15 +126,6 @@ luaA_root_keys(lua_State *L)
while(lua_next(L, 1)) while(lua_next(L, 1))
key_array_append(&globalconf.keys, key_ref(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; return 1;
} }

View File

@ -23,12 +23,8 @@
#include <xcb/xcb_atom.h> #include <xcb/xcb_atom.h>
#include "window.h" #include "window.h"
#include "button.h"
#include "common/atoms.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. /** Set client state (WM_STATE) property.
* \param win The window to set state. * \param win The window to set state.
* \param state The state to set. * \param state The state to set.
@ -96,19 +92,6 @@ 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); 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. /** Get the opacity of a window.
* \param win The window. * \param win The window.
* \return The opacity, between 0 and 1 or -1 or no opacity set. * \return The opacity, between 0 and 1 or -1 or no opacity set.

View File

@ -28,11 +28,9 @@ void window_state_set(xcb_window_t, long);
xcb_get_property_cookie_t window_state_get_unchecked(xcb_window_t); xcb_get_property_cookie_t window_state_get_unchecked(xcb_window_t);
uint32_t window_state_get_reply(xcb_get_property_cookie_t); uint32_t window_state_get_reply(xcb_get_property_cookie_t);
void window_configure(xcb_window_t, area_t, int); 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(xcb_window_t);
double window_opacity_get_from_reply(xcb_get_property_reply_t *); double window_opacity_get_from_reply(xcb_get_property_reply_t *);
void window_opacity_set(xcb_window_t, double); 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_takefocus(xcb_window_t);
#endif #endif