Interactions Between XKB and the Core Protocol In addition to providing a number of new requests, XKB replaces or extends existing core protocol requests and events. Some aspects of the this extension, such as the ability to lock any key or modifier, are visible even to clients that are unaware of the XKB extension. Other capabilities, such as control of keysym selection on a per-key basis, are available only to XKB-aware clients. Though they do not have access to some advanced extension capabilities, the XKB extension includes compatibility mechanisms to ensure that non-XKB clients behave as expected and operate at least as well with an XKB-capable server as they do today. There are a few significant areas in which XKB state and mapping differences might be visible to XKB-unaware clients: The core protocol uses a modifier to choose between two keyboard groups, while this extension provides explicit support for multiple groups. The order of the symbols associated with any given key by XKB might not match the ordering demanded by the core protocol. To minimize problems that might result from these differences, XKB includes ways to specify the correspondence between core protocol and XKB modifiers and symbols. This section describes the differences between the core X protocol’s notion of a keyboard mapping and XKB and explains the ways they can interact. Group Compatibility Map As described in Keyboard State, the current keyboard group is reported to XKB-aware clients in bits 13-14 of the state field of many core protocol events. XKB-unaware clients cannot interpret those bits, but they might use a keyboard modifier to implement support for a single keyboard group. To ensure that pre-XKB clients continue to work when XKB is present, XKB makes it possible to map an XKB state field, which includes both keyboard group and modifier state into a pre-XKB state field which contains only modifiers. A keyboard description includes one group compatibility map per keyboard group (four in all). Each such map is a modifier definition (i.e. specifies both real and virtual modifiers) which specifies the modifiers to be set in the compatibility states when the corresponding keyboard group is active. Here are a few examples to illustrate the application of the group compatibility map: Group GroupCompat Map Effective Modifiers State for XKB Clients Compatibility Modifiers State for non-XKB Clients 1 Group1=None Shift x00xxxxx00000001 Shift xxxxxxxx00000001 2 Group2=Mod3 None x01xxxxx00000000 Mod3 xxxxxxxx00100000 3 Group3=Mod2 Shift x10xxxxx00000001 Shift+Mod2 xxxxxxxx00010001 4 Group4=None Control x11xxxxx00000100 Control xxxxxxxx00000100 Note that non-XKB clients (i.e. clients that are linked with a version of the X library that does not support XKB) cannot detect the fact that Group4 is active in this example because the group compatibility map for Group4 does not specify any modifiers. Setting a Passive Grab for an XKB State The fact that the state field of an event might look different when XKB is present can cause problems with passive grabs. Existing clients specify the modifiers they wish to grab using the rules defined by the core protocol, which use a normal modifier to indicate keyboard group. If we used an XKB state field, the high bits of the state field would be non-zero whenever the keyboard was in any group other than Group1 , and none of the passive grabs set by clients could ever be triggered. To avoid this behavior, the X server normally uses the compatibility grab state to decide whether or not to activate a passive grab, even for XKB-aware clients. The group compatibility map attempts to encode the keyboard group in one or more modifiers of the compatibility state, so existing clients continue to work exactly the way they do today. By default, there is no way to directly specify a keyboard group in a Grabbed or GrabButton request, but groups can be specified indirectly by correctly adjusting the group compatibility map. Clients that wish to specify an XKB keyboard state, including a separate keyboard group, can set the GrabsUseXKBState per-client flag which indicates that all subsequent key and button grabs from the requesting clients are specified using an XKB state. Whether the XKB or core state should be used to trigger a grab is determined by the setting of the GrabsUseXKBState flag for the requesting client at the time the key or button is grabbed. There is no way to change the state to be used for a grab that is already registered or for grabs that are set by some other client. Changing the Keyboard Mapping Using the Core Protocol An XKB keyboard description includes a lot of information that is not present in the core protocol description of a keyboard. Whenever a client remaps the keyboard using core protocol requests, XKB examines the map to determine likely default values for the components that cannot be specified using the core protocol. Some aspects of this automatic mapping are configurable, and make it fairly easy to take advantage of many XKB features using existing tools like xmodmap , but much of the process of mapping a core keyboard description into an XKB description is designed to preserve compatible behavior for pre-XKB clients and cannot be redefined by the user. Clients or users that want behavior that cannot be described using this mapping should use XKB functions directly. Explicit Keyboard Mapping Components This automatic remapping might accidentally replace definitions that were explicitly requested by an application, so the XKB keyboard description defines a set of explicit components for each key; any components that are listed in the explicit components for a key are not changed by the automatic keyboard mapping. The explicit components field for a key can contain any combination of the following values: Bit in Explicit Mask Protects Against ExplicitKeyType1 Automatic determination of the key type associated with Group1 (see Assigning Types To Groups of Symbols for a Key) ExplicitKeyType2 Automatic determination of the key type associated with Group2 (see Assigning Types To Groups of Symbols for a Key) ExplicitKeyType3 Automatic determination of the key type associated with Group3 (see Assigning Types To Groups of Symbols for a Key). ExplicitKeyType4 Automatic determination of the key type associated with Group4 (see Assigning Types To Groups of Symbols for a Key). ExplicitInterpret Application of any of the fields of a symbol interpretation to the key in question (see Assigning Actions To Keys). ExplicitAutoRepeat Automatic determination of autorepeat status for the key, as specified in a symbol interpretation (see Assigning Actions To Keys). ExplicitBehavior Automatic assignment of the KB_Lock behavior to the key, if the LockingKey flag is set in a symbol interpretation (see Assigning Actions To Keys). ExplicitVModMap Automatic determination of the virtual modifier map for the key based on the actions assigned to the key and the symbol interpretations which match the key (see Assigning Actions To Keys). Assigning Symbols To Groups The first step in applying the changes specified by a core protocol ChangeKeyboardMapping request to the XKB description of a keyboard is to determine the number of groups that are defined for the key and the width of each group. The XKB extension does not change key types in response to core protocol SetModifierMapping requests, but it does choose key actions as described in Assigning Actions To Keys. Determining the number of symbols required for each group is straightforward. If the key type for some group is not protected by the corresponding ExplicitKeyType component, that group has two symbols. If any of the explicit components for the key include ExplicitKeyType3 or ExplicitKeyType4 , the width of the key type currently assigned to that group determines the number of symbols required for the group in the core protocol keyboard description. The explicit type components for Group1 and Group2 behave similarly, but for compatibility reasons the first two groups must have at least two symbols in the core protocol symbol mapping. Even if an explicit type assigned to either of the first two keyboard groups has fewer than two symbols, XKB requires two symbols for it in the core keyboard description. If the core protocol request contains fewer symbols than XKB needs, XKB adds trailing NoSymbol keysyms to the request to pad it to the required length. If the core protocol request includes more symbols than it needs, XKB truncates the list of keysyms to the appropriate length. Finally, XKB divides the symbols from the (possibly padded or truncated) list of symbols specified by the core protocol request among the four keyboard groups. In most cases, the symbols for each group are taken from the core protocol definition in sequence (i.e. the first pair of symbols is assigned to Group1 , the second pair of symbols is assigned to Group2 , and so forth). If either Group1 or Group2 has an explicitly defined key type with a width other than two, it gets a little more complicated. Assigning Symbols to Groups One and Two with Explicitly Defined Key Types The server assigns the first four symbols from the expanded or truncated map to the symbol positions G1L1 , G1L2, G2L1 and G2L2, respectively. If the key type assigned to Group1 reports more than two shift levels, the fifth and following symbols contain the extra keysyms for Group2 . If the key type assigned to Group2 reports more than two shift levels, the extra symbols follow the symbols (if any) for Group1 in the core protocol list of symbols. Symbols for Group3 and Group4 are contiguous and follow the extra symbols, if any, for Group1 and Group2 . For example, consider a key with a key type that returns three shift levels bound to each group. The symbols bound to the core protocol are assigned in sequence to the symbol positions: G1L1, G1L2, G2L1, G2L2, G1L3, G2L3, G3L1, G3L2, G3L3, G4L1, G4L2, and G4L3 For a key with a width one key type on group one, a width two key type on group two and a width three key type on group three, the symbols bound to the key by the core protocol are assigned to the following key positions: G1L1, (G1L2), G2L1, G2L2, G3L1, G3L2, G3L3 Note that the second and fourth symbols (positions G1L2 and G2L2 ) can never be generated if the key type associated with the group yields only one symbol. XKB accepts and ignores them in order to maintain compatibility with the core protocol. Assigning Types To Groups of Symbols for a Key Once the symbols specified by ChangeKeyboardMapping have been assigned to the four keyboard groups for a key, the X server assigns a key type to each group on the key from a canonical list of key types. The first four key types in any keyboard map are reserved for these standard key types: Key Type Name Standard Definition ONE_LEVEL Describes keys that have exactly one symbol per group. Most special or function keys (such as Return ) are ONE_LEVEL keys. Any combination of modifiers yields level 0 . Index 0 in any key symbol map specifies key type ONE_LEVEL . TWO_LEVEL Describes non-keypad and non-alphabetic keys that have exactly two symbols per group. By default, the TWO_LEVEL type yields column 1 if the Shift modifier is set, column 0 otherwise. Index 1 in any key symbol map specifies key type TWO_LEVEL . ALPHABETIC Describes alphabetic keys that have exactly two symbols per group. The default definition of the ALPHABETIC type provides shift-cancels-caps behavior as described in Key Types. Index 2 in any key symbol map specifies key type ALPHABETIC . KEYPAD Describes numeric keypad keys with two symbols per group. Yields column 1 if either of the Shift modifier or the real modifier bound to the virtual modifier named NumLock are set. Yields column 0 if neither or both modifiers are set. Index 3 in any key symbol map specifies key type KEYPAD . Users or applications may change these key types to get different default behavior (to make shift cancel caps lock, for example) but they must always have the specified number of symbols per group. Before assigning key types to groups, the X server expands any alphanumeric symbol definitions as follows: If the second symbol of either group is NoSymbol and the first symbol of that group is an alphabetic keysym for which both lowercase and uppercase forms are defined, the X server treats the key as if the first element of the group were the lowercase form of the symbol and the second element were the uppercase form of the symbol. For the purposes of this expansion, XKB ignores the locale and uses the capitalization rules defined in Default Symbol Transformations. For each keyboard group that does not have an explicit type definition, XKB chooses a key type from the canonical key types. If the second symbol assigned to a group is NoSymbol (after alphabetic expansion), the server assigns key type ONE_LEVEL . If the group contains the lowercase and uppercase forms of a single glyph (after alphanumeric expansion), the server assigns key type ALPHABETIC . If either of the symbols in a group is a numeric keypad keysym ( KP_* ), the server assigns key type KEYPAD . Otherwise, it assigns key type TWO_LEVEL . Finally, XKB determines the number of groups of symbols that are actually defined for the key. Trailing empty groups (i.e. groups that have NoSymbol in all symbol positions) are ignored. There are two last special cases for compatibility with the core protocol: If, after trailing empty groups are excluded, all of the groups of symbols bound to the key have identical type and symbol bindings, XKB assigns only one group to the key. If Group2 is empty and either of Group3 or Group4 are not, and if neither Group1 nor Group2 have explicit key types, XKB copies the symbols and key type from Group1 into Group2 . Assigning Actions To Keys Once symbols have been divided into groups and key types chosen for the keys affected by a ChangeKeyboardMapping request, XKB examines the symbols and modifier mapping for each changed key and assigns server actions where appropriate. XKB also automatically assigns server actions to changed keys if the client issues a core protocol SetModifierMapping request, and does so optionally in response to XkbSetMap and XkbSetCompatMap requests. The compatibility map includes a list of symbol interpretations , which XKB compares to each symbol associated with any changed keys in turn, unless the ExplicitInterp component is set for a key. Setting the ExplicitInterp component prevents the application of symbol interpretations to that key. If the modifiers and keysym specified in a symbol interpretation match the modifier mapping and a symbol bound to a changed key that is not protected by ExplicitInterp , the server applies the symbol interpretation to the symbol position. The server considers all symbol interpretations which specify an explicit keysym before considering any that do not. The server uses the first interpretation which matches the given combination of keysym and modifier mapping; other matching interpretations are ignored. XKB uses four of the fields of a symbol interpretation to decide if it matches one of the symbols bound to some changed key: The symbol field is a keysym which matches if it has the value NoSymbol or is identical to the symbol in question. The modifiers specified in the mods field are compared to the modifiers affected by the key in question as indicated by match . The match field can specify any of the comparisons: NoneOf , AnyOfOrNone , AnyOf , AllOf or Exactly . The levelOneOnly setting, indicates that the interpretation in question should only use the modifiers bound to this key by the modifier mapping if the symbol that matches in level one of its group. Otherwise, if the symbol being considered is not in shift level one of its group, the server behaves as if the modifier map for the key were empty. Note that it is still possible for such an interpretation to apply to a symbol in a shift level other than one if it matches a key without modifiers; the levelOneOnly flag only controls the way that matches are determined and that the key modifiers are applied when an interpretation does match. Applying a symbol interpretation can affect several aspects of the XKB definition of the key symbol mapping to which it is applied: The action specified in the symbol interpretation is bound to the symbol position; any key event which yields that symbol will also activate the new action. If the matching symbol is in position G1L1, the autorepeat behavior of the key is set from the autorepeat field of the symbol interpretation. The ExplicitAutoRepeat component protects the autorepeat status of a key from symbol interpretation initiated changes. If the symbol interpretation specifies an associated virtual modifier, that virtual modifier is added to the virtual modifier map for the key. The ExplicitVModMap component guards the virtual modifier map for a key from automatic changes. If the levelOneOnly flag is set for the interpretation, and the symbol in question is not in position G1L1, the virtual modifier map is not updated. If the matching symbol is in position G1L1, and the locking key field is set in the symbol interpretation, the behavior of the key is changed to KB_Lock (see Key Behavior). The ExplicitBehavior component prevents this change. If no interpretations match a given symbol or key, the server uses: SA_NoAction , autorepeat enabled, non-locking key. with no virtual modifiers. If all of the actions computed for a key are SA_NoAction , the server assigns an length zero list of actions to the key. If the core protocol modifier mapping is changed, the server regenerates actions for the affected keys. The XkbSetMap and XkbSetCompatMap requests can also cause actions for some or all keyboard keys to be recomputed. Updating Everything Else Changes to the symbols or modifier mapping can affect the bindings of virtual modifiers. If any virtual modifiers change, XKB updates all of its data structures to reflect the change. Applying virtual modifier changes to the keyboard mapping night result in changes to types, the group compatibility map, indicator maps, internal modifiers or ignore locks modifiers. Effects of XKB on Core Protocol Events After applying server actions which modify the base, latched or locked modifier or group state of the keyboard, the X server recomputes the effective group and state. Several components of the keyboard state are reported to XKB-aware clients depending on context (see Keyboard State for a detailed description of each of the keyboard state components): The effective modifier state is reported in XkbStateNotify events and in response to XkbGetState requests. The symbol lookup state is reported to XKB-aware clients in the state field of core protocol and input extension key press and release events that do not activate passive grabs. Unless the LookupStateWhenGrabbed per-client flag is set, the lookup state is only reported in these events when no grabs are active. The grab state is reported to XKB-aware clients in the state field of all core protocol events that report keyboard state, except KeyPress and KeyRelease events that do not activate passive grabs. The effective group is the sum of the base, latched and locked keyboard groups. An out of range effective group is wrapped or truncated into range according to the setting of the groupsWrap flag for the keyboard. The server reports compatibility states to any clients that have not issued a successful XkbUseExtension request. The server computes the compatibility symbol lookup state and the compatibility effective grab state by applying the compatibility modifier map to the corresponding computed XKB states. The compatibility symbol lookup state is reported to non-XKB clients whenever an XKB-aware client would receive the XKB lookup state. The compatibility grab state is reported to XKB-unaware clients whenever an XKB client would receive the XKB grab state. If the GrabsUseXKBState per-client option is not set, even XKB-aware clients receive the compatibility grab state in events that trigger or terminate passive grabs. If this flag is not set, XKB clients also receive the compatibility grab or lookup state whenever any keyboard grab is active. If the LookupStateWhenGrabbed per-client option is set, clients receive either the XKB or compatibility lookup state when the keyboard is grabbed, otherwise they receive either the XKB or compatibility grab state. All non-XKB clients receive the compatibility form of the appropriate state component; the form that is sent to an XKB-aware client depends on the setting of the GrabsUseXKBState option for that client. Effect of XKB on Core Protocol Requests Whenever a client updates the keyboard mapping using a core protocol request, the server saves the requested core protocol keyboard mapping and reports it to any clients that issue GetKeyboardMapping or GetModifierMapping requests. Whenever a client updates the keyboard mapping using XKB requests, the server discards the affected portion of the stored core keyboard description and regenerates it based on the XKB description of the keyboard. The symbols associated with the XKB keyboard description appear in the order: G1L1 G1L2 G2L1 G2L2 G1L3-n G2L3-n G3L* G4L* If the type associated with Group1 is width one, the second symbol is NoSymbol ; if the type associated with Group2 is width one, the fourth symbol is NoSymbol . If a key has only one group but the keyboard has several, the symbols for Group1 are repeated for each group. For example, given a keyboard with three groups and a key with one group that contains the symbols { a A }, the core protocol description would contain the six symbols: { a A a A a A }. As a slightly more complicated example, an XKB key which had a single width three group with the symbols { a b c } would show up in the generated core protocol keyboard description with the symbols { a b a b c c a b c } for a keyboard with three groups. The generated modifier mapping for a key contains all of the modifiers affected by all of the actions associated with the key plus all of the modifiers associated with any virtual modifiers bound to the key by the virtual modifier mapping. If any of the actions associated with a key affect any component of the keyboard group, any modifiers specified in any entry of the group compatibility map (see Group Compatibility Map) are reported in the modifier mask. The SA_ISOLock action can theoretically affect any modifier, but the modifier map of an SA_ISOLock key contains only the modifiers or group state that it sets by default. The server notifies interested clients of keyboard map changes in one of two ways. It sends XkbMapNotify to clients that have explicitly selected them and core protocol MappingNotify events to clients that have not. Once a client requests XkbMapNotify events, the server stops sending it MappingNotify events to inform it of keyboard changes. Sending Events to Clients XKB normally assumes that events sent to clients using the core protocol SendEvent request contain a core protocol state, if applicable. If the client which will receive the event is not XKB-capable, XKB attempts to convert the core state to an XKB state as follows: if any of the modifiers bound to Group2 in the group compatibility map are set in the event state, XKB clears them in the resulting event but sets the effective group in the event state to Group2 . If the PCF_SendEventUsesXKBState per-client flag is set at the time of the SendEvent request, XKB instead assumes that the event reported in the event is an XKB state. If the receiving client is not XKB-aware, the extension converts the XKB state (which contains the effective state in bits 13-14) to a core state by applying the group compatibility map just as it would for actual key events.