2 * key.c - Key bindings configuration management
4 * Copyright © 2008 Julien Danjou <julien@danjou.info>
5 * Copyright © 2008 Pierre Habouzit <madcoder@debian.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 /* XStringToKeysym() and XKeysymToString()*/
27 #include "common/xutil.h"
28 #include "common/tokenize.h"
30 LUA_OBJECT_FUNCS(keyb_t
, key
, "key")
33 key_unref_simplified(keyb_t
**b
)
35 key_unref(globalconf
.L
, *b
);
38 ARRAY_FUNCS(keyb_t
*, key
, key_unref_simplified
)
39 DO_LUA_TOSTRING(keyb_t
, key
, "key")
41 /** Garbage collect a key.
42 * \param L The Lua VM state.
46 luaA_key_gc(lua_State
*L
)
48 keyb_t
*kbp
= luaL_checkudata(L
, 1, "key");
49 luaL_unref(globalconf
.L
, LUA_REGISTRYINDEX
, kbp
->press
);
50 luaL_unref(globalconf
.L
, LUA_REGISTRYINDEX
, kbp
->release
);
54 /** Grab key on a window.
55 * \param win The window.
59 window_grabkey(xcb_window_t win
, keyb_t
*k
)
62 xcb_grab_key(globalconf
.connection
, true, win
,
63 k
->mod
, k
->keycode
, XCB_GRAB_MODE_ASYNC
, XCB_GRAB_MODE_ASYNC
);
66 xcb_keycode_t
*keycodes
= xcb_key_symbols_get_keycode(globalconf
.keysyms
, k
->keysym
);
69 for(xcb_keycode_t
*kc
= keycodes
; *kc
; kc
++)
70 xcb_grab_key(globalconf
.connection
, true, win
,
71 k
->mod
, *kc
, XCB_GRAB_MODE_ASYNC
, XCB_GRAB_MODE_ASYNC
);
78 window_grabkeys(xcb_window_t win
, key_array_t
*keys
)
81 window_grabkey(win
, *k
);
84 /** Return the keysym from keycode.
85 * \param detail The keycode received.
86 * \param state The modifier state.
90 key_getkeysym(xcb_keycode_t detail
, uint16_t state
)
94 /* 'col' (third parameter) is used to get the proper KeySym
95 * according to modifier (XCB doesn't provide an equivalent to
98 * If Mode_Switch is ON we look into second group.
100 if(state
& globalconf
.modeswitchmask
)
102 k0
= xcb_key_symbols_get_keysym(globalconf
.keysyms
, detail
, 2);
103 k1
= xcb_key_symbols_get_keysym(globalconf
.keysyms
, detail
, 3);
107 k0
= xcb_key_symbols_get_keysym(globalconf
.keysyms
, detail
, 0);
108 k1
= xcb_key_symbols_get_keysym(globalconf
.keysyms
, detail
, 1);
111 /* If the second column does not exists use the first one. */
112 if(k1
== XCB_NO_SYMBOL
)
115 /* The numlock modifier is on and the second KeySym is a keypad
117 if((state
& globalconf
.numlockmask
) && xcb_is_keypad_key(k1
))
119 /* The Shift modifier is on, or if the Lock modifier is on and
120 * is interpreted as ShiftLock, use the first KeySym */
121 if((state
& XCB_MOD_MASK_SHIFT
)
122 || (state
& XCB_MOD_MASK_LOCK
&& (state
& globalconf
.shiftlockmask
)))
128 /* The Shift and Lock modifers are both off, use the first
130 else if(!(state
& XCB_MOD_MASK_SHIFT
) && !(state
& XCB_MOD_MASK_LOCK
))
133 /* The Shift modifier is off and the Lock modifier is on and is
134 * interpreted as CapsLock */
135 else if(!(state
& XCB_MOD_MASK_SHIFT
)
136 && (state
& XCB_MOD_MASK_LOCK
&& (state
& globalconf
.capslockmask
)))
137 /* The first Keysym is used but if that KeySym is lowercase
138 * alphabetic, then the corresponding uppercase KeySym is used
142 /* The Shift modifier is on, and the Lock modifier is on and is
143 * interpreted as CapsLock */
144 else if((state
& XCB_MOD_MASK_SHIFT
)
145 && (state
& XCB_MOD_MASK_LOCK
&& (state
& globalconf
.capslockmask
)))
146 /* The second Keysym is used but if that KeySym is lowercase
147 * alphabetic, then the corresponding uppercase KeySym is used
151 /* The Shift modifer is on, or the Lock modifier is on and is
152 * interpreted as ShiftLock, or both */
153 else if((state
& XCB_MOD_MASK_SHIFT
)
154 || (state
& XCB_MOD_MASK_LOCK
&& (state
& globalconf
.shiftlockmask
)))
157 return XCB_NO_SYMBOL
;
161 luaA_keystore(keyb_t
*key
, const char *str
, ssize_t len
)
167 key
->keysym
= XStringToKeysym(str
);
173 warn("there's no keysym named \"%s\"", str
);
177 key
->keycode
= atoi(str
+ 1);
181 /** Define a global key binding. This key binding will always be available.
182 * \param L The Lua VM state.
185 * \lparam A table with modifier keys: can be Control or Ctrl, Shift, Lock,
186 * Mod1, Mod2, Mod3, Mod4, Mod5 or Any.
187 * \lparam A key name.
188 * \lparam A function to execute on key press.
189 * \lparam A function to execute on key release.
193 luaA_key_new(lua_State
*L
)
198 luaA_ref press
= LUA_REFNIL
, release
= LUA_REFNIL
;
200 /* arg 2 is key mod table */
201 luaA_checktable(L
, 2);
203 key
= luaL_checklstring(L
, 3, &len
);
206 luaA_registerfct(L
, 4, &press
);
208 if(lua_gettop(L
) == 5 && !lua_isnil(L
, 5))
209 luaA_registerfct(L
, 5, &release
);
212 luaA_keystore(k
, key
, len
);
215 k
->release
= release
;
217 luaA_setmodifiers(L
, 2, &k
->mod
);
222 /** Set a key array with a Lua table.
223 * \param L The Lua VM state.
224 * \param idx The index of the Lua table.
225 * \param keys The array key to fill.
228 luaA_key_array_set(lua_State
*L
, int idx
, key_array_t
*keys
)
230 luaA_checktable(L
, idx
);
232 key_array_wipe(keys
);
233 key_array_init(keys
);
236 while(lua_next(L
, idx
))
237 key_array_append(keys
, key_ref(L
));
240 /** Push an array of key as an Lua table onto the stack.
241 * \param L The Lua VM state.
242 * \param keys The key array to push.
243 * \return The number of elements pushed on stack.
246 luaA_key_array_get(lua_State
*L
, key_array_t
*keys
)
248 lua_createtable(L
, keys
->len
, 0);
249 for(int i
= 0; i
< keys
->len
; i
++)
251 key_push(L
, keys
->tab
[i
]);
252 lua_rawseti(L
, -2, i
+ 1);
257 /** Push a modifier set to a Lua table.
258 * \param L The Lua VM state.
259 * \param mod The modifier.
260 * \return The number of elements pushed on stack.
263 luaA_pushmodifiers(lua_State
*L
, uint16_t modifiers
)
268 for(uint32_t maski
= XCB_MOD_MASK_SHIFT
; maski
<= XCB_BUTTON_MASK_ANY
; maski
<<= 1)
269 if(maski
& modifiers
)
273 xutil_key_mask_tostr(maski
, &mod
, &slen
);
274 lua_pushlstring(L
, mod
, slen
);
275 lua_rawseti(L
, -2, i
++);
281 /** Take a modifier table from the stack and set modifiers in mod.
282 * \param L The Lua VM state.
283 * \param ud The index of the table.
284 * \param mod Where to set the modifiers.
287 luaA_setmodifiers(lua_State
*L
, int ud
, uint16_t *mod
)
289 luaA_checktable(L
, ud
);
290 ssize_t len
= lua_objlen(L
, ud
);
291 for(int i
= 1; i
<= len
; i
++)
293 lua_rawgeti(L
, ud
, i
);
295 const char *key
= luaL_checklstring(L
, -1, &blen
);
296 *mod
|= xutil_key_mask_fromstr(key
, blen
);
302 * \param L The Lua VM state.
303 * \return The number of elements pushed on stack.
305 * \lfield key The key to press to triggers an event.
306 * \lfield modifiers The modifier key that should be pressed while the key is
307 * pressed. An array with all the modifiers. Valid modifiers are: Any, Mod1,
308 * Mod2, Mod3, Mod4, Mod5, Shift, Lock and Control.
309 * \lfield press The function which is called when the key combination is pressed.
310 * \lfield release The function which is called when the key combination is released.
313 luaA_key_index(lua_State
*L
)
316 keyb_t
*k
= luaL_checkudata(L
, 1, "key");
317 const char *attr
= luaL_checklstring(L
, 2, &len
);
319 if(luaA_usemetatable(L
, 1, 2))
322 switch(a_tokenize(attr
, len
))
328 int slen
= snprintf(buf
, sizeof(buf
), "#%u", k
->keycode
);
329 lua_pushlstring(L
, buf
, slen
);
332 lua_pushstring(L
, XKeysymToString(k
->keysym
));
335 luaA_pushmodifiers(L
, k
->mod
);
338 lua_rawgeti(L
, LUA_REGISTRYINDEX
, k
->press
);
341 lua_rawgeti(L
, LUA_REGISTRYINDEX
, k
->release
);
349 /** Key object newindex.
350 * \param L The Lua VM state.
351 * \return The number of elements pushed on stack.
354 luaA_key_newindex(lua_State
*L
)
357 keyb_t
*k
= luaL_checkudata(L
, 1, "key");
358 const char *attr
= luaL_checklstring(L
, 2, &len
);
360 switch(a_tokenize(attr
, len
))
365 const char *key
= luaL_checklstring(L
, 3, &klen
);
366 luaA_keystore(k
, key
, klen
);
370 luaA_setmodifiers(L
, 3, &k
->mod
);
373 luaA_registerfct(L
, 3, &k
->press
);
376 luaA_registerfct(L
, 3, &k
->release
);
384 const struct luaL_reg awesome_key_methods
[] =
386 { "__call", luaA_key_new
},
389 const struct luaL_reg awesome_key_meta
[] =
391 { "__tostring", luaA_key_tostring
},
392 { "__index", luaA_key_index
},
393 { "__newindex", luaA_key_newindex
},
394 { "__gc", luaA_key_gc
},