client: implements per-client key bindings

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2009-01-05 16:59:20 +01:00
parent bf44ae1e03
commit d9c868b627
7 changed files with 335 additions and 210 deletions

View File

@ -168,7 +168,6 @@ root.buttons({
-- }}}
-- {{{ Key bindings
-- Bind keyboard digits
-- Compute the maximum number of digit we need, limited to 9
keynumber = 0
@ -176,120 +175,135 @@ for s = 1, screen.count() do
keynumber = math.min(9, math.max(#tags[s], keynumber));
end
globalkeys = {}
clientkeys = {}
for i = 1, keynumber do
key({ modkey }, i,
function ()
local screen = mouse.screen
if tags[screen][i] then
awful.tag.viewonly(tags[screen][i])
end
end):add()
key({ modkey, "Control" }, i,
function ()
local screen = mouse.screen
if tags[screen][i] then
tags[screen][i].selected = not tags[screen][i].selected
end
end):add()
key({ modkey, "Shift" }, i,
function ()
if client.focus and tags[client.focus.screen][i] then
awful.client.movetotag(tags[client.focus.screen][i])
end
end):add()
key({ modkey, "Control", "Shift" }, i,
function ()
if client.focus and tags[client.focus.screen][i] then
awful.client.toggletag(tags[client.focus.screen][i])
end
end):add()
table.insert(globalkeys,
key({ modkey }, i,
function ()
local screen = mouse.screen
if tags[screen][i] then
awful.tag.viewonly(tags[screen][i])
end
end))
table.insert(globalkeys,
key({ modkey, "Control" }, i,
function ()
local screen = mouse.screen
if tags[screen][i] then
tags[screen][i].selected = not tags[screen][i].selected
end
end))
table.insert(globalkeys,
key({ modkey, "Shift" }, i,
function ()
if client.focus and tags[client.focus.screen][i] then
awful.client.movetotag(tags[client.focus.screen][i])
end
end))
table.insert(globalkeys,
key({ modkey, "Control", "Shift" }, i,
function ()
if client.focus and tags[client.focus.screen][i] then
awful.client.toggletag(tags[client.focus.screen][i])
end
end))
end
key({ modkey }, "Left", awful.tag.viewprev):add()
key({ modkey }, "Right", awful.tag.viewnext):add()
key({ modkey }, "Escape", awful.tag.history.restore):add()
table.insert(globalkeys, key({ modkey }, "Left", awful.tag.viewprev))
table.insert(globalkeys, key({ modkey }, "Right", awful.tag.viewnext))
table.insert(globalkeys, key({ modkey }, "Escape", awful.tag.history.restore))
table.insert(globalkeys, key({ modkey }, "j", function () awful.client.focus.byidx(1); if client.focus then client.focus:raise() end end))
table.insert(globalkeys, key({ modkey }, "k", function () awful.client.focus.byidx(-1); if client.focus then client.focus:raise() end end))
table.insert(globalkeys, key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx(1) end))
table.insert(globalkeys, key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx(-1) end))
table.insert(globalkeys, key({ modkey, "Control" }, "j", function () awful.screen.focus(1) end))
table.insert(globalkeys, key({ modkey, "Control" }, "k", function () awful.screen.focus(-1) end))
table.insert(globalkeys, key({ modkey }, "Tab", function () awful.client.focus.history.previous(); if client.focus then client.focus:raise() end end))
table.insert(globalkeys, key({ modkey }, "u", awful.client.urgent.jumpto))
-- Standard program
key({ modkey }, "Return", function () awful.util.spawn(terminal) end):add()
table.insert(globalkeys, key({ modkey }, "Return", function () awful.util.spawn(terminal) end))
key({ modkey, "Control" }, "r", function ()
mypromptbox[mouse.screen].text =
awful.util.escape(awful.util.restart())
end):add()
key({ modkey, "Shift" }, "q", awesome.quit):add()
table.insert(globalkeys, key({ modkey, "Control" }, "r", function ()
mypromptbox[mouse.screen].text =
awful.util.escape(awful.util.restart())
end))
table.insert(globalkeys, key({ modkey, "Shift" }, "q", awesome.quit))
-- Client manipulation
key({ modkey }, "m", function () if client.focus then client.focus.maximized_horizontal = not client.focus.maximized_horizontal
client.focus.maximized_vertical = not client.focus.maximized_vertical end end):add()
key({ modkey }, "f", function () if client.focus then client.focus.fullscreen = not client.focus.fullscreen end end):add()
key({ modkey, "Shift" }, "c", function () if client.focus then client.focus:kill() end end):add()
key({ modkey }, "j", function () awful.client.focus.byidx(1); if client.focus then client.focus:raise() end end):add()
key({ modkey }, "k", function () awful.client.focus.byidx(-1); if client.focus then client.focus:raise() end end):add()
key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx(1) end):add()
key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx(-1) end):add()
key({ modkey, "Control" }, "j", function () awful.screen.focus(1) end):add()
key({ modkey, "Control" }, "k", function () awful.screen.focus(-1) end):add()
key({ modkey, "Control" }, "space", awful.client.floating.toggle):add()
key({ modkey, "Control" }, "Return", function () if client.focus then client.focus:swap(awful.client.getmaster()) end end):add()
key({ modkey }, "o", awful.client.movetoscreen):add()
key({ modkey }, "Tab", function () awful.client.focus.history.previous(); if client.focus then client.focus:raise() end end):add()
key({ modkey }, "u", awful.client.urgent.jumpto):add()
key({ modkey, "Shift" }, "r", function () if client.focus then client.focus:redraw() end end):add()
table.insert(clientkeys, key({ modkey }, "m", function (c) c.maximized_horizontal = not c.maximized_horizontal
c.maximized_vertical = not c.maximized_vertical end))
table.insert(clientkeys, key({ modkey }, "f", function (c) c.fullscreen = not c.fullscreen end))
table.insert(clientkeys, key({ modkey, "Shift" }, "c", function (c) c:kill() end))
table.insert(clientkeys, key({ modkey, "Control" }, "space", awful.client.floating.toggle))
table.insert(clientkeys, key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end))
table.insert(clientkeys, key({ modkey }, "o", awful.client.movetoscreen))
table.insert(clientkeys, key({ modkey, "Shift" }, "r", function (c) c:redraw() end))
table.insert(clientkeys, key({ modkey, "Ctrl" }, "i", function (c)
local s = c.screen
if mypromptbox[s].text then
mypromptbox[s].text = nil
else
mypromptbox[s].text = nil
if c.class then
mypromptbox[s].text = "Class: " .. c.class .. " "
end
if c.instance then
mypromptbox[s].text = mypromptbox[s].text .. "Instance: ".. c.instance .. " "
end
if c.role then
mypromptbox[s].text = mypromptbox[s].text .. "Role: ".. crole
end
end
end))
-- Layout manipulation
key({ modkey }, "l", function () awful.tag.incmwfact(0.05) end):add()
key({ modkey }, "h", function () awful.tag.incmwfact(-0.05) end):add()
key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster(1) end):add()
key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end):add()
key({ modkey, "Control" }, "h", function () awful.tag.incncol(1) end):add()
key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1) end):add()
key({ modkey }, "space", function () awful.layout.inc(layouts, 1) end):add()
key({ modkey, "Shift" }, "space", function () awful.layout.inc(layouts, -1) end):add()
table.insert(globalkeys, key({ modkey }, "l", function () awful.tag.incmwfact(0.05) end))
table.insert(globalkeys, key({ modkey }, "h", function () awful.tag.incmwfact(-0.05) end))
table.insert(globalkeys, key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster(1) end))
table.insert(globalkeys, key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end))
table.insert(globalkeys, key({ modkey, "Control" }, "h", function () awful.tag.incncol(1) end))
table.insert(globalkeys, key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1) end))
table.insert(globalkeys, key({ modkey }, "space", function () awful.layout.inc(layouts, 1) end))
table.insert(globalkeys, key({ modkey, "Shift" }, "space", function () awful.layout.inc(layouts, -1) end))
-- Prompt
key({ modkey }, "F1", function ()
awful.prompt.run({ prompt = "Run: " }, mypromptbox[mouse.screen],
awful.util.spawn, awful.completion.bash,
awful.util.getdir("cache") .. "/history")
end):add()
key({ modkey }, "F4", function ()
awful.prompt.run({ prompt = "Run Lua code: " }, mypromptbox[mouse.screen],
awful.util.eval, awful.prompt.bash,
awful.util.getdir("cache") .. "/history_eval")
end):add()
key({ modkey, "Ctrl" }, "i", function ()
local s = mouse.screen
if mypromptbox[s].text then
mypromptbox[s].text = nil
elseif client.focus then
mypromptbox[s].text = nil
if client.focus.class then
mypromptbox[s].text = "Class: " .. client.focus.class .. " "
end
if client.focus.instance then
mypromptbox[s].text = mypromptbox[s].text .. "Instance: ".. client.focus.instance .. " "
end
if client.focus.role then
mypromptbox[s].text = mypromptbox[s].text .. "Role: ".. client.focus.role
end
end
end):add()
table.insert(globalkeys, key({ modkey }, "F1", function ()
awful.prompt.run({ prompt = "Run: " },
mypromptbox[mouse.screen],
awful.util.spawn, awful.completion.bash,
awful.util.getdir("cache") .. "/history")
end))
table.insert(globalkeys, key({ modkey }, "F4", function ()
awful.prompt.run({ prompt = "Run Lua code: " },
mypromptbox[mouse.screen],
awful.util.eval, awful.prompt.bash,
awful.util.getdir("cache") .. "/history_eval")
end))
-- Client awful tagging: this is useful to tag some clients and then do stuff like move to tag on them
key({ modkey }, "t", awful.client.togglemarked):add()
table.insert(clientkeys, key({ modkey }, "t", awful.client.togglemarked))
for i = 1, keynumber do
key({ modkey, "Shift" }, "F" .. i,
function ()
local screen = mouse.screen
if tags[screen][i] then
for k, c in pairs(awful.client.getmarked()) do
awful.client.movetotag(tags[screen][i], c)
end
end
end):add()
table.insert(globalkeys, key({ modkey, "Shift" }, "F" .. i,
function ()
local screen = mouse.screen
if tags[screen][i] then
for k, c in pairs(awful.client.getmarked()) do
awful.client.movetotag(tags[screen][i], c)
end
end
end))
end
-- Set keys
root.keys(globalkeys)
-- }}}
-- {{{ Hooks
@ -374,6 +388,9 @@ awful.hooks.manage.register(function (c, startup)
-- Do this after tag mapping, so you don't see it on the wrong tag for a split second.
client.focus = c
-- Set key bindings
c:keys(clientkeys)
-- Set the windows at the slave,
-- i.e. put it at the end of others instead of setting it master.
-- awful.client.setslave(c)

View File

@ -1897,6 +1897,30 @@ luaA_client_buttons(lua_State *L)
return luaA_button_array_get(L, buttons);
}
/** Get or set keys bindings for a client.
* \param L The Lua VM state.
* \return The number of element pushed on stack.
* \luastack
* \lvalue A client.
* \lparam An array of key bindings objects, or nothing.
* \return The array of key bindings objects of this client.
*/
static int
luaA_client_keys(lua_State *L)
{
client_t **c = luaA_checkudata(L, 1, "client");
keybindings_t *keys = &(*c)->keys;
if(lua_gettop(L) == 2)
{
luaA_key_array_set(L, 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, keys);
}
/** Send fake events to a client.
* \param L The Lua VM state.
* \return The number of element pushed on stack.
@ -2045,6 +2069,7 @@ const struct luaL_reg awesome_client_meta[] =
{ "isvisible", luaA_client_isvisible },
{ "geometry", luaA_client_geometry },
{ "buttons", luaA_client_buttons },
{ "keys", luaA_client_keys },
{ "tags", luaA_client_tags },
{ "kill", luaA_client_kill },
{ "swap", luaA_client_swap },

57
event.c
View File

@ -542,6 +542,8 @@ event_handle_key(void *data __attribute__ ((unused)),
xcb_connection_t *connection __attribute__ ((unused)),
xcb_key_press_event_t *ev)
{
client_t *c;
if(globalconf.keygrabber != LUA_REFNIL)
{
lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, globalconf.keygrabber);
@ -557,9 +559,32 @@ event_handle_key(void *data __attribute__ ((unused)),
}
lua_pop(globalconf.L, 1); /* pop returned value or function if not called */
}
else if((c = client_getbywin(ev->event)))
{
keyb_t *k = key_find(&c->keys, ev);
if(k)
switch(ev->response_type)
{
case XCB_KEY_PRESS:
if(k->press != LUA_REFNIL)
{
luaA_client_userdata_new(globalconf.L, c);
luaA_dofunction(globalconf.L, k->press, 1, 0);
}
break;
case XCB_KEY_RELEASE:
if(k->release != LUA_REFNIL)
{
luaA_client_userdata_new(globalconf.L, c);
luaA_dofunction(globalconf.L, k->release, 1, 0);
}
break;
}
}
else
{
keyb_t *k = key_find(ev);
keyb_t *k = key_find(&globalconf.keys, ev);
if(k)
switch(ev->response_type)
@ -746,9 +771,6 @@ event_handle_mappingnotify(void *data,
if(ev->request == XCB_MAPPING_MODIFIER
|| ev->request == XCB_MAPPING_KEYBOARD)
{
int nscreen = xcb_setup_roots_length(xcb_get_setup(connection));
int phys_screen = 0;
/* Send the request to get the NumLock, ShiftLock and CapsLock masks */
xmapping_cookie = xcb_get_modifier_mapping_unchecked(globalconf.connection);
@ -761,23 +783,22 @@ event_handle_mappingnotify(void *data,
globalconf.keysyms, &globalconf.numlockmask,
&globalconf.shiftlockmask, &globalconf.capslockmask);
do
{
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);
phys_screen++;
} while(phys_screen < nscreen);
int nscreen = xcb_setup_roots_length(xcb_get_setup(connection));
/* regrab everything */
key_array_t *arr = &globalconf.keys.by_sym;
for(int i = 0; i < arr->len; i++)
window_root_grabkey(arr->tab[i]);
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);
}
arr = &globalconf.keys.by_code;
for(int i = 0; i < arr->len; i++)
window_root_grabkey(arr->tab[i]);
for(client_t *c = globalconf.clients; c; c = c->next)
{
xcb_ungrab_key(connection, XCB_GRAB_ANY, c->win, XCB_BUTTON_MASK_ANY);
window_grabkeys(c->win, &c->keys);
}
}
return 0;

181
key.c
View File

@ -40,6 +40,20 @@ ARRAY_FUNCS(keyb_t *, key, key_unref)
DO_LUA_NEW(static, keyb_t, key, "key", key_ref)
DO_LUA_GC(keyb_t, key, "key", key_unref)
static void
keybindings_init(keybindings_t *kb)
{
key_array_init(&kb->by_code);
key_array_init(&kb->by_sym);
}
static void
keybindings_wipe(keybindings_t *kb)
{
key_array_wipe(&kb->by_code);
key_array_wipe(&kb->by_sym);
}
static int
key_ev_cmp(xcb_keysym_t keysym, xcb_keycode_t keycode,
unsigned long mod, const keyb_t *k)
@ -68,68 +82,45 @@ key_cmp(const keyb_t *k1, const keyb_t *k2)
return k1->mod == k2->mod ? 0 : (k2->mod > k1->mod ? 1 : -1);
}
/** Grab key on the root windows.
/** Grab key on a window.
* \param win The window.
* \param k The key.
*/
void
window_root_grabkey(keyb_t *k)
static void
window_grabkey(xcb_window_t win, keyb_t *k)
{
int phys_screen = 0;
int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
xcb_screen_t *s;
xcb_keycode_t kc;
if((kc = k->keycode)
|| (k->keysym
&& (kc = xcb_key_symbols_get_keycode(globalconf.keysyms, k->keysym))))
do
{
s = xutil_screen_get(globalconf.connection, phys_screen);
xcb_grab_key(globalconf.connection, true, s->root,
k->mod, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
xcb_grab_key(globalconf.connection, true, s->root,
k->mod | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
xcb_grab_key(globalconf.connection, true, s->root,
k->mod | globalconf.numlockmask, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
xcb_grab_key(globalconf.connection, true, s->root,
k->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC);
phys_screen++;
} while(phys_screen < nscreen);
{
xcb_grab_key(globalconf.connection, true, win,
k->mod, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
xcb_grab_key(globalconf.connection, true, win,
k->mod | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
xcb_grab_key(globalconf.connection, true, win,
k->mod | globalconf.numlockmask, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
xcb_grab_key(globalconf.connection, true, win,
k->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC);
}
}
/** Ungrab key on the root windows.
* \param k The key.
*/
static void
window_root_ungrabkey(keyb_t *k)
void
window_grabkeys(xcb_window_t win, keybindings_t *keys)
{
int phys_screen = 0;
int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
xcb_screen_t *s;
xcb_keycode_t kc;
for(int i = 0; i < keys->by_code.len; i++)
window_grabkey(win, keys->by_code.tab[i]);
if((kc = k->keycode)
|| (k->keysym && (kc = xcb_key_symbols_get_keycode(globalconf.keysyms, k->keysym))))
do
{
s = xutil_screen_get(globalconf.connection, phys_screen);
xcb_ungrab_key(globalconf.connection, kc, s->root,
k->mod);
xcb_ungrab_key(globalconf.connection, kc, s->root,
k->mod | XCB_MOD_MASK_LOCK);
xcb_ungrab_key(globalconf.connection, kc, s->root,
k->mod | globalconf.numlockmask);
xcb_ungrab_key(globalconf.connection, kc, s->root,
k->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK);
phys_screen++;
} while(phys_screen < nscreen);
for(int i = 0; i < keys->by_sym.len; i++)
window_grabkey(win, keys->by_sym.tab[i]);
}
static void
key_register_root(keyb_t *k)
key_register(keybindings_t *keys, keyb_t *k)
{
key_array_t *arr = k->keysym ? &globalconf.keys.by_sym : &globalconf.keys.by_code;
key_array_t *arr = k->keysym ? &keys->by_sym : &keys->by_code;
int l = 0, r = arr->len;
key_ref(&k);
@ -151,31 +142,6 @@ key_register_root(keyb_t *k)
}
key_array_splice(arr, r, 0, &k, 1);
window_root_grabkey(k);
}
static void
key_unregister_root(keyb_t **k)
{
key_array_t *arr = (*k)->keysym ? &globalconf.keys.by_sym : &globalconf.keys.by_code;
int l = 0, r = arr->len;
while (l < r) {
int i = (r + l) / 2;
switch (key_cmp(*k, arr->tab[i])) {
case -1: /* k < arr->tab[i] */
r = i;
break;
case 0: /* k == arr->tab[i] */
key_array_take(arr, i);
window_root_ungrabkey(*k);
key_unref(k);
return;
case 1: /* k > arr->tab[i] */
l = i + 1;
break;
}
}
}
/** Return the keysym from keycode.
@ -256,9 +222,9 @@ key_getkeysym(xcb_keycode_t detail, uint16_t state)
keyb_t *
key_find(const xcb_key_press_event_t *ev)
key_find(keybindings_t *keys, const xcb_key_press_event_t *ev)
{
const key_array_t *arr = &globalconf.keys.by_sym;
const key_array_t *arr = &keys->by_sym;
int l, r, mod = XUTIL_MASK_CLEAN(ev->state);
xcb_keysym_t keysym;
@ -283,9 +249,9 @@ key_find(const xcb_key_press_event_t *ev)
break;
}
}
if (arr != &globalconf.keys.by_code)
if(arr != &keys->by_code)
{
arr = &globalconf.keys.by_code;
arr = &keys->by_code;
goto again;
}
return NULL;
@ -360,6 +326,55 @@ luaA_key_new(lua_State *L)
return luaA_key_userdata_new(L, k);
}
/** Set a key array with a Lua table.
* \param L The Lua VM state.
* \param idx The index of the Lua table.
* \param keys The array key to fill.
*/
void
luaA_key_array_set(lua_State *L, int idx, keybindings_t *keys)
{
luaA_checktable(L, idx);
for(int i = 0; i < keys->by_code.len; i++);
for(int i = 0; i < keys->by_sym.len; i++);
keybindings_wipe(keys);
keybindings_init(keys);
lua_pushnil(L);
while(lua_next(L, idx))
{
keyb_t **k = luaA_checkudata(L, -1, "key");
key_register(keys, *k);
lua_pop(L, 1);
}
}
/** Push an array of key as an Lua table onto the stack.
* \param L The Lua VM state.
* \param keys The key array to push.
* \return The number of elements pushed on stack.
*/
int
luaA_key_array_get(lua_State *L, keybindings_t *keys)
{
luaA_otable_new(L);
for(int i = 0; i < keys->by_code.len; i++)
{
luaA_key_userdata_new(L, keys->by_code.tab[i]);
lua_rawseti(L, -2, i + 1);
}
for(int i = 0; i < keys->by_sym.len; i++)
{
luaA_key_userdata_new(L, keys->by_sym.tab[i]);
lua_rawseti(L, -2, i + 1);
}
return 1;
}
/** Add a global key binding. This key binding will always be available.
* \param L The Lua VM state.
*
@ -369,8 +384,19 @@ luaA_key_new(lua_State *L)
static int
luaA_key_add(lua_State *L)
{
luaA_deprecate(L, "root.keys");
keyb_t **k = luaA_checkudata(L, 1, "key");
key_register_root(*k);
int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
key_register(&globalconf.keys, *k);
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 0;
}
@ -383,8 +409,7 @@ luaA_key_add(lua_State *L)
static int
luaA_key_remove(lua_State *L)
{
keyb_t **k = luaA_checkudata(L, 1, "key");
key_unregister_root(k);
luaA_deprecate(L, "root.keys");
return 0;
}

15
key.h
View File

@ -44,9 +44,20 @@ typedef struct keyb_t
ARRAY_TYPE(keyb_t *, key)
keyb_t *key_find(const xcb_key_press_event_t *);
/** Key bindings */
typedef struct
{
key_array_t by_code;
key_array_t by_sym;
} keybindings_t;
keyb_t *key_find(keybindings_t *, const xcb_key_press_event_t *);
xcb_keysym_t key_getkeysym(xcb_keycode_t, uint16_t);
void window_root_grabkey(keyb_t *);
void luaA_key_array_set(lua_State *, int, keybindings_t *);
int luaA_key_array_get(lua_State *, keybindings_t *);
void window_grabkeys(xcb_window_t, keybindings_t *);
int luaA_key_new(lua_State *);

42
luaa.c
View File

@ -84,24 +84,51 @@ static ev_io csio = { .fd = -1 };
#define XDG_CONFIG_HOME_DEFAULT "/.config"
/** Get or
/** Get or set global key bindings.
* This binding will be available when you'll press keys on root window.
* \param L The Lua VM state.
* \return The number of element pushed on stack.
* \luastack
* \lvalue A client.
* \lparam An array of key bindings objects, or nothing.
* \return The array of key bindings objects of this client.
*/
static int
luaA_root_keys(lua_State *L)
{
if(lua_gettop(L) == 1)
{
luaA_key_array_set(L, 1, &globalconf.keys);
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 luaA_key_array_get(L, &globalconf.keys);
}
/** Get or set global mouse bindings.
* This binding will be available when you'll click on root window.
* \param L The Lua VM state.
* \return The number of element pushed on stack.
* \luastack
* \lvalue A client.
* \lparam An array of mouse button bindings objects, or nothing.
* \return The array of mouse button bindings objects of this client.
* \return The array of mouse button bindings objects.
*/
static int
luaA_root_buttons(lua_State *L)
{
button_array_t *buttons = &globalconf.buttons;
if(lua_gettop(L) == 1)
luaA_button_array_set(L, 1, buttons);
luaA_button_array_set(L, 1, &globalconf.buttons);
return luaA_button_array_get(L, buttons);
return luaA_button_array_get(L, &globalconf.buttons);
}
/** Get or set global mouse bindings (DEPRECATED).
@ -111,7 +138,7 @@ luaA_root_buttons(lua_State *L)
* \luastack
* \lvalue A client.
* \lparam An array of mouse button bindings objects, or nothing.
* \return The array of mouse button bindings objects of this client.
* \return The array of mouse button bindings objects.
*/
static int
luaA_buttons(lua_State *L)
@ -808,6 +835,7 @@ luaA_init(void)
static const struct luaL_reg root_lib[] =
{
{ "buttons", luaA_root_buttons },
{ "keys", luaA_root_keys },
{ NULL, NULL }
};

View File

@ -218,6 +218,8 @@ struct client_t
wibox_t *titlebar;
/** Button bindings */
button_array_t buttons;
/** Key bindings */
keybindings_t keys;
/** Icon */
image_t *icon;
/** Size hints */
@ -290,13 +292,9 @@ struct awesome_t
int nscreen;
/** True if xinerama is active */
bool xinerama_is_active;
/** Key bindings */
struct
{
key_array_t by_code;
key_array_t by_sym;
} keys;
/** Mouse bindings list */
/** Root window key bindings */
keybindings_t keys;
/** Root window mouse bindings */
button_array_t buttons;
/** Numlock mask */
unsigned int numlockmask;