Living my Fullest on Home Row
2020-09-06
Audience
- I agree the most useless key is CAPS
- Fed up with placement of alt, ctrl, ESC, Meta
- Already remapped CAPS to ESC or Meta using
xmodmap
- can I use Meta as ESC only inside vi*
- can I use ESC as modifier so I can share it for WM and vi*
- can I use TAB as modifier and retain it's auto-complete on shell
- Don't have fancy (your paycheck worth) 60% Mechanical
Keyboard with QMK firmware to try out a new layout every
week with multiple layers underneath.
What's this?
- Map a key to 2 different functions based on tapping & holding
- A bare minimum solution for reducing travel
- Slope of learning curve converges to 0 within a week
Disrupt Inertia
I was using Meta (CAPS being remapped) as my modifier for all WMs I use,
problem was when using Vim I have to travel a lot for reaching ESC
Going through vim fandom I'm no where satisfied with the alternatives,
Alt
placement strains me more than CTRL
(exception looking at my X201's funky FN key )
Went with Ctrl-c, there were many drawbacks with this one.
Real bummer was shift+i to insert in multiple lines
plus it's not simple as tapping a single key.
Also I don't want to compromise Meta CAPS remap.
I was lazy relying on my cheap 60% keyboard's (Bnne Pro)
tap function untill quarantine (my KB was struck in my dorm)
Double Frustated me :/
Solution
- Tab_hold as ALT
- CAPS_hold as Meta_key; CAPS tap as ESC
- Semicolon_hold (;) as RIGHT_CTRL
Prerequisites
(this should work regardless of X11 or wayland)
- Interception Tools
- Dual-function-keys plugin
- Reading Description of Interception-tools
Setup
Tested on MX-linux, Artix, Manjaro (all running kernal > 5.6)
Dependencies, I find names are quite different on Debian-based
$ apt-file search libevdev-uinput.h
libevdev-dev: /usr/include/libevdev-1.0/libevdev/libevdev-uinput.h
$ apt-file search libudev.h
libudev-dev: /usr/include/libudev.h
$ apt install libevdev-dev libudev-dev libyaml-cpp-dev cmake
and follow build instructions
AUR (simple as ever), packages interception-tools dual-function-keys
Getting started
Figuring right input device,
$ cat /dev/input/event<x>
/* in my case platform-i8042-serio-0-event-kbd is linked to event3 */
pressing keys for the right input device will stdout some weird characters so one can be sure.
intercept -g /dev/input/event<x> | uinput -d /dev/input/event<x>
virtual device (uinput) will deny reading unless
the user is in input group or running uinput as root.
here's the caveat intercept
hijacks the input so password cannot be typed..
workaround would be permitting uinput to run as root without password
as I'm using doas
echo "permit nopass :hisacro cmd uinput" >> /etc/doas.conf
should be similar for sudo
(with hard syntax gimmicks & editing with visudo..)
note : use udevmon instead see below,
if it's just for testing make sudo persist on shell
so typing passwd is avoided
Succeding above, it's pretty much done by piping the hijacked input
into Dual-function-keys plugin before it goes to virtual device
Dual-function-keys need yaml config file, (simple syntax for layman)
TIMING:
TAP_MILLISEC: 200
DOUBLE_TAP_MILLISEC: 150
MAPPINGS:
- KEY: KEY_TAB
TAP: KEY_TAB
HOLD: KEY_LEFTALT
- KEY: KEY_CAPSLOCK
TAP: KEY_ESC
HOLD: KEY_LEFTMETA
- KEY: KEY_SEMICOLON
TAP: KEY_SEMICOLON
HOLD: KEY_RIGHTCTRL
If everything goes well this should work
$ intercept -g /dev/input/event<x> | dual-function-keys -c /path/to/tapping.yaml | sudo uinput -d /dev/input/event<x>`
As udevmon is included in interception-tools,
it helps combining these also supports config for multiple devices,
auto reads files under /etc/interception/udevmon.d/best_tap.yaml
- JOB: "intercept -g /dev/input/event3 | dual-function-keys -c ~/.myscripts/tapping.yaml | uinput -d /dev/input/event3"
DEVICE:
EVENTS:
EV_KEY: [KEY_TAB, KEY_CAPSLOCK, KEY_SEMICOLON]
now $ udevmon
is all you need
If you're planning to run udevmon as init script,
sample systemd.service is provided beware
this affects all users if you're on shared desktop.
(personally I prefer udevmon on my WM's startup script)
Tips
$ uinput -p -d /dev/input/event<x>
will list all the keys
Use evtest instead of xev to check the Event_codes
Most of the packages share [shift] + ctrl + tab to toggle back and forth
in addition if alt or ctrl overrides with default maps,
use shift + ctrl + some_key
My UseCase
i3, herbstluftwm (heavy on Meta as mod which is CAPS_hold)
sudo tiling shortcuts on xfce. (account on family desktop)
nethack - close to few hundreds of YASD in a week
remapped few uppercases to CTRL
(I got into Vi from nethack when looking
for similar key-bind editor still miss yubn)
vim - all other options makes much sense
notably, Tab + hjkl moves from insert to normal in resp. direction
Terminal Tabs (unpopular but I highly relay on them)
with tab_hold + num to navigate
mutt - only mail client.
Gimp - More than 5 hrs in a day (cleaning manga),
modified shortcuts to relay on tab_hold
Mtpaint - Pixel art, not as heavy on shortcuts compared to GIMP
firefox, (remember holding ; is ctrl now)
tab_hold + D focus address bar,
shift + ; + tab previous tab
; + tab next tab
; + t new tab
; + w close tab
; + u web page source code
Luakit as secondary.
Cons
Using it for almost 3 months, this has been hard encoded into my muscle memory
to the point I cannot work without it :)
The lag isn't humanly noticeable (don't trust me see it for yourselves)
Disclosure
- Author Francisco Lopes
- my previous beddit post and u/the_shiro_usagi for pointing this out
Any suggestions, unique keybinds, stories, improvements are much welcome
(and fellow hacker with long unix beard tips for getting similar function on OBSD)
Tinker around with multiple devices, Tap timings, extra modifier on home row.. endless
Happy input Hacking!