Hash :
9ede705b
Author :
Date :
2025-04-13T09:50:18
state: Capitalization transformation in xkb_state_key_get_syms
Previously `xkb_state_key_get_syms()` did not perform capitalization
tranformation, while `xkb_state_key_get_one_sym()` does perform it.
This is unfortunate if we want to promote the use of multiple keysyms
per levels.
The API make it difficult to change now though: we return a pointer to
an immutable array rather than filling a buffer. While we could use an
internal buffer in `xkb_state`, this option would limit the API to
*sequential* calls of `xkb_state_key_get_syms()` or require some buffer
handling (e.g. rotation).
Instead we now store the capitalization directly in `xkb_level`. We
modified `xkb_level` like so (see below for discussion about the size):
```diff
struct xkb_level {
- unsigned int num_syms;
+ uint16_t num_syms;
- unsigned int num_actions;
+ uint16_t num_actions;
+ union {
+ /** num_syms == 1: Upper keysym */
+ xkb_keysym_t upper;
+ /** num_syms > 1: Indicate if `syms` contains the upper case
+ * keysyms after the lower ones. */
+ bool has_upper;
+ };
union {
xkb_keysym_t sym; /* num_syms == 1 */
xkb_keysym_t *syms; /* num_syms > 1 */
} s;
union {
union xkb_action action; /* num_actions == 1 */
union xkb_action *actions; /* num_actions > 1 */
} a;
};
```
- When `level.num_syms` <= 1, we store the upper keysym in `level.upper`.
- Else if there no cased syms, we set `level.has_upper` to false.
- Else if there are some cased syms, we set `level.has_upper`` to `true`
and we double the original size of `level.s.syms`, but *without*
modifying `level.num_syms`. We then append the transformed keysyms
right after the original ones, so that we can access them by a simple
pointer operation: `level.s.syms + level.num_syms`.
The memory footprint is *unchanged*, thanks to the reduced fields for
actions and keysyms counts.
libxkbcommon is a keyboard keymap compiler and support library which processes a reduced subset of keymaps as defined by the XKB (X Keyboard Extension) specification. It also contains a module for handling Compose and dead keys and a separate registry library for listing available keyboard layouts.
libxkbcommon is built with Meson:
meson setup build
meson compile -C build
meson test -C build # Run the tests.
To build for use with Wayland, you can disable X11 support while still using the X11 keyboard configuration resource files thusly:
meson setup build \
-Denable-x11=false \
-Dxkb-config-root=/usr/share/X11/xkb \
-Dx-locale-root=/usr/share/X11/locale
meson compile -C build
While libxkbcommon’s API is somewhat derived from the classic XKB API as found
in X11/extensions/XKB.h and friends, it has been substantially reworked to
expose fewer internal details to clients.
See the API Documentation.
libxkbcommon does not distribute a keyboard layout 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. Further information on xkeyboard-config is available at its homepage and at its repository.
The dataset for Compose is distributed in libX11, as part of the X locale data.
See Compatibility notes.
An extremely rudimentary homepage can be found at
https://xkbcommon.org
xkbcommon is maintained in git at
https://github.com/xkbcommon/libxkbcommon
Patches are always welcome, and may be sent to either xorg-devel@lists.x.org or wayland-devel@lists.freedesktop.org or in a GitHub pull request.
Bug reports (and usage questions) are also welcome, and may be filed at GitHub.
The maintainers are:
Many thanks are due to Dan Nicholson for his heroic work in getting xkbcommon off the ground initially.