The XKB configuration has been decomposed into a number of components. The basic idea is that you can adopt a mix-and-match approach to building a keyboard configuration. Some pretty sophisticated inclusion and augmentation rules allow a component to be built from a basic set-up and a number of modifications for odd keyboard layouts and national peculiarities. The basic components are:
There are a number of other components: rules, semantics, keymaps that are essentially ways of packaging the main components into more usable collections.
The modifier keys are those keys, like Shift, Control or Alt that are used to change the meaning of other keys. Modifier keys can be combined, to give combinations like Control+Shift+Alt. Handling extended combinations of modifier keys is, to a certain extent, what makes XKB so complex.
At the base level, XKB recognises eight modifier keys: the explicitly named Control, Shift and Lock keys and the generic Mod1-Mod5 keys. These keys correspond to the keys in the core X protocol and need to be there so that older programs can understand what's going on. Keys like the ubiquitous Alt keys are mapped onto one of the Mod keys.
The basic modifier keys are all very well but it would be handy to be able to introduce a level of abstraction, so that you can talk about modifier keys by function, rather than by explicit key name. XKB allows the use of virtual modifier keys, where a basic modifier key (or combination) is mapped onto a named virtual modifier. Virtual modifiers can then be used to describe the behaviour of the keyboard, decoupling the exact physical capabilities of the keyboard you are using from the sort of characters that you want to type. The types and compat components are largely responsible for handling this side of things.
Once the modifier keys have been set up, it now becomes possible to have different combinations of keys produce different characters from the keyboard. In theory, you could do more or less anything that you wanted to here. However, a complete free for all approach would make combining different components very difficult. To provide some structure, XKB uses two organising principles: levels and groups.
A level represents the sort of thing that a shift key is expected to do. Normally, when you press the key marked A you would expect an a character to appear. If you hold the shift key down and press the same key, you would expect an A to appear instead.
The a and A characters are clearly related. And this is what you would expect a level shift to do, provide you with some sort of variation of the same thing, capitalisation in this case. Combinations such as 8 and * are less obvious, but have a sort of honorary status, since they appear together on both Qwerty and Dvorak layouts.
For most purposes, two levels are enough, shifted and non-shifted. There is a fairly standard way of invoking different levels, which is to press the Shift or Lock keys. This nice state of affairs is complicated by keys that don't have multiple levels -- such as the Return key -- and keys that often have more complex levels -- such as the numeric keypad. But more on that later.
In contrast to levels, which are relatively straightforward, groups are a more slippery concept. The basic idea behind groups is that, sometimes, you want to shift the entire keyboard over to some other character set, so that you can access characters not usually considered part of a standard keyboard, such as , , or . The need for these characters isn't so obvious for an English speaker but people who write in languages with richer character sets than English, such as Czech, Arabic or Chinese, not to mention those writing mathematics or using languages such as A, will immediately see the need for multiple groups.
The keys needed to shift groups are less obvious than those needed to shift levels, since there isn't any immediate equivalent to the Shift key and the Alt key is often given other duties. The standard XKB configuration files supply a number of possible combinations that could be used and it's up to the user to choose what they want.
Within each group, there can be multiple levels, with each level reflecting the suitable shifts for the characters in the group. For example, would be shifted to , as shown in figure 1
At the bottom of the XKB food chain are key codes. Raw key codes are the numeric codes generated by a particular keyboard to indicate that a key has been pressed or released. The X system generates two events for each key press: one to indicate that the key has been pressed, one to indicate that it has been released.4In both cases, the key code indicates which key has been pressed or released.
Hardware designers are free to choose whatever numbers they like for keycodes. So, left to themselves, raw keycodes tend to obscure the fact that most keyboards, no matter who made them, have a similar layout. The keycodes component of XKB allows symbolic names to be assigned to the various key codes. These symbolic names can then be used to look up similar keyboard layouts in the symbols component (see below).
Key symbols are the actual characters or glyphs that pressing a key produces. A symbols map maps symbolic key codes (see above) onto the appropriate symbol. Symbols map also handle specifications for which keys are modifier keys.
Each symbol has a name, defined as part of the X protocol, with a few extra added by XKB.[7,3]. The actual symbol names are taken, as far as I can see from the /usr/X11R6/include/X11/keysymdefh file. Each name is the name in this list, with the initial XK_ stripped off. The name of simple symbols, such as a is a. The name of more complex symbols, such as , is spelt out as ssharp. The XKB protocol specification also spells out a number of odd key symbols in appendix C.
Groups and levels (see section 2.2) alter the meaning of the keys on the keyboard. The symbol map is, therefore, similar to a matrix. Symbol maps usually list multiple symbols for each key, with the group and level being used to look up the appropriate symbol.
Doug Palmer 2004-10-11