Several tools exist that may do this, like KMonad, Interception Tools, and keyd.
I've had complete success with keyd
under Wayland, so I describe what I did with that. I suggest reading the short the README for inspiration. The deamon can do a lot more than what's used here.
The present solution does what I want, but circumvents using the AltGr
detour. It treats CapsLock
as Control
everywhere, except in h ,j ,k , l
, which it changes to arrow keys.
1. INSTALLATION
I build keyd
from source, as that was easy. The next lines first install dependencies (including C compiler), downloads the source, builds and installs it, and enables it as service, and starts it and runs it at startup.
When done, it'll tell you where it installed what so you can delete it for uninstall. You can delete the source code after installation.
sudo apt install cmake libudev-dev
git clone https://github.com/rvaiya/keyd
cd keyd
make && sudo make install
sudo systemctl enable keyd && sudo systemctl start keyd
2. FIND THE NAME OF THE KEYBOARD YOU WANT TO REMAP
You can skip this step and remap the default keyboard, see below on default.conf
You should find the name of your keyboard, so we can make a remapping just for that. Run
sudo keyd -m
and press some keys. It'll show the name of the keyboard and the keys pressed. Note down the name. Mine was AT Translated Set 2 keyboard
.
Tip: keyd -m
is useful find the name of keys by pressing them. keyd -l
lists the key names you can map to.
3. MAKE A CONFIGURATION FILE
Wherever, make a configuration file called whatever. We'll move it later. Let's say you use ~/my_keyboard.conf
.
In it, put the following. The #'ed are comments that explains the behavior defined:
[ids]
The keyboards remapped. * for all, else explicit IDs.
[main]
MAIN LAYER
Make capslock activate the second layer:
capslock = layer(movement_layer)
SECOND LAYER (called "movement_layer")
Define the new layer, which while active
by default treats every key as if Control was pressed,
(":C" means the layer should inherit the Control layer),
and overrides this default for only h, j, k and l, which
are mapped to directions.
[movement_layer:C]
h = left
j = down
k = up
l = right
In sum, in the main default layer, everything is standard, except
when CapsLock is pressed, then the second layer is activated.
When the second layer is activate, everything but h, j, k, l
acts as if Control is held---e.g., c copies and v pastes,
which we want, as we are holding down CapsLock.)
4. COPY AND RENAME THE CONFIGURATION FILE AND RESTART KEYD
Next, we copy the configuration to the right location and name it properly, namely according to the keyboard we want to remap.
sudo cp ~/my_keyboard.conf /etc/keyd/AT\ Translated\ Set\ 2\ keyboard.conf
Note on default.conf
and keyboard IDs
You can also copy your config file to /etc/keyd/default.conf
to make it apply to all keyboards. But if you mess up and remap your Enter key, you cannot plugin another keyboard to undo the changes...
You can however replace the *
(for "all") under [ids]
with ids of keyboards for which to apply the remapping. From keyd -m
, note down the <vendor id>:<product id>
of your keyboard. Mine is 0002:000a
. Replace *
with your 0002:000a
.
We then restart keyd
so it loads the new configuration:
sudo systemctl restart keyd
You're now up and running :)
5. CREATE AN ALIAS TO COPY CONFIG AND RESTART KEYD
I ended up playing a lot with the config files. I edited them in a subdirectory of my home folder, then copied them over and restarted keyd.
To make this less of a hassle, in ~/.bash_aliases
, I added
alias rekeyd='sudo cp ~/my_keyboard.conf /etc/keyd/AT\ Translated\ Set\ 2\ keyboard.conf && sudo systemctl restart keyd'
ydotool
and possibly some other tools. Binding then can be done from within your window manager instead ofxmodmap
. No experience myself, so that is why I cannot develop this in an answer for now. – vanadium Sep 19 '21 at 08:42