I've got this working using the snippet below in rc.lua. The one thing I
can't get to work is the bit to escape the prefix so that doing "Ctrl-t
t" will send "Ctrl-t" onto the client. Can anyone help with this:
keygrabber.stop()
root.fake_input("key_press", keycodes["Control"])
root.fake_input("key_press", keycodes["t"])
root.fake_input("key_release", keycodes["t"])
root.fake_input("key_release", keycodes["Control"])
I fired up `xev` and this is what I see when I'm using an rc.lua with
that code and I hit "Ctrl-t t" in the xev window::
KeyPress event, serial 29, synthetic NO, window 0x3800001,
root 0xae, subw 0x0, time 25151798, (117,90), root:(118,116),
state 0x0, keycode 66 (keysym 0xffe3, Control_L), same_screen YES,
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False
FocusOut event, serial 29, synthetic NO, window 0x3800001,
mode NotifyGrab, detail NotifyAncestor
FocusOut event, serial 29, synthetic NO, window 0x3800001,
mode NotifyUngrab, detail NotifyPointer
FocusIn event, serial 29, synthetic NO, window 0x3800001,
mode NotifyUngrab, detail NotifyAncestor
KeymapNotify event, serial 29, synthetic NO, window 0x0,
keys: 4294967214 0 0 16 0 0 0 0 0 0 0 0 0 0 0
0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
MappingNotify event, serial 29, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 248
KeyPress event, serial 29, synthetic NO, window 0x3800001,
root 0xae, subw 0x0, time 25154364, (117,90), root:(118,116),
state 0x0, keycode 66 (keysym 0xffe3, Control_L), same_screen YES,
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False
KeyRelease event, serial 29, synthetic NO, window 0x3800001,
root 0xae, subw 0x0, time 25154365, (117,90), root:(118,116),
state 0x4, keycode 28 (keysym 0x74, t), same_screen YES,
XLookupString gives 1 bytes: (14) ""
XFilterEvent returns: False
KeyRelease event, serial 29, synthetic NO, window 0x3800001,
root 0xae, subw 0x0, time 25154365, (117,90), root:(118,116),
state 0x4, keycode 66 (keysym 0xffe3, Control_L), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
MappingNotify event, serial 30, synthetic NO, window 0x0,
request MappingKeyboard, first_keycode 8, count 248
It looks to me like `root.fake_input("key_press", keycodes["t"])` never
gets to the client but the release does. Why might that be?
I ran into some bugs. It's really kind of stupid that the keygrabber
stuff returns string letter for the key that it grabbed, it should
really be passing in keycodes. The keygrabber also doesn't pass
modifiers in the `mod` argument as documented, they are passed in
individually in the `key` argument. Hence I have to collect them. It
would also be nice if awesome provided access to keycodes in the LUA
API.
Here's the code.
...
num_shift = { "!", "@", "#", "$", "%", "^", "&", "*", "(", ")" }
keycodes = { ["t"] = 28,
["Control"] = 66 }
-- Bind all key numbers to tags.
-- Be careful: we use keycodes to make it works on any keyboard layout.
-- This should map on the top row of your keyboard, usually 1 to 9.
for i = 1, keynumber do
globalkeys = awful.util.table.join(globalkeys,
awful.key({ modkey }, "#" .. i + 9,
function ()
local screen = mouse.screen
if tags[screen][i] then
awful.tag.viewonly(tags[screen][i])
end
end),
awful.key({ modkey, "Control" }, "#" .. i + 9,
function ()
local screen = mouse.screen
if tags[screen][i] then
awful.tag.viewtoggle(tags[screen][i])
end
end),
awful.key({ modkey, "Shift" }, "#" .. i + 9,
function ()
if client.focus and tags[client.focus.screen][i] then
awful.client.movetotag(tags[client.focus.screen][i])
end
end),
awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
function ()
if client.focus and tags[client.focus.screen][i] then
awful.client.toggletag(tags[client.focus.screen][i])
end
end))
keycodes[tostring(i)] = tonumber(i + 9)
keycodes[num_shift[i]] = keycodes[tostring(i)]
end
clientbuttons = awful.util.table.join(
awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
awful.button({ modkey }, 1, awful.mouse.client.move),
awful.button({ modkey }, 3, awful.mouse.client.resize))
-- Make Ctrl-t prefix act like modkey
mod_prefixes = {["Shift_"] = "Shift",
["Control_"] = "Control",
["Alt_"] = "Mod2" ,
["Super_"] = modkey}
globalkeys = awful.util.table.join(
globalkeys,
awful.key(
{ "Control" }, "t",
function(c)
-- compare the modifiers as if modkey was included
mod_match = {modkey}
keygrabber.run(
function(mod, key, event)
if event == "release" then return true end
-- collect grabbed modifiers
for i, modifier in pairs(mod) do
if not awful.util.table.hasitem(mod_match, modifier) then
table.insert(mod_match, modifier)
end
end
if key == "t" and #mod_match == 1 then
-- escape to send a Ctrl-t to the client
keygrabber.stop()
root.fake_input("key_press", keycodes["Control"])
root.fake_input("key_press", keycodes["t"])
root.fake_input("key_release", keycodes["t"])
root.fake_input("key_release", keycodes["Control"])
return false
end
for mod_prefix, modifier in pairs(mod_prefixes) do
if string.sub(
key, 1, string.len(mod_prefix)) == mod_prefix then
-- Grabbed key was a modifier,
-- add to the list and keep grabbing
if not awful.util.table.hasitem(mod_match, modifier)
then
table.insert(mod_match, modifier)
end
return true
end
end
-- Time to handle it so stop grabbing
keygrabber.stop()
-- Look for a matching key binding
-- TODO doesn't delegate to client bindings
found_globalkey = nil
for i, binding in pairs(globalkeys) do
if (awful.util.table.hasitem(binding.modifiers, modkey)
and
(awful.key.match(binding, mod_match, key) or
(keycodes[key] ~= nil and
awful.key.match(
binding, mod_match, "#" .. keycodes[key])))
) then
found_binding = binding
break
end
end
if found_binding == nil then
-- Didn't match a global binding, raise an error
awesome.emit_signal(
"debug::error",
string.format("No keybinding for '%s-%s' found",
table.concat(mod_match, "-"), key))
return false
end
-- Act as if the key press had been done with modkey
found_binding:emit_signal("press")
return false
end)
end))
-- Set keys
root.keys(globalkeys)
-- }}}
...
I'd love any help with the Escape stuff,
Ross
On Wed, Oct 3, 2012 at 10:32 AM, Ignas Anikevicius <[email protected]>
wrote:
> Hello,
>
> I was thinking about it a while back, when I wanted to make modular key
> bindings, and I my thinking was as follows (I didn't implement it
> because I was lazy-or-busy....
>
> So the idea I had was:
> - Set globalkeys variable to several keys which let you enter
> several modes.
> - Those modes have different values for globalkeys and the variable
> for globalkeys is set to a different value when switching to
> some mode.
> - Each globalkeys set has a keybinding to exit the mode and restore
> the initial globalkeys value.
>
> Last step might not be necessary if one changes the bindings, so that
> the globalkeys are restored automatically. This could be more easily
> done by wrapping awful.key command in a helper function. For example (if
> I haven't made silly mistakes):
>
> myhelperfunc = function (mod, key, press, release)
> if release then
> return awful.key(mod, key, press,
> function ()
> release
> globalkeys = globalkeys_init
> end)
> else
> return awful.key(mod, key,
> function ()
> press
> globalkeys = globalkeys_init
> end)
> end
> end
>
> In theory this should work, but there might be something, which I did
> not think about. If you would like an example of some code, maybe I
> would be able to provide some hack, on which you could build on.
>
> All the best,
>
> Ignas A.
--
To unsubscribe, send mail to [email protected].