The long journey of a key press
I have finally got to the root of the issue of why _ and : do not work on Bookworm.
Since we all want to learn something I did a bit of a writeup about what is going on deep behind layers of key codes and keysyms, and what was the issue and how to fix it.
Let's start with the journey of our dear electrons once a key gets pressed.
Pyrainput does a few things
A keycode alone does not do much. xkb is part of X11.
The issue of missing keycodes?
Remember how above we specified that a US keyboard is being used as a base for keycodes, the lowest layer?
On a US keyboard there is no key defined for ?_+{}:".
Also remember how every orange(FN) key gets its own key code?
You see the problem?
Right, pyrainput must translate FN+D on the Pyra keyboard to a keycode for _ that does not exist in the Linux keycode definition header.
And this is the utterly stupid part here.
We have hundreds of keycodes like KEY_SOUND, KEY_VIDEOPHONE, KEY_SPREADSHEET, KEY_SPELLCHECK.
You can find the list here.
Can you imagine how there exists a dedicated keycode for anything you can and can not think of except for a hand full of ASCII codes?
How do we get out of this?
The solution to this is as easy as it sounds.
Let pyrainput translate FN+D to KEY_SOUND and let xkb translate KEY_SOUND to _.
That is exactly what we do and it works, except that it doesn't.
An other chain of events: xkb symbol layers.
So what we did was to define our oen Pyra xkb layout that translates all the keycodes we get to the keysyms we need.
That works super well for those keycodes that are defined like SF;[]=.
However when translating KEY_SOUND to _ that has no effect.
To understand that we must understand that a xkb layout consists out of layers of symbol definitions.
For our pyra that is
Do you spot the problem? inet(evdev) loads after pyra and overwrites it.
As fate wants, pretty much all of the weird non ASCII codes are defined in that inet layout.
Can we get rid of that? Unfortunately not.
To understand that, we must understand an other topic regarding xkb.
There are rules, in our case evdev, that define the order in which symbol files are being loaded.
And how fate wants once again that rule file contains the nice letters
That is right, no easy editing of that.
How to get out of this mess?
Ther are 2 very simple solutions that work.
This solution however is super tedious to do and shares the biggest disadvantage with 1 (see below).
This was the first attempt I trued and for that I improved pyrainput so that users now can set their own keycodes via a config file.
That however will be an other topic and we can fix the current issue luckily without touching pyrainput at all.
Why _ and : stopped working in Bookworm?
It is very simple, since we manually edit
That file is different between Debian versions.
The keycode we use for _ has no keysym defined in
In Buster and Bookworm however the keycode we use is defined in that file.
Issue in the chain and poof, ther fors your _
The fix was as simple as commenting out 2 lines in
I do not like this fix at all, since it is very fragile and once thgat file changes, we are in trouble again.
What are better ways to handle this?
How to procede?
Until the dev team has decided on this matter I publish a .zip file attached to this post that executes solution (1).
The file contains an edited
Unzip and execute the installer as sudo
This will copy the files you need in place and comment out all the keysyms we need and bring back your _ and : on Bookworm.
Even wit hthat in place I strongly vote for solution (2) and to add a systemd service to the mix that loads the pyra symbols manually and saves us from debugging this in the future again.
also we need to make sure that this will be documented properly and easy accessible somewhere.
I spent many days debugging this, starting with pyrainput and working my way through the xkb stack.
What about the headlessterminal?
You might have noticed that in the terminal, without X11 running, many of the orange (FN) letters do not work.
It is all those letters that do not have keycodes and rely on xkb to translate them into keysyms.
so are we lost?
No
It is a bit of extra work to do, but according to the all mighty Internet, we need to use a different mechanism to get all the specia; characters to work in the terminal.
That mechanism is localectl and most sources say that it's required to define xkb for X11 and locales for the terminal.
I have not looked into it and do not know if localectl can handle our keycodes.
However this is also something in my list since some people (mainly aTc) request this.
Unfortunately there is no built in solution to handle X11 and a headless terminal with just one edit.
Let me conclude with a personal message
UPDATE - 2024 - 03 - 10?
I spent quite a bit of time trying to get solution (2) to work.
So I tried to make a systemd service that reloads the pyra symbols manually after xorg got initialized.
Can this even work?
I dpecified DISPLAY=0 but still the log says that it can not find the display.
So can anyone help here?
Can systemd be used to do a
I have manually started my service while the display was running and that did not work.
Also I have specified to run as a regular user.
I have finally got to the root of the issue of why _ and : do not work on Bookworm.
Since we all want to learn something I did a bit of a writeup about what is going on deep behind layers of key codes and keysyms, and what was the issue and how to fix it.
Let's start with the journey of our dear electrons once a key gets pressed.
- Key gets pressed
- The kernel does something and invokes a keycode (see keyboard matrix, however that is not relevant here)
- pyrainput/funkeymonkey catches that keycode and translates it to a different key code [Pyra specific]
- xkb translates the keycode into a keysym
Pyrainput does a few things
- Hides all the input devices and creates 3 new ones (nubs, gamepad, keyboard)
This is needed because oiginally each nub, the gamepad and the keyboard are all different input devices.
With funkeymonkey running, the rest of the OS does not see the original input devices any more, but only the one we defined - Handle the easy switching between gamepad and mouse/keyboard mode for the gamepad section
- Hide FN and assign a separate keycode for each orange(FN) key.
That is required because with only X alone we would not be able to to CTRL+ALT+F6 to switch terminal.
So with pyrainput, each fn key has its dedicated keycode.
Remember, keycodes are the lowest value of the key press chain
A keycode alone does not do much. xkb is part of X11.
- xkb has it's own version of keycodes. They are called keysyms.
- A keysym specifies what symbol a keycode is assigned to.
KEY_1 for example is assigned to "1". - Keycodes use a US QWERTY keyboard as base.
Kexsyms will then define the layout according to the keyboard set in the window manager
For example on a QWERTZ keyboard KEY_Y would be assigned to "Z"
The issue of missing keycodes?
Remember how above we specified that a US keyboard is being used as a base for keycodes, the lowest layer?
On a US keyboard there is no key defined for ?_+{}:".
Also remember how every orange(FN) key gets its own key code?
You see the problem?
Right, pyrainput must translate FN+D on the Pyra keyboard to a keycode for _ that does not exist in the Linux keycode definition header.
And this is the utterly stupid part here.
We have hundreds of keycodes like KEY_SOUND, KEY_VIDEOPHONE, KEY_SPREADSHEET, KEY_SPELLCHECK.
You can find the list here.
Can you imagine how there exists a dedicated keycode for anything you can and can not think of except for a hand full of ASCII codes?
How do we get out of this?
The solution to this is as easy as it sounds.
Let pyrainput translate FN+D to KEY_SOUND and let xkb translate KEY_SOUND to _.
That is exactly what we do and it works, except that it doesn't.
An other chain of events: xkb symbol layers.
So what we did was to define our oen Pyra xkb layout that translates all the keycodes we get to the keysyms we need.
That works super well for those keycodes that are defined like SF;[]=.
However when translating KEY_SOUND to _ that has no effect.
To understand that we must understand that a xkb layout consists out of layers of symbol definitions.
For our pyra that is
Code:
pc+pyra(pyra)+inet(evdev)
As fate wants, pretty much all of the weird non ASCII codes are defined in that inet layout.
Can we get rid of that? Unfortunately not.
To understand that, we must understand an other topic regarding xkb.
There are rules, in our case evdev, that define the order in which symbol files are being loaded.
And how fate wants once again that rule file contains the nice letters
Code:
Do not edit this file, it has been automatically generated
How to get out of this mess?
Ther are 2 very simple solutions that work.
- Edit the inet keysum definition file and comment out the ones we need to use for the Pyra [We use that one currently]
- Run a command after xkb initialized its symbols
setxkbmap -symbols pyra
This command makes so that our pyra layout hets highest priority and loads its keysym definitions after inet
/usr/share/X11/symbols/inet
and use those for _ and :.This solution however is super tedious to do and shares the biggest disadvantage with 1 (see below).
This was the first attempt I trued and for that I improved pyrainput so that users now can set their own keycodes via a config file.
That however will be an other topic and we can fix the current issue luckily without touching pyrainput at all.
Why _ and : stopped working in Bookworm?
It is very simple, since we manually edit
/usr/share/X11/symbols/inet
, this is a very fragile foundation we built our house on.That file is different between Debian versions.
The keycode we use for _ has no keysym defined in
/usr/share/X11/symbols/inet
. So that keycode is free to use.In Buster and Bookworm however the keycode we use is defined in that file.
Issue in the chain and poof, ther fors your _
The fix was as simple as commenting out 2 lines in
/usr/share/X11/symbols/inet
and out _ and : are back again.I do not like this fix at all, since it is very fragile and once thgat file changes, we are in trouble again.
What are better ways to handle this?
- Define a xkb rule to load the pyra symbols after the inet symbols and fix the core of the issue
- Issue a command later than the xkb initialization and load the pyra symbols again to overwrite the initial xkb layout
- Advantage
We want this, no questions asked. This would be the clean way to handl the issue - Disadvantage
I could not get this to work.
I spent so many hours and tried pretty much everything the internet and ChatGPT (man that was trash) suggested and it did not work.
The issue is that we may not edit manually the evdev rules and neither editingthat nor any other solutions I tried changed the symbol load order.
Also I have pretty much no experience in that and do not know how to debug tis properly.
- Advantage
- Easy to do (systemd or .bashrc)
- Way more future proof that nwhat we have now since we do not need to edit/usr/share/X11/symbols/inet
any more - Disadvantage
- Not as clean as 1, a bit more of a hack
- Needs to add a systemd service
- Obfuscates what's going on
-> If one is not aware of that manual overwrite and prints the xkb layout, then it will be very unclear why the pyra symbols have precedence over the inet symbols and why that even works.
How to procede?
Until the dev team has decided on this matter I publish a .zip file attached to this post that executes solution (1).
The file contains an edited
/usr/share/X11/symbols/pyra
and /usr/share/X11/symbols/inet
file as well as an install script.Unzip and execute the installer as sudo
sudo ./install.sh
This will copy the files you need in place and comment out all the keysyms we need and bring back your _ and : on Bookworm.
Even wit hthat in place I strongly vote for solution (2) and to add a systemd service to the mix that loads the pyra symbols manually and saves us from debugging this in the future again.
also we need to make sure that this will be documented properly and easy accessible somewhere.
I spent many days debugging this, starting with pyrainput and working my way through the xkb stack.
What about the headlessterminal?
You might have noticed that in the terminal, without X11 running, many of the orange (FN) letters do not work.
It is all those letters that do not have keycodes and rely on xkb to translate them into keysyms.
so are we lost?
No
It is a bit of extra work to do, but according to the all mighty Internet, we need to use a different mechanism to get all the specia; characters to work in the terminal.
That mechanism is localectl and most sources say that it's required to define xkb for X11 and locales for the terminal.
I have not looked into it and do not know if localectl can handle our keycodes.
However this is also something in my list since some people (mainly aTc) request this.
Unfortunately there is no built in solution to handle X11 and a headless terminal with just one edit.
Let me conclude with a personal message
Take out your Pyra
Give it some love
Get this project rolling once again
Give it some love
Get this project rolling once again
UPDATE - 2024 - 03 - 10?
I spent quite a bit of time trying to get solution (2) to work.
So I tried to make a systemd service that reloads the pyra symbols manually after xorg got initialized.
Can this even work?
I dpecified DISPLAY=0 but still the log says that it can not find the display.
So can anyone help here?
Can systemd be used to do a
setxkbmap -symbols pyra
after xorg initializes?I have manually started my service while the display was running and that did not work.
Also I have specified to run as a regular user.
Attachments
Last edited: