XKB Compatibility {#xkbcommon-compatibility}
July 22, 2026 · View on GitHub
@tableofcontents{html:2}
This page presents the differences between the XKB 1.0 specification implemented in current X servers and its implementation in libxkbcommon.
xkbcommon has removed support for some parts of the specification which introduced unnecessary complications. Many of these removals were in fact not implemented, or half-implemented at best, as well as being totally unused in the standard keyboard layout database, xkeyboard-config.
On the other hand, xkbcommon has notable additions that lift hard-coded limitation of the X11 Protocol.
@todo This page is work in progress. It aims to be exhaustive. Please report any issue.
Keymap support {#keymap-support}
General features
| Feature | X11 | xkbcommon ([v1 format](@ref XKB_KEYMAP_FORMAT_TEXT_V1)) | xkbcommon ([v2 format](@ref XKB_KEYMAP_FORMAT_TEXT_V2)) | |
|---|---|---|---|---|
| Wayland support |
❌️ No supportWayland support requires the XWayland compatibility layer. |
✅ Full supportlibxkbcommon is the *reference* implementation of the keyboard keymap handling (parsing/serializing, state) for Wayland. |
||
| User configuration |
❌️ No supportLayout database path is *hard-coded* in xserver.
|
✅ Full supportMultiple layout database paths can be used simultaneously, enabling user-space configuration.See @ref custom-option "" for further information. |
||
| Configuration via third-party packages |
❌️ No supportLayout database path is *hard-coded* in xserver.
|
✅ Full support (since 1.13)Multiple layout database paths can be used simultaneously, enabling third-party packages to extend the base configuration without hacking its files.See @ref packaging-keyboard-layouts "" for further information. |
||
| Keycode override with aliases |
❌️ No supportKeycodes have always priority over aliases. |
✅ Full support (since 1.12)Keycodes and aliases share the same namespace. |
||
| Extended keycodes |
❌️ No supportLimited to **8**-bit keycodes. |
✅ Full supportSupport all Linux keycodes using **32**-bit keycodes. |
||
| Extended key names |
❌️ No supportLimited to **4**-character names. |
⚠️ Serializing requires renaming- *Parse* keys and aliases names of any length. - *Serialize* names > 4 characters by renaming them (since 1.14) |
✅ Full supportSupport any key and aliases names of any length. |
|
| Extended number of layouts |
❌️ No supportLimited to **4** layouts. |
❌️ No supportLimited to **4** layouts. |
✅ Full support (since 1.11)Enable up to **32** layouts when using `::XKB_KEYMAP_FORMAT_TEXT_V2`. |
|
| Unified modifiers |
❌️ No supportClear separation between *real* (i.e. core) and *virtual* modifiers. |
✅ Full supportReal and virtual modifiers have been collapsed into the same namespace, with a “significant” flag that largely parallels the core/virtual split.Real modifiers are predefined modifiers with fixed encoding and considered merely as an X11 compatibility feature. |
||
| Extended modifiers |
❌️ No supportLimited to up to **8** *independent* modifiers. |
✅ Full supportEnable up to **32** *independent* modifiers. |
||
| Canonical virtual modifiers |
❌️ No supportVirtual modifiers can only mapped to *real* modifiers (8 bits). |
⚠️ Partial supportOnly if using explicit mapping: e.g. `virtual_modifiers M = 0x100;` if `M` has the modifier index 8. |
✅ Full supportVirtual modifiers that are not mapped either *explicitly* (using e.g. `virtual_modifiers M = …`) or *implicitly* (using `modifier_map` and `virtualModifier`) [automatically](@ref auto-modifier-encoding) use to their [canonical mapping](@ref canonical-modifier-def). |
|
| Multiple groups per key |
✅ Full supportContiguous identical groups are merged together. |
⚠️ Not supported in the [RMLVO] APISince version 1.8 the [RMLVO] API does not support parsing multiple groups per key anymore, because it may break the expectation of most desktop environments and tools that the number of groups should be equal to the number of configured layouts.See @ref how-do-i-define-multiple-groups-per-key "" for migration instructions. |
||
| Multiple keysyms per level |
❌️ Parsing onlyIgnored: fallback to `NoSymbol`. |
✅ Full support@todo rationale |
||
| Multiple actions per level |
❌️ Parsing only- xkbcomp \< 1.5: Parse error - xkbcomp ≥ 1.5: Parsing only |
⚠️ Parsing & handling, no serializationCurrently limited to 1 action for each action type “group” and “modifier”.@since 1.8: Enable multiple actions per level (parsing, serializing & handling).
@since 1.11: Serialize to |
⚠️ Partial supportCurrently limited to 1 action for each action type “group” and “modifier”.@since 1.11 |
|
| Keyboard controls |
✅ Full supportOnly *overlay* controls [`1`][Overlay1] and [`2`][Overlay2] are supported, consistent with the [keyboard overlay](@ref key-behavior-overlay) support. |
⚠️ Partial support (since 1.14)Only *overlay* controls [`1`][Overlay1] and [`2`][Overlay2] are supported, consistent with the [keyboard overlay](@ref key-behavior-overlay) support. |
⚠️ Partial support (since 1.14)See the supported keyboard controls in `xkb_keyboard_control_flags`, as well as the [corresponding actions](@ref compatibility-key-actions).Overlay controls [ |
|
| [Key behaviors](@ref key-behaviors) | [Overlays](@ref key-behavior-overlay) |
⚠️ Partial support- Only **2** overlays - [Disjoint overlays][Overlapping overlays] |
⚠️ Partial support (since 1.14)- libxkbcommon \< 1.14: Parsing overlays 1-2 only. - libxkbcommon ≥ 1.14: Supported. Note that the API support requires using the `xkb_machine` API. - Only **2** overlays - [Disjoint overlays][Overlapping overlays] |
✅ Full support (since 1.14)- libxkbcommon \< 1.14: Parsing overlays 1-2 only. - libxkbcommon ≥ 1.14: Full support. Note that the API support requires using the `xkb_machine` API. - **8** overlays - [Overlapping overlays] |
| [Radio groups](@ref key-behavior-radio-groups) | ✅ Full support |
❌️ Parsing onlyUnused in [xkeyboard-config] layouts. |
||
| [Lock](@ref key-behavior-lock) | ✅ Full support |
❌️ Parsing onlyUnused in [xkeyboard-config] layouts. |
||
| [Indicator behaviors] | ✅ Full support |
⚠️ Partial supportE.g. LED-controls-key behavior (X11’s `IM_LEDDrivesKB` flag enabled) is not supported.The only supported LED behavior is key-controls-LED. Unused in xkeyboard-config layouts. |
||
| Geometry @anchor geometry-support | ✅ Full support |
❌️ Parsing onlyRational:
|
||
[Overlay1]: @ref XKB_KEYBOARD_CONTROL_OVERLAY1 [Overlay2]: @ref XKB_KEYBOARD_CONTROL_OVERLAY2 [Overlay8]: @ref XKB_KEYBOARD_CONTROL_OVERLAY8 [Overlapping overlays]: @ref overlapping-overlays
Key actions {#compatibility-key-actions}
| Type | Action | X11 | xkbcommon ([v1 format](@ref XKB_KEYMAP_FORMAT_TEXT_V1)) | xkbcommon ([v2 format](@ref XKB_KEYMAP_FORMAT_TEXT_V2)) |
|---|---|---|---|---|
| Ineffectual | `NoAction()` | ✅ Full support | ✅ Full support | |
| `VoidAction()` | ❌️ No support | ❌️ Parsing only (since 1.10) | ✅ Full support (since 1.11) | |
| Modifiers | `SetModifiers()` |
⚠️ Partial support- `unlockOnPress` parameter is not supported. |
⚠️ Partial support- `unlockOnPress` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`. |
✅ Full support- `unlockOnPress` parameter (since 1.11). See @ref set-mods-action "its documentation" for further details. |
| `LatchModifiers()` |
⚠️ Partial support- `latchOnPress` parameter is not supported. - `unLockOnPress` parameter is not supported. |
⚠️ Partial support- `latchOnPress` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`. - `unLockOnPress` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`. |
✅ Full support- `latchOnPress` parameter (since 1.11). See @ref latch-mods-action "its documentation" for further details. - `unLockOnPress` parameter (since 1.11). See @ref latch-mods-action "its documentation" for further details. |
|
| `LockModifiers()` |
⚠️ Partial support- `unlockOnPress` parameter is not supported. |
⚠️ Partial support- `unlockOnPress` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`. |
✅ Full support- `unlockOnPress` parameter (since 1.11). See @ref lock-mods-action "its documentation" for further details. |
|
| Groups | `SetGroup()` | ✅ Full support | ✅ Full support | |
| `LatchGroup()` | ✅ Full support | ✅ Full support | ||
| `LockGroup()` |
⚠️ Partial support- `lockOnRelease` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`. |
⚠️ Partial support- `lockOnRelease` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`. |
✅ Full support- `lockOnRelease` (since 1.11). See @ref lock-group-action "its documentation" for further details. |
|
| Keyboard controls | `SetControls()` | ✅ Full support |
⚠️ Partial support- libxkbcommon \< 1.14: Parsing and serializing only, no API support - libxkbcommon ≥ 1.14: API support for a limited number of controls: see `xkb_keyboard_control_flags`. |
|
| `LockControls()` | ✅ Full support |
⚠️ Partial support- libxkbcommon \< 1.14: Parsing and serializing only, no API support - libxkbcommon ≥ 1.14: API support for a limited number of controls: see `xkb_keyboard_control_flags`. |
||
| Keyboard emulation | `RedirectKey()` |
✅ Full supportNote that the[auto](@ref redirect-key-auto) value for the `keycode`
parameter is not supported: the default value is 0, an invalid X11 keycode.
|
✅ Full support (since 1.14)- libxkbcommon \< 1.14: Parsing only. - libxkbcommon ≥ 1.14: Full support. Note that the API support requires using the `xkb_machine` API. |
|
| Legacy action | `MovePointer()` | ✅ Full support | ⚠️ Parsing and serializing only, no API support | |
| `PointerButton()` | ✅ Full support | ⚠️ Parsing and serializing only, no API support | ||
| `LockPointerButton()` | ✅ Full support | ⚠️ Parsing and serializing only, no API support | ||
| `SetPointerDefault()` | ✅ Full support | ⚠️ Parsing and serializing only, no API support | ||
| `TerminateServer()` | ✅ Full support | ⚠️ Parsing and serializing only, no API support | ||
| `SwitchScreen()` | ✅ Full support | ⚠️ Parsing and serializing only, no API support | ||
| `Private()` | ✅ Full support | ⚠️ Parsing and serializing only, no API support | ||
| Unsupported legacy action | `ISOLock()` | ✅ Full support | ❌️ Parsing only | |
| `DeviceButton()` | ✅ Full support | ❌️ Parsing only | ||
| `LockDeviceButton()` | ✅ Full support | ❌️ Parsing only | ||
| `DeviceValuator()` | ✅ Full support | ❌️ Parsing only | ||
| `MessageAction()` | ✅ Full support | ❌️ Parsing only | ||
Keymap text format
| Feature | X11 (xkbcomp) | xkbcommon ([v1 format](@ref XKB_KEYMAP_FORMAT_TEXT_V1)) | xkbcommon ([v2 format](@ref XKB_KEYMAP_FORMAT_TEXT_V2)) |
|---|---|---|---|
| Optional keymap components | ❌️ All components are mandatory |
✅ Full support (since 1.9)Keymap components are no longer mandatory, e.g. a keymap without a `xkb_types` section is legal. |
|
| Strong type check | ❌️ Weak type check |
⚠️ Stronger type check (WIP)Floating-point numbers cannot be used where an integer is expected. |
|
| `replace` merge mode in include statements | ❌️ No support |
✅ Full support (since 1.9)Supported using the prefix `^`, in addition to the standard *merge* `|` and *override* `+` modes. |
|
| Keysym as strings | ❌️ No support |
✅ Full support (since 1.9)Keysyms can be written as their corresponding string, e.g. `udiaeresis` can be written `"ü"`. A string with multiple Unicode code points denotes a list of the corresponding keysyms. An empty string denotes the keysym `NoSymbol`. |
|
| Unicode escape sequence | ❌️ No support |
✅ Full support (since 1.9)`\u{NNNN}`.See @ref keymap-string-literal "string literal" for further information. |
|
| `First`/`Last` group indices and masks constants | ❌️ No support |
✅ Full support (since 1.14)Enable defining e.g. a proper interpretation entry of the keysym `ISO_Last_Group`:
Note that contrary to These constants are parsed but never used for serialization, in order to maintain compatibility with xkbcomp and older libxkbcommon versions. |
|
| Extended `GroupN` constants |
❌️ No supportOnly `Group1`..`Group8` are supported, although the resulting group must be in the range 1..4. |
❌️ No supportOnly `Group1`..`Group4` are supported.Use |
✅ Full support (since 1.11)The pattern `Group |
| Extended `LevelN` constants |
❌️ No supportOnly `Level1`..`Level8` are supported. |
✅ Full support (since 1.11)Since 1.11, the pattern `LevelBefore 1.11, only |
|
| Extended include | ❌️ No support |
✅ Full support (since 1.11)Enable *absolute* paths and *`%`-expansion*.See @ref keymap-include-percent-expansion "" for further details. |
|
| Include predefined maps | ✅ Full support |
❌️ No supportThe modern approach is to use [RMLVO]. |
|
| Exponent syntax for floating-point numbers | ✅ Full support |
❌️ No support@todo syntax description |
|
| `alternate` merge mode | ✅ Full support |
⚠️ Parsing, fallback to default merge mode`alternate` was used in `xkb_keycodes` type sections and meant that if a new keycode name conflicts with an old one, consider it as a keycode *alias*. |
|
| Multiple group definition in symbols section | ✅ Full support |
⚠️ Supported, except in the [RMLVO] APISince 1.8, only 1 group per symbol section is supported in the [RMLVO] API, to avoid unintuitive results.Multiple groups per symbol section is supported when parsing a [KcCGST] keymap. |
|
API
| Feature | X11 | xkbcommon ([v1 format](@ref XKB_KEYMAP_FORMAT_TEXT_V1)) | xkbcommon ([v2 format](@ref XKB_KEYMAP_FORMAT_TEXT_V2)) |
|---|---|---|---|
| Full Unicode support | ❌️ Incomplete |
✅ Full supportFull support of simple case mappings for `xkb_keysym_to_lower()` and `xkb_keysym_to_upper()`. |
|
| [KcCGST] @anchor KcCGST-support | ✅ Full support |
⚠️ Partial support (since 1.10)- [KcCGST] is considered an implementation detail, use [RMLVO] instead. - Use `xkb_component_names::xkb_components_names_from_rules()` for debugging purposes. |
|
| XKM file format | ✅ Full support |
❌️ No supportObsolete legacy file format tied to X11 ecosystem. |
|
[KcCGST]: @ref KcCGST-intro [RMLVO]: @ref RMLVO-intro
Rules support {#rules-support}
| Feature | X11 | xkbcommon ([v1 format](@ref XKB_KEYMAP_FORMAT_TEXT_V1)) | xkbcommon ([v2 format](@ref XKB_KEYMAP_FORMAT_TEXT_V2)) |
|---|---|---|---|
| Partial `*.pre` and `*.post` rules files | ❌️ No support |
✅ Full support (since 1.13)See @ref rmlvo-resolution "" for further details. |
|
| `! include` statement | ❌️ No support |
✅ Full supportSee @ref rules-include-expansion "rules include statement" for further details. |
|
| `replace` merge mode | ❌️ No support |
✅ Full support (since 1.9)Support the merge mode *replace* via the prefix `^`, in addition to the standard *merge* `|` and *override* `+` modes. |
|
| Extended layout indices | ❌️ No support |
✅ Full support (since 1.8)- *single*: matches a single layout; `layout[single]` is the same as without explicit index: `layout`. - *first*: matches the first layout/variant, no matter how many layouts are in the RMLVO configuration. Acts as both `layout` and `layout[1]`. - *later*: matches all but the first layout. This is an index range. Acts as `layout[2]` .. `layout[MAX_LAYOUT]`, where `MAX_LAYOUT` is currently 4. - *any*: matches layout at any position. This is an index range.
See @ref rules-extended-layout-indices "extended layout indices" for further details. |
|
| `:all` qualifier | ❌️ No support |
✅ Full support (since 1.8)the `:all` qualifier: it applies the qualified item to all layouts.See @ref rules-all-qualifier ":all qualifier" for further details. |
|
| Extended wild cards | ❌️ No support |
✅ Full support (since 1.9)- `See @ref rules-wildcard-def "rules wildcards" for further information. |
|
Keyboard layout registry {#registry-support}
| Feature | X11 | xkbcommon |
|---|---|---|
| XML format | ❌️ No support |
✅ Full support@todo rationale |
Compose support {#compose-support}
Relative to the standard implementation in libX11 (described in the Compose(5) man-page):
| Feature | X11 (`libX11`) | xkbcommon |
|---|---|---|
| `[!] MODIFIER` syntax | ✅ Full support |
❌️ Parsing onlySyntax: `[([!] ([~] MODIFIER)...) | None]If the modifier list is preceded by @todo removal rationale |
| Modifier keysyms in sequences | ✅ Full support |
⚠️ Parsed, but key events are ignoredModifiers should not be used in Compose sequences. Use keymap’s features or a keysym with more appropriate semantics. |
| Interactions with Braille keysyms | ✅ Full support |
❌️ No support@todo feature description, removal rationale |