keymap-text-format-v1-v2.md 145 KB

The XKB keymap text format, V1 and V2 {#keymap-text-format-v1-v2}

This document describes the following [keymap] formats, as implemented by libxkbcommon:

`::XKB_KEYMAP_FORMAT_TEXT_V1` @anchor keymap-text-format-v1
The classic XKB text format, as generated by `xkbcomp -xkb`. See @ref xkbcommon-compatibility "" for further information.
`::XKB_KEYMAP_FORMAT_TEXT_V2` @anchor keymap-text-format-v2
Xkbcommon extensions of the classic XKB text format, **incompatible with X11**. See @ref xkbcommon-compatibility "" for further information.

@see For an overview of the role of this format, please see “@ref xkb-the-config ""”.

@see For examples of keymaps in this format, please see “@ref custom-configuration ""”. For further examples see xkeyboard-config, the standard database of keyboard configuration data.

@note Due to the complexity of the format, this document is still is construction. Some additional resources are:

@note

@tableofcontents{html:2}

[terminology]: @ref terminology [introduction]: @ref introduction-to-the-xkb-text-format [xkb_keymap]: @ref the-xkb_keymap-block [xkb_keycodes]: @ref the-xkb_keycodes-section [xkb_types]: @ref the-xkb_types-section [xkb_compat]: @ref the-xkb_compat-section [xkb_symbols]: @ref the-xkb_symbols-section [virtual modifier statements]:@ref virtual-modifier-statements [actions]: @ref key-actions

Terminology {#terminology}

Keycode
Code that identifies a physical key on a keyboard. - _Raw_ keycodes are the numeric identifiers used as input in XKB. They are the result of the low-level processing of the data that keyboards send to a computer. For instance `36` may represent the return key. - _XKB_ keycodes are _symbolic_ names assigned to raw keycodes in order to facilitate their mapping to symbols. For instance the keycode for the return key is the abbreviation `RTRN`. See [xkb_keycodes] for further details.
Symbols
A _keysym_ (short for “key symbol”) is a numeric encoding of a symbol on the cap of a key. Some keysyms have a canonical name for convenience. The complete list of canonical names is defined in `xkbcommon/xkbcommon-keysyms.h` and conveniently consultable at @ref predefined-keysyms. Common types of keysyms are: - A _character:_ e.g. `a` and `A` for Latin scripts, `alpha` “α” and `ALPHA` “Α” for Greek, etc. - A _dead key:_ e.g. `dead_grave` and `dead_diaeresis`, corresponding respectively to the [grave accent](https://en.wikipedia.org/wiki/Grave_accent) and the [diaeresis](https://en.wikipedia.org/wiki/Diaeresis_%28diacritic%29) diacritics. A [dead key](https://en.wikipedia.org/wiki/Dead_key) is a special kind of key that does not generate a character by itself, but modifies the character generated by the key struck(s) immediately after. - A [modifier]⁠: e.g. `Shift_L`, `Control_R`, `Caps_Lock`. See hereinafter. - A _system action:_ e.g. the arrow `Left`, `Pause`, `Escape`, `F1`. @sa [xkb_symbols] for further details on binding keysyms to keycodes. @sa [Keysym syntax](@ref keysym-syntax) @sa @ref predefined-keysyms
Modifier
A _modifier key_ is a key that modifies the effect of other keys: e.g. Shift, Control, Caps Lock, etc. The state of a modifier key (active/inactive) is encoded as a _modifier index_ (or modifier bit or simply modifier) and has an associated _unique name_. For historical reasons, modifiers are divided in two categories:
Real modifiers
They are the 8 _predefined_ (AKA *core*, *X11*) modifiers (see [usual modifiers] hereinafter). A real modifier that is not predefined is called an *extended real modifier*. Real modifiers ensure backward compatibility: indeed they are the actual bits used to compute the [levels][level] and are communicated via the API of xkbcommon. Some are generic modifiers (`Mod[1-5]`) that do not have a conventional interpretation and are the motivation of the introduction of [virtual modifiers].
Virtual modifiers
They are names of real modifiers *masks* and are not predefined. [Core real modifiers][core modifier] are also interpreted as virtual modifiers, specifically they are [canonical virtual modifiers][canonical modifier].

Each modifier has an associated [encoding][modifier encoding]. In keymaps compatible with X11, the encoding can be interpreted as a mapping to one or multiple real modifier. Real modifiers map to themselves: they are [canonical modifiers][canonical modifier]. See the “@ref modifiers-encoding ""” section for further information.

The following table lists the predefined and usual modifiers present in the standard keyboard configuration. Note that this is provided for information only, as it may change depending on the user configuration.

| Modifier | Type | Predefined | Usual mapping | Comment | | ------------ | -------------- | ---------- | ----------------- | --------------------------- | | Shift | Real + Virtual | Yes (Core) | Shift (fixed) | The usual Shift | | Lock | Real + Virtual | Yes (Core) | Lock (fixed) | The usual Caps Lock | | Control | Real + Virtual | Yes (Core) | Control (fixed) | The usual Control | | Mod1 | Real + Virtual | Yes (Core) | Mod1 (fixed) | Not conventional | | Mod2 | Real + Virtual | Yes (Core) | Mod2 (fixed) | Not conventional | | Mod3 | Real + Virtual | Yes (Core) | Mod3 (fixed) | Not conventional | | Mod4 | Real + Virtual | Yes (Core) | Mod4 (fixed) | Not conventional | | Mod5 | Real + Virtual | Yes (Core) | Mod5 (fixed) | Not conventional | | Alt | Virtual | No | Mod1 | The usual Alt | | Meta | Virtual | No | Mod1 | The legacy Meta key | | NumLock | Virtual | No | Mod2 | The usual NumLock | | Super | Virtual | No | Mod4 | The usual Super/GUI | | LevelThree | Virtual | No | Mod5 | ISO level 3, aka AltGr | | LevelFive | Virtual | No | Mod3 | ISO level 5 |

[core modifier]: @ref core-modifiers [extended modifier]: @ref extended-real-mod-def [usual modifiers]: @ref usual-modifiers

A modifier key can report its state in one of the following 3 ways:

<dt><a name="depressed-mod-def">Depressed</a></dt>
<dd>Active while logically depressed; e.g. the usual Shift.</dd>
<dt><a name="latched-mod-def">Latched</a></dt>
<dd>
  Activated when pressed and released, then automatically deactivated
  after the next key event that produces a symbol (i.e. a non-modifier
  key press). Useful for one-shot modifier keys (e.g. a sticky Shift).
</dd>
<dt><a name="locked-mod-def">Locked</a></dt>
<dd>
  Activated when pressed and deactivated when pressed again;
  e.g. the usual Caps Lock.
</dd>

See [modifiers declaration and binding] for further details.

[depressed]: @ref depressed-mod-def [latched]: @ref latched-mod-def [locked]: @ref locked-mod-def

Shift Level
A key may produce different results depending of the active modifiers: e.g. for a Latin script, pressing the key A produces “a” and holding Shift while pressing A produces “A”.

This various results are organized in an ordered list; the index of each entry is called a shift level or simply level. By convention the lowest level is the result when no modifier is active. Example for the key A on a latin script keyboard:

| Level | Description | Keysym | Active key modifiers | |-------|--------------------------------|--------|----------------------| | 1 | Lower case letters | a | None | | 2 | Upper case letters. | A | Shift | | 3 | Alternative lower case letters | ae | AltGr | | 4 | Alternative upper case letters | AE | Shift + AltGr |

A key shift level is the logical state of a key corresponding to the current shift level it used.

Key shift levels are derived from the modifiers states, but not necessarily in the same way for all keys. For example, for Latin script the Caps Lock modifier selects the level 2 for alphabetic keys such as A but has no effect on a numeric key.

There are groups of keys with the same characteristics: letters, punctuation, numeric keypad, etc. The meaning of their levels is identical and thus can be shared: this generalization is called a key type (see hereinafter).

Key type
A key type defines the levels available for a key and how to derive the active level from the modifiers states. Examples:
  • ONE_LEVEL: the key has only one level, i.e. it is not affected by any modifiers. Example: the modifiers themselves.
  • [TWO_LEVEL][TWO_LEVEL]: the key has two levels:
    • Level 1: default level, active when the Shift modifier is not active.
    • Level 2: level activated with the Shift modifier.
  • [FOUR_LEVEL][FOUR_LEVEL]: see the example in the previous section.

See [xkb_types] for further details.

Layout
A mapping of keycodes to symbols, actions and key types.

A user who deals with multiple languages may need two or more different layouts: e.g. a layout for Arabic and another one for English. In this context, layouts are called groups in XKB, as defined in the standard ISO/IEC 9995.

Layouts are ordered and identified by their index. Example:

  • Layout 1: Arabic
  • Layout 2: English

Similarly to modifiers, layouts have depressed, latched and locked components, which are summed to give the effective layout. Unlike modifiers — which are masks, so multiple can be active simultaneously — only a single layout is active at any time, the components being numeric offsets or indices rather than bits.

@todo out-of-range layout policy xkb_layout_out_of_range_policy @todo effective layout

Depressed layout
Offsets the active layout by the given amount for as long as the
triggering key is physically held down, then the offset is removed.
Corresponds to a [`SetGroup`][SetGroup] action.

Latched layout
Offsets the active layout by the given amount when the triggering key
is pressed and released, then the offset is removed after the next
symbol-producing key press. Corresponds to a
[`LatchGroup`][LatchGroup] action.

Locked layout
Sets the active layout to the given index until explicitly changed
again. Corresponds to a [`LockGroup`][LockGroup] action. This is the
usual behaviour of a layout-switch key (e.g. toggling between a
Latin and a Greek layout).

Key Action
In XKB world, a key action defines the effect a key has on the state of the keyboard or the state of the display server. Examples:
  • Change the state of a modifier.
  • Change the active group.
  • Move the mouse pointer.

See the section “[Key actions][actions]” for further details.

Indicator
A keyboard indicator is a mean to report a specific aspect of the keyboard state.

<dt><em>Physical</em> indicator</dt>
<dd>
Typically a labelled LED on the keyboard, e.g. “Caps Lock” and
“Num Lock”.
</dd>
<dt><em>Logical</em> indicator</dt>
<dd>
A customizable derived state of the keyboard.
Its changes creates events that can be monitored.

There are two categories:

- _Real_ indicators are those associated to a physical indicator.
  For example, the “Caps Lock” logical modifier controls the
  corresponding physical LED.

  Because indicators are customizable, if one misses a “Num Lock”
  LED, one could define instead the “Caps Lock” _indicator_ to
  activate its LED when the “Num Lock” _modifier_ is active.
- _Virtual_ indicators are not associated to a physical indicator.
  Their effect is only visible for programs monitoring them.

Note that the meanings of _real_ and _virtual_ is slightly
different than the one used for [modifier].
</dd>

See: [xkb_keycodes][indicator name] to define indicators and [xkb_compat][indicator effect] to define their effects.

Keymap
The complete definition of the mapping of raw keycodes to symbols and actions. It fully defines the behavior of a keyboard.

Depending of the context, a keymap may refer to:

  • the software object defined and managed by libxkbcommon;
  • the text configuration used to create this software object.

See @ref keymap-components-intro and [xkb_keymap] for further details.

Keyboard configuration database @anchor database-def
A database that provides the [keymap components](@ref keymap-components-intro).
\*nix OSs uses the _standard_ database [xkeyboard-config]. One may extend
this database with _custom_ layouts: see “@ref custom-configuration ""” for
further details.

[keycode]: @ref keycode-def [keysym]: @ref keysym-def [keysyms]: @ref keysym-def [modifier]: @ref modifier-def [modifiers]: @ref modifier-def [real modifier]: @ref real-modifier-def [real modifiers]: @ref real-modifier-def [virtual modifier]: @ref virtual-modifier-def [virtual modifiers]: @ref virtual-modifier-def [level]: @ref level-def [shift level]: @ref level-def [level index]: @ref level-index-def [key type]: @ref key-type-def [key types]: @ref key-type-def [layout]: @ref layout-def [action]: @ref key-action-def [indicator]: @ref indicator-def [keymap]: @ref keymap-def [database]: @ref database-def

Introduction to the XKB text format

The XKB text format uses a syntax similar to the C programming language. Note that the similarity with C stops here: the XKB text format is only a configuration format and is not intended for programming.

The XKB text format is used to configure a keyboard keymap, which is introduced in “@ref xkb-the-config ""”. It has the following two main use cases, illustrated in the diagram hereinafter:

  • Server: Load a keymap from the keymap configuration database, then handle input events by updating the keyboard state. The keymap is assembled from an [RMLVO configuration][RMLVO] and its corresponding [KcCGST components][KcCGST] files.

@see xkb_keymap::xkb_keymap_new_from_names2

@see xkeyboard-config for the implementation of the standard keymap configuration database.

@see@ref custom-configuration ""” to add a custom layout or option.

  • Client: Load the active keymap from the server, then handle update events sent by the server. The [complete keymap] is directly available in a self-contained file.

@see xkb_keymap::xkb_keymap_new_from_string

@anchor xkb-keymap-components-diagram @dotfile xkb-keymap-components "XKB text format use cases"

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

XKB file

There are two kinds of files for the XKB text format:

Keymap file @anchor keymap-file-def
A file with the _complete_ description of the [keymap] object. It is the kind of file that the server sends to the client (see the [diagram](@ref xkb-keymap-components-diagram) above). Its top-level structure consists of the [xkb_keymap] block.
Keymap _component_ file @anchor keymap-component-file-def
A file with the description of a _particular_ [KcCGST component][KcCGST]. It is the kind of file that the server uses to assemble a [keymap file]. Its top-level structure consists of a _single type_ of [keymap sections]. A component file may contain multiple such sections.

[keymap file]: @ref keymap-file-def [keymap component file]: @ref keymap-component-file-def [keymap sections]: @ref keymap-section-def [section]: @ref keymap-section-def [keymap components]: @ref keymap-component-def

Keymap components {#keymap-components-intro}

[Keymap components][keymap components] are described with [keymap sections]. They are grouped in [keymap component files][keymap component file] to form a [keyboard configuration database][database].

Keymap _component_ @anchor keymap-component-def
A part of the keymap _object_. The set of keymap components is referred as [KcCGST]. They are presented in the [table hereinafter][keymap components table].
Keymap _section_ @anchor keymap-section-def
A part of the keymap _text configuration_ dedicated to one of the [keymap components][keymap components table].
Component _folder_
A folder in the [keymap configuration database][database], dedicated to files with partial definitions of the same keymap section.

[keymap components table]: @ref keymap-components-table

@anchor keymap-components-table

Keymap components

<th>[Component](@ref keymap-component-def)</th>
<th>[Section][section] in a [keymap][xkb_keymap]</th>
<th>Folder in a keymap configuration database</th>
<th>Description</th>

<th><u>K</u>ey <u>c</u>odes</th>
<td>[xkb_keycodes]</td>
<td>`keycodes`</td>
<td>
A translation of the raw [key codes][keycode] from the keyboard into
symbolic names.
</td>

<th><u>C</u>ompatibility</th>
<td>[xkb_compat]</td>
<td>`compat`</td>
<td>
A specification of what internal actions modifiers and various
special-purpose keys produce.
</td>

<th>(<u>G</u>eometry)</th>
<td>xkb_geometry</td>
<td>`geometry`</td>
<td>
A description of the physical layout of a keyboard.

@attention This legacy feature is [not supported](@ref geometry-support)
by _xkbcommon_.

</td>

<th>Key <u>s</u>ymbols</th>
<td>[xkb_symbols]</td>
<td>`symbols`</td>
<td>
A translation of symbolic [key codes][keycode] into actual [key symbols][keysyms]
(*keysyms*).
@sa @ref predefined-keysyms
</td>

<th>Key <u>t</u>ypes</th>
<td>[xkb_types]</td>
<td>`types`</td>
<td>
Types describe how a pressed key is affected by active [modifiers]
such as Shift, Control, Alt, etc.
</td>

Comments

Comments are introduced following either // or # until the end of the line.

Literals

String literal @anchor keymap-string-literal
A string is surrounded by double quotes: “"”. The following _escape sequences_ are supported: | Escape sequence | Meaning | | ------------------ | -------------------------------------------------------- | | `\\` | Backslash “`\`” | | `\"` | Double quote “`"`” | | `\b` | Backspace | | `\e` | Escape | | `\f` | Form feed | | `\n` | Line feed (newline) | | `\r` | Carriage return | | `\t` | Horizontal tabulation | | `\v` | Vertical tabulation | | `\` + octal number | Corresponding ASCII character: `\1` → `SOH`, `\42` → `"`. Up to **4** octal digits `0‥7` are parsed. The result must fit into a byte. | | `\u{` + hexadecimal number + `}` | `\u{NNNN}` produce the corresponding [Unicode code point] `U+NNNN`, encoded in [UTF-8]. Supported code points are in the range `U+0001‥U+10FFFF`. | @note The string _encoding_ is unspecified and not validated, but for best results, stick to ASCII. @since \<1.9.0: Octal escape sequences accept up to **3** digits. @since 1.9.0: Octal escape sequences accept up to **4** digits. Added \\" and `\u{NNNN}` escape sequences.
Number literal
A number can be written in three forms: - _decimal integer:_ `1`, `123`, etc. - _decimal floating-point number:_ `1.23`, etc. - _hexadecimal integer:_ prefixed with `0x`: `0x123`, `0xff`, `0xAB`, etc.

Keysyms {#keysym-syntax}

[Keysyms][keysym] may be written in multiple ways:

Name
Keysym names are defined in `xkbcommon/xkbcommon-keysyms.h` and the list is conveniently consultable at @ref predefined-keysyms "". > [!tip] > Remove the `XKB_KEY_` prefix to get the name. > Example: the keysym `0xffbe = XKB_KEY_F1` has the name `F1`.
Unicode
The *Unicode* syntax `Unnnn` denotes a keysym whose corresponding character is the Unicode code point `U+nnnn`, where `nnnn` is an hexadecimal number in the range `0x100 .. 0x10ffff`. The resulting keysym value is `0x01000000 + nnnn`. Example: `U1F3BA` has value `0x0101F3BA` and corresponds to the code point `U+1F3BA`: ‘🎺’ (TRUMPET).
String literal
A keysym or list of keysyms can be written as a *string literal*, with the following semantics: 1. The string must be encoded in UTF-8. 2. If the encoding is invalid, it raises a syntax error. 3. If the string expands to 0 Unicode code point, the resulting keysym is `NoSymbol`. 4. If the string expands to 1 Unicode code point, the resulting keysym is the output of `xkb_utf32_to_keysym`. 5. Otherwise the string expands to a list `{ ... }` with each Unicode code point converted via `xkb_utf32_to_keysym`. @note This is only possible where multiple keysyms is valid, e.g. in the @ref key-multiple-symbols-per-level "key symbols". Examples:
Keysym string Keysym name Keysym value
`""` `NoSymbol` `0x0000`
`"a"` `a` `0x0061`
`"ü"` `udiaeresis` `0x00dc`
`"🎺"` `U1F3BA` `0x0101F3BA`
`"g̃"` `{g, combining_tilde}` `{0x0101F3BA, 0x01000303}`
@sa @ref keysyms-string "Keysym strings" @since 1.9.0
Numeric value
A keysym can be written directly with its *numeric* value: e.g. `0x61` is `a`. This syntax is mostly useful in the following use cases: - the corresponding keysym has no associated name nor is in the Unicode range; - the corresponding keysym has/had a name but it is not supported in all the ecosystem; - keymap serialization by tools. @note Digits `0 .. 9` have a special treatment because they are interpreted as names, not values. E.g. `1` is the keysym with name `1` and value `0x31`. @note The previous special case does not apply to integers values in range `0 .. 9` that are written with *2+* characters: e.g. `01` and `0x1` are both interpreted as the *unnamed* keysym with value `0x01`, not the keysym named `1` and with value `0x31`. @warning Do not use this syntax to *manually* write keymap files unless there is no other option: it is the least human-friendly syntax.

Keywords

The following table presents the keywords used in the format. They are case-sensitive.

Keyword Use
action Action of an interpret statement
alias Keycode alias
alphanumeric_keys Section flag
alternate_group Section flag
alternate Merge mode qualifier for [include] statements
augment Merge mode qualifier for [include] statements
default Section flag
deprecated Section flag
function_keys Section flag
group TODO
hidden Section flag
include [Include statement][include]
indicator Indicator statement in either the keycode section or the compatibility section
interpret [Interpret statement][interpret]
key Key statement
keypad_keys Section flag
keys Legacy [geometry element][xkb_geometry]
logo Legacy [geometry element][xkb_geometry]
mod_map Alias of modifier_map
modifier_keys Section flag
modmap Alias of modifier_map
modifier_map Real modifier bindings
outline Legacy [geometry element][xkb_geometry]
overlay Legacy [geometry element][xkb_geometry]
override Merge mode qualifier for [include] statements
partial Section flag
replace Merge mode qualifier for [include] statements
row Legacy [geometry element][xkb_geometry]
section Legacy [geometry element][xkb_geometry]
shape Legacy [geometry element][xkb_geometry]
solid Legacy [geometry element][xkb_geometry]
text Legacy [geometry element][xkb_geometry]
type Key type statement
virtual_modifiers Virtual modifiers mappings
virtual Flag for the indicator statement
xkb_compat_map Alias of xkb_compatibility_map
xkb_compat Alias of xkb_compatibility_map
xkb_compatibility_map Declare a [compatibility section][xkb_compat]
xkb_compatibility Alias of xkb_compatibility_map
xkb_geometry Declare a [geometry section][xkb_geometry]
xkb_keycodes Declare a [keycodes section][xkb_keycodes]
xkb_keymap Declare a [keymap block][xkb_keymap]
xkb_layout Declare a legacy [layout compound section][xkb_layout]
xkb_semantics Declare a legacy [semantics compound section][xkb_semantics]
xkb_symbols Declare a [symbols section][xkb_symbols]
xkb_types Declare a [key types section ][xkb_types]

[include]: @ref xkb-include [interpret]: @ref interpret-statements [interpretations]: @ref interpret-statements [xkb_geometry]: @ref the-xkb_geometry-section [xkb_layout]: @ref legacy-layout-section [xkb_semantics]: @ref legacy-semantics-section

Built-in settings

There are many built-in settings; they are explained in the following relevant sections.

These settings are case-insensitive, e.g. the following strings denote the same key word: SETMODS, SetMods, setMods and setmods.

Merge modes {#merge-mode-def}

Each statement has a merge mode property that defines how to handle conflicts with previous statements. This property can be set explicitly by prefixing the statement with one of the merge modes presented hereinafter.

@anchor merge-mode-augment augment
If two declarations conflict, update the properties which are *explicitly* defined in the *new* declaration, *only* if they were *implicit* in the *old* declaration. ```c key { [a , NoSymbol , ae ] }; augment key { [Greek_alpha, Greek_ALPHA, NoSymbol, AE] }; // Result key { [a , Greek_ALPHA, ae , AE] }; ```
@anchor merge-mode-override override
If two declarations conflict, update only the properties which are *explicitly* defined in the *new* declaration. @note @anchor merge-mode-default Override is the *default* merge mode. ```c key { [a , NoSymbol , ae ] }; // Explicit merge mode override key { [Greek_alpha, Greek_ALPHA, NoSymbol, AE] }; // Result key { [Greek_alpha, Greek_ALPHA, ae , AE] }; ``` ```c key { [a , NoSymbol , ae ] }; // Implicit merge mode is override key { [Greek_alpha, Greek_ALPHA, NoSymbol, AE] }; // Result key { [Greek_alpha, Greek_ALPHA, ae , AE] }; ```
@anchor merge-mode-replace replace
If two declarations conflict, ignore the old declaration and use the new one. ```c key { [a , NoSymbol , ae ] }; replace key { [Greek_alpha, Greek_ALPHA, NoSymbol, AE] }; // Result key { [Greek_alpha, Greek_ALPHA, NoSymbol, AE] }; ```
@anchor merge-mode-alternate alternate
Legacy merge mode for keycodes. Its purpose is to allow to assign the same key name to multiple key codes, which is not allowed otherwise. This is unfortunately poorly documented and not used in xkeyboard-config. The xkblib specification implies that this was part of the overlay functionality, which is currently not supported by libxkbcommon. @warning This merge mode is not supported by libxkbcommon and is ignored.

[default merge mode]: @ref merge-mode-default

The include mechanism {#xkb-include}

Syntax

Statements of the form:

// Implicit section name: use the default map
include "<PATH>"
// Explicit section name
include "<PATH>(<SECTION_NAME>)"

will merge data from another [section] of the same type, possibly located in another file. Note that the statement does not have a trailing semicolon.

If no section name is provided, the [default map] is looked up.

[default map]: @ref default-map-def

The path is usually relative to its corresponding directory in an XKB configuration: e.g. given the configuration directory <XKB>, files of section type xkb_symbols are looked up in <XKB>/symbols. Since 1.11, the paths can also be absolute or use %-expansion: @anchor keymap-include-percent-expansion

`%%`
A literal %.
\%H
The value of the `$HOME` environment variable.
\%S
The *main* system-installed XKB directory of the corresponding [component] \(usually `/usr/share/X11/xkb/`). This enables e.g. to override a system file using @ref custom-configuration "" with the exact *same name*: ```c // File: ~/.config/xkb/symbols/de xkb_symbols "basic" { // Include the system file /usr/share/X11/xkb. // // Note that it is not be possible to use `include "de(basic)"` because // it would create an include *loop*. include "%S/de(basic)" // Override the system file entries key { [z, Z] }; key { [y, Y] }; } ```
\%E
The *extra* system-wide XKB directory of the corresponding [component] \(usually `/etc/xkb/`).

[component]: @ref keymap-components-table

@warning Absolute paths and %-expansion are supported by libxkbcommon but not by the legacy X11 tools.

The include keyword uses the default [merge mode]. The following keywords can be used instead to use the corresponding explicit [merge modes][]:

  • [augment][augment]
  • [override][override]
  • [replace][replace]

[merge mode]: @ref merge-mode-def [merge modes]: @ref merge-mode-def [augment]: @ref merge-mode-augment [override]: @ref merge-mode-override [replace]: @ref merge-mode-replace

Multiple files can be included using the same statement. They are separated using one of the following [merge mode] prefixes:

  • ‘|’ selects the [augment] merge mode.
  • ‘+’ selects the [override] merge mode (default).
  • ‘^’ selects the [replace] merge mode.

The following example illustrates the complete syntax:

// Default merge mode, 1 file with an implicit section name
include "<PATH>"
// Augment merge mode, 1 file with an implicit section name
augment "<PATH>(<SECTION_NAME>)"
// Absolute path and %-expansion
include "/usr/share/X11/xkb/symbols/pc"
include "%S/pc"
// Override merge mode, 2 files: a first file with an implicit section name merged
// using the augment mode with a second file with an explicit section name
override "<PATH_1>|<PATH_2>(<SECTION_NAME>)

Processing

@important Since xkbcommon 1.9.0 the included files are processed in isolation and are not affected by the parent file (e.g. defaults), except for the virtual modifiers indices.

@important Since xkbcommon 1.9.0 local merge modes are not propagated outside the section scope, i.e. an included file does not leaks its local merge modes to its parent.

The statement is processed as follow:

  1. Set PARENT as the current [section] containing the include statement.
  2. Set INCLUDED_MERGE_MODE to the merge mode corresponding to the keyword.
  3. Initialize an empty [section] as INCLUDED.
  4. Select the first file as the current file to process.
  5. Set CURRENT_MERGE_MODE to the merge mode corresponding to the current file merge mode prefix.
  6. The current file path is searched sequentially in the

    • If a section name is provided, select the first exact match of file + section.
    • If no section name is provided, select the first explicit [default map] in matched files, else if no exact match was found in the path list, then fallback to the first implicit [default map] as a weak match.

Then if no match is found, raise an error; else go to the next step.

  1. The current file is processed and results in the CURRENT [section].
  2. The INCLUDED [section] is merged with the CURRENT [section] using the merge mode CURRENT_MERGE_MODE.
  3. If they are more files, select the next file as the current file and go to step 5). Else go to step 10).
  4. Once all files have been processed, merge PARENT with INCLUDED using the merge mode INCLUDED_MERGE_MODE.

[XKB configuration path list]: @ref xkb_context::xkb_context_include_path_append()

Example: include path list

Let’s illustrate using the following [XKB configuration path list][]:

  1. /home/<USER>/.config/xkb: user configuration directory (see @ref user-configuration "").
  2. /usr/share/X11/xkb: system directory.

The relevant directory structure is:

  • /home/<USER>/.config/xkb
    • symbols
    • es
    • my_own_file
  • /usr/share/X11/xkb
    • symbols
    • es
    • it

Then the following file:

xkb_symbols {
    include "it"          // Exists only in system directory
    include "my_own_file" // Exists only in user directory
    include "es"          // Exists in both user and system directory
};

is equivalent to:

xkb_symbols {
    include "/usr/share/X11/xkb/symbols/it"
    include "/home/<USER>/.config/xkb/symbols/my_own_file"
    include "/home/<USER>/.config/xkb/symbols/es"
};

Example: simple include

Given the following files:

  • symbols/A

    xkb_symbols {
      key <A> { [a, A, ae, AE] };
      include "B(S2)"
    };
    
  • symbols/B

    // This section is not used (does not match)
    xkb_symbols "S1" {
      key <B> { [b, B] };
    };
    // This section will be included (match the included section name)
    xkb_symbols "S2" {
      key <A> { [Greek_alpha, Greek_ALPHA] };
      key <B> { [Greek_beta , Greek_BETA ] };
    };
    

the resulting section in A will be:

xkb_symbols {
    // Key overridden: mix of old + new
    key <A> { [Greek_alpha, Greek_ALPHA, ae, AE] };
    // New key
    key <B> { [Greek_beta , Greek_BETA         ] };
};

Example: merge modes

Given the same file symbols/B of the previous example, the following section:

Input Output
```c xkb_symbols { key { [a, A, ae, AE] }; augment "B(S2)" }; ``` ```c xkb_symbols { // Key unchanged key { [a, A, ae, AE] }; // New key key { [Greek_beta , Greek_BETA] }; }; ```
```c xkb_symbols { key { [a, A, ae, AE] }; replace "B(S2)" }; ``` ```c xkb_symbols { // Key replaced key { Greek_alpha, Greek_ALPHA] }; // New key key { [Greek_beta , Greek_BETA ] }; }; ```
```c xkb_symbols { key { [a, A, ae, AE] }; // Two files merged together with the merge mode // augment, then the result is merged this the // statement above using the override merge mode include "B(S1)|B(S2)" }; ``` ```c xkb_symbols { // Key overridden: mix of old + new key { [Greek_alpha, Greek_ALPHA, ae, AE] }; // New key; "B(2)" had no effect with the // merge mode augment "|" key { [b, B] }; }; ```

The “xkb_keymap” block {#the-xkb_keymap-block}

A [keymap file] consists of a single top-level xkb_keymap block, under which are nested the following sections:

[xkb_keycodes]
A translation of the hardware/evdev scancodes from the keyboard into XKB symbolic keycodes.
[xkb_types]
A specification of the modifier mask, target level and preserved modifiers various modifiers combination produce.
[xkb_compat]
A specification of what actions various special-purpose keys produce.
[xkb_symbols]
A translation of symbolic key codes into actual symbols and actions.

Overview of a keymap file:

xkb_keymap {
  xkb_keycodes "XXX" {
    // ...
  }
  xkb_types "XXX" {
    // ...
  };
  xkb_compatibility "XXX" {
    // ...
  };
  xkb_symbols "XXX" {
    // ...
  };
};

@since 1.9.0 All the component are optional.

@remark The XKB file format historically supported the following compound section types:

  • xkb_semantics: @anchor legacy-semantics-section must contain a [xkb_compat] section and can contain a [xkb_types] section.
  • xkb_layout: @anchor legacy-layout-section must contain [xkb_keycodes], [xkb_types] and [xkb_symbols] sections and can contain [xkb_geometry] section.
  • xkb_keymap: must contain [xkb_keycodes], [xkb_compat], [xkb_types] and [xkb_symbols] sections and can contain [xkb_geometry] section.
Since such distinction is purely semantic and would have niche use cases lost to history, these compound sections are treated equally as xkb_keymap in libxkbcommon.

Section flags {#section-flags-def}

A section can have various flags applied to it, separated by whitespaces:

partial alphanumeric_keys
xkb_symbols "basic" {
    ...
}

Generic flags

The possible flags are:

partial@anchor section-flag-partial
Indicates that the map doesn’t cover a complete keyboard.
default@anchor section-flag-default
@anchor default-map-def Marks the symbol map as the *explicit* **default map** in the file. If no map is marked as a default, the first map in the file is the *implicit* default. Only **one** section can be marked as the default in each file.
hidden@anchor section-flag-hidden
Variant that can only be used internally.
default@anchor section-flag-deprecated
Section is deprecated

Symbols flags

Additionally, xkb_symbols may also have the following flags:

alphanumeric_keys@anchor section-flag-alphanum
Indicates that the map contains alphanumeric keys.
modifier_keys@anchor section-flag-modifier
Indicates that the map contains modifier keys: Control, Shift, Alt, Meta, etc.
keypad_keys@anchor section-flag-keypad
Indicates that the map contains keypad keys.
function_keys@anchor section-flag-function
Indicates that the map contains function keys: F1, F2, etc.
alternate_group@anchor section-flag-alt-group
Indicates that the map contains keys for an alternate group.

If no *_keys flags are supplied, then the symbols section is assumed to cover a complete keyboard.

At present, except for default (see: [default map]), none of the flags affect key processing in libxkbcommon, and only serve as metadata.

The “xkb_keycodes” section {#the-xkb_keycodes-section}

This is the simplest [section] type, and is the first one to be compiled. The purpose of this is mostly to map between the hardware/evdev scancodes and XKB [keycodes][keycode]. Each key is given a name by which it can be referred to later, e.g. in the symbols section.

Keycode statements

Statements of the form:

<TLDE> = 49;
<AE01> = 10;

The above would let 49 and 10 be valid keycodes in the keymap, and assign them the names TLDE and AE01 respectively. The format <WXYZ> is always used to refer to a key by name.

Keycode naming convention

The naming convention <AE01> is based on the standard ISO/IEC 9995-1. It denotes the position of the key in the keyboard grid. It means: the main alphanumeric section (A), row E and column 01.

The following figure illustrates the grid on a staggered standard US QWERTY keyboard. <AE01> corresponds to the key 1.

   \ 99 \ 00 \ 01 \ 02 \ 03 \ 04 \ 05…
    \    \    \    \    \    \    \
-----------------------------------------
E     \    \ ^  \ 1  \ 2  \ 3  \ 4  \ 5…
------------------------------------------
D      \     Tab \ Q  \ W  \ E  \ R  \ T…
-------------------------------------------
C       \Caps     \ A  \ S  \ D  \ F  \ G…
--------------------------------------------
B        \Shift    \ Z  \ X  \ C  \ V  \ B…
---------------------------------------------
A         \Ctrl\GUI \Alt \Space…
----------------------------------------------

Keycode values

In the common case this just maps to the evdev scancodes from /usr/include/linux/input.h, e.g. the following definitions:

#define KEY_GRAVE            41
#define KEY_1                2

correspond to the ones above. Similar definitions appear in the X11’s xf86-input-keyboard driver. Note that in all current keymaps there’s a constant offset of 8 (for historical reasons).

Note that contrary to xkbcommon, the X11 protocol supports keycodes only up to 255. Therefore, when interfacing with X11, keymaps and applications using keycodes beyond 255 should expect warnings.

Keycode conflicts

If there’s a conflict, like the same name given to different keycodes, or same keycode given different names, it is resolved according to the [merge mode] which applies to the definitions.

Alias statements {#keycode-alias}

Statements of the form:

alias <MENU> = <COMP>;

Allows to refer to a previously defined key (here <COMP>) by another name (here <MENU>). Conflicts are handled similarly to keycode statements.

LED name statements {#indicator-name}

[indicator name]: @ref indicator-name

Statements of the form:

indicator 1 = "Caps Lock";
indicator 2 = "Num Lock";
indicator 3 = "Scroll Lock";

Assigns a name to the keyboard LED (AKA [indicator]) with the given index. The LED may be referred by this name later in the [compat section][@ref the-xkb_compat-section] and by the user.

@todo virtual flag

The “xkb_types” section {#the-xkb_types-section}

This [section] is the second to be processed, after xkb_keycodes. However, it is completely independent and could have been the first to be processed (it does not refer to specific keys as specified in the xkb_keycodes section).

This section defines [key types], which, given a key and a keyboard state (i.e. modifier state and group), determine the [shift level] to be used in translating the key to [keysyms]. These types are assigned to each group in each key, in the xkb_symbols section.

Key types are called this way because, in a way, they really describe the “type” of the key (or more correctly, a specific group of the key). For example, an ordinary keymap will provide a type called KEYPAD, which consists of two levels, with the second level being chosen according to the state of the Num Lock (or Shift) modifiers. Another example is a type called ONE_LEVEL, which is usually assigned to keys such as Escape; these have just one level and are not affected by the modifier state. Yet more common examples are [TWO_LEVEL]TWO_LEVEL, [ALPHABETIC]ALPHABETIC, etc.

How key types work

Key types define a mapping between the [modifiers] and [shift levels]. Key types have four parameters:

@ref key-type-level-name "Shift level names"
Declare [shift levels]. Mainly for documentation.
@ref key-type-modifiers "Modifiers filter"
Declare what modifiers should be taken into account in the mapping.
@ref key-type-map "Modifiers mapping"
Lookup table to translate modifiers combinations into shift levels.
@ref key-type-preserve "Modifiers preservation"
Tweak the computation of [consumed modifiers].

[consumed modifiers]: @ref consumed-modifiers [shift levels]: @ref level-def

Key types are used to compute:

  • the [shift level][]: see xkb_state::xkb_state_key_get_level().
  • the [consumed modifiers][]: see xkb_state::xkb_state_key_get_consumed_mods() and xkb_state::xkb_state_key_get_consumed_mods2().

The following diagram presents an overview of theses computations:

@anchor xkb-types-explanation-diagram @dotfile xkb-types-explanation "Use of key types to compute shift level and consumed modifiers"

Type definitions {#key-type-statement}

Statements of the form:

type "FOUR_LEVEL" { ... }

The above would create a new type named [FOUR_LEVEL][FOUR_LEVEL]. The body of the definition may include statements of the following forms:

“level_name” statements {#key-type-level-name}

level_name[Level1] = "Base";

Mandatory for each level in the type.

Gives each level in this type a descriptive name. It isn’t used for anything.

Note: A level may be specified as Level[1-8] or just a number (can be more than 8).

“modifiers” statement {#key-type-modifiers}

modifiers = Shift+Lock+LevelThree;

Mandatory, should be specified only once.

A mask of real and virtual [modifiers]. These are the only modifiers being considered when matching the modifier state against the type. The other modifiers, whether active or not, are masked out in the calculation.

“map” entry statements {#key-type-map}

map[Shift+LevelThree] = Level4;

Should have at least as many mappings as there are levels in the type.

If the active modifiers, masked with the type’s modifiers (as stated above), match (i.e. equal) the modifiers inside the map[] statement, then the level in the right hand side is chosen. For example, in the above, if in the current keyboard state the Shift and LevelThree modifiers are active, while the Lock modifier is not, then the keysym(s) in the 4th level of the group will be returned to the user.

“preserve” statements {#key-type-preserve}

map[Shift+Lock+LevelThree] = Level5;
preserve[Shift+Lock+LevelThree] = Lock;

When a key type is used for keysym translation, its modifiers are said to be consumed in this translation. For example, in a simple US keymap, the “G” key is assigned an ordinary [ALPHABETIC][ALPHABETIC] key type, whose modifiers are Shift and Lock; then for the “G” key, these two modifiers are consumed by the translation. This information is relevant for applications which further process the modifiers, since by then the consumed modifiers have already “done their part” and should be masked out.

However, sometimes even if a modifier had already affected the key translation through the type, it should not be reported as consumed, for various reasons. In this case, a preserve[] statement can be used to augment the map entry. The modifiers inside the square brackets should match one of the map[] statements in the type (if there is no matching map entry, one mapping to Level1 is implicitly added). The right hand side should consists of modifiers from the type’s modifiers; these modifiers are then “preserved” and not reported as consumed.

@attention Consuming a locked modifier does not unlock it and it can be consumed again in further keysym translations.

@note Remember that @ref keysym-transformations may affect the resulting keysym when some modifiers are not consumed.

@remark preserve statements may be used to tweak keyboard shortcuts. @remark@figure @figcaption Example of use of preserve to tweak Control shortcuts. Note it would require further work in order to support other modifiers. @endfigcaption

xkb_types {
    // ...
    type "TWO_LEVEL_PLUS_CONTROL" {
        modifiers = Shift + Control;
        map[None]          = Level1;
        map[Shift]         = Level2;
        map[Control]       = Level3;
        map[Control+Shift] = Level4;
        // Using preserve will make Control not consumed and allow
        // applications to detect keyboard shortcuts with alternative
        // keysyms in levels 3 and 4 rather than the levels 1 and 2.
        preserve[Control]       = Control;
        preserve[Control+Shift] = Control;
        level_name[Level1] = "Base";
        level_name[Level2] = "Shift";
        level_name[Level3] = "Tweaked Control";
        level_name[Level4] = "Tweaked Control + Shift";
    };
};
xkb_symbols {
    // ...
    // The following key would produce Greek keysym on Base and Shift levels,
    // but will produce the corresponding ASCII Latin keysyms when using Control.
    key <AC01> {
        type[Group1]="TWO_LEVEL_PLUS_CONTROL",
        [Greek_alpha, Greek_ALPHA, a, A]
    };
};

@endfigure

Key types examples {#key-type-examples}

Definitions examples

@note The convention is that Lock affect only “alphabetic” types. For such types, Lock “cancels” Shift by default, i.e. Shift+Lock has the same result as neither modifier. “semi-alphabetic” types have an asymmetry: their first two levels are alphabetic while the next are not.

Two levels

The following examples compare two basic types with two levels: [TWO_LEVEL][TWO_LEVEL] and [ALPHABETIC][ALPHABETIC]. They differ on their handling of the Lock modifier. See the next section for an illustration with concrete layouts.

[TWO_LEVEL]: @ref TWO_LEVEL [ALPHABETIC]: @ref ALPHABETIC

`TWO_LEVEL` @anchor TWO_LEVEL
@figure@figcaption Definition code ([source][two-type-src]) @endfigcaption ```c type "TWO_LEVEL" { // Only care about Shift; Lock will be filter out modifiers = Shift; // Define mapping map[None] = Level1; // No modifier -> level 1 map[Shift] = Level2; // Exactly Shift -> level 2 // (no map entry with Lock) // Define level names level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; ``` @endfigure @figure@figcaption Mapping test @endfigcaption | *Active* modifiers | *Filtered* modifiers | Match? | Shift level | | ------------------ | -------------------- | ------ | ----------- | | (none) | (none) | Yes | 1 | | `Shift` | `Shift` | Yes | 2 | | `Lock` | (none) | Yes | 1           | | `Shift + Lock` | `Shift` | Yes | 2 | @endfigure
`ALPHABETIC` @anchor ALPHABETIC
@figure@figcaption Definition code ([source][alphabetic-type-src]) @endfigcaption ```c type "ALPHABETIC" { // Only care about Shift and Lock modifiers = Shift + Lock; // Define mapping map[None] = Level1; // No modifier -> level 1 map[Shift] = Level2; // Exactly Shift -> level 2 map[Lock] = Level2; // Exactly Lock -> level 2 // Define level names level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; ``` @endfigure @figure@figcaption Mapping test @endfigcaption | *Active* modifiers | *Filtered* modifiers | Match? | Shift level | | ------------------ | -------------------- | ------ | ----------- | | (none) | (none) | Yes | 1 | | `Shift` | `Shift` | Yes | 2 | | `Lock` | `Lock` | Yes | 2           | | `Shift + Lock` | `Shift + Lock` | No | 1 | @endfigure
Four levels

The following examples compare basic types with four levels: [FOUR_LEVEL][FOUR_LEVEL], [FOUR_LEVEL_SEMIALPHABETIC][FOUR_LEVEL_SEMIALPHABETIC] and [FOUR_LEVEL_ALPHABETIC][FOUR_LEVEL_ALPHABETIC]. They differ on their handling of the Lock modifier. See the next section for an illustration with concrete layouts.

[FOUR_LEVEL]: @ref FOUR_LEVEL [FOUR_LEVEL_SEMIALPHABETIC]: @ref FOUR_LEVEL_SEMIALPHABETIC [FOUR_LEVEL_ALPHABETIC]: @ref FOUR_LEVEL_ALPHABETIC

`FOUR_LEVEL` @anchor FOUR_LEVEL
@figure@figcaption Definition code ([source][four-level-src]) @endfigcaption ```c type "FOUR_LEVEL" { modifiers = Shift + LevelThree; map[None] = Level1; map[Shift] = Level2; // (no map entry with Lock) // (no map entry with Lock) map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; // (no map entry with Lock) // (no map entry with Lock) // (no preserve entry with Lock) // (no preserve entry with Lock) level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "AltGr"; level_name[Level4] = "Shift AltGr"; }; ``` @endfigure @figure@figcaption Mapping test @endfigcaption | *Active* modifiers | *Filtered* modifiers | Match? | Shift level | | ----------------------- | -------------------- | ------ | ----------- | | (none) | (none) | Yes | 1 | | `Shift` | `Shift` | Yes | 2 | | `Lock` | (none) | Yes | 1           | | `Shift+Lock` | `Shift` | Yes | 2 | | `LevelThree` | `LevelThree` | Yes | 3 | | `LevelThree+Shift` | `LevelThree+Shift` | Yes | 4 | | `LevelThree+Lock` | `LevelThree` | Yes | 3 | | `LevelThree+Shift+Lock` | `LevelThree+Shift` | Yes | 4 | @endfigure
`FOUR_LEVEL_SEMIALPHABETIC` @anchor FOUR_LEVEL_SEMIALPHABETIC
@figure@figcaption Definition code ([source][four-level-semialphabetic-src]) @endfigcaption ```c type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift + Lock + LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[Shift+Lock] = Level1; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Shift+Lock+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Shift+Lock+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "AltGr"; level_name[Level4] = "Shift AltGr"; }; ``` @endfigure @figure@figcaption Mapping test @endfigcaption | *Active* modifiers | *Filtered* modifiers | Match? | Shift level | | ----------------------- | ----------------------- | ------ | ----------- | | (none) | (none) | Yes | 1 | | `Shift` | `Shift` | Yes | 2 | | `Lock` | `Lock` | Yes | 2           | | `Shift+Lock` | `Shift+Lock` | Yes | 1 | | `LevelThree` | `LevelThree` | Yes | 3 | | `LevelThree+Shift` | `LevelThree+Shift` | Yes | 4 | | `LevelThree+Lock` | `LevelThree+Lock` | Yes | 3 | | `LevelThree+Shift+Lock` | `LevelThree+Shift+Lock` | Yes | 4 | @endfigure
`FOUR_LEVEL_ALPHABETIC` @anchor FOUR_LEVEL_ALPHABETIC
@figure@figcaption Definition code ([source][four-level-alphabetic-src]) @endfigcaption ```c type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift + Lock + LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[Shift+Lock] = Level1; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Shift+Lock+LevelThree] = Level3; // (no preserve entry with Lock) // (no preserve entry with Lock) level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "AltGr"; level_name[Level4] = "Shift AltGr"; }; ``` @endfigure @figure@figcaption Mapping test @endfigcaption | *Active* modifiers | *Filtered* modifiers | Match? | Shift level | | ----------------------- | ----------------------- | ------ | ----------- | | (none) | (none) | Yes | 1 | | `Shift` | `Shift` | Yes | 2 | | `Lock` | `Lock` | Yes | 2           | | `Shift+Lock` | `Shift+Lock` | Yes | 1 | | `LevelThree` | `LevelThree` | Yes | 3 | | `LevelThree+Shift` | `LevelThree+Shift` | Yes | 4 | | `LevelThree+Lock` | `LevelThree+Lock` | Yes | 4 | | `LevelThree+Shift+Lock` | `LevelThree+Shift+Lock` | Yes | 3 | @endfigure

Examples with standard keyboard layouts {#key-type-mappings-examples}

See the detailed table of mappings The following table compares the mappings of various key types for the modifiers `Shift`, `Lock` and `LevelThree`, using the standard layouts [`us`][us-layout] (US English) and [`es`][es-layout] (Spanish). | Key | Layout | Key type | Active modifiers | Level | Keysym | Comment | | ------ | ------ | ------------------------------- | ------------------------------- | ----- | ------------ | ----------- | | `AE01` | [`us`][us-layout] | [`TWO_LEVEL`][TWO_LEVEL] | (none) | 1 | `1` | | | ^ | ^ | ^ | `Shift` | 2 | `exclam` | | | ^ | ^ | ^ | `Lock` | 1 | `1` | `Lock` filtered out | | ^ | ^ | ^ | `Shift` + `Lock` | 2 | `exclam` | `Lock` filtered out | | ^ | ^ | ^ | `LevelThree` | 1 | `1` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` | 2 | `exclam` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Lock` | 1 | `1` | Modifiers `LevelThree` and `Lock` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 2 | `exclam` | Modifiers `LevelThree` and `Lock` filtered out | | ^ | [`es`][es-layout] | [`FOUR_LEVEL`][FOUR_LEVEL] | (none) | 1 | `1` | | | ^ | ^ | ^ | `Shift` | 2 | `exclam` | | | ^ | ^ | ^ | `Lock` | 1 | `1` | `Lock` filtered out | | ^ | ^ | ^ | `Shift` + `Lock` | 2 | `exclam` | `Lock` filtered out | | ^ | ^ | ^ | `LevelThree` | 3 | `bar` | | | ^ | ^ | ^ | `LevelThree` + `Shift` | 4 | `exclamdown` | | | ^ | ^ | ^ | `LevelThree` + `Lock` | 3 | `bar` | `Lock` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 4 | `exclamdown` | `Lock` filtered out | | `AD01` | [`us`][us-layout] | [`ALPHABETIC`][ALPHABETIC] | (none) | 1 | `q` | | | ^ | ^ | ^ | `Shift` | 2 | `Q` | | | ^ | ^ | ^ | `Lock` | 2 | `Q` | | | ^ | ^ | ^ | `Shift` + `Lock` | 1 | `q` | `Lock` cancelled by `Shift` | | ^ | ^ | ^ | `LevelThree` | 1 | `q` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` | 1 | `q` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Lock` | 2 | `Q` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 1 | `q` | `LevelThree` filtered out, `Lock` cancelled by `Shift` | | ^ | [`es`][es-layout] | [`FOUR_LEVEL_SEMIALPHABETIC`][FOUR_LEVEL_SEMIALPHABETIC] | (none) | 1 | `q` | | | ^ | ^ | ^ | `Shift` | 2 | `Q` | | | ^ | ^ | ^ | `Lock` | 2 | `Q` | | | ^ | ^ | ^ | `Shift` + `Lock` | 1 | `q` | `Lock` cancelled by `Shift` | | ^ | ^ | ^ | `LevelThree` | 3 | `at` | | | ^ | ^ | ^ | `LevelThree` + `Shift` | 4 | `Greek_OMEGA`| | | ^ | ^ | ^ | `LevelThree` + `Lock` | 3 | `at` | `Lock` does not affect `LevelThree` combos | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 4 | `Greek_OMEGA`| `Lock` does not affect `LevelThree` combos | | `AD05` | [`us`][us-layout] | [`ALPHABETIC`][ALPHABETIC] | (none) | 1 | `t` | | | ^ | ^ | ^ | `Shift` | 2 | `T` | | | ^ | ^ | ^ | `Lock` | 2 | `T` | | | ^ | ^ | ^ | `Shift` + `Lock` | 1 | `t` | `Lock` cancelled by `Shift` | | ^ | ^ | ^ | `LevelThree` | 1 | `t` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` | 1 | `t` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Lock` | 2 | `T` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 1 | `t` | `LevelThree` filtered out, `Lock` cancelled by `Shift` | | ^ | [`es`][es-layout] | [`FOUR_LEVEL_ALPHABETIC`][FOUR_LEVEL_ALPHABETIC] | (none) | 1 | `t` | | | ^ | ^ | ^ | `Shift` | 2 | `T` | | | ^ | ^ | ^ | `Lock` | 2 | `T` | | | ^ | ^ | ^ | `Shift` + `Lock` | 1 | `t` | `Lock` cancelled by `Shift` | | ^ | ^ | ^ | `LevelThree` | 3 | `tslash` | | | ^ | ^ | ^ | `LevelThree` + `Shift` | 4 | `Tslash` | | | ^ | ^ | ^ | `LevelThree` + `Lock` | 4 | `Tslash` | | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 3 | `tslash` | `Lock` cancelled by `Shift` |

The “xkb_compat” section {#the-xkb_compat-section}

This [section] is the third to be processed, after xkb_keycodes and xkb_types.

Interpret statements {#interpret-statements}

Statements of the form:

interpret Num_Lock+Any { ... }
interpret Shift_Lock+AnyOf(Shift+Lock) { ... }

The [xkb_symbols] section (see below) allows the keymap author to perform, among other things, the following things for each key:

  • Bind a sequence of [actions], like SetMods or LockGroup, to the key. Actions, like symbols, are specified for each level of each group in the key separately.

  • Add a [virtual modifier] to the key’s virtual modifier mapping (vmodmap).

  • Specify whether the key should repeat or not.

However, doing this for each key (or level) is tedious and inflexible. Interpret’s are a mechanism to apply these settings to a bunch of keys/levels at once.

@anchor interpret-mechanism Each interpret specifies a condition by which it attaches to certain levels. The condition consists of two parts:

  • A [keysym]. If the level has a different (or more than one) keysym, the match fails. Leaving out the keysym is equivalent to using the special value Any or the NoSymbol keysym, which always matches successfully.

  • A [modifier] predicate. The predicate consists of:

    • A mask of real modifiers: a +-separated list of modifiers or the special value all, which denotes all the modifiers.

    The modifiers are matched against the key’s modifier map (modmap).

    • A matching operation, that is one of the following:

    • AnyOfOrNone – The modmap must either be empty or include at least one of the specified modifiers.

    • AnyOf – The modmap must include at least one of the specified modifiers.

    • Any – Alias for AnyOf(all).

    • NoneOf – The modmap must not include any of the specified modifiers.

    • AllOf – The modmap must include all of the specified modifiers (but may include others as well).

    • Exactly – The modmap must be exactly the same as the specified modifiers.

Leaving out the predicate is equivalent to using AnyOfOrNone(all). Leaving out just the matching condition is equivalent to using Exactly.

An interpret may also include useModMapMods = level1; – see below.

If a [level] fulfils the conditions of several interprets, only the most specific one is used:

  • A specific keysym will always match before a generic NoSymbol condition.

  • If the keysyms are the same, the interpret with the more specific matching operation is used. The above list is sorted from least to most specific.

  • If both the keysyms and the matching operations are the same (but the modifiers are different), the first interpret is used.

As described above, once an interpret “attaches” to a level, it can bind an action to that level, add one virtual modifier to the key’s vmodmap, or set the key’s repeat setting. You should note the following:

  • The key repeat is a property of the entire key; it is not level-specific. In order to avoid confusion, it is only inspected for the first level of the first group; the interpret’s repeat setting is ignored when applied to other levels.

  • If one of the above fields was set directly for a key in xkb_symbols, the explicit setting takes precedence over the interpret.

The body of the statement may include statements of the following forms (all of which are optional):

“useModMapMods” statement

useModMapMods = level1;

When set to level1, the interpret will only match keysyms which are on the first level of the first group of the keys. This can be useful in conjunction with e.g. a virtualModifier statement, because virtualModifier is an attribute of the key rather than a specific level.

Note: the other possible value is any and is the default value.

See [virtual modifier map] for further information.

“virtualModifier” statement {#interpret-virtualModifier}

virtualModifier = NumLock;

Add this virtual modifier to the key’s vmodmap. The given virtual modifier must be declared at the top level of the file with a virtual_modifiers statement, e.g.:

virtual_modifiers NumLock;

See [virtual modifier map] for further information.

“repeat” statement {#interpret-repeat}

repeat = True;

Set whether the key should repeat or not. Must be a boolean value.

“action” statement {#interpret-action}

action = LockMods(modifiers=NumLock);

Bind this action to the matching levels. See [key actions][actions] for the list of available key actions.

Since 1.9.0, it is also possible to assign a sequence of actions, mirroring the feature used in the key statement.

action = {SetMods(modifiers=NumLock),SetGroup(group=2)};

LED map statements {#indicator-effect}

[indicator effect]: @ref indicator-effect

Statements of the form:

indicator "Shift Lock" { ... }

This statement specifies the behavior and binding of the LED (AKA [indicator]) with the given name (“Shift Lock” above). The name should have been declared previously in the xkb_keycodes section (see [LED name][indicator name] statement), and given an index there. If it wasn’t, it is created with the next free index.

The body of the statement describes the conditions of the keyboard state which will cause the LED to be lit. It may include the following statements:

“modifiers” statement

modifiers = ScrollLock;

If the given [modifiers] are in the required state (see below), the LED is lit.

“whichModState” statement

whichModState = Latched+Locked;

Can be any combination of:

  • base, latched, locked, effective
  • any (i.e. all of the above)
  • none (i.e. none of the above)
  • compat (legacy value, treated as effective)

This will cause the respective portion of the modifier state (see struct xkb_state) to be matched against the modifiers given in the modifiers statement.

Here’s a simple example:

indicator "Num Lock" {
    modifiers = NumLock;
    whichModState = Locked;
};

Whenever the NumLock modifier is locked, the Num Lock LED will light up.

“groups” statement

groups = All - group1;

This is a mask of group indices.

The following special values can be used in the expression:

`GroupN`
Denotes the N-th group, e.g. `Group3` is `0x4` = `1 << (3 - 1)`.
`First`
Denotes the *first* group and always equals to `0x1`. @since 1.14
`Last`
Denotes the *last* group and depends on the keymap setup: e.g. with 3 layouts it is to `0x4 = 1 << (3 - 1)`. @since 1.14

If the given groups are in the required state (see below), the LED is lit.

“whichGroupState” statement

whichGroupState = Effective;

Can be any combination of:

  • base, latched, locked, effective
  • any (i.e. all of the above)
  • none (i.e. none of the above)

This will cause the respective portion of the group state (see struct xkb_state) to be matched against the groups given in the groups statement.

Note: the above conditions are disjunctive, i.e. if any of them are satisfied the LED is lit.

Set default values

One may change the default values of the following statements:

  • interpret: use interpret.FIELD = VALUE;
  • indicator: use indicator.FIELD = VALUE;
  • actions: use ACTION_NAME.FIELD = VALUE;. E.g. setMods.clearLocks= True;.

The “xkb_symbols” section {#the-xkb_symbols-section}

This [section] is the fourth to be processed, after xkb_keycodes, xkb_types and xkb_compat.

Statements of the form:

xkb_symbols "basic" {
    ...
}

Declare a symbols map named basic. Statements inside the curly braces only affect the symbols map.

Name statements

Statements of the form:

name[Group1] = "US/ASCII";
groupName[1] = "US/ASCII";

Gives the name “US/ASCII” to the first group of symbols. Other groups can be named using a different group index (ex: Group2), and with a different name. A group must be named.

group and groupName mean the same thing, and the Group in Group1 is optional.

Key statement {#key-statement}

Statements of the form:

key <AD01> { ... };

defines the key description of the [keycode] <AD01> and is the main type of record of the xkb_symbols section. The possible keycodes are defined in the xkb_keycodes section.

A key description consists of:

Groups
Each key may have one or more associated [groups]. Each group can be configured with the following parameters: - @ref key-type-setting "Type" - @ref key-symbols-table "Symbols" - @ref key-actions-table "Actions"
Key behavior @anchor key-behaviors
[*Key behavior*][Key behaviors] enables to *alter the key events processing* before running the actions filters. Key behavior is independent of keyboard modifier or group state. Each key has exactly *one* behavior, described hereinafter. Key behaviors are used to *simulate* any of these types of keys. @note @anchor key-behavior-permanent All the parameters presented hereinafter can be optionally *prefixed* by `permanent` to indicate an *unmodifiable* physical, electrical or software driver characteristic of a key. @note The `permanent` flag indicates a characteristic of the underlying system that libxkbcommon cannot affect, so libxkbcommon treats all permanent behaviors as if they were [*default*](@ref key-behavior-default) and *ignore* the corresponding parameters.
Default @anchor key-behavior-default
Press and release events are processed normally.
Overlays @anchor key-behavior-overlay
A *keyboard overlay* allows some subset of the keyboard to report *alternate keycodes* when the corresponding [overlay control](@ref XKB_KEYBOARD_CONTROL_OVERLAY1) is enabled. For example a keyboard overlay can be used to *simulate* a numeric or editing keypad on keyboard that does not actually have one. This technique is very common on laptop computers and embedded systems with small keyboards, see an example hereinafter. @figure @figcaption Numeric keypad hardware overlay example.
The keys with a thick border and a blue background can be overlaid by using the `Fn` key. When the overlay is enabled, they produce alternative *numeric keypad* keycodes corresponding to their bottom-right label. E.g.: - the key `` and labelled `U` produces the keycode `` (numpad `4`), - the key `` and labelled `P` produces the keycode `` (numpad multiplication). @endfigcaption @image html numeric-keypad-overlay.svg width=100% @endfigure libxkbcommon supports *effectful* keyboard overlays since version 1.14.0. The differences between [keymap formats] is presented in the table hereinafter:
Overlay support by [keymap formats]
Feature `::XKB_KEYMAP_FORMAT_TEXT_V1` `::XKB_KEYMAP_FORMAT_TEXT_V2`
Number of overlays **2** **8**
Corresponding [keyboard controls] [`Overlay1`][Overlay1] and [`Overlay2`][Overlay2] [`Overlay1`][Overlay1] to [`Overlay8`][Overlay8]
Overlapping @anchor overlapping-overlays **Disjoint overlays:** *no* overlap is allowed, i.e. each key can be part of *at most* one overlay. A key may be assigned to **any overlay without restriction**, enabling **overlapping** overlays. There is no limitation on which overlay a given key may belong to, and a key may be assigned to *more than one overlay*. When *multiple* overlays are active at the same time and a key belongs to more than one of them, the effective mapping for that key is determined by **activation order**: the mapping defined by the **most recently activated** overlay takes precedence over all previously activated ones, regardless of the indices of the overlays involved. @important This behavior differs from classic X11 overlay semantics, where activation order carries no significance.
Example of 2 overlapping overlays @figure @figcaption Example of overlay overlap @endfigcaption Assume `` is assigned to two overlays: ```c xkb_symbols { key { [u, U], overlay1=, // numpad overlay overlay2= // edit overlay }; }; ``` Given the following activation sequence: 1. [`Overlay1`][Overlay1] is activated. `` resolves to ``. 2. [`Overlay2`][Overlay2] is subsequently activated, while [`Overlay1`][Overlay1] remains active. As [`Overlay2`][Overlay2] is now the most recently activated overlay to which `` belongs, it takes precedence: `` resolves to ``. 3. [`Overlay2`][Overlay2] is deactivated. [`Overlay1`][Overlay1] remains active and, being the most recently activated applicable overlay, resumes precedence. `` resolves once again to ``. @endfigure
[Overlay1]: @ref XKB_KEYBOARD_CONTROL_OVERLAY1 [Overlay2]: @ref XKB_KEYBOARD_CONTROL_OVERLAY2 [Overlay8]: @ref XKB_KEYBOARD_CONTROL_OVERLAY8 [keyboard controls]: @ref xkb_keyboard_control_flags [keymap formats]: @ref xkb_keymap_format
Lock @anchor key-behavior-lock
@warning Only parsing is supported - `locks` / `locking`: boolean @todo See [Key behaviors] for a complete description
Radio groups @anchor key-behavior-radio-groups
@warning Only parsing is supported - `radiogroup`: positive integer - `allownone`: boolean @todo See [Key behaviors] for a complete description
Additional attributes
These attributes are usually set via the [xkb_compat] section, but may be also set directly: - @ref key-virtual-modifiers "Virtual modifiers" - @ref key-repeat "Repeat" - group wrap control (see: `xkb_layout_out_of_range_policy`) @todo `groupsWrap`, `groupsClamp`, `groupsRedirect`

@warning Using multiple groups in symbols files is not recommended, because some tools rely on the assumption that an xkb_symbols section only affect a single group. It is fine with a keymap file though.

@note In what follows we assume the common use case with a single group, which benefits from a special syntax. See the section @ref key-groups "Multiple groups" for the general syntax.

[groups]: @ref layout-def

Symbols {#key-symbols-table}

The main part of the key description is the symbols table. It maps shift levels to keysyms, e.g.:

key <AD01> { [ q, Q ] }; // Level 1 → `q`, Level 2 → `Q`

Symbols are named using the symbolic names from the xkbcommon/xkbcommon-keysyms.h file. See the @ref keysym-syntax "keysym syntax" for further information. A group of symbols is enclosed in brackets and separated by commas. Each element of the symbol arrays corresponds to a different [shift level]. In this example, the symbol (keysym) XKB_KEY_q for level 1 and XKB_KEY_Q for level 2. These levels are configured by the @ref key-type-setting "key type", presented in the next section.

@remark Remember that @ref keysym-transformations may affect the resulting keysym when some modifiers are not consumed.

@remark Trailing NoSymbol are dropped.

@anchor key-multiple-symbols-per-level As an extension to the XKB legacy format, libxkbcommon supports multiple key symbols and actions per level (the latter since version 1.8.0):

key <AD08> { [ {i, j}        , U0132         ] }; // IJ Dutch digraph
key <AC05> { [ {g, U0303}    , {G, U0303}    ] }; // G̃ Guarani letter
key <AB05> { [ {U0644, U0627}, {U0644, U0622}] }; // ⁧لا⁩ ⁧لآ⁩ Arabic Lam-Alef ligatures decomposed
key <AD01> { [ {c, U2019, h} , {C, U2019, h} ] }; // C’H Breton trigraph

In this example, the keycode <AD08> produces two symbols on level 1 (XKB_KEY_i and XKB_KEY_j) and one symbol (Unicode keysym U0132 for “IJ”) on level 2. <AD08> and <AD01> produce letters that have no precomposed code point in Unicode. Key <AB05> avoids the need of using Compose.

@anchor keysyms-string Since 1.9.0, UTF-8-encoded strings may be used to denote a list of keysyms corresponding to the encoded Unicode code points. E.g. the previous example can be also written more intuitively as:

key <AD08> { [ "ij" , "IJ"   ] }; // IJ Dutch digraph
key <AC05> { [ "g̃"  , "G̃"   ] }; // G̃ Guarani letter
// NOTE: We use U+200E LEFT-TO-RIGHT MARK in order to display the strings in
//       in the proper order.
key <AB05> { [ "لا"‎  , "لآ"‎   ] }; // ⁧لا⁩ ⁧لآ⁩ Arabic Lam-Alef ligatures decomposed
key <AD01> { [ "c’h", "C’h" ] }; // C’H Breton trigraph

When no actions are explicitly given, they are automatically filled thanks to [interpretations] from the [compat section][xkb_compat]. In the following example,

key <LCTL> { [ { Control_L, ISO_Group_Shift } ] };

is equivalent to (given standard definitions from xkeyboard-config):

key <LCTL> {
    symbols[1] = [ { Control_L,                  ISO_Group_Shift    } ],
    actions[1] = [ { SetMods(modifiers=Control), SetGroup(group=+1) } ]
};

When using this example with e.g. two layouts fr,us (respectively Azerty and Qwerty layouts), typing Control + A in the first layout fr will in fact result in Control + Q, because the actions are run sequentially: first set the base modifiers to Control, then switch to the second layout while Control is pressed.

@remark Given a level, keysyms and actions may have a different count. For instance, the following would achieve the same effect than the former example with only 1 keysym, but it requires to use 2 explicit actions:

key <LCTL> {
    symbols[1] = [ Control_L                                          ],
    actions[1] = [ { SetMods(modifiers=Control), SetGroup(group=+1) } ]
};

@note There are some limitations with this extension:

  • For now, at most one action of each following categories is allowed per level:
    • [modifier actions][]: SetMods, LatchMods, LockMods;
    • [group actions][]: SetGroup, LatchGroup, LockGroup.

Some examples of actions combination:

  • SetMods + SetGroup: ok
  • SetMods + SetMods: error
  • SetMods + LockMods: error
  • SetMods + LockGroup: ok
  • Multiple actions are only supported from version 1.8.0.
@since 1.8.0: When using multiple keysyms or actions per level, `NoSymbol` and `NoAction()` are dropped in order to normalize the levels: ```c // Before normalization key <> { [{NoSymbol}, {a, NoSymbol}, {NoSymbol,b}, {a, NoSymbol, b}] }; // After normalization key <> { [NoSymbol, a, b, {a, b}] }; ```
@since 1.9.0: Trailing `NoSymbol` and `NoAction()` are dropped in groups: ```c // Before normalization key <> { [a, NoSymbol] }; // After normalization key <> { [a] }; ``` This affects the automatic key type detection.
@since 1.9.0: Added support for keysyms and actions lists of length 0 and 1, respectively `{}` and `{a}`. `{}` is equivalent to the corresponding `NoSymbol` or `NoAction()`.

@warning Keymaps containing multiple key symbols per level are not supported by the various X11-related tools (setxkbmap, xkbcomp, etc.).

[symbols table]: @ref key-symbols-table

Type {#key-type-setting}

Each key has a [key type] set per group. This key type is defined in the [xkb_types] section. Its associated [shift levels] are used to index the [symbols table] presented in the previous section.

A key type is set using the following syntax:

key <AD01> {
    type[Group1] = "TWO_LEVEL", // Type
    [q, Q]                      // Symbols
};

The name of the key type is enclosed between double quotes.

The key type may be omitted and will default to:

  • key.type global defaults, if set.
  • a standard type using the following heuristic:
    • 1 keysym: ONE_LEVEL
    • 2 keysyms:
    • if the two keysyms are letter and the first is lower case and the other upper case, then [ALPHABETIC][ALPHABETIC];
    • if one of the keysyms is numpad, then KEYPAD else [TWO_LEVEL][TWO_LEVEL].
    • 3 or 4 keysyms (a missing 4th keysym is set to NoSymbol):
    • if the first two keysyms are letters and the first is lower case and the other upper case:
      • if the last two keysyms are letters and the first is lower case and the other upper case then [FOUR_LEVEL_ALPHABETIC][FOUR_LEVEL_ALPHABETIC];
      • else [FOUR_LEVEL_SEMIALPHABETIC][FOUR_LEVEL_SEMIALPHABETIC].
    • if one of the first two keysyms is numpad, then FOUR_LEVEL_KEYPAD;
    • else [FOUR_LEVEL][FOUR_LEVEL].

@figure@figcaption Commented examples for inferred types: @endfigcaption

// 1 to 2 keysyms
key <LFSH> { [Shift_L] };                    // Type: ONE_LEVEL
key <AE01> { [1, exclam] };                  // Type: TWO_LEVEL
key <AD01> { [q, Q] };                       // Type: ALPHABETIC
key <KP1>  { [KP_End, KP_1] };               // Type: KEYPAD
// Edge case: this is consider alphabetic, although
// the lower case does not correspond to the upper case.
key <AD01> { [q, N] };                       // Type: ALPHABETIC

// 3 to 4 keysyms
key <AE01> { [1, exclam, bar] };             // Type: FOUR_LEVEL
key <AE01> { [1, exclam, bar, exclamdown] }; // Type: FOUR_LEVEL
key <AD01> { [q, Q, at] };                   // Type: FOUR_LEVEL_SEMIALPHABETIC
key <AD01> { [q, Q, at, Greek_OMEGA] };      // Type: FOUR_LEVEL_SEMIALPHABETIC
key <AD05> { [t, T, tslash, Tslash] };       // Type: FOUR_LEVEL_ALPHABETIC

// The inferred type is `FOUR_LEVEL`, but using `LevelThree+Lock`
// will produce `Q`, because of the keysyms transformations and
// the corresponding internal capitalization processing.
key <AE01> { [1, exclam, q, Q] };            // Type: FOUR_LEVEL

// Won’t work, because there is no heuristic for more than 4 keysyms
// It will trigger the warnings XKB-183 and XKB-516 and default to ONE_LEVEL,
// ignoring all the keysyms but the first one.
key <AD01> {[q, Q, at, any, masculine, U2642]};
// Will work as expected
key <AD01> {
    type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC",
    [q, Q, at, any, masculine, U2642]
};

@endfigure

Actions {#key-actions-table}

@note This is usually not set explicitly but via the [interpret mechanism] by using the action statement in the [xkb_compat] section.

@figure@figcaption Example: Set the modifier action of the key <LALT> manually. @endfigcaption

key <LALT> {
    symbols[Group1]=[Alt_L],
    actions[Group1]=[SetMods(modifiers=modMapMods)]
};

@endfigure

For further details see [key actions][actions].

@remark Trailing NoAction() are dropped.

Multiple groups {#key-groups}

Each group represents a list of symbols mapped to a keycode:

name[Group1]= "US/ASCII";
name[Group2]= "Russian";
...
key <AD01> { [ q, Q ],
             [ Cyrillic_shorti, Cyrillic_SHORTI ] };

A long-form syntax can also be used:

key <AD01> {
    symbols[Group1]= [ q, Q ],
    symbols[Group2]= [ Cyrillic_shorti, Cyrillic_SHORTI ]
};

Groups can also be omitted, but the brackets must be present. The following statement only defines the Group3 of a mapping:

key <AD01> { [], [], [ q, Q ] };

@warning Using multiple groups in symbols files is not recommended, because some tools rely on the assumption that an xkb_symbols section only affect a single group. It is fine with a keymap file though.

Virtual modifiers {#key-virtual-modifiers}

@note This is usually not set explicitly but via the [interpret mechanism] by using the virtualModifier statement from the [xkb_compat] section.

@remarks When setting a modifier action, it is required to declare the corresponding virtual modifier using a virtual_modifiers statement.

@figure@figcaption Example: Set the virtual modifier of the key <LALT> to Alt. @endfigcaption

// Declare the virtual modifier that will be used
virtual_modifiers Alt;

key  <LALT> {
    virtualModifiers = Alt,
    [ Alt_L ]
};

@endfigure

See [virtual modifier map] for further information.

[interpret mechanism]: @ref interpret-mechanism

Repeat {#key-repeat}

@note This is usually not set explicitly but via the [interpret mechanism] by using the repeat statement in the [xkb_compat] section.

@figure@figcaption Example: make the <LALT> key not repeating. @endfigcaption

key  <LALT> {
    repeat = False,
    [ Alt_L ]
};

@endfigure

Real Modifier map {#modmap-statement}

Bind a real modifier to a key, e.g.:

// Bind the real modifier `Control` to the key `<LCTL>` and/or the first key with
// the keysym `Control_L`.
modifier_map Control { <LCTL>, Control_L };

The formats ::XKB_KEYMAP_FORMAT_TEXT_V1 (all libxkbcommon versions) and ::XKB_KEYMAP_FORMAT_TEXT_V2 (libxkbcommon < 1.14) accepts only a single [X11 core modifier][core modifier].

Since libxkbcommon 1.14, any modifier mask expression can be used in ::XKB_KEYMAP_FORMAT_TEXT_V2:

[X11 core modifiers][core modifier]
```c modifier_map Shift { … }; // New: numeric equivalent of the previous entry modifier_map 0x001 { … }; // New: modifier mask expression modifier_map Mod1+Mod2 { … }; // New: numeric equivalent of the previous entry modifier_map 0x018 { … }; ```
[Extended real modifiers][extended modifier]
```c // New: non-X11 core modifiers modifier_map 0x100 { … }; // New: multiple non-X11 core modifiers modifier_map 0xf00 { … }; // New: Mix of X11 core and non core modifiers modifier_map Mod2+0x100 { … }; // New: Numeric equivalent of the previous entry modifier_map 0x110 { … }; ```
Fallback to `::XKB_KEYMAP_FORMAT_TEXT_V1`
Due to backward compatibility with the X11 ecosystem, serializing to the `::XKB_KEYMAP_FORMAT_TEXT_V1` is subject to the following restrictions: - Non-[X11 core modifiers][core modifier] are not supported. - Multiple modifiers per key are not supported, unless using keysyms in the original `modifier_map` entry.

See [real modifier map] for further information.

Set default values

One may change the default values of the following statements:

  • key: use key.FIELD = VALUE;. E.g. key.type = "ALPHABETIC";.
  • action: use ACTION_NAME.FIELD = VALUE;. E.g. setMods.clearLocks= True;.

Modifiers declaration and binding {#modifiers-declaration-and-binding}

[modifiers declaration and binding]: @ref modifiers-declaration-and-binding

Real and virtual modifiers

[Modifiers] are a particularly tricky part of XKB and deserve their own section. For historical reasons they are divided in two categories:

Real modifier
They are the **8** *predefined* (AKA *core*, *X11*) modifiers: | Name | Index/Bit | Mask | Description | | --------- | --------- | ------ | -------------------------- | | `Shift` | 0 | `0x01` | Used to type upper case letters of [bicameral scripts]; keyboard shortcuts | | `Lock` | 1 | `0x02` | Used to type upper case letters of [bicameral scripts]: “Caps Lock” | | `Control` | 2 | `0x04` | Used in keyboard shortcuts | | `Mod1` | 3 | `0x08` | Generic modifier 1 | | `Mod2` | 4 | `0x10` | Generic modifier 2 | | `Mod3` | 5 | `0x20` | Generic modifier 3 | | `Mod4` | 6 | `0x40` | Generic modifier 4 | | `Mod5` | 7 | `0x80` | Generic modifier 5 | They are the modifiers defined in the [*core* X11 protocol][X11 Core Protocol]. They are qualified as “real”, because in the XKB protocol they denote the *bits* that *encode* the modifiers state. See @ref modifiers-encoding "" for further information. Since they are predefined, they require no [explicit declaration](@ref virtual-modifier-statements) and have a *fixed* [encoding](@ref modifiers-encoding).
Virtual modifier
They are the modifiers that are *not* predefined. They require an [*explicit* declaration](@ref virtual-modifier-statements) and their [encoding](@ref modifiers-encoding) is *user-defined*. Note that in X11, the maximum of virtual modifiers is **16** (see `XkbNumVirtualMods`), whereas up to **24** virtual modifiers can be defined in libxkbcommon, for a total of **32** modifiers (real + virtual).

Modifiers declarations {#virtual-modifier-statements}

Virtual modifiers must be declared before their first use with the virtual_modifiers statement:

  • Declare a single modifier:

    virtual_modifiers MyModifier;
    
  • Declare multiple modifiers using a comma-separated list:

    virtual_modifiers M1, M2, M3.
    

Furthermore, it is possible to set the [explicit modifier encoding] with the following syntax:

  • Use a real modifier mask:

    // Single modifier: real modifier
    virtual_modifiers M1 = Mod3;
    // Single modifier: using mask as a plus-separated list
    virtual_modifiers M2 = Mod4+Mod5;
    // Multiple modifiers
    virtual_modifiers M1 = Mod3, M2 = Mod4+Mod5;
    
  • Use a numeric mask:

    virtual_modifiers M1 = 0x20;
    virtual_modifiers M2 = 0xC0;
    virtual_modifiers M1 = 0x20, M2 = 0xC0;
    
  • Use none, an alias for 0:

    virtual_modifiers M1 = none;
    // Equivalent to: M1 = 0;
    

This can be done in the [xkb_types][xkb_types], [xkb_compat][xkb_compat] and [xkb_symbols][xkb_symbols] sections.

Modifiers key bindings {#modifiers-bindings}

[modifiers bindings]: @ref modifiers-bindings

Each key has two modifiers maps:

*Real* modifier map
List the [*real* modifiers](@ref real-modifier) associated to the key. It is used as a compatibility layer for the X11 core protocol and to apply [interpretations]. See @ref set-real-mod-map "" for further information.
*Virtual* modifier map
List the [*virtual* modifiers](@ref virtual-modifier) associated to the key. It is used to set the [implicit encoding](@ref implicit-modifier-encoding) of virtual modifiers. See @ref set-virtual-mod-map "" for further information.

[real modifier map]: @ref real-modifier-map [real modifier maps]: @ref real-modifier-map [virtual modifier map]: @ref virtual-modifier-map

Setting the real modifier map {#set-real-mod-map}

The [real modifier map] is set in the [xkb_symbols][xkb_symbols] section using the modifier_map statement:

  • Bind directly to a keycode, e.g.:

    // Bind `Mod1` to the keycode <LALT>.
    modifier_map Mod1 { <LALT> };
    
  • Bind indirectly via a keysym, e.g.:

    // Bind `Mod1` looking up for the keysym `Alt_L`
    modifier_map Mod1 { Alt_L };
    

Indirect bindings require to be resolved to a single direct bindings. Given a keysym, there can be multiple keys that generate it, so the corresponding key is chosen following this order:

  1. by lowest group in which the keysym appears,
  2. by lowest level,
  3. by lowest key code.
  4. Bind using a comma-separated list of keycodes and keysyms:

    // Bind `Mod1` diretly to keycode <LALT> and indirectly via the keysym `Alt_L`
    modifier_map Mod1 { <LALT>, Alt_L };
    

There is also a special entry, None, that enable deleting a previous entry:

modifier_map None { <LALT> };

@note None must use the exact same target (keycode or keysym) in order to delete the corresponding previous entry:

xkb_symbols {
    key <LALT> { [Alt_L] };
    modifier_map Mod1 { <LALT> };
    // Does *not* delete previous entry (expected keycode, got keysym)
    modifier_map None { Alt_L };
    // *Does* delete previous entry (correct expected keycode)
    modifier_map None { <LALT> };
};

Setting the virtual modifier map {#set-virtual-mod-map}

The [virtual modifier map] can be set in 2 ways:

  • Directly in the [xkb_symbols][xkb_symbols] section using the virtualModifiers key property:

    xkb_symbols {
      // Virtual modifiers must be declared before use
      virtual_modifiers Alt;
    
      key <LALT> {
          // Explicit virtual modifier map
          virtualModifiers = Alt,
          ...
      };
    };
    
  • Indirectly using [interpretations] in [xkb_compat][xkb_compat] and the corresponding [xkb_symbols][xkb_symbols] keysyms:

    xkb_compat {
      // Virtual modifiers must be declared before use
      virtual_modifiers Alt, Super;
    
      interpret Alt_L {
          // Bind the virtual modifier…
          virtualModifier = Alt;
          // … independently of the group and level (default)
          useModMap = AnyLevel;
      };
      interpret Super_L {
          // Bind the virtual modifier…
          virtualModifier = Super;
          // … only if the keysym is on the first level of the first group
          useModMap = Level1;
      };
    };
    xkb_symbols {
      // Successful bindings
      key <LALT> { [Alt_L] };
      key <LALT> { [No,Symbol, Alt_L] };    // independent of group and level
      key <LALT> { [], [NoSymbol, Alt_L] }; // independent of group and level
    
      key <LWIN> { [Super_L] };
    
      // Unsuccessful bindings
      key <LWIN> { [NoSymbol, Super_L] };   // requires first level
      key <LWIN> { [], [Super_L] };         // requires first group
    };
    

Modifiers encoding {#modifiers-encoding}

[modifier encoding]: @ref modifiers-encoding

Each modifier has an associated 32 bit mask used to encode it in the keyboard state. The keyboard state represents active modifiers with the bitwise OR of the encoding of each active modifiers.

@note Display servers may use a different encoding in their protocols:

  • Wayland protocol: use the same 32-bit encoding as libxkbcommon and support its full range of modifiers.
  • X11 protocol: use a 8-bit encoding. It supports only using real modifiers to encode virtual modifiers.

@important

  • Real modifiers have a fixed predefined encoding.
  • Virtual modifiers have a user-defined encoding.

Virtual modifiers require to be encoded by the user, implicitly (using the auto mode and/or the legacy mode) and/or explicitly, the combination resulting in their effective encoding.

*Implicit* modifier encoding
Virtual modifiers *always* compute their implicit encoding, which is defined for a given virtual modifier by the bitwise OR of all the [real modifier maps] where the virtual modifier is in the [virtual modifier map] of the corresponding key. Example: ```c xkb_symbols { virtual_modifiers Alt; // Virtual modifier map: Alt is bound to // Note: alternatively one can use xkb_compat interpretations. key { virtualModifier = Alt }; // Real modifier map: Mod1 is bound to modifier_map Mod1 { }; // Implicit encoding: Alt = Mod1 }; ```
*Explicit* modifier encoding
Virtual modifiers can optionally define an initial mapping using the [`virtual_modifiers`](@ref virtual-modifier-statements) statements: ```c virtual_modifiers M1 = Mod1; // Single real modifier virtual_modifiers M2 = Mod4+Mod5;// Real modifier mask virtual_modifiers M3 = 0x400; // Numeric mask ``` See @ref virtual-modifier-statements "" for further information. @warning Although it is explicit, this may not be the [effective encoding][effective modifier encoding], detailed hereinafter.
*Effective* modifier encoding
The effective encoding is the bitwise OR of the [explicit modifier encoding] and the [implicit modifier encoding]. @note @anchor auto-modifier-encoding If using `::XKB_KEYMAP_FORMAT_TEXT_V2`, virtual modifiers that were not mapped either *implicitly* using the `virtualModifier`/`modifier_map` feature hereinabove or [*explicitly*](@ref explicit-modifier-encoding), then they are mapped to their [*canonical* mapping](@ref canonical-modifier-def). Example: ```c xkb_symbols { virtual_modifiers Alt, Meta, Super = none, Hyper = 0x1000, Useless = none; // Virtual modifier maps // Note: alternatively one can use xkb_compat interpretations. key { virtualModifier = Alt }; // Alt is bound to key { virtualModifier = Super }; // Super is bound to key { virtualModifier = Super }; // Super is bound to key { virtualModifier = Hyper }; // Hyper is bound to // Real modifier maps modifier_map Mod1 { }; // Mod1 is bound to modifier_map Mod4 { }; // Mod4 is bound to modifier_map Mod5 { }; // Mod5 is bound to modifier_map Mod3 { }; // Mod3 is bound to }; ```
Modifiers encoding of the previous example
Modifier Index Encoding
Canonical Explicit Implicit Effective
(xkbcommon) `::XKB_KEYMAP_FORMAT_TEXT_V1` `::XKB_KEYMAP_FORMAT_TEXT_V2`
Alt 8 `0x100` `Mod1` `Mod1` `Mod1`
Meta 9 `0x200` 0 (unmapped) `0x200` (canonical, xkbcommon value)
Super 10 `0x400` 0 `Mod4 + Mod5` `Mod4 + Mod5` `Mod4 + Mod5`
Hyper 11 `0x800` `0x1000` `0x1000` `0x1000`
Useless 12 `0x1000` 0 0 (unmapped) 0 (explicit mapping)

[explicit modifier encoding]: @ref explicit-modifier-encoding [implicit modifier encoding]: @ref implicit-modifier-encoding [effective modifier encoding]: @ref effective-modifier-encoding

Canonical and non-canonical modifiers

@anchor canonical-modifier-def A canonical modifier have an encoding defined by: 1 << mod_index, where mod_index is:

  • Fixed for the real modifiers, in order to match the X11 values. See real modifiers mapping.
  • Implementation-dependent for the the virtual modifiers. See @ref xkbcommon-vmod-encoding "" for further details.

[canonical modifier]: @ref canonical-modifier-def

Usual modifiers and associated keysyms {#usual-modifiers-keysyms}

The following table summarizes the modifiers defined in xkeyboard-config 2.44:

Modifier Type Compat files Associated keysyms
Shift Real compat/basic Shift_L, Shift_R
^ ^ compat/iso9995 Shift_L, Shift_R, ISO_Level2_Latch
Lock Real compat/basic, Caps_Lock
^ ^ compat/caps ^
Control Real compat/basic Control_L, Control_R
Alt Virtual compat/misc, Alt_L, Alt_R
^ ^ compat/pc ^
Meta Virtual compat/misc Meta_L, Meta_R
Super Virtual compat/misc Super_L, Super_R
Hyper Virtual compat/misc Hyper_L, Hyper_R
ScrollLock Virtual compat/misc Scroll_Lock
NumLock Virtual compat/basic, Num_Lock,
^ ^ compat/level5 (ISO_Level5_Lock)
LevelThree Virtual compat/iso9995 ISO_Level3_Shift, ISO_Level3_Latch, ISO_Level3_Lock
LevelFive Virtual compat/level5 ISO_Level5_Shift, ISO_Level5_Latch, ISO_Level5_Lock
Kana_Lock Virtual compat/japan Kana_Lock
Square Virtual compat/olpc KP_Home
Cross Virtual compat/olpc KP_Next
Circle Virtual compat/olpc KP_End
Triangle Virtual compat/olpc KP_Prior

Modifiers portability {#modifiers-portability}

Avoid using numeric modifier masks

@note Any field that accept virtual modifier names is a virtual modifier mask, denoting virtual modifiers indices. These indices are implementation-specific and should not be leaked. Therefore any numeric value used for these fields should be interpreted equally as a virtual modifier mask, and is thus implementation-specific.

@important In order to preserve [modifier encoding] portability, XKB implementations are recommended to avoid numeric modifier masks and to use virtual modifiers names whenever possible when serializing the keymap. This avoids leaking the indices of the modifiers.

xkbcomp and libxkbcommon implementations {#xkbcommon-vmod-encoding}

@attention This section is not part of the keymap text format specification and presents libxkbcommon’s implementation details that may change, solely for the purpose of informing other XKB implementation. Users should not rely on this!

Both X11 xkbcomp and libxkbcommon currently implement modifiers indices as follow:

  1. Real modifiers have the following indices: @anchor real-modifier-indices | Name | Index | | --------- | ----- | | Shift | 0 | | Lock | 1 | | Control | 2 | | Mod1 | 3 | | Mod2 | 4 | | Mod3 | 5 | | Mod4 | 6 | | Mod5 | 7 |
  2. Virtual modifiers names are assigned to virtual modifier indices following their order of appearance in a keymap component, if that name was not previously assigned.
  3. Indices are assigned in ascending order, from 0.
  4. If an index is already assigned to a different name, then the next free index is used.
  5. The order of the relevant keymap components used for virtual mods assignment is:
    1. [xkb_types]
    2. [xkb_compat]
    3. [xkb_symbols]
  6. A virtual modifier mask always denotes virtual modifiers indices.

@note It suffices to declare all virtual modifiers in [xkb_types] (or if empty, whatever non-empty section afterwards, in the order specified above) in their ascending indices order to use virtual modifiers indices compatible with libxkbcommon.

Example: define and use a modifier, step by step

We will use the example of the real modifier Shift and the virtual modifier LevelThree in xkeyboard-config.

In order to define and use a modifier, one must:

  1. Define its behavior and [keysym] binding in the [xkb_compat] section:

    // Declare virtual modifiers. Shift being real modifier,
    // we do not need to add it here.
    virtual_modifiers LevelThree;
    
    // Set defaults. They are overridden if set directly in the xkb_symbols.
    interpret.repeat= False; // only applied on first level
    setMods.clearLocks= True;
    latchMods.clearLocks= True;
    latchMods.latchToLock= True;
    
    // Default statement for real modifiers: any key bound to a real
    // modifier via modifier_map will set this modifier at all its
    // levels.
    // Here only to illustrate: do not add it!
    interpret Any + Any {
        action= SetMods(modifiers=modMapMods);
    };
    
    // Shift being real modifier, we do not need a corresponding
    // interpret statement because the previous one suffices.
    
    // Let’s associate LevelThree to the keysym ISO_Level3_Shift
    
    // First, match the keys and their levels with the
    // ISO_Level3_Shift keysym and with any real modifier
    // (Any = AnyOf(all)) in its modmap.
    interpret ISO_Level3_Shift+Any {
        // Only match the first level of the first group
        useModMapMods= level1;
        // Add the virtual modifier to the key’s vmodmap
        virtualModifier= LevelThree;
        // Activate the LevelThree modifier (depressed mode)
        action= SetMods(modifiers=LevelThree);
    };
    
    // Then for keys and their levels with the
    // ISO_Level3_Shift keysym but with either no real modifier
    // in its modmap or a level higher than 1.
    // Indeed:
    // • In case the level is higher than 1 there is no match
    //   in the previous statement.
    // • The condition is equivalent to
    //   ISO_Level3_Shift+AnyOfOrNone(all), but since
    //   the previous statement ISO_Level3_Shift+Any is more
    //   specific, it will be matched before this one.
    interpret ISO_Level3_Shift {
        // Activate the LevelThree modifier (depressed mode)
        action= SetMods(modifiers=LevelThree);
    };
    
  2. Define [key types] that use it in the [xkb_types] section:

    // Declare virtual modifiers. Shift being real modifier,
    // we do not need to add it here.
    virtual_modifiers LevelThree;
    
    type "FOUR_LEVEL" {
        // Key type modifier mask: all the modifiers used in the key type
        modifiers = Shift + LevelThree;
        map[None] = Level1;
        map[Shift] = Level2;
        map[LevelThree] = Level3;
        map[Shift+LevelThree] = Level4;
        level_name[Level1] = "Base";
        level_name[Level2] = "Shift";
        level_name[Level3] = "AltGr";
        level_name[Level4] = "Shift AltGr";
    };
    
  3. Bind it to a [keycode] in the [xkb_symbols] section:

    1. Map [keysyms] used in the xkb_compat section hereinabove.
    2. Bind [real modifiers] to keys using these keysyms with modifier_map.

    Note: Only one key binding to real modifier is required. The corresponding keysym must then be on the first level of the first Group.

    Note: One can optionally bind directly a virtual modifier to a key using virtualmodifiers instead of doing it in the xkb_compat section. But the recommended way is to use the xkb_compat section.

    // Shift: defined in pc symbols
    key <LFSH> {[  Shift_L    ]};
    key <RTSH> {[  Shift_R    ]};
    modifier_map Shift { Shift_L, Shift_R };
    // The previous will resolve to:
    // modifier_map Shift { <LFSH>, <RTSH> };
    // Thus the real modifier Shift is added to the modmap of
    // <LFSH> and <RTSH>.
    // The “Any + Any” interpret statement matches <LFSH> and <RTSH>,
    // therefore these keys set the Shift modifier.
    
    // LevelThree: defined in pc symbols
    // With the following 2 lines:
    // 1. The modifier keysym is on the first level of the first group.
    // 2. The real modifier Mod5 is bound to <LVL3>,
    //    i.e. Mod5 is added to its modmap.
    // 3. It matches the interpret statement “ISO_Level3_Shift+Any”,
    //    which adds the LevelThree modifier to the vmodmap of <LVL3>.
    // 4. The mapping of LevelThree to real modifiers is the union
    //    of modmaps with corresponding vmodmaps containing
    //    LevelThree. In our case there is only one: therefore
    //    LevelThree maps to Mod5.
    key <LVL3> {[  ISO_Level3_Shift  ]};
    modifier_map Mod5  { <LVL3> };
    
    // LevelThree: defined in level3 symbols
    // Not bound to a real modifier, so interpret statement
    // “ISO_Level3_Shift” applies.
    key <RALT> {[ISO_Level3_Shift], type[group1]="ONE_LEVEL" };
    
    // Note: we could have the following line, but it is not necessary
    // because we have the mappings of <LVL3>.
    // modifier_map Mod5  { <RALT> };
    
    // Warning: if we had the for example the following line, the
    // mapping of LevelThree to real modifiers would be “Mod1+Mod5”.
    // modifier_map Mod1  { <RALT> };
    
    // Alternative definitions, without using interpret statements
    virtual_modifiers LevelThree;
    key <LVL3> { virtualmodifiers=LevelThree
               , repeats=False
               , symbols[Group1] = [ISO_Level3_Shift]
               , actions[Group1] = [SetMods(modifiers=LevelThree)] };
    modifier_map Mod5  { <LVL3> };
    key <RALT> { repeat=False
               , symbols[Group1] = [ISO_Level3_Shift]
               , actions[Group1] = [SetMods(modifiers=LevelThree)]
               , type[group1]="ONE_LEVEL" };
    
    // FOUR_LEVEL key type example from latin symbols
    key <AB05> {[b, B, leftdoublequotemark, leftsinglequotemark]};
    

Key actions {#key-actions}

The following table provide an overview of the available actions:

Category Action name Alias Description
[Ineffectual action] [NoAction][NoAction] Default action: implicitly do nothing
^ [VoidAction][VoidAction] Explicitly do nothing
[Modifier action] [SetMods][SetMods] Modifies the [depressed] modifiers
^ [LatchMods][Latchmods] Modifies the [latched] modifiers
^ [LockMods][LockMods] Modifies the [locked] modifiers
[Group action] [SetGroup][SetGroup] Modifies the base group
^ [LatchGroup][LatchGroup] Modifies the latched group
^ [LockGroup][LockGroup] Modifies the locked group
[Keyboard controls action] [SetControls][SetControls] Set the standard XKB controls
^ [LockControls][LockControls] Lock the standard XKB controls
[Keyboard emulation action] [RedirectKey][redirectkey] Redirect Emulate pressing a key with a different key code
[Legacy action] MovePointer MovePtr Move the mouse pointer
^ PointerButton PtrBtn Simulate a mouse button press
^ LockPointerButton LockPtrBtn Simulate a mouse button press, locked until the action’s key is pressed again.
^ SetPointerDefault SetPtrDflt Set the default select button (???)
^ [TerminateServer][TerminateServer] Terminate Shut down the X server
^ SwitchScreen Switch virtual X screen
^ [Private][Private] Raw encoding of an action
[Unsupported legacy action] ISOLock Convert ordinary modifier key actions into lock actions while this action is active
^ DeviceButton DevBtn Emulate an event from an arbitrary input device such as a joystick
^ LockDeviceButton LockDevBtn Emulate an event from an arbitrary input device such as a joystick
^ DeviceValuator DevVal TODO
^ MessageAction Message Generate an arbitrary special-purpose XKB event

Common syntax:

  • Boolean values:
    • true, yes, on
    • false, no, off

Ineffectual actions {#ineffectual-actions}

[ineffectual action]: @ref ineffectual-actions [NoAction]: @ref no-action [VoidAction]: @ref void-action

`NoAction` @anchor no-action
**Default action**: *implicitly* do nothing. Does *not* override previous actions and is dropped. No parameters.
`VoidAction` @anchor void-action
*Explicitly* do nothing. *Does* override previous actions and is not dropped. No parameters. @note This is a libxkbcommon *extension*. In order to maintain backward-compatibility, it serializes to `LockControls(controls=none,affect=neither)`. @since 1.10.0

Modifiers actions {#modifiers-actions}

[modifier action]: @ref modifiers-actions [modifier actions]: @ref modifiers-actions [SetMods]: @ref set-mods-action [LatchMods]: @ref latch-mods-action [LockMods]: @ref lock-mods-action

There are 3 modifiers actions:

`SetMods` @anchor set-mods-action
Modifies the [depressed] modifiers.
Parameters
Name Aliases Data type Default value Description
`modifiers` `mods` Modifier mask `none` (0) The list of modifiers to modify, separated by `+`, or the special value `modMapMods`. The latter means the parameter value has to be read from the `vmodmap` attribute of the key.
`clearLocks` boolean `false` See its use [hereinafter](@ref set-modifier-action-effects)
`unlockOnPress` boolean `false` Control whether [locked] modifiers are unlocked on key press or release (default). See [hereinafter](@ref set-modifier-action-effects) for further details. @note Available since 1.11, only with `::XKB_KEYMAP_FORMAT_TEXT_V2`.
`LatchMods` @anchor latch-mods-action
Modifies the [latched] modifiers
Parameters
Name Aliases Data type Default value Description
`modifiers` `mods` Modifier mask `none` (0) see [`SetMods`][SetMods].
`clearLocks` boolean `false` See its use [hereinafter](@ref latch-modifier-action-effects)
`latchToLock` boolean `false` See its use [hereinafter](@ref latch-modifier-action-effects)
`latchOnPress` boolean `false` Control whether [latched] modifiers are latched on key press or release (default). See [hereinafter](@ref latch-modifier-action-effects) for further details. @note Available since 1.11, only with `::XKB_KEYMAP_FORMAT_TEXT_V2`.
`unlockOnPress` boolean `false` Control whether [locked] modifiers are unlocked on key press or release (default). See [hereinafter](@ref latch-modifier-action-effects) for further details. @note It is *implied* if both `latchOnPress=true` and `clearLocks=true`. @note Available since 1.11, only with `::XKB_KEYMAP_FORMAT_TEXT_V2`.
`LockMods` @anchor lock-mods-action
Modifies the [locked] modifiers.
Parameters
Name Aliases Data type Default value Description
`modifiers` `mods` Modifier mask `none` (0) see [`SetMods`][SetMods]
`affect` enumeration: - `lock` - `unlock` - `both` - `neither` `both` - `lock`: the action only locks the modifier, but cannot unlock it. - `unlock`: the action only unlocks modifier, but cannot lock it. - `both`: the first key press locks the modifier and the second key press releases the modifier. - `neither`: do not lock nor unlock, i.e. do nothing.
`unlockOnPress` boolean `false` Control whether [locked] modifiers are unlocked on key press or release. See [hereinafter](@ref lock-modifier-action-effects) for further details. @note Available since 1.11, only with `::XKB_KEYMAP_FORMAT_TEXT_V2`.

@todo highlight that there is reference counting for the modifiers, e.g. to manage multiple physical keys for the same modifier.

These actions perform different tasks on key press and on key release:

Effects of modifiers actions @anchor modifier-actions-effects
Action On key press On key release
`SetMods` @anchor latch-modifier-action-effects - If `clearLocks` and `unlockOnPress` are true, unlock the target modifiers. - Adds modifiers to [depressed] modifiers that were not unlocked. - Removes modifiers added on press from [depressed] modifiers, provided that no other key which affects the same modifiers is logically down. - If `clearLocks` is true, `unlockOnPress` is false and no other key were operated simultaneously with this key, then the modifiers will be removed as well from the [locked] modifiers.
`LatchMods` @anchor set-modifier-action-effects - If `unLockOnPress` and `clearLocks` are true and target modifiers were locked, then unlocks them and clear the action. - Otherwise if `latchOnPress` is true, then adds modifiers to the [latched] modifiers. - Otherwise adds modifiers to [depressed] modifiers. - If `latchOnPress` is false, then: - Removes modifiers from [depressed] modifiers. - If no keys were operated simultaneously with the latching modifier key: - If `clearLocks` is true and `unLockOnPress` is false and target modifiers were locked, then unlock then stop here and clear the action. - Otherwise add modifiers to [latched] modifiers. - If `latchToLock` is true and if the target modifiers are latched, then unlatch them and [lock][locked] them. - Latch target modifiers that were not used by `clearLocks` and `latchToLock`. - Otherwise unlatch the target modifiers and clear the action.
`LockMods` @anchor lock-modifier-action-effects - If `unlockOnPress` is true and some of the target modifiers were [locked] before the key press, then unlock them if `noUnlock` false. - Otherwise: - add target modifiers to [depressed] modifiers; - if `noLock` is false, add target modifiers to the [locked] modifiers. - If `unlockOnPress` is true and triggered unlocking on key press, do nothing. - Otherwise: - remove modifiers from the [depressed] modifiers, if no other key that affect the same modifiers is down; - if `noUnlock` is false and if any target modifiers was locked before the key press, *[unlock][locked]* them.

Group actions {#group-actions}

[group action]: @ref group-actions [group actions]: @ref group-actions [SetGroup]: @ref set-group-action [LatchGroup]: @ref latch-group-action [LockGroup]: @ref lock-group-action

There are 3 group actions:

`SetGroup` @anchor set-group-action
Modifies the *base* group.
Parameters
Name Data type Default value Description
`group` Group index: - 1-based numbering - Named constants:
`GroupN`
Denotes the N-th group, e.g. `Group2` is the second group.
`First`
Denotes the *first* group and always equals to `1`. @since 1.14
`Last`
Denotes the *last* group and depends on the keymap setup: e.g. with 3 layouts it equals to 3. @since 1.14
- either absolute (no sign) or relative (`+`/`-` sign)
0 Target group or group delta
`clearLocks` boolean `false` See its use [hereinafter](@ref set-group-action-effects)
`LatchGroup` @anchor latch-group-action
Modifies the *latched* group.
Parameters
Name Data type Default value Description
`group` Group index (see [`SetGroup`][SetGroup]) 0 Target group or group delta
`clearLocks` boolean `false` See its use [hereinafter](@ref latch-group-action-effects)
`latchToLock` boolean `false` See its use [hereinafter](@ref latch-group-action-effects)
`LockGroup` @anchor lock-group-action
Modifies the *locked* group.
Parameters
Name Data type Default value Description
`group` Group index (see [`SetGroup`][SetGroup]) 0 Target group or group delta
`lockOnRelease` @anchor lockOnRelease boolean false Control whether to trigger the group change on key press (default) or release. See further details [hereinafter](@ref lock-group-action-effects) @note Available since 1.11, only with `::XKB_KEYMAP_FORMAT_TEXT_V2`.
Effects of group actions
Action On key press On key release
`SetGroup` @anchor set-group-action-effects - If the `group` parameter is *absolute*, key press events sets the *base* keyboard group to `group`. - Otherwise, it adds `group` to the *base* keyboard group. In either case, the resulting *effective* keyboard group is brought back into range depending on the value of the `GroupsWrap` control for the keyboard. See `xkb_layout_out_of_range_policy` for further details. If *no* keys were operated simultaneously with this key and the `clearLocks` parameter is set, key release also sets the *locked* keyboard group to `Group1`.
`LatchGroup` @anchor latch-group-action-effects Same as `SetGroup`. Same as `SetGroup`. If no keys were operated simultaneously with the latching group key and the `clearLocks` parameter was not set or had no effect, key release has the following additional effects: - If `latchToLock` parameter is set and the *latched* keyboard group is not the first group, the key release adds the *delta* applied by the corresponding key press to the locked keyboard group and subtracts it from the latched keyboard group. The *locked* and *effective* keyboard group are brought back into range according to the value of the global `GroupsWrap` control for the keyboard. See `xkb_layout_out_of_range_policy` for further details. - Otherwise, key release adds the key press *delta* to the latched keyboard group.
`LockGroup` @anchor lock-group-action-effects - If `lockOnRelease` is set, then key press has no effect. - Otherwise: - if the `group` is absolute, key press sets the *locked* keyboard group to `group`; - otherwise, key press adds `group` to the *locked* keyboard group. In either case, the resulting *locked* and *effective* group is brought back into range depending on the value of the `GroupsWrap` control for the keyboard. See `xkb_layout_out_of_range_policy` for further details. - If `lockOnRelease` is not set, then key release has no effect. - Otherwise, if any other key was *pressed* after the locking key, then key release has no effect.
This enables e.g. using `Alt+Shift` combination in any order. - `Shift` down, `Alt` down, `Alt` up, `Shift` up - `Shift` down, `Alt` down, `Shift` up, `Alt` up - `Alt` down, `Shift` down, `Shift` up, `Alt` up - `Alt` down, `Shift` down, `Alt` up, `Shift` up This would not be possible if locking was cancelled by key *release* too.
- Otherwise, it has the same effect than a key press *without* `lockOnRelease` set.

Keyboard controls actions {#kbd-control-actions}

[Keyboard controls action]: @ref kbd-control-actions [SetControls]: @ref set-controls-action [LockControls]: @ref lock-controls-action

`SetControls` @anchor set-controls-action
Set the standard XKB controls
Parameters
Name Alias Data type Default value Description
`controls` `ctrls` Mask of the following enumeration: - `RepeatKeys` - `Repeat` - `AutoRepeat` - `SlowKeys` - `BounceKeys` - `StickyKeys` - `MouseKeys` - `MouseKeysAccel` - `AccessXKeys` - `AccessXTimeout` - `AccessXFeedback` - `AudibleBell` - `IgnoreGroupLock` - [`Overlay1`](@ref XKB_KEYBOARD_CONTROL_OVERLAY1) - [`Overlay2`](@ref XKB_KEYBOARD_CONTROL_OVERLAY2) - Requires `::XKB_KEYMAP_FORMAT_TEXT_V2` and version 1.14+ - [`Overlay3`](@ref XKB_KEYBOARD_CONTROL_OVERLAY3) - [`Overlay4`](@ref XKB_KEYBOARD_CONTROL_OVERLAY4) - [`Overlay5`](@ref XKB_KEYBOARD_CONTROL_OVERLAY5) - [`Overlay6`](@ref XKB_KEYBOARD_CONTROL_OVERLAY6) - [`Overlay7`](@ref XKB_KEYBOARD_CONTROL_OVERLAY7) - [`Overlay8`](@ref XKB_KEYBOARD_CONTROL_OVERLAY8) Plus 2 special values: - `all` - `none` 0 Standard XKB *boolean* controls
`LockControls` @anchor lock-controls-action
Lock the standard XKB controls
Parameters
Name Alias Data type Default value Description
`controls` `ctrls` Mask (see [`SetControls`][SetControls]) 0 Standard XKB *boolean* controls
`affect` enumeration: - `lock` - `unlock` - `both` - `neither` `both` - `lock`: the action only locks the controls, but cannot unlock them. - `unlock`: the action only unlocks controls, but cannot lock them. - `both`: the first key press locks the controls and the second key press releases the controls. - `neither`: do not lock nor unlock, i.e. do nothing.

@warning Only a subset of the original XKB controls are effectual. See xkb_keyboard_control_flags for further details.

Effects of controls actions @anchor controls-actions-effects
Action On key press On key release
`SetControls` @anchor set-controls-action-effects Enable any boolean controls that are specified in `controls` and not already enabled at the time of the key press. Disable any controls that were enabled by the corresponding key press.
`LockControls` @anchor lock-controls-action-effects If `noLock` is false, locks and enables any boolean controls that are specified in `controls` and not already locked at the time of the key press. If `noUnlock` is False, key release unlocks and disables any controls that are specified in `controls` and *were* enabled at the time of the corresponding key press.

Keyboard emulation actions {#kbd-emulation-actions}

RedirectKey {#redirect-key-action}

[Keyboard emulation action]: @ref kbd-emulation-actions [redirectkey]: @ref redirect-key-action

RedirectKey emulates pressing a key with a different key code.

RedirectKey normally redirects to another key on the same device as the key or button which caused the event, else on the core keyboard device.

Parameters
Name Aliases Data type Default value Description
`key` `keycode`, `kc` keycode or `auto`. @anchor redirect-key-auto `auto` is a special value that resolves to the keycode where the action is located, e.g.: ```c // Original: implict parameter key { [RedirectKey(…) ] }; // Original: explicit parameter key { [RedirectKey(keycode=auto, …) ] }; // Resolved key { [RedirectKey(keycode=, …) ] }; ``` `auto` @since 1.0.0: invalid keycode @since 1.14.0: `auto` Target keycode to emulate
`clearmodifiers` `clearmods` modifier mask `none` (0) Modifiers to clear
`modifiers` `mods` modifier mask `none` (0) Modifiers to add
Effects
On key *press* On key *release*
Key press causes a key press event for the key specified by the `key` parameter instead of for the actual key. The state reported in this event reports of the current *effective* modifiers changed as follow: - Modifiers in the `clearmodifiers` parameter are cleared. - Modifiers in the `modifiers` parameter are set. Key release causes a key release event for the key specified by the `key` parameter; the state field for this event consists of the *effective* modifiers at the time of the release, changed as described on the key press.

Legacy X11 actions {#legacy-x11-actions}

[legacy action]: @ref legacy-x11-actions

@attention The following legacy actions are kept for compatibility only: they are parsed and validated but have no effect. This allows to use keymaps defined in xkeyboard-config for both X11 and Wayland.

Pointer actions

`MovePointer`
`MovePtr`
Move the mouse pointer @todo MovePointer parameters
`PointerButton`
`PtrBtn`
Simulate a mouse button press @todo PointerButton parameters
`LockPointerButton`
`LockPointerBtn`
`LockPtrButton`
`LockPtrBtn`
Simulate a mouse button press, locked until this actiion’s key is pressed again @todo LockPointerButton parameters
`SetPointerDefault`
`SetPtrDflt`
Set the default select button (???) @todo SetPointerDefault parameters

Server actions

[TerminateServer]: @ref terminate-server-action

`TerminateServer` @anchor terminate-server-action
Shut down the X server No parameters.
`SwitchScreen`
@todo SwitchScreen

Private action {#private-action}

[Private]: @ref private-action

Raw encoding of an action. Aimed to support arbitrary action unknown to the XKB compiler.

@warning This assumes that the corresponding action’s C struct is laid out in memory exactly as described in the XKB specification and libraries. However, libxkbcommon have changed these structs in various ways, so this assumption is no longer true and the actions defined in the XKB protocol are unsupported.

Parameters
Name Data type Default value Description
`type` integer 0 Action type, as encoded in the XKB protocol
`data` byte array or a string of *exactly 7 bytes* "0000000" Raw byte encoding of the action following the XKB protocol

Examples:

  • Private(type=123, data="abcdefg");
  • Private(type=123, data[1]=0, data[2]=100, data[3]=12);

Unsupported legacy X11 actions {#unsupported-legacy-x11-actions}

[unsupported legacy action]: @ref unsupported-legacy-x11-actions

@attention The following legacy actions are unsupported: they are parsed and but not validated and are then completely ignored.

ISO lock

@todo ISOLock

Device actions

`DeviceButton`
@todo DeviceButton
`LockDeviceButton`
@todo LockDeviceButton
`DeviceValuator`
@todo DeviceValuator

Message

@todo ActionMessage

The “xkb_geometry” section {#the-xkb_geometry-section}

This section aims to describe the physical layout of a keyboard and its main use case is to produce a picture of the keyboard via e.g. the xkbprint program.

@warning libxkbcommon does not support this section: while it can parse the syntax, it does not interpret it; the section is simply dropped so there is no API to query it and the keymap serialization does not contain it.

@sa @ref geometry-support "Compatibility with X11".