client: implements per-client key bindings
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
bf44ae1e03
commit
d9c868b627
213
awesomerc.lua.in
213
awesomerc.lua.in
|
@ -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)
|
||||
|
|
25
client.c
25
client.c
|
@ -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
57
event.c
|
@ -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
181
key.c
|
@ -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
15
key.h
|
@ -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
42
luaa.c
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
12
structs.h
12
structs.h
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue