tag: Improve tag property::index support (FS#1229)
[awesome.git] / objects / key.c
blob495d7e57e87bf03dd29674d4a8e6fbb190398897
1 /*
2 * key.c - Key bindings configuration management
4 * Copyright © 2008-2009 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 #include "objects/key.h"
24 #include "common/xutil.h"
25 #include "keyresolv.h"
27 /* XStringToKeysym() and XKeysymToString */
28 #include <X11/Xlib.h>
30 static void
31 luaA_keystore(lua_State *L, int ud, const char *str, ssize_t len)
33 keyb_t *key = luaA_checkudata(L, ud, &key_class);
34 if(len)
36 if(*str != '#')
38 key->keysym = XStringToKeysym(str);
39 if(!key->keysym)
41 if(len == 1)
42 key->keysym = *str;
43 else
44 warn("there's no keysym named \"%s\"", str);
46 key->keycode = 0;
48 else
50 key->keycode = atoi(str + 1);
51 key->keysym = 0;
53 luaA_object_emit_signal(L, ud, "property::key", 0);
57 /** Create a new key object.
58 * \param L The Lua VM state.
59 * \return The number of elements pushed on stack.
61 static int
62 luaA_key_new(lua_State *L)
64 return luaA_class_new(L, &key_class);
67 /** Set a key array with a Lua table.
68 * \param L The Lua VM state.
69 * \param oidx The index of the object to store items into.
70 * \param idx The index of the Lua table.
71 * \param keys The array key to fill.
73 void
74 luaA_key_array_set(lua_State *L, int oidx, int idx, key_array_t *keys)
76 luaA_checktable(L, idx);
78 foreach(key, *keys)
79 luaA_object_unref_item(L, oidx, *key);
81 key_array_wipe(keys);
82 key_array_init(keys);
84 lua_pushnil(L);
85 while(lua_next(L, idx))
86 if(luaA_toudata(L, -1, &key_class))
87 key_array_append(keys, luaA_object_ref_item(L, oidx, -1));
88 else
89 lua_pop(L, 1);
92 /** Push an array of key as an Lua table onto the stack.
93 * \param L The Lua VM state.
94 * \param oidx The index of the object to get items from.
95 * \param keys The key array to push.
96 * \return The number of elements pushed on stack.
98 int
99 luaA_key_array_get(lua_State *L, int oidx, key_array_t *keys)
101 lua_createtable(L, keys->len, 0);
102 for(int i = 0; i < keys->len; i++)
104 luaA_object_push_item(L, oidx, keys->tab[i]);
105 lua_rawseti(L, -2, i + 1);
107 return 1;
110 /** Push a modifier set to a Lua table.
111 * \param L The Lua VM state.
112 * \param modifiers The modifier.
113 * \return The number of elements pushed on stack.
116 luaA_pushmodifiers(lua_State *L, uint16_t modifiers)
118 lua_newtable(L);
120 int i = 1;
121 for(uint32_t maski = XCB_MOD_MASK_SHIFT; maski <= XCB_BUTTON_MASK_ANY; maski <<= 1)
122 if(maski & modifiers)
124 const char *mod;
125 size_t slen;
126 xutil_key_mask_tostr(maski, &mod, &slen);
127 lua_pushlstring(L, mod, slen);
128 lua_rawseti(L, -2, i++);
131 return 1;
134 /** Take a modifier table from the stack and return modifiers mask.
135 * \param L The Lua VM state.
136 * \param ud The index of the table.
137 * \return The mask value.
139 uint16_t
140 luaA_tomodifiers(lua_State *L, int ud)
142 luaA_checktable(L, ud);
143 ssize_t len = luaA_rawlen(L, ud);
144 uint16_t mod = XCB_NONE;
145 for(int i = 1; i <= len; i++)
147 lua_rawgeti(L, ud, i);
148 const char *key = luaL_checkstring(L, -1);
149 mod |= xutil_key_mask_fromstr(key);
150 lua_pop(L, 1);
152 return mod;
155 static int
156 luaA_key_set_modifiers(lua_State *L, keyb_t *k)
158 k->modifiers = luaA_tomodifiers(L, -1);
159 luaA_object_emit_signal(L, -3, "property::modifiers", 0);
160 return 0;
163 LUA_OBJECT_EXPORT_PROPERTY(key, keyb_t, modifiers, luaA_pushmodifiers)
165 static int
166 luaA_key_get_key(lua_State *L, keyb_t *k)
168 if(k->keycode)
170 char buf[12];
171 int slen = snprintf(buf, sizeof(buf), "#%u", k->keycode);
172 lua_pushlstring(L, buf, slen);
174 else
176 char buf[MAX(MB_LEN_MAX, 32)];
177 if(!keyresolv_keysym_to_string(k->keysym, buf, countof(buf)))
178 return 0;
180 lua_pushstring(L, buf);
182 return 1;
185 static int
186 luaA_key_get_keysym(lua_State *L, keyb_t *k)
188 lua_pushstring(L, XKeysymToString(k->keysym));
189 return 1;
192 static int
193 luaA_key_set_key(lua_State *L, keyb_t *k)
195 size_t klen;
196 const char *key = luaL_checklstring(L, -1, &klen);
197 luaA_keystore(L, -3, key, klen);
198 return 0;
201 void
202 key_class_setup(lua_State *L)
204 static const struct luaL_Reg key_methods[] =
206 LUA_CLASS_METHODS(key)
207 { "__call", luaA_key_new },
208 { NULL, NULL }
211 static const struct luaL_Reg key_meta[] =
213 LUA_OBJECT_META(key)
214 LUA_CLASS_META
215 { NULL, NULL },
218 luaA_class_setup(L, &key_class, "key", NULL,
219 (lua_class_allocator_t) key_new, NULL, NULL,
220 luaA_class_index_miss_property, luaA_class_newindex_miss_property,
221 key_methods, key_meta);
222 luaA_class_add_property(&key_class, "key",
223 (lua_class_propfunc_t) luaA_key_set_key,
224 (lua_class_propfunc_t) luaA_key_get_key,
225 (lua_class_propfunc_t) luaA_key_set_key);
226 luaA_class_add_property(&key_class, "keysym",
227 NULL,
228 (lua_class_propfunc_t) luaA_key_get_keysym,
229 NULL);
230 luaA_class_add_property(&key_class, "modifiers",
231 (lua_class_propfunc_t) luaA_key_set_modifiers,
232 (lua_class_propfunc_t) luaA_key_get_modifiers,
233 (lua_class_propfunc_t) luaA_key_set_modifiers);
235 signal_add(&key_class.signals, "press");
236 signal_add(&key_class.signals, "property::key");
237 signal_add(&key_class.signals, "property::modifiers");
238 signal_add(&key_class.signals, "release");
241 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80