The Simplest Thing In The World: Modifing Keymaps in Wayland

To remap the PrtSc key to the Hyper modifier key under Wayland with Gnome Shell on Ubuntu/Debian on the 28th of April 2024 (around noon) with a us keyboard mapping (I’m hedging my bets here), put the following in the ~/.config/xkb/symbol/us file:

partial alphanumeric_keys modifier_keys
xkb_symbols "hyper" {
    name[Group1]= "Hyper (US)";
    include "us(basic)"
    key <PRSC> { [ Hyper_L ] };
    modifier_map Mod3 { <PRSC> };
};

And then log out and back in again.

That’s it. That’s definitely all I had to say. Or perhaps…

Yes, it’s bitching and moaning time again, but I feel like I’m entitled — because I’ve been struggling with this for (and I’m not exaggerating) years. That is, I’ve taken stabs at making this work going back at least a decade. In total, I’ve probably spent more than a dozen hours pulling my hair and swearing at the computer. So:

In the Olden Days Of Yore, the first thing that happened when you used a computer for the first time was getting really annoyed with the keyboard because nothing was ever exactly like you wanted. (Especially with the national varieties of different keyboards from different companies — the horror!) I remember back at the university in the 90s, people had all kinds of fancy and amusing layouts, making it impossible for anybody to use anybody elses keyboards — keyboard encryption as a security feature, eh? And these shenanigans were possible because it was trivial to modify keyboard definitions. If you wanted to have a Hyper key on PrtSc (if that key did indeed exist back then; probably not on most keyboards), you put this in ~/.Xmodmap and went on with your life:

keycode 107 = Hyper_L
add Mod3 = Hyper_L

This still works to this day, three decades later — sort of. Any changes to the HID device hierarchy these days and the OS is likely to blank the setting and then you have to xmodmap it “manually”. And this only works if you’re still running X, of course, which is getting to be more and more difficult.

I got a new Lenovo Yoga X1 Gen 8, which is a nice laptop — I like a Yoga while travelling, because you can flip it around and watch movies on it without having the keyboard in front of you.

See? It’s nice.

And it has a built-in WWAN/5G modem, so I can use the laptop when there’s no WIFI and without tethering and stuff.

But the modem didn’t work in Debian/stable, so I installed Ubuntu. The modem works fine there, but:

I opened the Settings app, and there were all these horizontal stripes and glitches and stuff? I mean… what? This is a totally normal laptop with built-in normal Intel graphics:

00:02.0 VGA compatible controller: Intel Corporation Raptor Lake-P [Iris Xe Graphics] (rev 04)

And still, just opening the Settings apps displays oodles of glitches in the default configuration? So they’ve obviously stopped even testing in Xorg — everything is moving to Wayland anyway, right?

And then I tried watching a video with mpv! My god!

Googling showed a lot of people having problems in this area, and the solutions were along the lines of:

i915.enable_dc=0
intel_idle.max_cstate=2

And other boot parameters, none of which had any effect for me. So after trying that for a few hours, the writing’s on the wall, even if I’ve resisted for years: I have to switch to Wayland before I get so old that there’s no chance of me ever figuring out any computer stuff ever again: I have to finally make The Configuration For The Future.

So how do you do something as trivial as assigning Hyper_L to the PrtSc key? As the keyboard(5) man page says:

The specification of the keyboard layout in the keyboard file is based on the XKB options XkbModel, XkbLayout, XkbVariant and XkbOptions. Un- fortunately, there is little documentation how to use them.

The keyboard definition in an Ubuntu/Debian machine is in /etc/default/keyboard:

cat /etc/default/keyboard
# KEYBOARD CONFIGURATION FILE

# Consult the keyboard(5) manual page.

XKBMODEL="pc105"
XKBLAYOUT="us"
XKBVARIANT=""
XKBOPTIONS=""

BACKSPACE="guess"

OK. And Wayland is using the xkb stuff? Confusing, but OK. So I google how to redefine things in this system, and… there’s a million people as confused as I am. Because surely things can’t be as bad as this, fifteen years on since Wayland was created?

The story told on a thousand web sites is that to alter the keyboard layout, you “just” alter the layout definition file, which is in /usr/share/X11/xkb/symbols. (In my case, it’s /usr/share/X11/xkb/symbols/us, since I’m using a US layout.) But this is absurd! That’s a file that’s updated when the OS updates, so either your changes will be overwritten, or updating won’t touch the file at all, so you won’t get updates from the OS. (Which can be important — keyboards rarely change, but they do evolve slowly over time, and you want a solution you can use for decades, right?)

There’s official-looking pages like this that tries to tell you how to add new layout files:

OK, ignoring the empty “writing a symbol file” entry, they suggest creating a new file /usr/share/X11/xkb/symbols/test, which is nice, because it won’t be overwritten by the OS… but then you have to register that file in two other files, /usr/share/X11/xkb/rules/xorg.lst and /usr/share/X11/xkb/rules/xorg.xml, which will be overwritten by the OS! This shit is infuriating!

But I did take a stab at it — created the new file and changed /etc/default/keyboard to point to it… and it had absolutely no effect in Gnome Shell, because it doesn’t really rely on it? Only slightly? (Did I mention that none of this is really documented well?)

xkb has specific options for swapping around certain modifiers:

setxkbmap -option caps:hyper

So you can presumably put that into XKBOPTIONS in /etc/default/keyboard if you wanted to map Caps Lock to Hyper… but these options only exist for certain combinations of keys! How insane is that? I mean, it’s nice that the XKB developers thought it would be handy to swap certain keys around, but it’s absurd that they thought they could enumerate them all? Instead of making a handy general utility that allowed people to do whatever they wanted, they hard-coded a few possibilities and called it a day.

But some suggest you do something like this:

cd /usr/share/X11/xkb/symbols
mv us us-real
cp hyper us

And then you have

/usr/share/X11/xkb/symbols

be just:

xkb_symbols "basic" {
    name[Group1]= "Hyper (US)";
    include "us-real"
    key <PRSC> { [ Hyper_L ] };
    modifier_map Mod3 { <PRSC> };
};

And this works, and it has the advantage of you being able to actually make sense of whatever changes you’ve made to the layout. But still, it has the problem of not being updated when the OS updates (or conversely, being overwritten). (And in any case, keeping personal configuration under /usr is a horrible long term solution, anyway — you want your config to follow you around as you upgrade laptops, and that ideally means just copying your home directory.)

So many people are trying to make sense of this system — like this guy, who has been through my entire journey, and amusingly enough, he’s also trying to rebind PrtSc to Hyper!

This sounds excellent! Just what I need! This should be the official documentation for when you google “how do I rebind a key”, right? Except that it doesn’t work — at least not under Gnome Shell (the default in Ubuntu), which just seems to ignore the XKB_DEFAULT_LAYOUT variable. I’m guessing the “before starting my compositor” means that he runs Sway or something…

*sigh*

And one more deeply infuriating thing about this whole mess: Whenever you’re testing something, you can never know whether logging out and then in again, or a full reboot is necessary, because it’s never clear whether the changes are applied on login, or by the OS (probably in systemd somewhere nasty) when booting up. What used to be a priority in Unix — being able to try things out iteratively and interactively (with informative error messages when you screw something up) has been replaced by mysterious systems that nobody can tell exactly how interact. So while Wayland uses the XKB files, you can’t use setxkbmap to try out the changes you’re making.

(Instead, if you make a syntax error and log out/in again, the OS will just display the White Screen of Death saying that something’s wrong (but not what, of course.). ssh to the rescue.)

And people are desperately trying to make things work:

I didn’t find any well-working solutions in 2024, so I’ve made one. Search for the “Shyriiwook” extension in the GNOME Shell Extensions store.

I applaud their efforts, but surely this shouldn’t have to be necessary!

But there are other ways to remap key in Linux, surely? OK, let’s take a look at a guide. It lists four different applications that work under Wayland: keyd, kbct, kmonad and interception. These keyboard remapper things all rely on daemons that talk to the evdev layer in the Linux kernel, and should work no matter whether you use Wayland or X.

keyd looks nice, and is available on Ubuntu by default. But:

It doesn’t support a Hyper key.

kbct, kmonad and interception aren’t in Ubuntu, and I didn’t test them, because most guides on the Googles seem to suggest that the generically named input-remapper (which was previously called key-remapper) is the bee’s knees. And it’s in Ubuntu! But when I started it, it didn’t look anything like what people were talking about, and doesn’t match the documentation. Were there several of these?

No, it just turns out that there’s a new version out, and it looks totally different, and has a different configuration hierarchy:

Thanks, thanks. So I downloaded that from Github, managed to get it installed and the daemon running, and

# input-remapper-control --symbol-names | grep -i hyper
#

It doesn’t support remapping a key to Hyper.

*sigh*

This excellent page is what finally pointed me in the right direction. The recipe given there doesn’t work for me, and as he says:

Now, I fully agree that this is cumbersome, clunky and feels outdated.

But after testing a number of variations on this theme, I ended up with the solution I posted above. Which works. Today.

Who knows what these Gnome/Wayland people will come up with tomorrow. It would be nice if it were something that, you know, works, but I’m not really holding my breath.

So now that the first hurdle is out of the way, I just have to fix all the other things that don’t quite work under Wayland. I mean, it’s only fifteen years old; one can’t expect everything to work yet…

3 thoughts on “The Simplest Thing In The World: Modifing Keymaps in Wayland”

  1. “I have to switch to Wayland before I get so old that there’s no chance of me ever figuring out any computer stuff ever again”
    This line cracked me up and rang so true.

    I also hate that someone at Lenovo thought it was ok to put the Print Screen key in such a key (hehehe 😎) location. I used the “menu” key in that position, just like regular keyboards, because I had an Emacs personal keymap in there. And also use it to pop up the little spellcheck menu when typing.

    1. I moved to Fedora a couple years ago, it has used Wayland as default for a while now, can recommended. Most Gnome extensions work better because it has a very bare-bones DE setup (I don’t use any, though). Too big a change just for this one issue, but if you have more Wayland-related breakage, something to consider.

    2. I can recommend kmonad. It’s kind of a drag to set it up in systemd or put it in your .bashrc to run at startup (in my particular case, I had it running as an Emacs start up step, because I open it every time I start the computer anyway). But it works as advertised and it is very easy to configure. And to test changes – just restart it.

Leave a Reply