3 Contexts and Keymaps
dxtr edited this page 2026-10-18 15:10:49 +02:00

Contexts and Keymaps

Contexts

A context is where keymaps and compose tables are compiled. It knows where the system keeps keymap data, and it collects what libxkbcommon logs while compiling.

(xkb:with-context (context)
  ...)

;; or, for a context that outlives one dynamic extent:
(defvar *context* (xkb:make-context))
...
(xkb:destroy-context *context*)

make-context takes three keyword arguments. The first two are true by default:

Argument When true When false
:default-includes keymap data is found where the system keeps it, such as /usr/share/X11/xkb no include paths; only keymaps from text can be compiled
:environment names left out of make-keymap come from XKB_DEFAULT_RULES, XKB_DEFAULT_MODEL, XKB_DEFAULT_LAYOUT, XKB_DEFAULT_VARIANT and XKB_DEFAULT_OPTIONS names left out are libxkbcommon's built-in defaults, which is repeatable

Use :environment nil in tests, and wherever a keymap must not depend on the user's environment.

The third, :log-limit, is the most log messages the context keeps for take-log-messages, 100 by default. See Errors and Logging.

One context is enough for a whole program. Destroying it does not destroy the keymaps and compose tables made in it.

Keymaps from layout names

make-keymap compiles a keymap from RMLVO names (see Concepts):

(xkb:make-keymap context :layout "se")
(xkb:make-keymap context :layout "us" :variant "dvorak")
(xkb:make-keymap context :layout "us,se")               ; two layouts
(xkb:make-keymap context :layout "us,se" :variant ",nodeadkeys")
(xkb:make-keymap context :layout "us" :options "ctrl:nocaps,compose:ralt")
(xkb:make-keymap context)                                ; all defaults

All the arguments are strings or nil. Where several layouts are given, :variant lists one variant per layout, separated by commas. Names left out are the defaults, as described above.

with-keymap takes the same arguments and destroys the keymap afterwards:

(xkb:with-keymap (keymap context :layout "se" :variant "nodeadkeys")
  ...)

If the names make no keymap, make-keymap signals an xkb-error, which includes what libxkbcommon logged:

libxkbcommon could not compile a keymap for layout "nosuchlayout".  libxkbcommon said:
    error: [XKB-338] Couldn't find file "symbols/nosuchlayout" in include paths
    ...

To find the names available on a system, look in /usr/share/X11/xkb/rules/evdev.lst, or run localectl list-x11-keymap-layouts.

Keymaps from text

make-keymap-from-string compiles a keymap from the XKB text format. A Wayland compositor sends this text in wl_keyboard.keymap, and keymap-string writes it:

(let* ((text (xkb:keymap-string keymap))   ; "xkb_keymap {\nxkb_keycodes ..."
       (copy (xkb:make-keymap-from-string context text)))
  ...)

Use this to receive the keymap a compositor uses, to send a keymap somewhere else, or to save one to a file. The Recipes page shows the Wayland case.

Asking a keymap about itself

(xkb:with-context (context :environment nil)
  (xkb:with-keymap (keymap context :layout "us,se")
    (xkb:keymap-layouts keymap)
    ;; => ("English (US)" "Swedish")

    (xkb:keymap-modifiers keymap)
    ;; => ("Shift" "Lock" "Control" "Mod1" "Mod2" "Mod3" "Mod4" "Mod5"
    ;;     "NumLock" "Alt" "LevelThree" "Super" "LevelFive" "Meta" "Hyper" "ScrollLock")

    (xkb:keymap-modifier-p keymap :super)    ; => T
    (xkb:keymap-modifier-p keymap "Mod3")    ; => T

    (xkb:keymap-keycode-range keymap)        ; => 9, 709

    (xkb:key-name keymap 38)                 ; => "AC01"
    (xkb:find-key keymap "RTRN")             ; => 36
    (xkb:find-key keymap "NOPE")             ; => NIL

    (xkb:key-repeats-p keymap 38)            ; => T, A repeats
    (xkb:key-repeats-p keymap 50)))          ; => NIL, Shift does not
Function Returns
keymap-layouts the layout names, in index order
keymap-modifiers the modifier names, in index order: modifier n is bit n of a modifier mask
keymap-modifier-p whether the keymap has a modifier, given as a keyword or a name
keymap-keycode-range two values: the least and the greatest keycode the keymap may use
key-name the key name of a keycode, or nil
find-key the keycode of a key name, or nil
key-repeats-p whether a key should repeat while it is held
keymap-string the keymap in the text format

The modifier list depends on the keymap and on the libxkbcommon version. Do not hard-code modifier indices. Find them with keymap-modifiers, or name modifiers by keyword.

key-repeats-p only says whether a key repeats. Repeating it is the application's job: see Recipes.

Changing keymaps

A keymap cannot be changed after it is compiled. When the layout changes, or a Wayland compositor sends a new keymap, compile a new keymap. Then make a new keyboard state for it, and destroy the old keymap and keyboard state.