# Xkb Client Keyboard Mapping

The Xkb client map for a keyboard is the collection of information a client needs to interpret key events from the keyboard. It contains a global list of key types and an array of key symbol maps, each of which describes the symbols bound to a key and the rules to be used to interpret those symbols.

Figure 15.1 shows the relationships between elements in the client map:

Xkb Client Map

## The XkbClientMapRec Structure

The map field of the complete Xkb keyboard description (see section 6.1) is a pointer to the Xkb client map, which is of type XkbClientMapRec:

    typedef struct {                   /* Client Map */
        unsigned char   size_types;    /* # occupied entries in types */
        unsigned char   num_types;     /* # entries in types */
        XkbKeyTypePtr   types;         /* vector of key types used by this keymap */
        unsigned short  size_syms;     /* length of the syms array */
        unsigned short  num_syms;      /* # entries in syms */
        KeySym *        syms;          /* linear 2d tables of keysyms, 1 per key */
        XkbSymMapPtr    key_sym_map;   /* 1 per keycode, maps keycode to syms */
        unsigned char * modmap;        /* 1 per keycode, real mods bound to key */
    } XkbClientMapRec, *XkbClientMapPtr;

The following sections describe each of the elements of the XkbClientMapRec structure in more detail.

XkbClientMapRec

## Key Types

Key types are used to determine the shift level of a key given the current state of the keyboard. The set of all possible key types for the Xkb keyboard description are held in the types field of the client map, whose total size is stored in size_types, and whose total number of valid entries is stored in num_types. Key types are defined using the following structures:

    typedef struct {                     /* Key Type */
        XkbModsRec        mods;          /* modifiers used to compute shift level */
        unsigned char     num_levels;    /* total # shift levels, do not
                                            modify directly */
        unsigned char     map_count;     /* # entries in map, preserve
                                            (if non-NULL) */
        XkbKTMapEntryPtr  map;           /* vector of modifiers for each
                                            shift level */
        XkbModsPtr        preserve;      /* mods to preserve for
                                            corresponding map entry */
        Atom              name;          /* name of key type */
        Atom *            level_names;   /* array of names of each shift level */
    } XkbKeyTypeRec, *XkbKeyTypePtr;

    typedef struct {                     /* Modifiers for a key type */
        Bool              active;        /* True ⇒ entry active when
                                            determining shift level */
        unsigned char     level;         /* shift level if modifiers match mods */
        XkbModsRec        mods;          /* mods needed for this level to be
                                            selected */
    } XkbKTMapEntryRec, *XkbKTMapEntryPtr;

The mods field of a key type is an XkbModsRec (see section 7.2) specifying the modifiers the key type uses when calculating the shift level, and can be composed of both the core modifiers and virtual modifiers. To set the modifiers associated with a key type, modify the real_mods and vmods fields of the mods XkbModsRec accordingly. The mask field of the XkbModsRec is reserved for use by Xkb and is calculated from the real_mods and vmods fields.

The num_levels field holds the total number of shift levels for the key type. Xkb uses num_levels to ensure the array of symbols bound to a key is large enough. Do not modify num_levels directly to change the number if shift levels for a key type. Instead, use `XkbResizeKeyType` (see section 15.2.3).

The map field is a vector of XkbKTMapEntryRec structures, with map_count entries, that specify the modifier combinations for each possible shift level. Each map entry contains an active field, a mods field, and a level field. The active field determines whether the modifier combination listed in the mods field should be considered when determining shift level. If active is False, this map entry is ignored. If active is True, the level field of the map entry specifies the shift level to use when the current modifier combination matches the combination specified in the mods field of the map entry.

Any combination of modifiers not explicitly listed somewhere in the map yields shift level one. In addition, map entries specifying unbound virtual modifiers are not considered.

Any modifiers specified in mods are normally consumed by `XkbTranslateKeyCode` (see section 12.1.3). For those rare occasions a modifier should be considered despite having been used to look up a symbol, key types include an optional preserve field. If a preserve member of a key type is not NULL, it represents a list of modifiers where each entry corresponds directly to one of the key type’s map. Each entry lists the modifiers that should not be consumed if the matching map entry is used to determine shift level.

Each shift level has a name and these names are held in the level_names array, whose length is num_levels. The type itself also has a name, which is held in the name field.

For example, consider how the server handles the following possible symbolic description of a possible key type (note that the format used to specify keyboard mappings in the server database is not specified by the Xkb extension, although this format is one possible example):

Example Key Type

Symbolic Description | Key Type Data Structure
--- | ---
type "ALPHATHREE" { | Xkb->map->types[i].name
modifiers = Shift+Lock+LevelThree; | Xkb->map->types[i].mods
map[None]= Level1; | Xkb->map->types[i].map[0]
map[Lock]= Level1; | Xkb->map->types[i].map[1]
map[Shift]= Level2; | Xkb->map->types[i].map[2]
map[LevelThree]= Level3; | Xkb->map->types[i].map[3]
map[Shift+LevelThree]= Level3; | Xkb->map->types[i].map[4]
preserve[None]= None; | Xkb->map->types[i].preserve[0]
preserve[Lock]= Lock; | Xkb->map->types[i].preserve[1]
preserve[Shift]= None; | Xkb->map->types[i].preserve[2]
preserve[LevelThree]= None; | Xkb->map->types[i].preserve[3]
preserve[Shift+Level3]= None; | Xkb->map->types[i].preserve[4]
level_name[Level1]= "Base"; | Xkb->map->types[i].level_names[0]
level_name[Level2]= "Caps"; | Xkb->map->types[i].level_names[1]
level_name[Level3]= "Level3"; | Xkb->map->types[i].level_names[2]
}; |

The name of the example key type is "ALPHATHREE," and the modifiers it pays attention to are Shift, Lock, and the virtual modifier LevelThree. There are three shift levels. The name of shift level one is "Base," the name of shift level two is "Caps," and the name of shift level three is "Level3."

Given the combination of the map and preserve specifications, there are five map entries. The first map entry specifies that shift level one is to be used if no modifiers are set. The second entry specifies the Lock modifier alone also yields shift level one. The third entry specifies the Shift modifier alone yields shift level two. The fourth and fifth entries specify that the virtual LevelThree modifier alone, or in combination with the Shift modifier, yields shift level three.

Shift level three can be reached only if the virtual modifier LevelThree is bound to a real modifier (see section 16.4). If LevelThree is not bound to a real modifier, the map entries associated with it are ignored.

Because the Lock modifier is to be preserved for further event processing, the preserve list is not NULL and parallels the map list. All preserve entries, except for the one corresponding to the map entry that specifies the Lock modifier, do not list any modifiers. For the map entry that specifies the Lock modifier, the corresponding preserve list entry lists the Lock modifier, meaning do not consume the Lock modifier. In this particular case, the preserved modifier is passed to Xlib translation functions and causes them to notice that the Lock modifier is set; consequently, the Xlib functions apply the appropriate capitalization rules to the symbol. Because this preserve entry is set only for a modifier that yields shift level one, the capitalization occurs only for level-one symbols.

### The Canonical Key Types

Xkb allows up to XkbMaxKeyTypes (255) key types to be defined, but requires at least XkbNumRequiredTypes (4) predefined types to be in a key map. These predefined key types are referred to as the canonical key types and describe the types of keys available on most keyboards. The definitions for the canonical key types are held in the first XkbNumRequiredTypes entries of the types field of the client map and are indexed using the following constants:

- XkbOneLevelIndex
- XkbTwoLevelIndex
- XkbAlphabeticIndex
- XkbKeypadIndex

#### ONE_LEVEL

The ONE_LEVEL key type describes groups that have only one symbol. The default ONE_LEVEL key type has no map entries and does not pay attention to any modifiers. A symbolic representation of this key type could look like the following:

        type "ONE_LEVEL" {
              modifiers = None;
              map[None]= Level1;
              level_name[Level1]= "Any";
        };

The description of the ONE_LEVEL key type is stored in the types [ XkbOneLevelIndex ] entry of the client key map.

#### TWO_LEVEL

The TWO_LEVEL key type describes groups that consist of two symbols but are neither alphabetic nor numeric keypad keys. The default TWO_LEVEL type uses only the Shift modifier. It returns shift level two if Shift is set, and level one if it is not. A symbolic representation of this key type could look like the following:

        type "TWO_LEVEL" {
              modifiers = Shift;
              map[Shift]= Level2;
              level_name[Level1]= "Base";
              level_name[Level2]= "Shift";
        };

The description of the TWO_LEVEL key type is stored in the types [ XkbTwoLevelIndex ] entry of the client key map.

#### ALPHABETIC

The ALPHABETIC key type describes groups consisting of two symbols: the lowercase form of a symbol followed by the uppercase form of the same symbol. The default ALPHABETIC type implements locale-sensitive Shift cancels CapsLock behavior using both the Shift and Lock modifiers as follows:

- If Shift and Lock are both set, the default ALPHABETIC type yields level one.

- If Shift alone is set, it yields level two.

- If Lock alone is set, it yields level one, but preserves the Lock modifier so Xlib notices and applies the appropriate capitalization rules. The Xlib functions are locale-sensitive and apply different capitalization rules for different locales.

- If neither Shift nor Lock is set, it yields level one.

A symbolic representation of this key type could look like the following:

        type "ALPHABETIC" {
              modifiers = Shift+Lock;
              map[Shift]= Level2;
              preserve[Lock]= Lock;
              level_name[Level1]= "Base";
              level_name[Level2]= "Caps";
        };

The description of the ALPHABETIC key type is stored in the types [ XkbAlphabeticIndex ] entry of the client key map.

#### KEYPAD

The KEYPAD key type describes groups that consist of two symbols, at least one of which is a numeric keypad symbol. The numeric keypad symbol is assumed to reside at level two. The default KEYPAD key type implements Shift cancels NumLock behavior using the Shift modifier and the real modifier bound to the virtual modifier named NumLock, known as the NumLock modifier, as follows:

- If Shift and NumLock are both set, the default KEYPAD type yields level one.

- If Shift alone is set, it yields level two.

- If NumLock alone is set, it yields level two.

- If neither Shift nor NumLock is set, it yields level one.

A symbolic representation of this key type could look like the following:

        type "KEYPAD" {
              modifiers = Shift+NumLock;
              map[None]= Level1;
              map[Shift]= Level2;
              map[NumLock]= Level2;
              map[Shift+NumLock]= Level1;
              level_name[Level1]= "Base";
              level_name[Level2]= "Caps";
        };

The description of the KEYPAD key type is stored in the types [ XkbKeypadIndex ] entry of the client key map.

#### Initializing the Canonical Key Types in a New Client Map

To set the definitions of the canonical key types in a client map to their default values, use `XkbInitCanonicalKeyTypes`.

Status `XkbInitCanonicalKeyTypes` XkbDescPtr xkb unsigned int which int keypadVMod

xkb

  keyboard description containing client map to initialize

which

  mask of types to initialize

keypadVMod

  index of NumLock virtual modifier

`XkbInitCanonicalKeyTypes` initializes the first XkbNumRequiredTypes key types of the keyboard specified by the xkb parameter to their default values. The which parameter specifies what canonical key types to initialize and is a bitwise inclusive OR of the following masks: XkbOneLevelMask, XkbTwoLevelMask, XkbAlphabeticMask, and XkbKeypadMask. Only those canonical types specified by the which mask are initialized.

If XkbKeypadMask is set in the which parameter, `XkbInitCanonicalKeyTypes` looks up the NumLock named virtual modifier to determine which virtual modifier to use when initializing the KEYPAD key type. If the NumLock virtual modifier does not exist, `XkbInitCanonicalKeyTypes` creates it.

`XkbInitCanonicalKeyTypes` normally returns Success. It returns BadAccess if the Xkb extension has not been properly initialized, and BadAccess if the xkb parameter is not valid.

XkbInitCanonicalKeyTypes

### Getting Key Types from the Server

To obtain the list of available key types in the server’s keyboard mapping, use `XkbGetKeyTypes`.

Status `XkbGetKeyTypes` Display *dpy unsigned int first unsigned int num XkbDescPtr xkb

dpy

  connection to X server

first

  index to first type to get, 0 ⇒ 1st type

num

  number of key types to be returned

xkb

  keyboard description containing client map to update

`XkbGetKeyTypes` is used to obtain descriptions of the key types themselves, not the key types bound to individual keys. To obtain the key types bound to an individual key, refer to the key_sym_map field of the client map (see section 15.3.1).

`XkbGetKeyTypes` queries the server for the desired types, waits for a reply, and returns the desired types in the xkb->map->types. If successful, it returns Success.

`XkbGetKeyTypes` returns BadAccess if the Xkb extension has not been properly initialized and BadValue if the combination of first and num results in numbers out of valid range.

XkbGetKeyTypes

### Changing the Number of Levels in a Key Type

To change the number of levels in a key type, use `XkbResizeKeyType`.

Status `XkbResizeKeyType` XkbDescPtr xkb int type_ndx int map_count Bool want_preserve int new_num_lvls

xkb

  keyboard description containing client map to update

type_ndx

  index in xkb->map->types of type to change

map_count

  total # of map entries needed for the type

want_preserve

  True ⇒ list of preserved modifiers is necessary

new_num_lvls

  new max # of levels for type

`XkbResizeKeyType` changes the type specified by xkb->map->types [ type_ndx ], and reallocates the symbols and actions bound to all keys that use the type, if necessary. `XkbResizeKeyType` updates only the local copy of the types in xkb; to update the server’s copy for the physical device, use `XkbSetMap` or `XkbChangeMap` after calling `XkbResizeKeyType`.

The map_count parameter specifies the total number of map entries needed for the type, and can be zero or greater. If map_count is zero, `XkbResizeKeyType` frees the existing map and preserve entries for the type if they exist and sets them to NULL.

The want_preserve parameter specifies whether a preserve list for the key should be created. If want_preserve is True, the preserve list with map_count entries is allocated or reallocated if it already exists. Otherwise, if want_preserve is False, the preserve field is freed if necessary and set to NULL.

The new_num_lvls parameter specifies the new maximum number of shift levels for the type and is used to calculate and resize the symbols and actions bound to all keys that use the type.

If type_ndx does not specify a legal type, new_num_lvls is less than 1, or the map_count is less than zero, `XkbResizeKeyType` returns BadValue. If `XkbResizeKeyType` encounters any problems with allocation, it returns BadAlloc. Otherwise, it returns Success.

XkbResizeKeyType

### Copying Key Types

Use `XkbCopyKeyType` and `XkbCopyKeyTypes` to copy one or more XkbKeyTypeRec structures.

Status `XkbCopyKeyType` XkbKeyTypePtr from XkbKeyTypePtr into

from

  pointer to XkbKeyTypeRec to be copied

into

  pointer to XkbKeyTypeRec to be changed

`XkbCopyKeyType` copies the key type specified by from to the key type specified by into. Both must point to legal XkbKeyTypeRec structures. Xkb assumes from and into point to different places. As a result, overlaps can be fatal. `XkbCopyKeyType` frees any existing map, preserve, and level_names in into prior to copying. If any allocation errors occur while copying from to into, `XkbCopyKeyType` returns BadAlloc. Otherwise, `XkbCopyKeyType` copies from to into and returns Success.

Status `XkbCopyKeyTypes` XkbKeyTypePtr from XkbKeyTypePtr into int num_types

from

  pointer to array of XkbKeyTypeRecs to copy

into

  pointer to array of XkbKeyTypeRecs to change

num_types

  number of types to copy

`XkbCopyKeyTypes` copies num_types XkbKeyTypeRec structures from the array specified by from into the array specified by into. It is intended for copying between, rather than within, keyboard descriptions, so it doesn’t check for overlaps. The same rules that apply to the from and into parameters in `XkbCopyKeyType` apply to each entry of the from and into arrays of `XkbCopyKeyTypes`. If any allocation errors occur while copying from to into, `XkbCopyKeyTypes` returns BadAlloc. Otherwise, `XkbCopyKeyTypes` copies from to into and returns Success.

XkbCopyKeyType
XkbCopyKeyTypes
XkbKeyTypeRec
XkbKTMapEntryRec

## Key Symbol Map

The entire list of key symbols for the keyboard mapping is held in the syms field of the client map. Whereas the core keyboard mapping is a two-dimensional array of KeySyms whose rows are indexed by keycode, the syms field of Xkb is a linear list of KeySyms that needs to be indexed uniquely for each key. This section describes the key symbol map and the methods for determining the symbols bound to a key.

The reason the syms field is a linear list of KeySyms is to reduce the memory consumption associated with a keymap; because Xkb allows individual keys to have multiple shift levels and a different number of groups per key, a single two-dimensional array of KeySyms would potentially be very large and sparse. Instead, Xkb provides a small two-dimensional array of KeySyms for each key. To store all of these individual arrays, Xkb concatenates each array together in the syms field of the client map.

In order to determine which KeySyms in the syms field are associated with each keycode, the client map contains an array of key symbol mappings, held in the key_sym_map field. The key_sym_map field is an array of XkbSymMapRec structures indexed by keycode. The key_sym_map array has min_key_code unused entries at the start to allow direct indexing using a keycode. All keycodes falling between the minimum and maximum legal keycodes, inclusive, have key_sym_map arrays, whether or not any key actually yields that code. The KeySymMapRec structure is defined as follows:

    #define XkbNumKbdGroups            4
    #define XkbMaxKbdGroup            (XkbNumKbdGroups-1)

    typedef struct {                 /* map to keysyms for a single keycode */
        unsigned char     kt_index[XkbNumKbdGroups];
                                             /* key type index for each group */
        unsigned char     group_info;        /* # of groups and out of range
                                                group handling */
        unsigned char     width;             /* max # of shift levels for key */
        unsigned short    offset;            /* index to keysym table in
                                                syms array */
    } XkbSymMapRec, *XkbSymMapPtr;

These fields are described in detail in the following sections.

### Per-Key Key Type Indices

The kt_index array of the XkbSymMapRec structure contains the indices of the key types (see section 15.2) for each possible group of symbols associated with the key. To obtain the index of a key type or the pointer to a key type, Xkb provides the following macros, to access the key types:

The array of key types is of fixed width and is large enough to hold key types for the maximum legal number of groups (XkbNumKbdGroups, currently four); if a key has fewer than XkbNumKbdGroups groups, the extra key types are reported but ignored.

int `XkbKeyKeyTypeIndex` XkbDescPtr xkb KeyCode keycode int group

xkb

  Xkb description of interest

keycode

  keycode of interest

group

  group index

`XkbKeyKeyTypeIndex` computes an index into the types vector of the client map in xkb from the given keycode and group index.

XkbKeyTypePtr `XkbKeyKeyType` XkbDescPtr xkb KeyCode keycode int group

xkb

  Xkb description of interest

keycode

  keycode of interest

group

  group index

`XkbKeyKeyType` returns a pointer to the key type in the types vector of the client map in xkb corresponding to the given keycode and group index.

XkbKeyKeyTypeIndex
XkbKeyKeyType

### Per-Key Group Information

The group_info field of an XkbSymMapRec is an encoded value containing the number of groups of symbols bound to the key as well as the specification of the treatment of out-of-range groups. It is legal for a key to have zero groups, in which case it also has zero symbols and all events from that key yield NoSymbol. To obtain the number of groups of symbols bound to the key, use `XkbKeyNumGroups`. To change the number of groups bound to a key, use `XkbChangeTypesOfKey` (see section 15.3.6). To obtain a mask that determines the treatment of out-of-range groups, use `XkbKeyGroupInfo` and `XkbOutOfRangeGroupInfo`.

The keyboard controls (see ) contain a groups_wrap field specifying the handling of illegal groups on a global basis. That is, when the user performs an action causing the effective group to go out of the legal range, the groups_wrap field specifies how to normalize the effective keyboard group to a group that is legal for the keyboard as a whole, but there is no guarantee that the normalized group will be within the range of legal groups for any individual key. The per-key group_info field specifies how a key treats a legal effective group if the key does not have a type specified for the group of concern. For example, the Enter key usually has just one group defined. If the user performs an action causing the global keyboard group to change to Group2, the group_info field for the Enter key describes how to handle this situation.

Out-of-range groups for individual keys are mapped to a legal group using the same options as are used for the overall keyboard group. The particular type of mapping used is controlled by the bits set in the group_info flag, as shown in Table 15.2. See section 10.7.1 for more details on the normalization methods in this table.

group_info Range Normalization

Bits set in group_info | Normalization method
--- | ---
XkbRedirectIntoRange | XkbRedirectIntoRange
XkbClampIntoRange | XkbClampIntoRange
none of the above | XkbWrapIntoRange

Xkb provides the following macros to access group information:

int `XkbKeyNumGroups` XkbDescPtr xkb KeyCode keycode

xkb

  Xkb description of interest

keycode

  keycode of interest

`XkbKeyNumGroups` returns the number of groups of symbols bound to the key corresponding to keycode.

unsigned char `XkbKeyGroupInfo` XkbDescPtr xkb KeyCode keycode

xkb

  Xkb description of interest

keycode

  keycode of interest

`XkbKeyGroupInfo` returns the group_info field from the XkbSymMapRec structure associated with the key corresponding to keycode.

unsigned char `XkbOutOfRangeGroupInfo` unsigned char grp_inf

grp_inf

  group_info field of XkbSymMapRec

`XkbOutOfRangeGroupInfo` returns only the out-of-range processing information from the group_info field of an XkbSymMapRec structure.

unsigned char `XkbOutOfRangeGroupNumber` unsigned char grp_inf

grp_inf

  group_info field of XkbSymMapRec

`XkbOutOfRangeGroupNumber` returns the out-of-range group number, represented as a group index, from the group_info field of an XkbSymMapRec structure.

XkbKeyNumGroups
XkbKeyGroupInfo
XkbOutOfRangeGroupInfo
XkbOutOfRangeGroupNumber

### Key Width

The maximum number of shift levels for a type is also referred to as the width of a key type. The width field of the key_sym_map entry for a key contains the width of the widest type associated with the key. The width field cannot be explicitly changed; it is updated automatically whenever the symbols or set of types bound to a key are changed.

### Offset in to the Symbol Map

The key width and number of groups associated with a key are used to form a small two-dimensional array of KeySyms for a key. This array may be different sizes for different keys. The array for a single key is stored as a linear list, in row-major order. The arrays for all of the keys are stored in the syms field of the client map. There is one row for each group associated with a key and one column for each level. The index corresponding to a given group and shift level is computed as:

         idx = group_index * key_width + shift_level

The offset field of the key_sym_map entry for a key is used to access the beginning of the array.

Xkb provides the following macros for accessing the width for individual keys, as well as macros for accessing the two-dimensional array of symbols bound to the key:

int `XkbKeyGroupsWidth` XkbDescPtr xkb KeyCode keycode

xkb

  Xkb description of interest

keycode

  keycode of interest

`XkbKeyGroupsWidth` computes the maximum width associated with the key corresponding to keycode.

int `XkbKeyGroupWidth` XkbDescPtr xkb KeyCode keycode int grp

xkb

  Xkb description of interest

keycode

  keycode of interest

grp

  group of interest

`XkbKeyGroupWidth` computes the width of the type associated with the group grp for the key corresponding to keycode.

int `XkbKeyNumSyms` XkbDescPtr xkb KeyCode keycode

xkb

  Xkb description of interest

keycode

  keycode of interest

`XkbKeyNumSyms` returns the total number of keysyms for the key corresponding to keycode.

KeySym *`XkbKeySymsPtr` XkbDescPtr xkb KeyCode keycode

xkb

  Xkb description of interest

keycode

  keycode of interest

`XkbKeySymsPtr` returns the pointer to the two-dimensional array of keysyms for the key corresponding to keycode.

KeySym `XkbKeySymEntry` XkbDescPtr xkb KeyCode keycode int shift int grp

xkb

  Xkb description of interest

keycode

  keycode of interest

shift

  shift level of interest

grp

  group of interest

`XkbKeySymEntry` returns the KeySym corresponding to shift level shift and group grp from the two-dimensional array of keysyms for the key corresponding to keycode

XkbKeyGroupsWidth
XkbKeyGroupWidth
XkbKeyNumSyms
XkbKeySymsPtr
XkbKeySymEntry

### Getting the Symbol Map for Keys from the Server

To obtain the symbols for a subset of the keys in a keyboard description, use `XkbGetKeySyms`:

Status `XkbGetKeySyms` Display *dpy unsigned int first unsigned int num XkbDescPtr xkb

dpy

  connection to X server

first

  keycode of first key to get

num

  number of keycodes for which syms desired

xkb

  Xkb description to be updated

`XkbGetKeySyms` sends a request to the server to obtain the set of keysyms bound to num keys starting with the key whose keycode is first. It waits for a reply and returns the keysyms in the map.syms field of xkb. If successful, `XkbGetKeySyms` returns Success. The xkb parameter must be a pointer to a valid Xkb keyboard description.

If the client map in the xkb parameter has not been allocated, `XkbGetKeySyms` allocates and initializes it before obtaining the symbols.

If a compatible version of Xkb is not available in the server or the Xkb extension has not been properly initialized, `XkbGetKeySyms` returns BadAccess. If num is less than 1 or greater than XkbMaxKeyCount, `XkbGetKeySyms` returns BadValue. If any allocation errors occur, `XkbGetKeySyms` returns BadAlloc.

XkbGetKeySyms

### Changing the Number of Groups and Types Bound to a Key

To change the number of groups and the types bound to a key, use `XkbChangeTypesOfKey`.

Status `XkbChangeTypesOfKey` XkbDescPtr xkb int key int n_groups unsigned int groups int *new_types_in XkbMapChangesPtr p_changes

xkb

  keyboard description to be changed

key

  keycode for key of interest

n_groups

  new number of groups for key

groups

  mask indicating groups to change

new_types_in

  indices for new groups specified in groups

p_changes

  notes changes made to xkb

`XkbChangeTypesOfKey` reallocates the symbols and actions bound to the key, if necessary, and initializes any new symbols or actions to NoSymbol or NoAction, as appropriate. If the p_changes parameter is not NULL, `XkbChangeTypesOfKey` adds the XkbKeySymsMask to the changes field of p_changes and modifies the first_key_sym and num_key_syms fields of p_changes to include the key that was changed. See section 14.3.1 for more information on the XkbMapChangesPtr structure. If successful, `XkbChangeTypesOfKey` returns Success.

The n_groups parameter specifies the new number of groups for the key. The groups parameter is a mask specifying the groups for which new types are supplied and is a bitwise inclusive OR of the following masks: XkbGroup1Mask, XkbGroup2Mask, XkbGroup3Mask, and XkbGroup4Mask.

The new_types_in parameter is an integer array of length n_groups. Each entry represents the type to use for the associated group and is an index into xkb->map->types. The new_types_in array is indexed by group index; if n_groups is four and groups only has XkbGroup1Mask and XkbGroup3Mask set, new_types_in looks like this:

         new_types_in[0] = type for Group1
         new_types_in[1] = ignored
         new_types_in[2] = type for Group3
         new_types_in[3] = ignored

For convenience, Xkb provides the following constants to use as indices to the groups:

Group Index Constants

Constant Name | Value
--- | ---
XkbGroup1Index | 0
XkbGroup2Index | 1
XkbGroup3Index | 2
XkbGroup4Index | 3

If the Xkb extension has not been properly initialized, `XkbChangeTypesOfKey` returns BadAccess. If the xkb parameter it not valid (that is, it is NULL or it does not contain a valid client map), `XkbChangeTypesOfKey` returns BadMatch. If the key is not a valid keycode, n_groups is greater than XkbNumKbdGroups, or the groups mask does not contain any of the valid group mask bits, `XkbChangeTypesOfKey` returns BadValue. If it is necessary to resize the key symbols or key actions arrays and any allocation errors occur, `XkbChangeTypesOfKey` returns BadAlloc.

XkbChangeTypesOfKey

### Changing the Number of Symbols Bound to a Key

To change the number of symbols bound to a key, use `XkbResizeKeySyms`.

KeySym *`XkbResizeKeySyms` XkbDescRec *xkb int key int needed

xkb

  keyboard description to be changed

key

  keycode for key to modify

needed

  new number of keysyms required for key

`XkbResizeKeySyms` reserves the space needed for needed keysyms and returns a pointer to the beginning of the new array that holds the keysyms. It adjusts the offset field of the key_sym_map entry for the key if necessary and can also change the syms, num_syms, and size_syms fields of xkb->map if it is necessary to reallocate the syms array. `XkbResizeKeySyms` does not modify either the width or number of groups associated with the key.

If needed is greater than the current number of keysyms for the key, `XkbResizeKeySyms` initializes all new keysyms in the array to NoSymbol.

Because the number of symbols needed by a key is normally computed as width * number of groups, and `XkbResizeKeySyms` does not modify either the width or number of groups for the key, a discrepancy exists upon return from `XkbResizeKeySyms` between the space allocated for the keysyms and the number required. The unused entries in the list of symbols returned by `XkbResizeKeySyms` are not preserved across future calls to any of the map editing functions, so you must update the key symbol mapping (which updates the width and number of groups for the key) before calling another allocator function. A call to `XkbChangeTypesOfKey` will update the mapping.

If any allocation errors occur while resizing the number of symbols bound to the key, `XkbResizeKeySyms` returns NULL.

A change to the number of symbols bound to a key should be accompanied by a change in the number of actions bound to a key. Refer to section 16.1.16 for more information on changing the number of actions bound to a key.

XkbResizeKeySyms
XkbSymMapRec

## The Per-Key Modifier Map

The modmap entry of the client map is an array, indexed by keycode, specifying the real modifiers bound to a key. Each entry is a mask composed of a bitwise inclusive OR of the legal real modifiers: ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask. If a bit is set in a modmap entry, the corresponding key is bound to that modifier.

Pressing or releasing the key bound to a modifier changes the modifier set and unset state. The particular manner in which the modifier set and unset state changes is determined by the behavior and actions assigned to the key (see ).

### Getting the Per-Key Modifier Map from the Server

To update the modifier map for one or more of the keys in a keyboard description, use `XkbGetKeyModifierMap`.

Status `XkbGetKeyModifierMap` Display *dpy unsigned int first unsigned int num XkbDescPtr xkb

dpy

  connection to X server

first

  keycode of first key to get

num

  number of keys for which information is desired

xkb

  keyboard description to update

`XkbGetKeyModifierMap` sends a request to the server for the modifier mappings for num keys starting with the key whose keycode is first. It waits for a reply and places the results in the xkb->map->modmap array. If successful, `XkbGetKeyModifierMap` returns Success.

If the map component of the xkb parameter has not been allocated, `XkbGetKeyModifierMap` allocates and initializes it.

If a compatible version of Xkb is not available in the server or the Xkb extension has not been properly initialized, `XkbGetKeySyms` returns BadAccess. If any allocation errors occur while obtaining the modifier map, `XkbGetKeyModifierMap` returns BadAlloc.

XkbGetKeyModifierMap
client map
map client