Remap Enter to Control in GNU/Linux (2020 Edition)
Note: Check out my original article from 2013 about the rationale behind this remapping.
Recently I’ve switched back from macOS to GNU/Linux, as my primary development
environment, and I found out that my old article on remapping Enter
to Control
was no longer the optimal way to achieve this (e.g. - xcape
operates at the X level, which means it doesn’t work with Wayland or without a
GUI). It took me a bit of digging, but eventually I found
dual-function-keys
(a plugin for the interception
framework), which does exactly
what I needed and it does it splendidly.
Unfortunately, the tool is not packaged for most GNU/Linux distros1, but setting it up from source is not that complex. In this article I’ll share instructions that are specific to Ubuntu, but they should be easy to modify for other Linux distros.
Let’s kick it off by downloading and installing the interception
framework and
dual-function-keys
:
# install build deps
$ sudo apt install libudev-dev libyaml-cpp-dev libevdev-dev cmake
# create a folder where to clone the source code
$ mkdir src && cd src
# clone the necessary code
$ git clone https://gitlab.com/interception/linux/tools
$ git clone https://gitlab.com/interception/linux/plugins/dual-function-keys
# build and install the interception framework
$ cd tools
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install
$ cd ../..
# build the dual-function-keys plugin
$ cd dual-functions-keys
$ make && sudo make install
That wasn’t so hard, right? Now we have to create a couple of configuration files and we’re ready for action. The first one is .dual-function-keys.yaml
(normally placed in your home folder):
# /home/username/.dual-function-keys.yaml
TIMING:
TAP_MILLISEC: 200
DOUBLE_TAP_MILLISEC: 150
MAPPINGS:
- KEY: KEY_ENTER
TAP: KEY_ENTER
HOLD: KEY_RIGHTCTRL
That’s the main config for dual-function-keys
, where we’re specifying the duration of a tap and double tap and our remapping rules. In our case there’s a single rule - Enter
acts as Enter
on tap (when pressed briefly) and as (right) Control
when held down longer.
Then we need to create /etc/udevmon.yaml
(you’ll need sudo
for this):
# /etc/udevmon.yaml
- JOB: "intercept -g $DEVNODE | dual-function-keys -c /home/bozhidar/.dual-function-keys.yaml | uinput -d $DEVNODE"
DEVICE:
EVENTS:
EV_KEY: [KEY_ENTER]
Note: Update the path the .dual-function-keys.yaml
accordingly.
Finally we need to create a systemd
service definition file for udevmon
and start the new service:
# /etc/systemd/system/udevmon.service
[Unit]
Description=udevmon
Wants=systemd-udev-settle.service
After=systemd-udev-settle.service
[Service]
ExecStart=/usr/bin/nice -n -20 /usr/local/bin/udevmon -c /etc/udevmon.yaml
[Install]
WantedBy=multi-user.target
Now we simply have to enable the udevmon
service our remapping will kick in:
$ sudo systemctl enable --now udevmon
That’s all! Now you can start enjoying your beloved productivity boost!
You can achieve a lot more with dual-function-keys
, so I’d advice you to explore the
tool further. Keep hacking!
Alternatives
Another option I considered was xkeysnail, which seemed a bit simpler to setup, as it’s written in Python, and even has an example config geared towards Emacs users. You might want to check it out.
If someone’s using another approach to achieve the same result I’d love to hear about it!
-
Seems currently it’s only packaged for Arch Linux and family (e.g. Manjaro). ↩