I'm using awesome window manager on my gentoo desktop. My configuration evaluate from time to time, like vim's does for example. These instruments highly optimized for my habits, it is right in my fingers. In this post I'll show how to extend awesome wm key bindings behind it boundaries to third-party applications with help of root.fake_input.

Proposal #1

Tmux multiplexer has it's own panes and you can switch between them with combination of prefix and arrow keys. Almost the same we have in awesome wm. The key of head aches is "almost". It's very hard to switch between different hot keys. The problem can be solved the problem in awesome configuration file. All needed is to check client while switching to next window. If the client is tmux - don't switch, send "prefix + arrow" instead. The solutions is very easy and effective. The code above

.tmux.conf

set-option -g prefix m-a
set-option -g repeat-time 0
set -g default-terminal "screen-256color"
set -g mode-keys vi
bind-key down select-pane -t:.+
bind-key up select-pane -t:.-

rc.lua:

...

function is_tmux(c)
    if string.find(string.lower(c.name), "tmux") ~= nil
    or string.find(string.lower(c.class), "tmux") ~= nil
    then
         return true
    end
    return false
end

function send_tmux_command(cmd)
    keygrabber.stop()
    root.fake_input("key_release", 64)
    root.fake_input("key_press", 64)
    root.fake_input("key_press", 38)
    root.fake_input("key_release", 38)
    root.fake_input("key_release", 64)
    waiter = timer({timeout = 0.01})
    if cmd == 'up' then
        waiter:connect_signal('timeout', function()
            waiter:stop()
            root.fake_input("key_press", 116)
            root.fake_input("key_release", 116)
            root.fake_input("key_press", 64)
        end)
    end
    if cmd == 'down' then
        waiter:connect_signal('timeout', function()
            waiter:stop()
            root.fake_input("key_press", 111)
            root.fake_input("key_release", 111)
            root.fake_input("key_press", 64)
        end)
    end
    waiter:start()
end

globalkeys = awful.util.table.join(
    awful.key({ modkey,           }, "j",
        function()
            if is_tmux(client.focus) then
                send_tmux_command('down')
            else
                awful.client.focus.byidx(1)
                if client.focus then client.focus:raise() end
            end
        end),
    awful.key({ modkey,           }, "k",
        function()
            if is_tmux(client.focus) then
                send_tmux_command('up')
            else
                awful.client.focus.byidx(-1)
                if client.focus then client.focus:raise() end
            end
        end))

...

proposal #2

There is common recommendation to use vim's native layout switching (default to <C+^>), when you have more than one keyboard layout to use. It solves problems with hot keys in vim. Other applications uses system-wide switcher with it's own key bindings. Similar to the proposal #1 we can tune awesome wm configuration:

.vimrc

inoremap <M-=> <C-^>
cnoremap <M-=> <C-^>

rc.lua

function is_vim(c)
    if string.find(string.lower(c.name), "vim") ~= nil
    or string.find(string.lower(c.class), "vim") ~= nil
    then
        return true;
    end
    return false
end

function switch_key_layout_vimspecial()
    if is_vim(client.focus) then
        keygrabber.stop()
        root.fake_input("key_press", 64)
        root.fake_input("key_press", 21)
        root.fake_input("key_release", 21)
        root.fake_input("key_release", 64)
    else
        mylswitcher.switch()
    end
end

globalkeys = awful.util.table.join(globalkeys,
    awful.key({modkey, }, "space", function () switch_key_layout_vimspecial() end))

Comments

comments powered by Disqus