Skip to content

XKB support#134

Draft
wismill wants to merge 22 commits intolegionus:masterfrom
wismill:xkb/v4
Draft

XKB support#134
wismill wants to merge 22 commits intolegionus:masterfrom
wismill:xkb/v4

Conversation

@wismill
Copy link
Contributor

@wismill wismill commented Jun 3, 2025

Fixes #72

TODO:

  • Moaar tests
  • Reduce XKB test data to strict minimum
  • Refactor commits (squash, proper messages)

@wismill
Copy link
Contributor Author

wismill commented Jun 3, 2025

⚠️ This is very much WIP ⚠️

legionus added 5 commits June 3, 2025 18:35
Signed-off-by: Alexey Gladkov <legion@kernel.org>
Xorg/Wayland uses its own keyboard configuration mechanism. Because of
this, the configuration of the text console and Xorg layouts may differ.
Not all combinations of Xorg layouts have a keymap in the kbd database.
It's inconvenient for users.

To solve this problem, it is possible to try convert the Xorg keymap
to the kernel keymap.

The XKB (X Keyboard Extension) database can be accessed with
libxkbcommon, which does not depend on the X11 libraries.

libxkbcommon is a keyboard keymap compiler and support library which
processes a reduced subset of keymaps as defined by the XKB
specification [1].

libxkbcommon does not distribute a keymap dataset itself, other than for
testing purposes. The most common dataset is xkeyboard-config, which is
used by all current distributions for their X11 XKB data [2].

There is a project that uses a similar approach to unify configurations.
This is console-setup [3].

I talked with Anton Zinoviev and he helped me figure out their idea of
switching multiple layouts with a single key combination:

  > how you solved the problem of switching more than two layouts with
  > one key combination ?

  The keys with ISO_Next_Group, for example the right Alt (keynumber
  100), are defined like this:

  keycode 100 = ShiftL_lock
  ShiftL keycode 100 = ShiftR_lock
  ShiftR keycode 100 = ShiftR_lock
  ShiftL ShiftR keycode 100 = ShiftL_lock

  So this key will work in the following way:

  no modifiers are active -> ShiftL is active
  ShiftL is active -> ShiftL and ShiftR are active
  ShiftL and ShiftR are active -> ShiftR is active
  ShiftR is active -> no modifiers are active

  The groups (the layouts) are placed in the following way:

  active modifiers  1 group    2 groups    3 groups    4 groups
  ----------------  -------    --------    --------    --------
  no modifier       group 1    group 1     group 1     group 1
  ShiftL            group 1    group 2     group 2     group 2
  ShiftR            group 1    group 2     group 3     group 4
  ShiftL+ShiftR     group 1    group 1     group 1     group 3

  In this way we have the following cycles:

  1 group: gr1->gr1->gr1->...
  2 groups: gr1->gr2->gr1->gr2->...
  3 groups: gr1->gr2->gr1->gr4->gr1->gr2->gr1->gr4->...
  4 groups: gr1->gr2->gr3->gr4->gr1->gr2->gr3->gr4->...

  --
  Anton Zinoviev

The difference with this implementation is that I am not trying to read
and parse the XKB base files. I analyze the resulting xkb keymap.

[1] https://xkbcommon.org/doc/current/index.html
[2] https://www.freedesktop.org/wiki/Software/XKeyboardConfig/
[3] https://salsa.debian.org/installer-team/console-setup.git

Signed-off-by: Alexey Gladkov <legion@kernel.org>
A binary search tree is created with all the unicodes that are used in
the generated keymap so that it can be checked later whether the unicode
symbol is used or not.

Signed-off-by: Alexey Gladkov <legion@kernel.org>
An external table allows it to be expanded without recompilation.

Signed-off-by: Alexey Gladkov <legion@kernel.org>
The approach to using compose differs between libxkbcommon and kernel.
Compose in the kernel has stricter restrictions.

1. Length of sequence.

xkb: The length of the compose sequence can be any (or very long).
kbd: The length of the sequence is 2.

2. Length of result.

xkb: Again, the result of the sequence can be anything.
kbd: The result of compose restricted by unsigned int.

3. How to use compose.

xkb: The libxkbcommon library loads the entire table for all locales
(more than 5000 combinations) and as characters are typed, it narrows
the number of variants until there is only one sequence left. The
library is not limited by the amount of memory by the number of stored
variants.

kbd: Compose sequences are loaded into the kernel (ioctl KDGKBDIACR) and
after that it is applied in the kernel without our participation. A table
in the kernel is limited to 256 records.

To reduce the number of combinations:

1. We must ignore all xkb compose sequences longer than 2.
2. We should ignore sequences that use unicodes that are not used in the
   generated keymap.

Such tricks allow you to reduce 5000+ to ~220 (for en,ru keymap).
Unfortunately, there is no guarantee yet that the amount of compose will
be within the limit and there is no way to control it yet.

Signed-off-by: Alexey Gladkov <legion@kernel.org>
wismill added 13 commits June 3, 2025 18:37
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
@wismill wismill force-pushed the xkb/v4 branch 2 times, most recently from fa6cfc4 to 1951339 Compare June 3, 2025 16:48
wismill added 2 commits June 3, 2025 18:49
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
wismill added 2 commits June 3, 2025 19:14
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Signed-off-by: Pierre Le Marre <dev@wismill.eu>
@wismill
Copy link
Contributor Author

wismill commented Jun 3, 2025

@legionus CI is finally running. XKB test is expected to fail for now: locally the issue is that stderr output does mot match (I have a bunch of unable to get symbol of…), but I need to first design a test that compare kbd and xkb keymap by traversing them, because I just cannot fully test the keymap manually. I should have started with a much simpler layout too (say, us) 😅. Oh well…

The kbd compose sequences currently use control characters; I am not sure if this is expected (some special encoding?).

@legionus
Copy link
Owner

legionus commented Jun 4, 2025

I was thinking that the testing could involve ckbcomp in some way (keymaps that were generated by it). Generate a keymap with this utility and use it as a sample. I don't know how possible that would be.

./ckbcomp -layout us,ru -compact

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add xkb support

2 participants