The Xkb Compatibility Map As shown in Figure 17.1, the X server is normally dealing with more than one client, each of which may be receiving events from the keyboard, and each of which may issue requests to modify the keyboard in some manner. Each client may be either Xkb-unaware, Xkb-capable, or Xkb-aware. The server itself may be either Xkb-aware or Xkb-unaware. If the server is Xkb-unaware, Xkb state and keyboard mappings are not involved in any manner, and Xkb-aware clients may not issue Xkb requests to the server. If the server is Xkb-aware, the server must be able to deliver events and accept requests in which the keyboard state and mapping are compatible with the mode in which the client is operating. Consequently, for some situations, conversions must be made between Xkb state / keyboard mappings and core protocol state / keyboard mappings, and vice versa. Server Interaction with Types of Clients In addition to these situations involving a single server, there are cases where a client that deals with multiple servers may need to configure keyboards on different servers to be similar and the different servers may not all be Xkb-aware. Finally, a client may be dealing with descriptions of keyboards (files, and so on) that are based on core protocol and therefore may need to be able to map these descriptions to Xkb descriptions. An Xkb-aware server maintains keyboard state and mapping as an Xkb keyboard state and an Xkb keyboard mapping plus a compatibility map used to convert from Xkb components to core components and vice versa. In addition, the server also maintains a core keyboard mapping that approximates the Xkb keyboard mapping. The core keyboard mapping may be updated piecemeal, on a per-key basis. When the server receives a core protocol ChangeKeyboardMapping or SetModifierMapping request, it updates its core keyboard mapping, then uses the compatibility map to update its Xkb keyboard mapping. When the server receives an XkbSetMap request, it updates those portions of its Xkb keyboard mapping specified by the request, then uses its compatibility map to update the corresponding parts of its core keyboard map. Consequently, the server’s Xkb keyboard map and also its core keyboard map may contain components that were set directly and others that were computed. Figure 17.2 illustrates these relationships. The core keyboard map is contained only in the server, not in any client-side data structures. Server Derivation of State and Keyboard Mapping Components There are three kinds of compatibility transformations made by the server: Xkb State to Core State Keyboard state information reported to a client in the state field of various core events may be translated from the Xkb keyboard state maintained by the server, which includes a group number, to core protocol state, which does not. In addition, whenever the Xkb state is retrieved, the compat_state , compat_grab_mods , and compat_lookup_mods fields of the XkbStateRec returned indicate the result of applying the compatibility map to the current Xkb state in the server. Core Keyboard Mapping to Xkb Keyboard Mapping After core protocol requests received by the server to change the keyboard mapping ( ChangeKeyboardMapping and SetModifierMapping ) have been applied to the server’s core keyboard map, the results must be transformed to achieve an equivalent change of the Xkb keyboard mapping maintained by the server. Xkb Keyboard Mapping to Core Keyboard Mapping After Xkb protocol requests received by the server to change the keyboard mapping ( XkbSetMap ) have been applied to the server’s Xkb keyboard map, the results are transformed to achieve an approximately equivalent change to the core keyboard mapping maintained by the server. This chapter discusses how a client may modify the compatibility map so that subsequent transformations have a particular result. The XkbCompatMap Structure All configurable aspects of mapping Xkb state and configuration to and from core protocol state and configuration are defined by a compatibility map, contained in an XkbCompatMap structure; plus a set of explicit override controls used to prevent particular components of type 2 (core-to-Xkb keyboard mapping) transformations from automatically occurring. These explicit override controls are maintained in a separate data structure discussed in section 16.3. The compat member of an Xkb keyboard description ( XkbDescRec ) points to the XkbCompatMap structure: typedef struct _XkbCompatMapRec { XkbSymInterpretPtr sym_interpret; /* symbol based key semantics*/ XkbModsRec groups[XkbNumKbdGroups]; /* group => modifier map */ unsigned short num_si; /* # structures used in sym_interpret */ unsigned short size_si; /* # structures allocated in sym_interpret */ } XkbCompatMapRec, *XkbCompatMapPtr; Xkb Compatibility Data Structures The subsections that follow discuss how the compatibility map and explicit override controls are used in each of the three cases where compatibility transformations are made. Xkb State to Core Protocol State Transformation As shown in Figure 17.3, there are four group compatibility maps (contained in groups [0..3]) in the XkbCompatMapRec structure, one per possible Xkb group. Each group compatibility map is a modifier definition (see section 7.2 for a description of modifier definitions). The mask component of the definition specifies which real modifiers should be set in the core protocol state field when the corresponding group is active. Because only one group is active at any one time, only one of the four possible transformations is ever applied at any one point in time. If the device described by the XkbDescRec does not support four groups, the extra groups fields are present, but undefined. Normally, the Xkb-aware server reports keyboard state in the state member of events such as a KeyPress event and ButtonPress event, encoded as follows: bits meaning 15 0 13-14 Group index 8-12 Pointer Buttons 0-7 Modifiers For Xkb-unaware clients, only core protocol keyboard information may be reported. Because core protocol does not define the group index, the group index is mapped to modifier bits as specified by the groups [group index] field of the compatibility map (the bits set in the compatibility map are ORed into bits 0-7 of the state), and bits 13-14 are reported in the event as zero. Core Keyboard Mapping to Xkb Keyboard Mapping Transformation When a core protocol keyboard mapping request is received by the server, the server’s core keyboard map is updated, and then the Xkb map maintained by the server is updated. Because a client may have explicitly configured some of the Xkb keyboard mapping in the server, this automatic regeneration of the Xkb keyboard mapping from the core protocol keyboard mapping should not modify any components of the Xkb keyboard mapping that were explicitly set by a client. The client must set explicit override controls to prevent this from happening (see section 16.3). The core-to-Xkb mapping is done as follows: Map the symbols from the keys in the core keyboard map to groups and symbols on keys in the Xkb keyboard map. The core keyboard mapping is of fixed width, so each key in the core mapping has the same number of symbols associated with it. The Xkb mapping allows a different number of symbols to be associated with each key; those symbols may be divided into a different number of groups (1-4) for each key. For each key, this process therefore involves partitioning the fixed number of symbols from the core mapping into a set of variable-length groups with a variable number of symbols in each group. For example, if the core protocol map is of width five, the partition for one key might result in one group with two symbols and another with three symbols. A different key might result in two groups with two symbols plus a third group with one symbol. The core protocol map requires at least two symbols in each of the first two groups. For each changed key, determine the number of groups represented in the new core keyboard map. This results in a tentative group count for each key in the Xkb map. For each changed key, determine the number of symbols in each of the groups found in step 1a. There is one explicit override control associated with each of the four possible groups for each Xkb key, ExplicitKeyType1 through ExplicitKeyType4 . If no explicit override control is set for a group, the number of symbols used for that group from the core map is two. If the explicit override control is set for a group on the key, the number of symbols used for that Xkb group from the core map is the width of the Xkb group with one exception: because of the core protocol requirement for at least two symbols in each of groups one and two, the number of symbols used for groups one and two is the maximum of 2 or the width of the Xkb group. For each changed key, assign the symbols in the core map to the appropriate group on the key. If the total number of symbols required by the Xkb map for a particular key needs more symbols than the core protocol map contains, the additional symbols are taken to be NoSymbol keysyms appended to the end of the core set. If the core map contains more symbols than are needed by the Xkb map, trailing symbols in the core map are discarded. In the absence of an explicit override for group one or two, symbols are assigned in order by group; the first symbols in the core map are assigned to group one, in order, followed by group two, and so on. For example, if the core map contained eight symbols per key, and a particular Xkb map contained 2 symbols for G1 and G2 and three for G3, the symbols would be assigned as (G is group, L is shift level): G1L1 G1L2 G2L1 G2L2 G3L1 G3L2 G3L3 If an explicit override control is set for group one or two, the symbols are taken from the core set in a somewhat different order. The first four symbols from the core set are assigned to G1L1, G1L2, G2L1, G2L2, respectively. If group one requires more symbols, they are taken next, and then any additional symbols needed by group two. Group three and four symbols are taken in complete sequence after group two. For example, a key with four groups and three symbols in each group would take symbols from the core set in the following order: G1L1 G1L2 G2L1 G2L2 G1L3 G2L3 G3L1 G3L2 G3L3 G4L1 G4L2 G4L3 As previously noted, the core protocol map requires at lease two symbols in groups one and two. Because of this, if an explicit override control for an Xkb key is set and group one and / or group two is of width one, it is not possible to generate the symbols taken from the core protocol set and assigned to position G1L2 and / or G2L2. For each group on each changed key, assign a key type appropriate for the symbols in the group. For each changed key, remove any empty or redundant groups. At this point, the groups and their associated symbols have been assigned to the corresponding key definitions in the Xkb map. Apply symbol interpretations to modify key operation. This phase is completely skipped if the ExplicitInterpret override control bit is set in the explicit controls mask for the Xkb key (see section 16.3). For each symbol on each changed key, attempt to match the symbol and modifiers from the Xkb map to a symbol interpretation describing how to generate the symbol. When a match is found in step 2a, apply the symbol interpretation to change the semantics associated with the symbol in the Xkb key map. If no match is found, apply a default interpretation. The symbol interpretations used in step 2 are configurable and may be specified using XkbSymInterpretRec structures referenced by the sym_interpret field of an XkbCompatMapRec (see Figure 17.3). Symbol Interpretations — the XkbSymInterpretRec Structure Symbol interpretations are used to guide the X server when it modifies the Xkb keymap in step 2. An initial set of symbol interpretations is loaded by the server when it starts. A client may add new ones using XkbSetCompatMap (see section 17.4). Symbol interpretations result in key semantics being set. When a symbol interpretation is applied, the following components of server key event processing may be modified for the particular key involved: Virtual modifier map Auto repeat Key behavior (may be set to XkbKB_Lock) Key action (see section 16.1) The XkbSymInterpretRec structure specifies a symbol interpretation: typedef struct { KeySym sym; /* keysym of interest or NULL */ unsigned char flags; /* XkbSI_AutoRepeat, XkbSI_LockingKey */ unsigned char match; /* specifies how mods is interpreted */ unsigned char mods; /* modifier bits, correspond to eight real modifiers */ unsigned char virtual_mod; /* 1 modifier to add to key virtual mod map */ XkbAnyAction act; /* action to bind to symbol position on key */ } XkbSymInterpretRec,*XkbSymInterpretPtr; If sym is not NULL , it limits the symbol interpretation to keys on which that particular keysym is selected by the modifiers matching the criteria specified by mods and match . If sym is NULL , the interpretation may be applied to any symbol selected on a key when the modifiers match the criteria specified by mods and match . match must be one of the values shown in Table 17.1 and specifies how the real modifiers specified in mods are to be interpreted. Symbol Interpretation Match Criteria Match Criteria Value Effect XkbSI_NoneOf (0) None of the bits that are on in mods can be set, but other bits can be. XkbSI_AnyOfOrNone (1) Zero or more of the bits that are on in mods can be set, as well as others. XkbSI_AnyOf (2) One or more of the bits that are on in mods can be set, as well as any others. XkbSI_AllOf (3) All of the bits that are on in mods must be set, but others may be set as well. XkbSI_Exactly (4) All of the bits that are on in mods must be set, and no other bits may be set.
In addition to the above bits, match may contain the XkbSI_LevelOneOnly bit, in which case the modifier match criteria specified by mods and match applies only if sym is in level one of its group; otherwise, mods and match are ignored and the symbol matches a condition where no modifiers are set. #define XkbSI_LevelOneOnly (0x80) /* use mods + match only if sym is level 1 */ If no matching symbol interpretation is found, the server uses a default interpretation where: sym = 0 flags = XkbSI_AutoRepeat match = XkbSI_AnyOfOrNone mods = 0 virtual_mod = XkbNoModifier act = SA_NoAction When a matching symbol interpretation is found in step 2a, the interpretation is applied to modify the Xkb map as follows. The act field specifies a single action to be bound to the symbol position; any key event that selects the symbol causes the action to be taken. Valid actions are defined in section 16.1. If the Xkb keyboard map for the key does not have its ExplicitVModMap control set, the XkbSI_LevelOneOnly bit and symbol position are examined. If the XkbSI_LevelOneOnly bit is not set in match or the symbol is in position G1L1, the virtual_mod field is examined. If virtual_mod is not XkbNoModifier , virtual_mod specifies a single virtual modifier to be added to the virtual modifier map for the key. virtual_mod is specified as an index in the range [0..15]. If the matching symbol is in position G1L1 of the key, two bits in the flags field potentially specify additional behavior modifications: #define XkbSI_AutoRepeat (1<<0) /* key repeats if sym is in position G1L1 */ #define XkbSI_LockingKey (1<<1) /* set KB_Lock behavior if sym is in psn G1L1 */ If the Xkb keyboard map for the key does not have its ExplicitAutoRepeat control set, its auto repeat behavior is set based on the value of the XkbSI_AutoRepeat bit. If the XkbSI_AutoRepeat bit is set, the auto-repeat behavior of the key is turned on; otherwise, it is turned off. If the Xkb keyboard map for the key does not have its ExplicitBehavior control set, its locking behavior is set based on the value of the XkbSI_LockingKey bit. If XkbSI_LockingKey is set, the key behavior is set to KB_Lock ; otherwise, it is turned off (see section 16.3).
Xkb Keyboard Mapping to Core Keyboard Mapping Transformations Whenever the server processes Xkb requests to change the keyboard mapping, it discards the affected portion of its core keyboard mapping and regenerates it based on the new Xkb mapping. When the Xkb mapping for a key is transformed to a core protocol mapping, the symbols for the core map are taken in the following order from the Xkb map: G1L1 G1L2 G2L1 G2L2 G1L3-n G2L3-n G3L1-n G4L1-n If group one is of width one in the Xkb map, G1L2 is taken to be NoSymbol; similarly, if group two is of width one in the Xkb map, G2L2 is taken to be NoSymbol. If the Xkb key map for a particular key has fewer groups than the core keyboard, the symbols for group one are repeated to fill in the missing core components. For example, an Xkb key with a single width-three group would be mapped to a core mapping counting three groups as: G1L1 G1L2 G1L1 G1L2 G1L3 G1L3 G1L1 G1L2 G1L3 When a core keyboard map entry is generated from an Xkb keyboard map entry, a modifier mapping is generated as well. The modifier mapping contains all of the modifiers affected by any of the actions associated with the key combined with all of the real modifiers associated with any of the virtual modifiers bound to the key. In addition, if any of the actions associated with the key affect any component of the keyboard group, all of the modifiers in the mask field of all of the group compatibility maps are added to the modifier mapping as well. While an XkbSA_ISOLock action can theoretically affect any modifier, if the Xkb mapping for a key specifies an XkbSA_ISOLock action, only the modifiers or group that are set by default are added to the modifier mapping.
Getting Compatibility Map Components From the Server Use XkbGetCompatMap to fetch any combination of the current compatibility map components from the server. When another client modifies the compatibility map, you are notified if you have selected for XkbCompatMapNotify events (see section 17.5). XkbGetCompatMap is particularly useful when you receive an event of this type, as it allows you to update your program’s version of the compatibility map to match the modified version now in the server. If your program is dealing with multiple servers and needs to configure them all in a similar manner, the updated compatibility map may be used to reconfigure other servers. To make a complete matching configuration you must also update the explicit override components of the server state. Status XkbGetCompatMap ( display, which, xkb ) Display * display ; /* connection to server */ unsigned int which ; /* mask of compatibility map components to fetch */ XkbDescRec * xkb ; /* keyboard description where results placed */ XkbGetCompatMap fetches the components of the compatibility map specified in which from the server specified by display and places them in the compat structure of the keyboard description xkb . Valid values for which are an inclusive OR of the values shown in Table 17.2. Compatibility Map Component Masks Mask Value Affecting XkbSymInterpMask (1<<0) Symbol interpretations XkbGroupCompatMask (1<<1) Group maps XkbAllCompatMask (0x3) All compatibility map components
If no compatibility map structure is allocated in xkb upon entry, XkbGetCompatMap allocates one. If one already exists, its contents are overwritten with the returned results. XkbGetCompatMap fetches compatibility map information for the device specified by the device_spec field of xkb . Unless you have specifically modified this field, it is the default keyboard device. XkbGetCompatMap returns Success if successful, BadAlloc if it is unable to obtain necessary storage for either the return values or work space, BadMatch if the dpy field of the xkb argument is non- NULL and does not match the display argument, and BadLength under certain conditions caused by server or Xkb implementation errors.
Using the Compatibility Map Xkb provides several functions that make it easier to apply the compatibility map to configure a client-side Xkb keyboard mapping, given a core protocol representation of part or all of a keyboard mapping. Obtain a core protocol representation of a keyboard mapping from an actual server (by using XGetKeyboardMapping , for example), a data file, or some other source. To update a local Xkb keyboard map to reflect the mapping expressed by a core format mapping by calling the function XkbUpdateMapFromCore . Bool XkbUpdateMapFromCore ( xkb , first_key , num_keys , map_width , core_keysyms , changes ) XkbDescPtr xkb ; /* keyboard description to update */ KeyCode first_key ; /* keycode of first key description to update */ int num_keys ; /* number of key descriptions to update */ int map_width ; /* width of core protocol keymap */ KeySym * core_keysyms ; /* symbols in core protocol keymap */ XkbChangesPtr changes ; /* backfilled with changes made to Xkb */ XkbUpdateMapFromCore interprets input argument information representing a keyboard map in core format to update the Xkb keyboard description passed in xkb . Only a portion of the Xkb map is updated — the portion corresponding to keys with keycodes in the range first_key through first_key + num_keys - 1. If XkbUpdateMapFromCore is being called in response to a MappingNotify event , first_key and num_keys are reported in the MappingNotify event. core_keysyms contains the keysyms corresponding to the keycode range being updated, in core keyboard description order. map_width is the number of keysyms per key in core_keysyms . Thus, the first map_width entries in core_keysyms are for the key with keycode first_key , the next map_width entries are for key first_key + 1, and so on. In addition to modifying the Xkb keyboard mapping in xkb , XkbUpdateMapFromCore backfills the changes structure whose address is passed in changes to indicate the modifications that were made. You may then use changes in subsequent calls such as XkbSetMap , to propagate the local modifications to a server. When dealing with core keyboard mappings or descriptions, it is sometimes necessary to determine the Xkb key types appropriate for the symbols bound to a key in a core keyboard mapping. Use XkbKeyTypesForCoreSymbols for this purpose: int XkbKeyTypesForCoreSymbols ( map_width , core_syms , protected, types_inout, xkb_syms_rtrn ) XkbDescPtr xkb ; /* keyboard description in which to place symbols*/ int map_width ; /* width of core protocol keymap in xkb_syms_rtrn */ KeySym * core_syms ; /* core protocol format array of KeySyms */ unsigned int protected ; /* explicit key types */ int * types_inout; /* backfilled with the canonical types bound to groups one and two for the key */ KeySym * xkb_syms_rtrn ; /* backfilled with symbols bound to the key in the Xkb mapping */ XkbKeyTypesForCoreSymbols expands the symbols in core_syms and types in types_inout according to the rules specified in section 12 of the core protocol, then chooses canonical key types (canonical key types are defined in section 15.2.1) for groups 1 and 2 using the rules specified by the Xkb protocol and places them in xkb_syms_rtrn , which will be non- NULL . A core keymap is a two-dimensional array of keysyms. It has map_width columns and max_key_code rows. XkbKeyTypesForCoreSymbols takes a single row from a core keymap, determines the number of groups associated with it, the type of each group, and the symbols bound to each group. The return value is the number of groups, types_inout has the types for each group, and xkb_syms_rtrn has the symbols in Xkb order (that is, groups are contiguous, regardless of size). protected contains the explicitly protected key types. There is one explicit override control associated with each of the four possible groups for each Xkb key, ExplicitKeyType1 through ExplicitKeyType4 ; protected is an inclusive OR of these controls. map_width is the width of the core keymap and is not dependent on any Xkb definitions. types_inout is an array of four type indices. On input, types_inout contains the indices of any types already assigned to the key, in case they are explicitly protected from change. Upon return, types_inout contains any automatically selected (that is, canonical) types plus any protected types. Canonical types are assigned to all four groups if there are enough symbols to do so. The four entries in types_inout correspond to the four groups for the key in question. If the groups mapping does not change, but the symbols assigned to an Xkb keyboard compatibility map do change, the semantics of the key may be modified. To apply the new compatibility mapping to an individual key to get its semantics updated, use XkbApplyCompatMapToKey . Bool XkbApplyCompatMapToKey ( xkb , key , changes ) XkbDescPtr xkb; /* keyboard description to be updated */ KeyCode key ; /* key to be updated */ XkbChangesPtr changes ; /* notes changes to the Xkb keyboard description */ XkbApplyCompatMapToKey essentially performs the operation described in section 17.1.2 to a specific key. This updates the behavior, actions, repeat status, and virtual modifier bindings of the key. Changing the Server’s Compatibility Map To modify the server’s compatibility map, first modify a local copy of the Xkb compatibility map, then call XkbSetCompatMap . You may allocate a new compatibility map for this purpose using XkbAllocCompatMap (see section 17.6). You may also use a compatibility map from another server, although you need to adjust the device_spec field in the XkbDescRec accordingly. Note that symbol interpretations in a compatibility map ( sym_interpret , the vector of XkbSymInterpretRec structures) are also allocated using this same function. Bool XkbSetCompatMap ( display, which, xkb, update_actions ) Display * display ; /* connection to server */ unsigned int which ; /* mask of compat map components to set */ XkbDescPtr xkb ; /* source for compat map components */ Bool update_actions ; /* True => apply to server’s keyboard map */ XkbSetCompatMap copies compatibility map information from the keyboard description in xkb to the server specified in display ’s compatibility map for the device specified by the device_spec field of xkb . Unless you have specifically modified this field, it is the default keyboard device. which specifies the compatibility map components to be set, and is an inclusive OR of the bits shown in Table 17.2. After updating its compatibility map for the specified device, if update_actions is True, the server applies the new compatibility map to its entire keyboard for the device to generate a new set of key semantics, compatibility state, and a new core keyboard map. If update_actions is False , the new compatibility map is not used to generate any modifications to the current device semantics, state, or core keyboard map. One reason for not applying the compatibility map immediately would be if one server was being configured to match another on a piecemeal basis; the map should not be applied until everything is updated. To force an update at a later time, use XkbSetCompatMap specifying which as zero and update_actions as True . XkbSetCompatMap returns True if successful and False if unsuccessful. The server may report problems it encounters when processing the request subsequently via protocol errors. To add a symbol interpretation to the list of symbol interpretations in an XkbCompatRec , use XkbAddSymInterpret . XkbSymInterpretPtr XkbAddSymInterpret ( xkb, si, updateMap, changes ) XkbDescPtr xkb ; /* keyboard description to be updated */ XkbSymInterpretPtr si ; /* symbol interpretation to be added */ Bool updateMap ; /* True =>apply compatibility map to keys */ XkbChangesPtr changes ; /* changes are put here */ XkbAddSymInterpret adds si to the list of symbol interpretations in xkb . If updateMap is True , it (re)applies the compatibility map to all of the keys on the keyboard. If changes is non- NULL , it reports the parts of the keyboard that were affected (unless updateMap is True , not much changes). XkbAddSymInterpret returns a pointer to the actual new symbol interpretation in the list or NULL if it failed. Tracking Changes to the Compatibility Map The server automatically generates MappingNotify events when the keyboard mapping changes. If you wish to be notified of changes to the compatibility map, you should select for XkbCompatMapNotify events. If you select for XkbMapNotify events, you no longer receive the automatically generated MappingNotify events. If you subsequently deselect XkbMapNotifyEvent delivery, you again receive MappingNotify events. To receive XkbCompatMapNotify events under all possible conditions, use XkbSelectEvents (see section 4.3) and pass XkbCompatMapNotifyMask in both bits_to_change and values_for_bits . To receive XkbCompatMapNotify events only under certain conditions, use XkbSelectEventDetails using XkbCompatMapNotify as the event_type and specifying the desired map changes in bits_to_change and values_for_bits using mask bits from Table 17.2. Note that you are notified of changes you make yourself, as well as changes made by other clients. The structure for the XkbCompatMapNotifyEvent is: typedef struct { int type; /* Xkb extension base event code */ unsigned long serial; /* X server serial number for event */ Bool send_event; /* True => synthetically generated */ Display * display; /* server connection where event generated */ Time time; /* server time when event generated */ int xkb_type; /* XkbCompatMapNotify */ int device; /* Xkb device ID, will not be XkbUseCoreKbd */ unsigned int changed_groups;/* number of group maps changed */ int first_si; /* index to 1st changed symbol interpretation */ int num_si; /* number of changed symbol interpretations */ int num_total_si; /* total number of valid symbol interpretations */ } XkbCompatMapNotifyEvent; changed_groups is the number of group compatibility maps that have changed. If you are maintaining a corresponding copy of the compatibility map, or get a fresh copy from the server using XkbGetCompatMap , changed_groups references groups [0.. changed_groups -1] in the XkbCompatMapRec structure. first_si is the index of the first changed symbol interpretation, num_si is the number of changed symbol interpretations, and num_total_si is the total number of valid symbol interpretations. If you are maintaining a corresponding copy of the compatibility map, or get a fresh copy from the server using XkbGetCompatMap , first_si , num_si , and num_total_si are appropriate for use with the compat.sym_interpret vector in this structure. Allocating and Freeing the Compatibility Map If you are modifying the compatibility map, you need to allocate a new compatibility map if you do not already have one available. To do so, use XkbAllocCompatMap . Status XkbAllocCompatMap ( xkb, which, num_si ) XkbDescPtr xkb ; /* keyboard description in which to allocate compat map */ unsigned int which ; /* mask of compatibility map components to allocate */ unsigned int num_si ; /* number of symbol interpretations to allocate */ xkb specifies the keyboard description for which compatibility maps are to be allocated. The compatibility map is the compat field in this structure. which specifies the compatibility map components to be allocated (see XkbGetCompatMap , in section 17.2). which is an inclusive OR of the bits shown in Table 17.2. num_si specifies the total number of entries to allocate in the symbol interpretation vector ( xkb.compat.sym_interpret ). Note that symbol interpretations in a compatibility map (the sym_interpret vector of XkbSymInterpretRec structures) are also allocated using this same function. To ensure that there is sufficient space in the symbol interpretation vector for entries to be added, use XkbAllocCompatMap specifying which as XkbSymInterpretMask and the number of free symbol interpretations needed in num_si . XkbAllocCompatMap returns Success if successful, BadMatch if xkb is NULL , or BadAlloc if errors are encountered when attempting to allocate storage. To free an entire compatibility map or selected portions of one, use XkbFreeCompatMap . void XkbFreeCompatMap ( xkb, which, free_map ) XkbDescPtr xkb ; /* Xkb description in which to free compatibility map */ unsigned int which ; /* mask of compatibility map components to free */ Bool free_map ; /* True => free XkbCompatMap structure itself */ which specifies the compatibility map components to be freed (see XkbGetCompatMap , in section 17.2). which is an inclusive OR of the bits shown in Table 17.2 free_map indicates whether the XkbCompatMap structure itself should be freed. If free_map is True , which is ignored, all non- NULL compatibility map components are freed, and the compat field in the XkbDescRec referenced by xkb is set to NULL .