gvalkov/python-evdev

Using evdev with international/non-US keyboard layouts?

Opened this issue · 5 comments

I've been using a keyboard input remapper (xkeysnail and its fork keyszer) that uses evdev and noticed that it can't handle international/non-US keyboard layouts very well. For instance, if you switch to an AZERTY layout instead of the usual US QWERTY layout and a remapped combo tries to use evdev to type a "Q", it will output an "A" into the application because the new keyboard layout interprets that key code as an "A".

I tried to understand why this happens, and it seems like evdev would need a different key definition file for each keyboard layout, whereas these projects only come with a key.py file containing key definitions for a US keyboard layout. So evdev always acts like it's typing on a US keyboard.

Are these projects misusing evdev in some way, or are there tools or techniques available to allow evdev to easily adapt to different international keyboard layouts, without having to create a new key definition file for each layout?

I'm not certain I actually understand the whole situation with evdev and non-US keyboard layouts. Any ideas on how to deal with international keyboard layouts while using evdev? There are not many references to keyboard layouts that I can find in the issues here, so I feel like I might be missing some obvious solution to this problem.

The project that uses these keymappers:
https://github.com/rbreaves/kinto

The keymappers projects I'm referring to:
https://github.com/joshgoebel/keyszer
https://github.com/mooz/xkeysnail

with Q you probably mean KEY_Q, right? This name comes from https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h

Instead of using "KEY_Q" to write a Q, try to inject the integer that comes from xmodmap -pke, minus an offset of 8. That is how input-remapper is doing it. See https://github.com/sezanzeb/input-remapper/blob/beta/inputremapper/configs/system_mapping.py

The key definition file I'm familiar with has dropped most of the "KEY_" prefixes, probably to reduce the verbosity of the combos in the user's config file, but it should be the same thing.

# xkb uses keycodes that are 8 higher than those from evdev
XKB_KEYCODE_OFFSET = 8

That is very interesting. So input-remapper is able to build the key definition on-the-fly from the output of xmodmap -pke, which would allow it to still be correct after the layout changes? Wonder if that's fast enough to be using on every keystroke, or if input-remapper also has a mechanism for noticing when the user changes the layout.

Thanks for the info/links. I will look into how this works.

Wonder if that's fast enough to be using on every keystroke, or if input-remapper also has a mechanism for noticing when the user changes the layout.

it doesn't actually, good point. Noone has ever opened an issue about this, so most people probably keep their keyboard layout forever without changing it. If a layout changes, I think the injection has to be restarted.

If there is a way to detect a layout change, it might be via dbus. But those messages are probably custom to the desktop environments.

I'm not sure how well this xmodmap -pke thing is going to work out on a system with multiple keyboard layouts enabled.

While most people may stick with a single layout, I have seen some indications that there is a pretty good slice of international users who need to use multiple layouts. And there is even an option in GNOME to use a different layout per window, which would mean there really would be a need to get the current layout at any given moment. That would be an essential feature for anyone working on documents in multiple languages in different windows.

Here's a snippet of the output from xmodmap -pke with three (3) different keyboard layouts enabled in GNOME:

keycode  24 = q Q a A q Q at Greek_OMEGA q Q
keycode  25 = w W z Z w W U017F section w W
keycode  26 = e E e E EuroSign NoSymbol e E EuroSign cent e E
keycode  27 = r R r R r R paragraph registered r R
keycode  28 = t T t T t T thorn THORN t T
keycode  29 = y Y y Y y Y ydiaeresis yen y Y
keycode  30 = u U u U u U udiaeresis Udiaeresis u U
keycode  31 = i I i I i I idiaeresis Idiaeresis i I
keycode  32 = o O o O o O ograve Ograve o O
keycode  33 = p P p P p P paragraph THORN p P

It's turning out to be quite difficult to get the active keyboard layout. Every command that I've seen offered as a solution for this purpose either shows the US layout (probably the locale default) no matter which layout is actually active, or shows a list of all enabled layouts on the system. Which is kind of what xmodmap -pke is showing above. It's collectively showing the symbols for "English French(AZERTY) Dutch(Dutch) English", and the output doesn't change at all when you switch to a different keyboard layout. So this output by itself can't tell you what the active layout is.

The only tool I've found so far that actually reports the currently active layout correctly is this one:
https://github.com/nonpop/xkblayout-state

Seems this is still a more difficult problem than I was hoping.

It gets worse: In Wayland, managing keyboard layouts seems to be the job of the desktop environment as far as I know, so implementations and possible solutions vary from environment to environment. That xmodmap -pke works at all in GNOME and KDE on Wayland is a miracle