Skip to content

Chapter 20. Server Database of Keyboard Components

The X server maintains a database of keyboard components, identified by component type. The database contains all the information necessary to build a complete keyboard description for a particular device, as well as to assemble partial descriptions. Table 20.1 identifies the component types and the type of information they contain.

Table 20.1. Server Database Keyboard Components

Component TypeComponent Primary ContentsMay also contain
Keymap

Complete keyboard description

Normally assembled using a complete component from each of the other types

 
Keycodes

Symbolic name for each key

Minimum and maximum legal keycodes

Aliases for some keys

Symbolic names for indicators

Description of indicators physically present

TypesKey types Real modifier bindings and symbolic names for some virtual modifiers
CompatibilityRules used to assign actions to keysyms

Maps for some indicators

Real modifier bindings and symbolic names for some virtual modifiers

Symbols

Symbol mapping for keyboard keys

Modifier mapping

Symbolic names for groups

Explicit actions and behaviors for some keys

Real modifier bindings and symbolic names for some virtual modifiers

GeometryLayout of the keyboard

Aliases for some keys; overrides keycodes component aliases

Symbolic names for some indicators

Description of indicators physically present


While a keymap is a database entry for a complete keyboard description, and therefore logically different from the individual component database entries, the rules for processing keymap entries are identical to those for the individual components. In the discussion that follows, the term component is used to refer to either individual components or a keymap.

There may be multiple entries for each of the component types. An entry may be either complete or partial . Partial entries describe only a piece of the corresponding keyboard component and are designed to be combined with other entries of the same type to form a complete entry.

For example, a partial symbols map might describe the differences between a common ASCII keyboard and some national layout. Such a partial map is not useful on its own because it does not include those symbols that are the same on both the ASCII and national layouts (such as function keys). On the other hand, this partial map can be used to configure any ASCII keyboard to use a national layout.

When a keyboard description is built, the components are processed in the order in which they appear in Table 20.1; later definitions override earlier ones.

Component Names

Component names have the form " class(member) " where class describes a subset of the available components for a particular type and the optional member identifies a specific component from that subset. For example, the name "atlantis(acme)" for a symbols component might specify the symbols used for the atlantis national keyboard layout by the vendor "acme." Each class has an optional default member — references that specify a class but not a member refer to the default member of the class, if one exists. Xkb places no constraints on the interpretation of the class and member names used in component names.

The class and member names are both specified using characters from the Latin-1 character set. Xkb implementations must accept all alphanumeric characters, minus (‘-’) and underscore (‘_’) in class or member names, and must not accept parentheses, plus, vertical bar, percent sign, asterisk, question mark, or white space. The use of other characters is implementation-dependent.

Listing the Known Keyboard Components

You may ask the server for a list of components for one or more component types. The request takes the form of a set of patterns, one pattern for each of the component types, including a pattern for the complete keyboard description. To obtain this list, use XkbListComponents .

XkbComponentListPtr XkbListComponents ( dpy , device_spec , ptrns , max_inout )
Display * dpy ; /* connection to X server */
unsigned int device_spec ; /* device ID, or XkbUseCoreKbd */
XkbComponentNamesPtr ptrns ; /* namelist for components of interest */
int * max_inout ; /* max # returned names, # left over */

XkbListComponents queries the server for a list of component names matching the patterns specified in ptrns . It waits for a reply and returns the matching component names in an XkbComponentListRec structure. When you are done using the structure, you should free it using XkbFreeComponentList . device_spec indicates a particular device in which the caller is interested. A server is allowed (but not required) to restrict its reply to portions of the database that are relevant for that particular device.

ptrns is a pointer to an XkbComponentNamesRec , described below. Each of the fields in ptrns contains a pattern naming the components of interest. Each of the patterns is composed of characters from the ISO Latin1 encoding, but can contain only parentheses, the wildcard characters ‘ ? ’ and ‘ * ’, and characters permitted in a component class or member name (see section 20.1). A pattern may be NULL , in which case no components for that type is returned. Pattern matches with component names are case sensitive. The ‘ ? ’ wildcard matches any single character, except a left or right parenthesis; the ‘ * ’ wildcard matches any number of characters, except a left or right parenthesis. If an implementation allows additional characters in a component class or member name other than those required by the Xkb extension (see section 20.1), the result of comparing one of the additional characters to either of the wildcard characters is implementation-dependent.

If a pattern contains illegal characters, the illegal characters are ignored. The matching process is carried out as if the illegal characters were omitted from the pattern.

max_inout is used to throttle the amount of data passed to and from the server. On input, it specifies the maximum number of names to be returned (the total number of names in all component categories). Upon return from XkbListComponents , max_inout contains the number of names that matched the request but were not returned because of the limit.

The component name patterns used to describe the request are passed to XkbListComponents using an XkbComponentNamesRec structure. This structure has no special allocation constraints or interrelationships with other structures; allocate and free this structure using standard malloc and free calls or their equivalent:

typedef struct _XkbComponentNames {
      char *       keymap;    /* keymap names */
      char *       keycodes;  /* keycode names */
      char *       types;     /* type names */
      char *       compat;    /* compatibility map names */
      char *       symbols;   /* symbol names */
      char *       geometry;  /* geometry names */
} XkbComponentNamesRec, *XkbComponentNamesPtr;
typedef struct _XkbComponentNames {
      char *       keymap;    /* keymap names */
      char *       keycodes;  /* keycode names */
      char *       types;     /* type names */
      char *       compat;    /* compatibility map names */
      char *       symbols;   /* symbol names */
      char *       geometry;  /* geometry names */
} XkbComponentNamesRec, *XkbComponentNamesPtr;

XkbListComponents returns a pointer to an XkbComponentListRec :

typedef struct _XkbComponentList {
      int                  num_keymaps;     /* number of entries in keymap */
      int                  num_keycodes;    /* number of entries in keycodes */
      int                  num_types;       /* number of entries in types */
      int                  num_compat;      /* number of entries in compat */
      int                  num_symbols;     /* number of entries in symbols */
      int                  num_geometry;    /* number of entries in geometry;
      XkbComponentNamePtr  keymap;          /* keymap names */
      XkbComponentNamePtr  keycodes;        /* keycode names */
      XkbComponentNamePtr  types;           /* type names */
      XkbComponentNamePtr  compat;          /* compatibility map names */
      XkbComponentNamePtr  symbols;         /* symbol names */
      XkbComponentNamePtr  geometry;        /* geometry names */
} XkbComponentListRec, *XkbComponentListPtr;
typedef struct _XkbComponentList {
      int                  num_keymaps;     /* number of entries in keymap */
      int                  num_keycodes;    /* number of entries in keycodes */
      int                  num_types;       /* number of entries in types */
      int                  num_compat;      /* number of entries in compat */
      int                  num_symbols;     /* number of entries in symbols */
      int                  num_geometry;    /* number of entries in geometry;
      XkbComponentNamePtr  keymap;          /* keymap names */
      XkbComponentNamePtr  keycodes;        /* keycode names */
      XkbComponentNamePtr  types;           /* type names */
      XkbComponentNamePtr  compat;          /* compatibility map names */
      XkbComponentNamePtr  symbols;         /* symbol names */
      XkbComponentNamePtr  geometry;        /* geometry names */
} XkbComponentListRec, *XkbComponentListPtr;
typedef struct _XkbComponentName {
      unsigned short         flags;     /* hints regarding component name */
      char *                 name;      /* name of component */
} XkbComponentNameRec, *XkbComponentNamePtr;
typedef struct _XkbComponentName {
      unsigned short         flags;     /* hints regarding component name */
      char *                 name;      /* name of component */
} XkbComponentNameRec, *XkbComponentNamePtr;

Note that the structure used to specify patterns on input is an XkbComponentNamesRec , and that used to hold the individual component names upon return is an XkbComponentNameRec (no trailing ‘s’ in Name).

When you are done using the structure returned by XkbListComponents , free it using XkbFreeComponentList .

void XkbFreeComponentList (list)
XkbComponentListPtr list; /* pointer to XkbComponentListRec to free */

Component Hints

A set of flags is associated with each component; these flags provide additional hints about the component’s use. These hints are designated by bit masks in the flags field of the XkbComponentNameRec structures contained in the XkbComponentListRec returned from XkbListComponents . The least significant byte of the flags field has the same meaning for all types of keyboard components; the interpretation of the most significant byte is dependent on the type of component. The flags bits are defined in Table 20.2. The symbols hints in Table 20.2 apply only to partial symbols components (those with XkbLC_Partial also set); full symbols components are assumed to specify all of the pieces.

The alphanumeric, modifier, keypad or function keys symbols hints should describe the primary intent of the component designer and should not be simply an exhaustive list of the kinds of keys that are affected. For example, national keyboard layouts affect primarily alphanumeric keys, but many affect a few modifier keys as well; such mappings should set only the XkbLC_AlphanumericKeys hint. In general, symbols components should set only one of the four flags ( XkbLC_AlternateGroup may be combined with any of the other flags).

Table 20.2. XkbComponentNameRec Flags Bits

Component TypeComponent Hints (flags)MeaningValue
All Components

XkbLC_Hidden

Do not present to user(1L<<0)
 XkbLC_DefaultDefault member of class(1L<<1)
 XkbLC_PartialPartial component(1L<<2)
Keymapnone  
Keycodesnone  
Typesnone  
Compatibilitynone  
SymbolsXkbLC_AlphanumericKeysBindings primarily for alphanumeric keyboard section(1L<<8)
 XkbLC_ModifierKeysBindings primarily for modifier keys(1L<<9)
 XkbLC_KeypadKeysBindings primarily for numeric keypad keys(1L<<10)
 XkbLC_FunctionKeysBindings primarily for function keys(1L<<11)
 XkbLC_AlternateGroupBindings for an alternate group(1L<<12)
Geometrynone  

Building a Keyboard Description Using the Server Database

A client may request that the server fetch one or more components from its database and use those components to build a new server keyboard description. The new keyboard description may be built from scratch, or it may be built starting with the current keyboard description for a particular device. Once the keyboard description is built, all or part of it may be returned to the client. The parts returned to the client need not include all of the parts used to build the description. At the time it requests the server to build a new keyboard description, a client may also request that the server use the new description internally to replace the current keyboard description for a specific device, in which case the behavior of the device changes accordingly.

To build a new keyboard description from a set of named components, and to optionally have the server use the resulting description to replace an active one, use XkbGetKeyboardByName .

XkbDescPtr XkbGetKeyboardByName ( dpy , device_spec , names , want , need , load )
Display * dpy ; /* connection to X server */
unsigned int device_spec ; /* device ID, or XkbUseCoreKbd */
XkbComponentNamesPtr names ; /* names of components to fetch */
unsigned int want ; /* desired structures in returned record */
unsigned int need ; /* mandatory structures in returned record */
Bool load ; /* True => load into device_spec */

names contains a set of expressions describing the keyboard components the server should use to build the new keyboard description. want and need are bit fields describing the parts of the resulting keyboard description that should be present in the returned XkbDescRec .

The individual fields in names are component expressions composed of keyboard component names (no wildcarding as may be used in XkbListComponents ), the special component name symbol ‘%’, and the special operator characters ‘ + ’ and ‘ | ’. A component expression is parsed left to right, as follows:

  • The special component name " computed " may be used in keycodes component expressions and refers to a component consisting of a set of keycodes computed automatically by the server as needed.

  • The special component name " canonical " may be used in types component expressions and refers to a partial component defining the four standard key types: ALPHABETIC , ONE_LEVEL , TWO_LEVEL , and KEYPAD .

  • The special component name ‘ % ’ refers to the keyboard description for the device specified in device_spec or the keymap names component. If a keymap names component is specified that does not begin with ‘+’ or ‘|’ and does not contain ‘ % ’, then ‘ % ’ refers to the description generated by the keymap names component. Otherwise, it refers to the keyboard description for device_spec .

  • The ‘ + ’ operator specifies that the following component should override the currently assembled description; any definitions that are present in both components are taken from the second.

  • The ‘ | ’ operator specifies that the next specified component should augment the currently assembled description; any definitions that are present in both components are taken from the first.

  • If the component expression begins with an operator, a leading ‘ % ’ is implied.

  • If any unknown or illegal characters appear anywhere in the expression, the entire expression is invalid and is ignored.

For example, if names->symbols contained the expression "+de", it specifies that the default member of the "de" class of symbols should be applied to the current keyboard mapping, overriding any existing definitions (it could also be written "+de(default)").

Here is a slightly more involved example: the expression "acme(ascii)+de(basic)|iso9995-3" constructs a German (de) mapping for the ASCII keyboard supplied by the "acme" vendor. The new definition begins with the symbols for the ASCII keyboard for Acme ( acme(ascii) ), overrides them with definitions for the basic German keyboard ( de(basic) ), and then applies the definitions from the default iso9995-3 keyboard ( iso9995-3 ) to any undefined keys or groups of keys (part three of the iso9995 standard defines a common set of bindings for the secondary group, but allows national layouts to override those definitions where necessary).

Note

The interpretation of the above expression components (acme, ascii, de, basic, iso9995-3) is not defined by Xkb; only the operations and their ordering are.

Note that the presence of a keymap names component that does not contain ‘ % ’ (either explicit or implied by virtue of an expression starting with an operator) indicates a description that is independent of the keyboard description for the device specified in device_spec . The same is true of requests in which the keymap names component is empty and all five other names components contain expressions void of references to ‘ % ’. Requests of this form allow you to deal with keyboard definitions independent of any actual device.

The server parses all non- NULL fields in names and uses them to build a keyboard description. However, before parsing the expressions in names , the server ORs the bits in want and need together and examines the result in relationship to the expressions in names . Table 20.3 identifies the components that are required for each of the possible bits in want or need . If a required component has not been specified in the names structure (the corresponding field is NULL ), the server substitutes the expression " % ", resulting in the component values being taken from device_spec . In addition, if load is True , the server modifies names if necessary (again using a " % " entry) to ensure all of the following fields are non- NULL : types , keycodes , symbols , and compat .

Table 20.3. Want and Need Mask Bits and Required Names Components

want or need mask bitRequired names Componentsvalue
XkbGBN_TypesMaskTypes(1L<<0)
XkbGBN_CompatMapMaskCompat(1L<<1)
XkbGBN_ClientSymbolsMaskTypes + Symbols + Keycodes(1L<<2)
XkbGBN_ServerSymbolsMaskTypes + Symbols + Keycodes(1L<<3)
XkbGBN_SymbolsMaskSymbols(1L<<1)
XkbGBN_IndicatorMapMaskCompat(1L<<4)
XkbGBN_KeyNamesMaskKeycodes(1L<<5)
XkbGBN_GeometryMaskGeometry(1L<<6)
XkbGBN_OtherNamesMaskTypes + Symbols + Keycodes + Compat + Geometry(1L<<7)
XkbGBN_AllComponentsMask (0xff)

need specifies a set of keyboard components that the server must be able to resolve in order for XkbGetKeyboardByName to succeed; if any of the components specified in need cannot be successfully resolved, XkbGetKeyboardByName fails.

want specifies a set of keyboard components that the server should attempt to resolve, but that are not mandatory. If the server is unable to resolve any of these components, XkbGetKeyboardByName still succeeds. Bits specified in want that are also specified in need have no effect in the context of want .

If load is True , the server updates its keyboard description for device_spec to match the result of the keyboard description just built. If load is False , the server’s description for device device_spec is not updated. In all cases, the parts specified by want and need from the just-built keyboard description are returned.

The names structure in an XkbDescRec keyboard description record (see Chapter 18) contains one field for each of the five component types used to build a keyboard description. When a keyboard description is built from a set of database components, the corresponding fields in this names structure are set to match the expressions used to build the component.

The entire process of building a new keyboard description from the server database of components and returning all or part of it is diagrammed in Figure 20.1:

Building a New Keyboard Description from the Server Database

The information returned to the client in the XkbDescRec is essentially the result of a series of calls to extract information from a fictitious device whose description matches the one just built. The calls corresponding to each of the mask bits are summarized in Table 20.4, together with the XkbDescRec components that are filled in.

Table 20.4. XkbDescRec Components Returned for Values of Want & Needs

Request (want+need)Fills in Xkb componentsEquivalent Function Call
XkbGBN_TypesMaskmap.typesXkbGetUpdatedMap(dpy, XkbTypesMask, Xkb)
XkbGBN_ServerSymbolsMaskserverXkbGetUpdatedMap(dpy, XkbAllClientInfoMask, Xkb)
XkbGBN_ClientSymbolsMaskmap, including map.typesXkbGetUpdatedMap(dpy, XkbAllServerInfoMask, Xkb)
XkbGBN_IndicatorMapsindicatorsXkbGetIndicatorMap(dpy, XkbAllIndicators, Xkb)
XkbGBN_CompatMapMaskcompatXkbGetCompatMap(dpy, XkbAllCompatMask, Xkb)
XkbGBN_GeometryMaskgeomXkbGetGeometry(dpy, Xkb)
XkbGBN_KeyNamesMask

names.keys

names.key_aliases

XkbGetNames(dpy, XkbKeyNamesMask | XkbKeyAliasesMask, Xkb)
XkbGBN_OtherNamesMask

names.keycodes

names.geometry

names.symbols

names.types

map.types[*].lvl_names[*]

names.compat

names.vmods

names.indicators

names.groups

names.radio_groups

names.phys_symbols

XkbGetNames(dpy, XkbAllNamesMask &

~(XkbKeyNamesMask | XkbKeyAliasesMask),

Xkb)


There is no way to determine which components specified in want (but not in need ) were actually fetched, other than breaking the call into successive calls to XkbGetKeyboardByName and specifying individual components.

XkbGetKeyboardByName always sets min_key_code and max_key_code in the returned XkbDescRec structure.

XkbGetKeyboardByName is synchronous; it sends the request to the server to build a new keyboard description and waits for the reply. If successful, the return value is non-NULL. XkbGetKeyboardByName generates a BadMatch protocol error if errors are encountered when building the keyboard description.

If you simply want to obtain information about the current keyboard device, rather than generating a new keyboard description from elements in the server database, use XkbGetKeyboard (see section 6.2).

XkbDescPtr XkbGetKeyboard ( dpy , which , device_spec )
Display * dpy ; /* connection to X server */
unsigned int which ; /* mask of components of XkbDescRec of interest */
unsigned int device_spec ; /* device ID */

XkbGetKeyboard is used to read the current description for one or more components of a keyboard device. It calls XkbGetKeyboardByName as follows:

XkbGetKeyboardByName ( dpy , device_spec , NULL , which , which , False ).