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

Keymap features compatibility table
Feature X11 xkbcommon ([v1 format](@ref XKB_KEYMAP_FORMAT_TEXT_V1)) xkbcommon ([v2 format](@ref XKB_KEYMAP_FORMAT_TEXT_V2))
Wayland support
❌️ No support Wayland support requires the XWayland compatibility layer.
✅ Full support libxkbcommon is the *reference* implementation of the keyboard keymap handling (parsing/serializing, state) for Wayland.
User configuration
❌️ No support Layout database path is *hard-coded* in xserver.

xkbcomp enables path configuration, but setxkbmap support is incomplete.

✅ Full support Multiple layout database paths can be used simultaneously, enabling user-space configuration.

See @ref custom-option "" for further information.

Configuration via third-party packages
❌️ No support Layout database path is *hard-coded* in xserver.

xkbcomp enables path configuration, but setxkbmap support is incomplete.

✅ 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 support Keycodes have always priority over aliases.
✅ Full support (since 1.12) Keycodes and aliases share the same namespace.
Extended keycodes
❌️ No support Limited to **8**-bit keycodes.
✅ Full support Support all Linux keycodes using **32**-bit keycodes.
Extended key names
❌️ No support Limited 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 support Support any key and aliases names of any length.
Extended number of layouts
❌️ No support Limited to **4** layouts.
❌️ No support Limited to **4** layouts.
✅ Full support (since 1.11) Enable up to **32** layouts when using `::XKB_KEYMAP_FORMAT_TEXT_V2`.
Unified modifiers
❌️ No support Clear separation between *real* (i.e. core) and *virtual* modifiers.
✅ Full support Real 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 support Limited to up to **8** *independent* modifiers.
✅ Full support Enable up to **32** *independent* modifiers.
Canonical virtual modifiers
❌️ No support Virtual modifiers can only mapped to *real* modifiers (8 bits).
⚠️ Partial support Only if using explicit mapping: e.g. `virtual_modifiers M = 0x100;` if `M` has the modifier index 8.
✅ Full support Virtual 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 support Contiguous identical groups are merged together.
⚠️ Not supported in the [RMLVO] API Since 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 only Ignored: 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 serialization Currently 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 VoidAction() for compatibility with X11.

⚠️ Partial support Currently limited to 1 action for each action type “group” and “modifier”.

@since 1.11

Keyboard controls
✅ Full support 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) 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 [1][Overlay1] to [8][Overlay8] are supported.

[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 only Unused in [xkeyboard-config] layouts.
[Lock](@ref key-behavior-lock) ✅ Full support
❌️ Parsing only Unused in [xkeyboard-config] layouts.
[Indicator behaviors] ✅ Full support
⚠️ Partial support E.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 only

Rational:

  • There were very few geometry definitions available in xkeyboard-config, and while xkbcommon was responsible for parsing this insanely complex format, it never actually did anything with it.
  • Hopefully someone will develop a companion library which supports keyboard geometries in a more useful format, e.g. SVG.

[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}

Key actions compatibility table
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 support Note 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

Keymap text format compatibility table
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`:
interpret ISO_Last_Group {
    action= LockGroup(group=last);
};

Note that contrary to First, Last cannot be used as an array index, i.e. symbols[Last] will be discarded or raise an error, depending of the API used.

These constants are parsed but never used for serialization, in order to maintain compatibility with xkbcomp and older libxkbcommon versions.

Extended `GroupN` constants
❌️ No support Only `Group1`..`Group8` are supported, although the resulting group must be in the range 1..4.
❌️ No support Only `Group1`..`Group4` are supported.

Use ::XKB_KEYMAP_FORMAT_TEXT_V2 in order to support further groups.

✅ Full support (since 1.11) The pattern `Group` can be used for any valid group index ``.
Extended `LevelN` constants
❌️ No support Only `Level1`..`Level8` are supported.
✅ Full support (since 1.11) Since 1.11, the pattern `Level` can be used for any valid level index ``.

Before 1.11, only Level1..Level8 were supported.

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 support The 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] API Since 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

API compatibility table
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 support Full 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 support Obsolete legacy file format tied to X11 ecosystem.

[KcCGST]: @ref KcCGST-intro [RMLVO]: @ref RMLVO-intro

Rules support {#rules-support}

API compatibility table
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 support See @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.
  • the :all qualifier: it applies the qualified item to all layouts.

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) - `` matches *empty* value; - `` matches *non-empty* value in *every* context. - `` matches *optionally empty* value in *every* context, contrary to the legacy `*` wild card which does not match empty values for layout and variant.

See @ref rules-wildcard-def "rules wildcards" for further information.

Keyboard layout registry {#registry-support}

Keyboard layout 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):

Compose support
Feature X11 (`libX11`) xkbcommon
`[!] MODIFIER` syntax ✅ Full support
❌️ Parsing only Syntax: `[([!] ([~] MODIFIER)...) | None] `

If the modifier list is preceded by ! it must match exactly. MODIFIER may be one of Ctrl, Lock, Caps, Shift, Alt or Meta. Each modifier may be preceded by a ~ character to indicate that the modifier must not be present. If None is specified, no modifier may be present.

@todo removal rationale

Modifier keysyms in sequences ✅ Full support
⚠️ Parsed, but key events are ignored Modifiers 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