keybinding: move to key
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
fa41e0d395
commit
53f58aa1a6
|
@ -45,6 +45,7 @@ set(AWE_SRCS
|
||||||
${SOURCE_DIR}/property.c
|
${SOURCE_DIR}/property.c
|
||||||
${SOURCE_DIR}/ewmh.c
|
${SOURCE_DIR}/ewmh.c
|
||||||
${SOURCE_DIR}/keybinding.c
|
${SOURCE_DIR}/keybinding.c
|
||||||
|
${SOURCE_DIR}/key.c
|
||||||
${SOURCE_DIR}/keygrabber.c
|
${SOURCE_DIR}/keygrabber.c
|
||||||
${SOURCE_DIR}/mousegrabber.c
|
${SOURCE_DIR}/mousegrabber.c
|
||||||
${SOURCE_DIR}/layout.c
|
${SOURCE_DIR}/layout.c
|
||||||
|
|
188
awesomerc.lua.in
188
awesomerc.lua.in
|
@ -177,116 +177,118 @@ for s = 1, screen.count() do
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, keynumber do
|
for i = 1, keynumber do
|
||||||
keybinding({ modkey }, i,
|
key({ modkey }, i,
|
||||||
function ()
|
function ()
|
||||||
local screen = mouse.screen
|
local screen = mouse.screen
|
||||||
if tags[screen][i] then
|
if tags[screen][i] then
|
||||||
awful.tag.viewonly(tags[screen][i])
|
awful.tag.viewonly(tags[screen][i])
|
||||||
end
|
end
|
||||||
end):add()
|
end):add()
|
||||||
keybinding({ modkey, "Control" }, i,
|
key({ modkey, "Control" }, i,
|
||||||
function ()
|
function ()
|
||||||
local screen = mouse.screen
|
local screen = mouse.screen
|
||||||
if tags[screen][i] then
|
if tags[screen][i] then
|
||||||
tags[screen][i].selected = not tags[screen][i].selected
|
tags[screen][i].selected = not tags[screen][i].selected
|
||||||
end
|
end
|
||||||
end):add()
|
end):add()
|
||||||
keybinding({ modkey, "Shift" }, i,
|
key({ modkey, "Shift" }, i,
|
||||||
function ()
|
function ()
|
||||||
if client.focus and tags[client.focus.screen][i] then
|
if client.focus and tags[client.focus.screen][i] then
|
||||||
awful.client.movetotag(tags[client.focus.screen][i])
|
awful.client.movetotag(tags[client.focus.screen][i])
|
||||||
end
|
end
|
||||||
end):add()
|
end):add()
|
||||||
keybinding({ modkey, "Control", "Shift" }, i,
|
key({ modkey, "Control", "Shift" }, i,
|
||||||
function ()
|
function ()
|
||||||
if client.focus and tags[client.focus.screen][i] then
|
if client.focus and tags[client.focus.screen][i] then
|
||||||
awful.client.toggletag(tags[client.focus.screen][i])
|
awful.client.toggletag(tags[client.focus.screen][i])
|
||||||
end
|
end
|
||||||
end):add()
|
end):add()
|
||||||
end
|
end
|
||||||
|
|
||||||
keybinding({ modkey }, "Left", awful.tag.viewprev):add()
|
key({ modkey }, "Left", awful.tag.viewprev):add()
|
||||||
keybinding({ modkey }, "Right", awful.tag.viewnext):add()
|
key({ modkey }, "Right", awful.tag.viewnext):add()
|
||||||
keybinding({ modkey }, "Escape", awful.tag.history.restore):add()
|
key({ modkey }, "Escape", awful.tag.history.restore):add()
|
||||||
|
|
||||||
-- Standard program
|
-- Standard program
|
||||||
keybinding({ modkey }, "Return", function () awful.util.spawn(terminal) end):add()
|
key({ modkey }, "Return", function () awful.util.spawn(terminal) end):add()
|
||||||
|
|
||||||
keybinding({ modkey, "Control" }, "r", function ()
|
key({ modkey, "Control" }, "r", function ()
|
||||||
mypromptbox[mouse.screen].text =
|
mypromptbox[mouse.screen].text =
|
||||||
awful.util.escape(awful.util.restart())
|
awful.util.escape(awful.util.restart())
|
||||||
end):add()
|
end):add()
|
||||||
keybinding({ modkey, "Shift" }, "q", awesome.quit):add()
|
key({ modkey, "Shift" }, "q", awesome.quit):add()
|
||||||
|
|
||||||
-- Client manipulation
|
-- Client manipulation
|
||||||
keybinding({ modkey }, "m", function () if client.focus then client.focus.maximized_horizontal = not client.focus.maximized_horizontal
|
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()
|
client.focus.maximized_vertical = not client.focus.maximized_vertical end end):add()
|
||||||
keybinding({ modkey }, "f", function () if client.focus then client.focus.fullscreen = not client.focus.fullscreen end end):add()
|
key({ modkey }, "f", function () if client.focus then client.focus.fullscreen = not client.focus.fullscreen end end):add()
|
||||||
keybinding({ modkey, "Shift" }, "c", function () if client.focus then client.focus:kill() end end):add()
|
key({ modkey, "Shift" }, "c", function () if client.focus then client.focus:kill() end end):add()
|
||||||
keybinding({ modkey }, "j", function () awful.client.focus.byidx(1); if client.focus then client.focus:raise() end end):add()
|
key({ modkey }, "j", function () awful.client.focus.byidx(1); if client.focus then client.focus:raise() end end):add()
|
||||||
keybinding({ modkey }, "k", 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()
|
||||||
keybinding({ modkey, "Shift" }, "j", function () awful.client.swap.byidx(1) end):add()
|
key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx(1) end):add()
|
||||||
keybinding({ modkey, "Shift" }, "k", function () awful.client.swap.byidx(-1) end):add()
|
key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx(-1) end):add()
|
||||||
keybinding({ modkey, "Control" }, "j", function () awful.screen.focus(1) end):add()
|
key({ modkey, "Control" }, "j", function () awful.screen.focus(1) end):add()
|
||||||
keybinding({ modkey, "Control" }, "k", function () awful.screen.focus(-1) end):add()
|
key({ modkey, "Control" }, "k", function () awful.screen.focus(-1) end):add()
|
||||||
keybinding({ modkey, "Control" }, "space", awful.client.floating.toggle):add()
|
key({ modkey, "Control" }, "space", awful.client.floating.toggle):add()
|
||||||
keybinding({ modkey, "Control" }, "Return", function () if client.focus then client.focus:swap(awful.client.getmaster()) end end):add()
|
key({ modkey, "Control" }, "Return", function () if client.focus then client.focus:swap(awful.client.getmaster()) end end):add()
|
||||||
keybinding({ modkey }, "o", awful.client.movetoscreen):add()
|
key({ modkey }, "o", awful.client.movetoscreen):add()
|
||||||
keybinding({ modkey }, "Tab", awful.client.focus.history.previous):add()
|
key({ modkey }, "Tab", awful.client.focus.history.previous):add()
|
||||||
keybinding({ modkey }, "u", awful.client.urgent.jumpto):add()
|
key({ modkey }, "u", awful.client.urgent.jumpto):add()
|
||||||
keybinding({ modkey, "Shift" }, "r", function () if client.focus then client.focus:redraw() end end):add()
|
key({ modkey, "Shift" }, "r", function () if client.focus then client.focus:redraw() end end):add()
|
||||||
|
|
||||||
-- Layout manipulation
|
-- Layout manipulation
|
||||||
keybinding({ modkey }, "l", function () awful.tag.incmwfact(0.05) end):add()
|
key({ modkey }, "l", function () awful.tag.incmwfact(0.05) end):add()
|
||||||
keybinding({ modkey }, "h", function () awful.tag.incmwfact(-0.05) end):add()
|
key({ modkey }, "h", function () awful.tag.incmwfact(-0.05) end):add()
|
||||||
keybinding({ modkey, "Shift" }, "h", function () awful.tag.incnmaster(1) end):add()
|
key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster(1) end):add()
|
||||||
keybinding({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end):add()
|
key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end):add()
|
||||||
keybinding({ modkey, "Control" }, "h", function () awful.tag.incncol(1) end):add()
|
key({ modkey, "Control" }, "h", function () awful.tag.incncol(1) end):add()
|
||||||
keybinding({ modkey, "Control" }, "l", function () awful.tag.incncol(-1) end):add()
|
key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1) end):add()
|
||||||
keybinding({ modkey }, "space", function () awful.layout.inc(layouts, 1) end):add()
|
key({ modkey }, "space", function () awful.layout.inc(layouts, 1) end):add()
|
||||||
keybinding({ modkey, "Shift" }, "space", function () awful.layout.inc(layouts, -1) end):add()
|
key({ modkey, "Shift" }, "space", function () awful.layout.inc(layouts, -1) end):add()
|
||||||
|
|
||||||
-- Prompt
|
-- Prompt
|
||||||
keybinding({ modkey }, "F1", function ()
|
key({ modkey }, "F1", function ()
|
||||||
awful.prompt.run({ prompt = "Run: " }, mypromptbox[mouse.screen], awful.util.spawn, awful.completion.bash,
|
awful.prompt.run({ prompt = "Run: " }, mypromptbox[mouse.screen],
|
||||||
awful.util.getdir("cache") .. "/history")
|
awful.util.spawn, awful.completion.bash,
|
||||||
end):add()
|
awful.util.getdir("cache") .. "/history")
|
||||||
keybinding({ modkey }, "F4", function ()
|
end):add()
|
||||||
awful.prompt.run({ prompt = "Run Lua code: " }, mypromptbox[mouse.screen], awful.util.eval, awful.prompt.bash,
|
key({ modkey }, "F4", function ()
|
||||||
awful.util.getdir("cache") .. "/history_eval")
|
awful.prompt.run({ prompt = "Run Lua code: " }, mypromptbox[mouse.screen],
|
||||||
end):add()
|
awful.util.eval, awful.prompt.bash,
|
||||||
|
awful.util.getdir("cache") .. "/history_eval")
|
||||||
|
end):add()
|
||||||
|
|
||||||
keybinding({ modkey, "Ctrl" }, "i", function ()
|
key({ modkey, "Ctrl" }, "i", function ()
|
||||||
local s = mouse.screen
|
local s = mouse.screen
|
||||||
if mypromptbox[s].text then
|
if mypromptbox[s].text then
|
||||||
mypromptbox[s].text = nil
|
mypromptbox[s].text = nil
|
||||||
elseif client.focus then
|
elseif client.focus then
|
||||||
mypromptbox[s].text = nil
|
mypromptbox[s].text = nil
|
||||||
if client.focus.class then
|
if client.focus.class then
|
||||||
mypromptbox[s].text = "Class: " .. client.focus.class .. " "
|
mypromptbox[s].text = "Class: " .. client.focus.class .. " "
|
||||||
end
|
end
|
||||||
if client.focus.instance then
|
if client.focus.instance then
|
||||||
mypromptbox[s].text = mypromptbox[s].text .. "Instance: ".. client.focus.instance .. " "
|
mypromptbox[s].text = mypromptbox[s].text .. "Instance: ".. client.focus.instance .. " "
|
||||||
end
|
end
|
||||||
if client.focus.role then
|
if client.focus.role then
|
||||||
mypromptbox[s].text = mypromptbox[s].text .. "Role: ".. client.focus.role
|
mypromptbox[s].text = mypromptbox[s].text .. "Role: ".. client.focus.role
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end):add()
|
end):add()
|
||||||
|
|
||||||
-- Client awful tagging: this is useful to tag some clients and then do stuff like move to tag on them
|
-- Client awful tagging: this is useful to tag some clients and then do stuff like move to tag on them
|
||||||
keybinding({ modkey }, "t", awful.client.togglemarked):add()
|
key({ modkey }, "t", awful.client.togglemarked):add()
|
||||||
|
|
||||||
for i = 1, keynumber do
|
for i = 1, keynumber do
|
||||||
keybinding({ modkey, "Shift" }, "F" .. i,
|
key({ modkey, "Shift" }, "F" .. i,
|
||||||
function ()
|
function ()
|
||||||
local screen = mouse.screen
|
local screen = mouse.screen
|
||||||
if tags[screen][i] then
|
if tags[screen][i] then
|
||||||
for k, c in pairs(awful.client.getmarked()) do
|
for k, c in pairs(awful.client.getmarked()) do
|
||||||
awful.client.movetotag(tags[screen][i], c)
|
awful.client.movetotag(tags[screen][i], c)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end):add()
|
end):add()
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
|
|
6
event.c
6
event.c
|
@ -33,7 +33,7 @@
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "widget.h"
|
#include "widget.h"
|
||||||
#include "titlebar.h"
|
#include "titlebar.h"
|
||||||
#include "keybinding.h"
|
#include "key.h"
|
||||||
#include "keygrabber.h"
|
#include "keygrabber.h"
|
||||||
#include "mousegrabber.h"
|
#include "mousegrabber.h"
|
||||||
#include "luaa.h"
|
#include "luaa.h"
|
||||||
|
@ -559,7 +559,7 @@ event_handle_key(void *data __attribute__ ((unused)),
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
keybinding_t *k = keybinding_find(ev);
|
keyb_t *k = key_find(ev);
|
||||||
|
|
||||||
if(k)
|
if(k)
|
||||||
switch(ev->response_type)
|
switch(ev->response_type)
|
||||||
|
@ -787,7 +787,7 @@ event_handle_mappingnotify(void *data,
|
||||||
} while(phys_screen < nscreen);
|
} while(phys_screen < nscreen);
|
||||||
|
|
||||||
/* regrab everything */
|
/* regrab everything */
|
||||||
keybinding_array_t *arr = &globalconf.keys.by_sym;
|
key_array_t *arr = &globalconf.keys.by_sym;
|
||||||
for(int i = 0; i < arr->len; i++)
|
for(int i = 0; i < arr->len; i++)
|
||||||
window_root_grabkey(arr->tab[i]);
|
window_root_grabkey(arr->tab[i]);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,400 @@
|
||||||
|
/*
|
||||||
|
* key.c - Key bindings configuration management
|
||||||
|
*
|
||||||
|
* Copyright © 2008 Julien Danjou <julien@danjou.info>
|
||||||
|
* Copyright © 2008 Pierre Habouzit <madcoder@debian.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* XStringToKeysym() */
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
#include "structs.h"
|
||||||
|
|
||||||
|
extern awesome_t globalconf;
|
||||||
|
|
||||||
|
static void
|
||||||
|
key_delete(keyb_t **kbp)
|
||||||
|
{
|
||||||
|
luaL_unref(globalconf.L, LUA_REGISTRYINDEX, (*kbp)->press);
|
||||||
|
luaL_unref(globalconf.L, LUA_REGISTRYINDEX, (*kbp)->release);
|
||||||
|
p_delete(kbp);
|
||||||
|
}
|
||||||
|
|
||||||
|
DO_RCNT(keyb_t, key, key_delete)
|
||||||
|
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 int
|
||||||
|
key_ev_cmp(xcb_keysym_t keysym, xcb_keycode_t keycode,
|
||||||
|
unsigned long mod, const keyb_t *k)
|
||||||
|
{
|
||||||
|
if (k->keysym) {
|
||||||
|
if (k->keysym != keysym)
|
||||||
|
return k->keysym > keysym ? 1 : -1;
|
||||||
|
}
|
||||||
|
if (k->keycode) {
|
||||||
|
if (k->keycode != keycode)
|
||||||
|
return k->keycode > keycode ? 1 : -1;
|
||||||
|
}
|
||||||
|
return k->mod == mod ? 0 : (k->mod > mod ? 1 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
key_cmp(const keyb_t *k1, const keyb_t *k2)
|
||||||
|
{
|
||||||
|
assert ((k1->keysym && k2->keysym) || (k1->keycode && k2->keycode));
|
||||||
|
assert ((!k1->keysym && !k2->keysym) || (!k1->keycode && !k2->keycode));
|
||||||
|
|
||||||
|
if (k1->keysym != k2->keysym)
|
||||||
|
return k2->keysym > k1->keysym ? 1 : -1;
|
||||||
|
if (k1->keycode != k2->keycode)
|
||||||
|
return k2->keycode > k1->keycode ? 1 : -1;
|
||||||
|
return k1->mod == k2->mod ? 0 : (k2->mod > k1->mod ? 1 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Grab key on the root windows.
|
||||||
|
* \param k The key.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
window_root_grabkey(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Ungrab key on the root windows.
|
||||||
|
* \param k The key.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
window_root_ungrabkey(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_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
key_register_root(keyb_t *k)
|
||||||
|
{
|
||||||
|
key_array_t *arr = k->keysym ? &globalconf.keys.by_sym : &globalconf.keys.by_code;
|
||||||
|
int l = 0, r = arr->len;
|
||||||
|
|
||||||
|
key_ref(&k);
|
||||||
|
|
||||||
|
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_unref(&arr->tab[i]);
|
||||||
|
arr->tab[i] = k;
|
||||||
|
return;
|
||||||
|
case 1: /* k > arr->tab[i] */
|
||||||
|
l = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
* \param detail The keycode received.
|
||||||
|
* \param state The modifier state.
|
||||||
|
* \return A keysym.
|
||||||
|
*/
|
||||||
|
xcb_keysym_t
|
||||||
|
key_getkeysym(xcb_keycode_t detail, uint16_t state)
|
||||||
|
{
|
||||||
|
xcb_keysym_t k0, k1;
|
||||||
|
|
||||||
|
/* 'col' (third parameter) is used to get the proper KeySym
|
||||||
|
* according to modifier (XCB doesn't provide an equivalent to
|
||||||
|
* XLookupString()).
|
||||||
|
*
|
||||||
|
* If Mod5 is ON we look into second group.
|
||||||
|
*/
|
||||||
|
if(state & XCB_MOD_MASK_5)
|
||||||
|
{
|
||||||
|
k0 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 2);
|
||||||
|
k1 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
k0 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 0);
|
||||||
|
k1 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The numlock modifier is on and the second KeySym is a keypad
|
||||||
|
* KeySym */
|
||||||
|
if((state & globalconf.numlockmask) && xcb_is_keypad_key(k1))
|
||||||
|
{
|
||||||
|
/* The Shift modifier is on, or if the Lock modifier is on and
|
||||||
|
* is interpreted as ShiftLock, use the first KeySym */
|
||||||
|
if((state & XCB_MOD_MASK_SHIFT) ||
|
||||||
|
(state & XCB_MOD_MASK_LOCK && (state & globalconf.shiftlockmask)))
|
||||||
|
return k0;
|
||||||
|
else
|
||||||
|
return k1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The Shift and Lock modifers are both off, use the first
|
||||||
|
* KeySym */
|
||||||
|
else if(!(state & XCB_MOD_MASK_SHIFT) && !(state & XCB_MOD_MASK_LOCK))
|
||||||
|
return k0;
|
||||||
|
|
||||||
|
/* The Shift modifier is off and the Lock modifier is on and is
|
||||||
|
* interpreted as CapsLock */
|
||||||
|
else if(!(state & XCB_MOD_MASK_SHIFT) &&
|
||||||
|
(state & XCB_MOD_MASK_LOCK && (state & globalconf.capslockmask)))
|
||||||
|
/* The first Keysym is used but if that KeySym is lowercase
|
||||||
|
* alphabetic, then the corresponding uppercase KeySym is used
|
||||||
|
* instead */
|
||||||
|
return k1;
|
||||||
|
|
||||||
|
/* The Shift modifier is on, and the Lock modifier is on and is
|
||||||
|
* interpreted as CapsLock */
|
||||||
|
else if((state & XCB_MOD_MASK_SHIFT) &&
|
||||||
|
(state & XCB_MOD_MASK_LOCK && (state & globalconf.capslockmask)))
|
||||||
|
/* The second Keysym is used but if that KeySym is lowercase
|
||||||
|
* alphabetic, then the corresponding uppercase KeySym is used
|
||||||
|
* instead */
|
||||||
|
return k1;
|
||||||
|
|
||||||
|
/* The Shift modifer is on, or the Lock modifier is on and is
|
||||||
|
* interpreted as ShiftLock, or both */
|
||||||
|
else if((state & XCB_MOD_MASK_SHIFT) ||
|
||||||
|
(state & XCB_MOD_MASK_LOCK && (state & globalconf.shiftlockmask)))
|
||||||
|
return k1;
|
||||||
|
|
||||||
|
return XCB_NO_SYMBOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
keyb_t *
|
||||||
|
key_find(const xcb_key_press_event_t *ev)
|
||||||
|
{
|
||||||
|
const key_array_t *arr = &globalconf.keys.by_sym;
|
||||||
|
int l, r, mod = XUTIL_MASK_CLEAN(ev->state);
|
||||||
|
xcb_keysym_t keysym;
|
||||||
|
|
||||||
|
/* get keysym ignoring shift and mod5 */
|
||||||
|
keysym = key_getkeysym(ev->detail, ev->state & ~(XCB_MOD_MASK_SHIFT | XCB_MOD_MASK_5 | XCB_MOD_MASK_LOCK));
|
||||||
|
|
||||||
|
again:
|
||||||
|
l = 0;
|
||||||
|
r = arr->len;
|
||||||
|
while (l < r)
|
||||||
|
{
|
||||||
|
int i = (r + l) / 2;
|
||||||
|
switch (key_ev_cmp(keysym, ev->detail, mod, arr->tab[i]))
|
||||||
|
{
|
||||||
|
case -1: /* ev < arr->tab[i] */
|
||||||
|
r = i;
|
||||||
|
break;
|
||||||
|
case 0: /* ev == arr->tab[i] */
|
||||||
|
return arr->tab[i];
|
||||||
|
case 1: /* ev > arr->tab[i] */
|
||||||
|
l = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arr != &globalconf.keys.by_code)
|
||||||
|
{
|
||||||
|
arr = &globalconf.keys.by_code;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
luaA_keystore(keyb_t *key, const char *str, ssize_t len)
|
||||||
|
{
|
||||||
|
if(len)
|
||||||
|
{
|
||||||
|
if(*str != '#')
|
||||||
|
{
|
||||||
|
key->keysym = XStringToKeysym(str);
|
||||||
|
if (!key->keysym)
|
||||||
|
{
|
||||||
|
if (len == 1)
|
||||||
|
key->keysym = *str;
|
||||||
|
else
|
||||||
|
warn("there's no keysym named \"%s\"", str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
key->keycode = atoi(str + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Define a global key binding. This key binding will always be available.
|
||||||
|
* \param L The Lua VM state.
|
||||||
|
*
|
||||||
|
* \luastack
|
||||||
|
* \lparam A table with modifier keys.
|
||||||
|
* \lparam A key name.
|
||||||
|
* \lparam A function to execute on key press.
|
||||||
|
* \lparam A function to execute on key release.
|
||||||
|
* \lreturn The key.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
luaA_key_new(lua_State *L)
|
||||||
|
{
|
||||||
|
size_t i, len;
|
||||||
|
keyb_t *k;
|
||||||
|
const char *key;
|
||||||
|
luaA_ref press = LUA_REFNIL, release = LUA_REFNIL;
|
||||||
|
|
||||||
|
/* arg 2 is key mod table */
|
||||||
|
luaA_checktable(L, 2);
|
||||||
|
/* arg 3 is key */
|
||||||
|
key = luaL_checklstring(L, 3, &len);
|
||||||
|
|
||||||
|
if(!lua_isnil(L, 4))
|
||||||
|
luaA_registerfct(L, 4, &press);
|
||||||
|
|
||||||
|
if(lua_gettop(L) == 5 && !lua_isnil(L, 5))
|
||||||
|
luaA_registerfct(L, 5, &release);
|
||||||
|
|
||||||
|
/* get the last arg as function */
|
||||||
|
k = p_new(keyb_t, 1);
|
||||||
|
luaA_keystore(k, key, len);
|
||||||
|
|
||||||
|
k->press = press;
|
||||||
|
k->release = release;
|
||||||
|
|
||||||
|
len = lua_objlen(L, 2);
|
||||||
|
for(i = 1; i <= len; i++)
|
||||||
|
{
|
||||||
|
size_t blen;
|
||||||
|
lua_rawgeti(L, 2, i);
|
||||||
|
key = luaL_checklstring(L, -1, &blen);
|
||||||
|
k->mod |= xutil_key_mask_fromstr(key, blen);
|
||||||
|
}
|
||||||
|
|
||||||
|
return luaA_key_userdata_new(L, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add a global key binding. This key binding will always be available.
|
||||||
|
* \param L The Lua VM state.
|
||||||
|
*
|
||||||
|
* \luastack
|
||||||
|
* \lvalue A key.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
luaA_key_add(lua_State *L)
|
||||||
|
{
|
||||||
|
keyb_t **k = luaA_checkudata(L, 1, "key");
|
||||||
|
key_register_root(*k);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove a global key binding.
|
||||||
|
* \param L The Lua VM state.
|
||||||
|
*
|
||||||
|
* \luastack
|
||||||
|
* \lvalue A key.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
luaA_key_remove(lua_State *L)
|
||||||
|
{
|
||||||
|
keyb_t **k = luaA_checkudata(L, 1, "key");
|
||||||
|
key_unregister_root(k);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct luaL_reg awesome_key_methods[] =
|
||||||
|
{
|
||||||
|
{ "__call", luaA_key_new },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
const struct luaL_reg awesome_key_meta[] =
|
||||||
|
{
|
||||||
|
{ "add", luaA_key_add },
|
||||||
|
{ "remove", luaA_key_remove },
|
||||||
|
{ "__tostring", luaA_key_tostring },
|
||||||
|
{ "__gc", luaA_key_gc },
|
||||||
|
{ NULL, NULL },
|
||||||
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* keybinding.h - Keybinding helpers
|
* key.h - Keybinding helpers
|
||||||
*
|
*
|
||||||
* Copyright © 2008 Pierre Habouzit <madcoder@debian.org>
|
* Copyright © 2008 Pierre Habouzit <madcoder@debian.org>
|
||||||
*
|
*
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
#include "luaa.h"
|
#include "luaa.h"
|
||||||
#include "common/array.h"
|
#include "common/array.h"
|
||||||
|
|
||||||
typedef struct keybinding_t
|
typedef struct keyb_t
|
||||||
{
|
{
|
||||||
/** Ref count */
|
/** Ref count */
|
||||||
int refcount;
|
int refcount;
|
||||||
|
@ -40,12 +40,14 @@ typedef struct keybinding_t
|
||||||
luaA_ref press;
|
luaA_ref press;
|
||||||
/** Lua function to execute on release */
|
/** Lua function to execute on release */
|
||||||
luaA_ref release;
|
luaA_ref release;
|
||||||
} keybinding_t;
|
} keyb_t;
|
||||||
|
|
||||||
ARRAY_TYPE(keybinding_t *, keybinding)
|
ARRAY_TYPE(keyb_t *, key)
|
||||||
|
|
||||||
keybinding_t *keybinding_find(const xcb_key_press_event_t *);
|
keyb_t *key_find(const xcb_key_press_event_t *);
|
||||||
xcb_keysym_t key_getkeysym(xcb_keycode_t, uint16_t);
|
xcb_keysym_t key_getkeysym(xcb_keycode_t, uint16_t);
|
||||||
void window_root_grabkey(keybinding_t *);
|
void window_root_grabkey(keyb_t *);
|
||||||
|
|
||||||
|
int luaA_key_new(lua_State *);
|
||||||
|
|
||||||
#endif
|
#endif
|
365
keybinding.c
365
keybinding.c
|
@ -2,7 +2,6 @@
|
||||||
* keybinding.c - Key bindings configuration management
|
* keybinding.c - Key bindings configuration management
|
||||||
*
|
*
|
||||||
* Copyright © 2008 Julien Danjou <julien@danjou.info>
|
* Copyright © 2008 Julien Danjou <julien@danjou.info>
|
||||||
* Copyright © 2008 Pierre Habouzit <madcoder@debian.org>
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,368 +19,23 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* XStringToKeysym() */
|
#include "key.h"
|
||||||
#include <X11/Xlib.h>
|
|
||||||
|
|
||||||
#include "structs.h"
|
|
||||||
|
|
||||||
extern awesome_t globalconf;
|
|
||||||
|
|
||||||
static void
|
|
||||||
keybinding_delete(keybinding_t **kbp)
|
|
||||||
{
|
|
||||||
luaL_unref(globalconf.L, LUA_REGISTRYINDEX, (*kbp)->press);
|
|
||||||
luaL_unref(globalconf.L, LUA_REGISTRYINDEX, (*kbp)->release);
|
|
||||||
p_delete(kbp);
|
|
||||||
}
|
|
||||||
|
|
||||||
DO_RCNT(keybinding_t, keybinding, keybinding_delete)
|
|
||||||
ARRAY_FUNCS(keybinding_t *, keybinding, keybinding_unref)
|
|
||||||
DO_LUA_NEW(static, keybinding_t, keybinding, "keybinding", keybinding_ref)
|
|
||||||
DO_LUA_GC(keybinding_t, keybinding, "keybinding", keybinding_unref)
|
|
||||||
|
|
||||||
static int
|
|
||||||
keybinding_ev_cmp(xcb_keysym_t keysym, xcb_keycode_t keycode,
|
|
||||||
unsigned long mod, const keybinding_t *k)
|
|
||||||
{
|
|
||||||
if (k->keysym) {
|
|
||||||
if (k->keysym != keysym)
|
|
||||||
return k->keysym > keysym ? 1 : -1;
|
|
||||||
}
|
|
||||||
if (k->keycode) {
|
|
||||||
if (k->keycode != keycode)
|
|
||||||
return k->keycode > keycode ? 1 : -1;
|
|
||||||
}
|
|
||||||
return k->mod == mod ? 0 : (k->mod > mod ? 1 : -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
keybinding_cmp(const keybinding_t *k1, const keybinding_t *k2)
|
|
||||||
{
|
|
||||||
assert ((k1->keysym && k2->keysym) || (k1->keycode && k2->keycode));
|
|
||||||
assert ((!k1->keysym && !k2->keysym) || (!k1->keycode && !k2->keycode));
|
|
||||||
|
|
||||||
if (k1->keysym != k2->keysym)
|
|
||||||
return k2->keysym > k1->keysym ? 1 : -1;
|
|
||||||
if (k1->keycode != k2->keycode)
|
|
||||||
return k2->keycode > k1->keycode ? 1 : -1;
|
|
||||||
return k1->mod == k2->mod ? 0 : (k2->mod > k1->mod ? 1 : -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Grab key on the root windows.
|
|
||||||
* \param k The keybinding.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
window_root_grabkey(keybinding_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Ungrab key on the root windows.
|
|
||||||
* \param k The keybinding.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
window_root_ungrabkey(keybinding_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_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keybinding_register_root(keybinding_t *k)
|
|
||||||
{
|
|
||||||
keybinding_array_t *arr = k->keysym ? &globalconf.keys.by_sym : &globalconf.keys.by_code;
|
|
||||||
int l = 0, r = arr->len;
|
|
||||||
|
|
||||||
keybinding_ref(&k);
|
|
||||||
|
|
||||||
while (l < r) {
|
|
||||||
int i = (r + l) / 2;
|
|
||||||
switch (keybinding_cmp(k, arr->tab[i])) {
|
|
||||||
case -1: /* k < arr->tab[i] */
|
|
||||||
r = i;
|
|
||||||
break;
|
|
||||||
case 0: /* k == arr->tab[i] */
|
|
||||||
keybinding_unref(&arr->tab[i]);
|
|
||||||
arr->tab[i] = k;
|
|
||||||
return;
|
|
||||||
case 1: /* k > arr->tab[i] */
|
|
||||||
l = i + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keybinding_array_splice(arr, r, 0, &k, 1);
|
|
||||||
window_root_grabkey(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
keybinding_unregister_root(keybinding_t **k)
|
|
||||||
{
|
|
||||||
keybinding_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 (keybinding_cmp(*k, arr->tab[i])) {
|
|
||||||
case -1: /* k < arr->tab[i] */
|
|
||||||
r = i;
|
|
||||||
break;
|
|
||||||
case 0: /* k == arr->tab[i] */
|
|
||||||
keybinding_array_take(arr, i);
|
|
||||||
window_root_ungrabkey(*k);
|
|
||||||
keybinding_unref(k);
|
|
||||||
return;
|
|
||||||
case 1: /* k > arr->tab[i] */
|
|
||||||
l = i + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the keysym from keycode.
|
|
||||||
* \param detail The keycode received.
|
|
||||||
* \param state The modifier state.
|
|
||||||
* \return A keysym.
|
|
||||||
*/
|
|
||||||
xcb_keysym_t
|
|
||||||
key_getkeysym(xcb_keycode_t detail, uint16_t state)
|
|
||||||
{
|
|
||||||
xcb_keysym_t k0, k1;
|
|
||||||
|
|
||||||
/* 'col' (third parameter) is used to get the proper KeySym
|
|
||||||
* according to modifier (XCB doesn't provide an equivalent to
|
|
||||||
* XLookupString()).
|
|
||||||
*
|
|
||||||
* If Mod5 is ON we look into second group.
|
|
||||||
*/
|
|
||||||
if(state & XCB_MOD_MASK_5)
|
|
||||||
{
|
|
||||||
k0 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 2);
|
|
||||||
k1 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 3);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
k0 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 0);
|
|
||||||
k1 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The numlock modifier is on and the second KeySym is a keypad
|
|
||||||
* KeySym */
|
|
||||||
if((state & globalconf.numlockmask) && xcb_is_keypad_key(k1))
|
|
||||||
{
|
|
||||||
/* The Shift modifier is on, or if the Lock modifier is on and
|
|
||||||
* is interpreted as ShiftLock, use the first KeySym */
|
|
||||||
if((state & XCB_MOD_MASK_SHIFT) ||
|
|
||||||
(state & XCB_MOD_MASK_LOCK && (state & globalconf.shiftlockmask)))
|
|
||||||
return k0;
|
|
||||||
else
|
|
||||||
return k1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The Shift and Lock modifers are both off, use the first
|
|
||||||
* KeySym */
|
|
||||||
else if(!(state & XCB_MOD_MASK_SHIFT) && !(state & XCB_MOD_MASK_LOCK))
|
|
||||||
return k0;
|
|
||||||
|
|
||||||
/* The Shift modifier is off and the Lock modifier is on and is
|
|
||||||
* interpreted as CapsLock */
|
|
||||||
else if(!(state & XCB_MOD_MASK_SHIFT) &&
|
|
||||||
(state & XCB_MOD_MASK_LOCK && (state & globalconf.capslockmask)))
|
|
||||||
/* The first Keysym is used but if that KeySym is lowercase
|
|
||||||
* alphabetic, then the corresponding uppercase KeySym is used
|
|
||||||
* instead */
|
|
||||||
return k1;
|
|
||||||
|
|
||||||
/* The Shift modifier is on, and the Lock modifier is on and is
|
|
||||||
* interpreted as CapsLock */
|
|
||||||
else if((state & XCB_MOD_MASK_SHIFT) &&
|
|
||||||
(state & XCB_MOD_MASK_LOCK && (state & globalconf.capslockmask)))
|
|
||||||
/* The second Keysym is used but if that KeySym is lowercase
|
|
||||||
* alphabetic, then the corresponding uppercase KeySym is used
|
|
||||||
* instead */
|
|
||||||
return k1;
|
|
||||||
|
|
||||||
/* The Shift modifer is on, or the Lock modifier is on and is
|
|
||||||
* interpreted as ShiftLock, or both */
|
|
||||||
else if((state & XCB_MOD_MASK_SHIFT) ||
|
|
||||||
(state & XCB_MOD_MASK_LOCK && (state & globalconf.shiftlockmask)))
|
|
||||||
return k1;
|
|
||||||
|
|
||||||
return XCB_NO_SYMBOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
keybinding_t *
|
|
||||||
keybinding_find(const xcb_key_press_event_t *ev)
|
|
||||||
{
|
|
||||||
const keybinding_array_t *arr = &globalconf.keys.by_sym;
|
|
||||||
int l, r, mod = XUTIL_MASK_CLEAN(ev->state);
|
|
||||||
xcb_keysym_t keysym;
|
|
||||||
|
|
||||||
/* get keysym ignoring shift and mod5 */
|
|
||||||
keysym = key_getkeysym(ev->detail, ev->state & ~(XCB_MOD_MASK_SHIFT | XCB_MOD_MASK_5 | XCB_MOD_MASK_LOCK));
|
|
||||||
|
|
||||||
again:
|
|
||||||
l = 0;
|
|
||||||
r = arr->len;
|
|
||||||
while (l < r)
|
|
||||||
{
|
|
||||||
int i = (r + l) / 2;
|
|
||||||
switch (keybinding_ev_cmp(keysym, ev->detail, mod, arr->tab[i]))
|
|
||||||
{
|
|
||||||
case -1: /* ev < arr->tab[i] */
|
|
||||||
r = i;
|
|
||||||
break;
|
|
||||||
case 0: /* ev == arr->tab[i] */
|
|
||||||
return arr->tab[i];
|
|
||||||
case 1: /* ev > arr->tab[i] */
|
|
||||||
l = i + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (arr != &globalconf.keys.by_code)
|
|
||||||
{
|
|
||||||
arr = &globalconf.keys.by_code;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
luaA_keystore(keybinding_t *key, const char *str, ssize_t len)
|
|
||||||
{
|
|
||||||
if(len)
|
|
||||||
{
|
|
||||||
if(*str != '#')
|
|
||||||
{
|
|
||||||
key->keysym = XStringToKeysym(str);
|
|
||||||
if (!key->keysym)
|
|
||||||
{
|
|
||||||
if (len == 1)
|
|
||||||
key->keysym = *str;
|
|
||||||
else
|
|
||||||
warn("there's no keysym named \"%s\"", str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
key->keycode = atoi(str + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Define a global key binding. This key binding will always be available.
|
/** Define a global key binding. This key binding will always be available.
|
||||||
|
* (DEPRECATED, see key).
|
||||||
* \param L The Lua VM state.
|
* \param L The Lua VM state.
|
||||||
*
|
|
||||||
* \luastack
|
* \luastack
|
||||||
* \lparam A table with modifier keys.
|
* \lparam A table with modifier keys.
|
||||||
* \lparam A key name.
|
* \lparam A key name.
|
||||||
* \lparam A function to execute on key press.
|
* \lparam A function to execute on key press.
|
||||||
* \lparam A function to execute on key release.
|
* \lparam A function to execute on key release.
|
||||||
* \lreturn The keybinding.
|
* \lreturn The key.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
luaA_keybinding_new(lua_State *L)
|
luaA_keybinding_new(lua_State *L)
|
||||||
{
|
{
|
||||||
size_t i, len;
|
luaA_deprecate(L, "key");
|
||||||
keybinding_t *k;
|
return luaA_key_new(L);
|
||||||
const char *key;
|
|
||||||
luaA_ref press = LUA_REFNIL, release = LUA_REFNIL;
|
|
||||||
|
|
||||||
/* arg 2 is key mod table */
|
|
||||||
luaA_checktable(L, 2);
|
|
||||||
/* arg 3 is key */
|
|
||||||
key = luaL_checklstring(L, 3, &len);
|
|
||||||
|
|
||||||
if(!lua_isnil(L, 4))
|
|
||||||
luaA_registerfct(L, 4, &press);
|
|
||||||
|
|
||||||
if(lua_gettop(L) == 5 && !lua_isnil(L, 5))
|
|
||||||
luaA_registerfct(L, 5, &release);
|
|
||||||
|
|
||||||
/* get the last arg as function */
|
|
||||||
k = p_new(keybinding_t, 1);
|
|
||||||
luaA_keystore(k, key, len);
|
|
||||||
|
|
||||||
k->press = press;
|
|
||||||
k->release = release;
|
|
||||||
|
|
||||||
len = lua_objlen(L, 2);
|
|
||||||
for(i = 1; i <= len; i++)
|
|
||||||
{
|
|
||||||
size_t blen;
|
|
||||||
lua_rawgeti(L, 2, i);
|
|
||||||
key = luaL_checklstring(L, -1, &blen);
|
|
||||||
k->mod |= xutil_key_mask_fromstr(key, blen);
|
|
||||||
}
|
|
||||||
|
|
||||||
return luaA_keybinding_userdata_new(L, k);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add a global key binding. This key binding will always be available.
|
|
||||||
* \param L The Lua VM state.
|
|
||||||
*
|
|
||||||
* \luastack
|
|
||||||
* \lvalue A keybinding.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
luaA_keybinding_add(lua_State *L)
|
|
||||||
{
|
|
||||||
keybinding_t **k = luaA_checkudata(L, 1, "keybinding");
|
|
||||||
keybinding_register_root(*k);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remove a global key binding.
|
|
||||||
* \param L The Lua VM state.
|
|
||||||
*
|
|
||||||
* \luastack
|
|
||||||
* \lvalue A keybinding.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
luaA_keybinding_remove(lua_State *L)
|
|
||||||
{
|
|
||||||
keybinding_t **k = luaA_checkudata(L, 1, "keybinding");
|
|
||||||
keybinding_unregister_root(k);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct luaL_reg awesome_keybinding_methods[] =
|
const struct luaL_reg awesome_keybinding_methods[] =
|
||||||
|
@ -389,12 +43,3 @@ const struct luaL_reg awesome_keybinding_methods[] =
|
||||||
{ "__call", luaA_keybinding_new },
|
{ "__call", luaA_keybinding_new },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
const struct luaL_reg awesome_keybinding_meta[] =
|
|
||||||
{
|
|
||||||
{ "add", luaA_keybinding_add },
|
|
||||||
{ "remove", luaA_keybinding_remove },
|
|
||||||
{ "__tostring", luaA_keybinding_tostring },
|
|
||||||
{ "__gc", luaA_keybinding_gc },
|
|
||||||
{ NULL, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
#include "keygrabber.h"
|
#include "keygrabber.h"
|
||||||
#include "keybinding.h"
|
#include "key.h"
|
||||||
|
|
||||||
extern awesome_t globalconf;
|
extern awesome_t globalconf;
|
||||||
|
|
||||||
|
|
8
luaa.c
8
luaa.c
|
@ -73,8 +73,9 @@ extern const struct luaL_reg awesome_widget_methods[];
|
||||||
extern const struct luaL_reg awesome_widget_meta[];
|
extern const struct luaL_reg awesome_widget_meta[];
|
||||||
extern const struct luaL_reg awesome_wibox_methods[];
|
extern const struct luaL_reg awesome_wibox_methods[];
|
||||||
extern const struct luaL_reg awesome_wibox_meta[];
|
extern const struct luaL_reg awesome_wibox_meta[];
|
||||||
|
extern const struct luaL_reg awesome_key_methods[];
|
||||||
|
extern const struct luaL_reg awesome_key_meta[];
|
||||||
extern const struct luaL_reg awesome_keybinding_methods[];
|
extern const struct luaL_reg awesome_keybinding_methods[];
|
||||||
extern const struct luaL_reg awesome_keybinding_meta[];
|
|
||||||
|
|
||||||
static struct sockaddr_un *addr;
|
static struct sockaddr_un *addr;
|
||||||
static ev_io csio = { .fd = -1 };
|
static ev_io csio = { .fd = -1 };
|
||||||
|
@ -304,7 +305,7 @@ luaAe_type(lua_State *L)
|
||||||
CHECK_TYPE(wibox);
|
CHECK_TYPE(wibox);
|
||||||
CHECK_TYPE(client);
|
CHECK_TYPE(client);
|
||||||
CHECK_TYPE(image);
|
CHECK_TYPE(image);
|
||||||
CHECK_TYPE(keybinding);
|
CHECK_TYPE(key);
|
||||||
CHECK_TYPE(button);
|
CHECK_TYPE(button);
|
||||||
CHECK_TYPE(tag);
|
CHECK_TYPE(tag);
|
||||||
CHECK_TYPE(widget);
|
CHECK_TYPE(widget);
|
||||||
|
@ -836,7 +837,8 @@ luaA_init(void)
|
||||||
luaA_openlib(L, "client", awesome_client_methods, awesome_client_meta);
|
luaA_openlib(L, "client", awesome_client_methods, awesome_client_meta);
|
||||||
|
|
||||||
/* Export keys */
|
/* Export keys */
|
||||||
luaA_openlib(L, "keybinding", awesome_keybinding_methods, awesome_keybinding_meta);
|
luaA_openlib(L, "key", awesome_key_methods, awesome_key_meta);
|
||||||
|
luaA_openlib(L, "keybinding", awesome_keybinding_methods, awesome_key_meta);
|
||||||
|
|
||||||
lua_pushliteral(L, "AWESOME_VERSION");
|
lua_pushliteral(L, "AWESOME_VERSION");
|
||||||
lua_pushstring(L, AWESOME_VERSION);
|
lua_pushstring(L, AWESOME_VERSION);
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "luaa.h"
|
#include "luaa.h"
|
||||||
#include "swindow.h"
|
#include "swindow.h"
|
||||||
#include "keybinding.h"
|
#include "key.h"
|
||||||
#include "common/xutil.h"
|
#include "common/xutil.h"
|
||||||
#include "common/xembed.h"
|
#include "common/xembed.h"
|
||||||
#include "common/refcount.h"
|
#include "common/refcount.h"
|
||||||
|
@ -293,8 +293,8 @@ struct awesome_t
|
||||||
/** Key bindings */
|
/** Key bindings */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
keybinding_array_t by_code;
|
key_array_t by_code;
|
||||||
keybinding_array_t by_sym;
|
key_array_t by_sym;
|
||||||
} keys;
|
} keys;
|
||||||
/** Mouse bindings list */
|
/** Mouse bindings list */
|
||||||
button_array_t buttons;
|
button_array_t buttons;
|
||||||
|
|
Loading…
Reference in New Issue