# 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.

## 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].perserve[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 ( xkb, which, keypadVMod )
XkbDescPtr xkb ; /* keyboard description containing client map to initialize */
unsigned int which ; /* mask of types to initialize */
int 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.

### Getting Key Types from the Server

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

Status XkbGetKeyTypes ( dpy , first , num , xkb )
Display * dpy ; /* connection to X server */
unsigned int first ; /* index to first type to get, 0 => 1st type */
unsigned int num ; /* number of key types to be returned */
XkbDescPtr 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.

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

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

Status XkbResizeKeyType ( xkb , type_ndx , map_count , want_preserve , new_num_lvls )
XkbDescPtr xkb ; /* keyboard description containing client map to update */
int type_ndx ; /* index in xkb->map->types of type to change */
int map_count ; /* total # of map entries needed for the type */
Bool want_preserve ; /* True => list of preserved modifiers is necessary */
int 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 .

### Copying Key Types

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

Status XkbCopyKeyType ( from , into )
XkbKeyTypePtr from ; /* pointer to XkbKeyTypeRec to be copied */
XkbKeyTypePtr 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 ( from , into , num_types )
XkbKeyTypePtr from ; /* pointer to array of XkbKeyTypeRecs to copy */
XkbKeyTypePtr into ; /* pointer to array of XkbKeyTypeRecs to change */
int 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 .

## 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 XkbKeyTypeIndex ( xkb, keycode, group ) /* macro*/
XkbDescPtr xkb ; /* Xkb description of interest */
KeyCode keycode ; /* keycode of interest */
int group ; /* group index */

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

XkbKeyTypePtr XkbKeyType ( xkb, keycode, group ) /* macro */
XkbDescPtr xkb ; /* Xkb description of interest */
KeyCode keycode ; /* keycode of interest */
int group ; /* group index */

XkbKeyType 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.

### 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 Chapter 10) 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 ( xkb, keycode ) /* macro */
XkbDescPtr xkb ; /* Xkb description of interest */
KeyCode keycode ; /* keycode of interest */

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

unsigned char XkbKeyGroupInfo ( xkb, keycode ) /*macro */
XkbDescPtr xkb ; /* Xkb description of interest */
KeyCode keycode ; /* keycode of interest */

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

unsigned char XkbOutOfRangeGroupInfo ( grp_inf ) /* macro */
unsigned char 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 ( grp_inf ) /* macro */
unsigned char 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.

### 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 and offset for individual keys, as well as macros for accessing the two-dimensional array of symbols bound to the key:

int XkbKeyGroupsWidth ( xkb, keycode ) /* macro */
XkbDescPtr xkb ; /* Xkb description of interest */
KeyCode keycode ; /* keycode of interest */

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

int XkbKeyGroupWidth ( xkb, keycode, grp ) /* macro */
XkbDescPtr xkb ; /* Xkb description of interest */
KeyCode keycode ; /* keycode of interest */
int grp ; /* group of interest */

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

int XkbKeySymsOffset ( xkb, keycode ) /* macro */
XkbDescPtr xkb ; /* Xkb description of interest */
KeyCode keycode ; /* keycode of interest */

XkbKeySymsOffset returns the offset of the two-dimensional array of keysyms for the key corresponding to keycode .

int XkbKeyNumSyms ( xkb, keycode ) /* macro */
XkbDescPtr xkb ; /* Xkb description of interest */
KeyCode keycode ; /* keycode of interest */

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

KeySym * XkbKeySymsPtr ( xkb, keycode ) /* macro */
XkbDescPtr xkb ; /* Xkb description of interest */
KeyCode keycode ; /* keycode of interest */

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

KeySym XkbKeySymEntry ( xkb, keycode, shift, grp ) /* macro */
XkbDescPtr xkb ; /* Xkb description of interest */
KeyCode keycode ; /* keycode of interest */
int shift ; /* shift level of interest */
int 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

### 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 ( dpy , first , num , xkb )
Display * dpy ; /* connection to X server */
unsigned int first ; /* keycode of first key to get */
unsigned int num ; /* number of keycodes for which syms desired */
XkbDescPtr 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 .

### 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 ( xkb , key , n_groups , groups , new_types_in , p_changes )

XkbDescPtr xkb ; /* keyboard description to be changed */
int key ; /* keycode for key of interest */
int n_groups ; /* new number of groups for key */
unsigned int groups ; /* mask indicating groups to change */
int * new_types_in ; /* indices for new groups specified in groups */
XkbMapChangesPtr 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 Group1Mask and Group3Mask 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 Bad Match. 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 .

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

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

KeySym * XkbResizeKeySyms ( xkb , key , needed )
XkbDescRec * xkb ; /* keyboard description to be changed */
int key ; /* keycode for key to modify */
int 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.

## 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 Chapter 16).

### 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 ( dpy , first , num , xkb )
Display * dpy ; /* connection to X server */
unsigned int first ; /* keycode of first key to get */
unsigned int num ; /* number of keys for which information is desired */
XkbDescPtr 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, XkbGetKeyModifier 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 .