Some words about XKB internals.
The main XKB module function is convertion of the pressed keys scan-codes to the symbol codes.
In the XKB documentation scan-codes are named keycodes and the symbols codes are named simply symbols.
Of course the "symbols" term doesn't mean printable symbol codes only (letters, digits, punctuation, etc.). This term includes "control symbols" (such as Esc, Enter, Backspace, etc.) and codes that can influence to state of XKB itself and so to other symbols choice procedure (alphabet switcher, Control, Shift, Alt, etc.).
First of all I should tell some words how scan-codes to symbols conversion occurs in the X Window System without XKB module.
The X-server itself doesn't converts keycode to symbol. When you press or release any key X-server keyboard module sends "message about event" (or simply event) to application.
Such message contains scan-code and "keyboard state" only. The keyboard state is bit flags set that reflects the state of "modifer keys" - Shift, Control, Alt, CapsLock, etc.
So namely application has to decide what symbol match to this scan-code when such modifiers are set.
Of course for this purpose application can use "keyboard map table" stored in the X-server that contain lists of all possible symbols for each scan-code. Usually application gets this table from the X-server at start time.
Of course nobody writes such scan-code interpretation procedure for each application. There are special subroutines for this purpose in Xlib library.
So Xlib procedures knowing scan-code and modifiers state from event message choose appropriate symbol from keyboard map table derived from server at startup.
And the XKB module too sends to application scan-code and own state only. But unlike old module XKB have more complicated symbols table, different modifiers set and some other components of keyboard state.
Therefore for right working Xlib must contain procedures that are "XKB aware". Of course X's that have server with XKB module also has XKB-aware Xlib.
So we can say that the XKB consists of two parts - module built in server and Xlib subroutines set that are part of each application.
But nobody forbids to use applications that was linked with old Xlib that doesn't know about XKB. It leads to "compatibility problem". XKB must be able to communicate with own Xlib and with old "non XKB-aware" Xlib too.
What is simbols table that binds symbols with keycodes and modifiers state? Lets look for begining to "traditional" symbols table being used before XKB.
Like in many another keyboard modules it can be represented as simple two-dimensional table where each row corresponds to keycode and each column corresponds to modifier or modifiers combination.
First of all note that in the key press/release event only one byte (octet) allocated for modifiers. So there can be eight modifiers only. First three ones are named Shift, Lock, Control and all other are "unnamed" - Mod1, Mod2, Mod3, Mod4, Mod5.
But it's more important that the eight modifiers can form up to 256 different combinations. So in theory symbols table can include up to 256 columns. In the same time old standard strongly defines only first four columns. You can guess that only two modifiers are used to distinguish these columns, they are Shift and Mode_switch. (You can see that there isn't modifier with name Mode_switch. Yes, it's right. One of unnamed modifiers plays this role. And Mode_switch is name of one of control symbols. When application requests symbol table from server it also asks what modifier is bound to this control symbol.)
So first four columns corresponds to states:
Also note that neither Lock nor Control don't paricipate in symbol choice. If these modifiers are active so special Xlib subroutines makes additional convertion for symbol after its choice.
Lets return to XKB module. You can see that the main disadvantage of traditional symbols table is its unflexibility. Though there can be up to 256 columns but only first four can be standardly processed and their dependence on modifiers hardcoded in Xlib.
Therefore one of the basic improvements brought by XKB is large flexibility in the table construction.
It is very usefull to devide table into groups. First of all it makes easier to separate different alphabets in one keyboard map. Note that someone use two and more alphabets simultaneously. And strong bounds between alphabets allow to complete such parts independly.
So XKB design use radical approach - one keybord map can contain some (up to four) tables. And these different table in XKB has name "XKB groups" (or simply groups).
It is more correctly to tell not "some two-dimensional tables in one map" but "each keycode can have up to four one-dimensional tables - groups".
And finally I should say that the number of groups can be from 1 to 4 and number of levels can be up to 64.
Besides "symbols table" keycode can have bound "actions table". This table also can be devided to group sub-tables and levels.
Unlike symbols table that is used by application (X-server only keeps it) actions table is used by server itself.
But it's more correctly to say that the actions functions isn't limited by XKB state changing. They also are used for:
More detaily about all possible actions you can read in Actions description.
It is important that if some cell (defined by group and shift level)in action table is filled with action so corresponded cell in symbols table must exist and be filled with symbol (usually it's "control symbol").
Note that the old keyboard module has not actions mechanism.
XKB keeps current group number in "internal state" table.
And there is term effective group that is sum of all three mentioned variables. This value XKB server part calculates at every key press or release and reports to application in key event to allow aplication choose needed symbol. (Of course the same value server uses for action choice.)
Of course this sum can be bigger than number of groups are really used in keyboard map. To make from it some reasonable value XKB can use one of three methods:
Besides group number variables "XKB state" contains variables for bit flags that are named modifiers. These flags changes own state when keys like Shift, CapsLock, Alt, Control, etc. are pressed or released.
As I said above old protocol also has modifiers set. Their names are Shift, Lock, Control, Mod1-Mod5. In dependence on their state Xlib choose symbol from symbols table and can perform some additional actions such as make control symbols from ordinar symbols, change small letters to capital ones and so on.
XKB has more modifiers and thier behavior dependence on modifiers can be flexibly changed (not at start only but at work time too). But becouse of compatibility problem XKB needs to emulate traditional modifiers set for old client program (linked with old Xlib).
So traditional modifiers set in XKB have name real modifiers and names of each modifier are the same as in old standard.
Unfortunatly one part of compatibility problem is that the key event allocates only eight bits for modifiers. So there is not way to report all sixteen XKB internal modifiers to the application in key event message. And XKB needs to map own virtual modifiers to real modifiers even when it communicates with XKB-aware application. The only consolation is you can map to one real modifiers as many virtual modifiers as you want.
Modifiers has some function:
Like group number modifiers set inside XKB distributed to three variables
And as for group there is term effective modifiers that is boolean sum (bitwise OR) of three mentioned variables. Of course since it is boolean addition XKB needn't any additional acts to keep sum in range.
XKB doesn't keep shift level like group number inside but calculates it from modifiers state every time when need it. And for each key level from modifiers dependence can be different.
To allow such flexibility XKB uses "key type".
When key is pressed XKB takes key type description from sub-table and useing this description and modifiers state as argument calculates cell number (what shift level means) symbol have to be chosen from.
I should note that though key type for each keycode sub-table can be changed flexibly XKB has "basic set" of key types and each keycode has any type as default. Therefore usually one needn't specify key types in keyboard map.
Besides symbols and actions tables each keycode description has some other variables:
Since different keys can have different number of groups it can occur that the effective group value legal for whole keyboard map is too big for some particilar keys.
Possible methods are the same as "global" ones. By default Wrap method is used.
This variable consists of two parts - boolean flags and additional argument. In most cases additional argument is not needed but some flags assume additional numeric value. Of course argument meaning depends on flag meaning.
These flags defines:
It is bit mask that defines what keycode related data is "specified explicitly" and must not be changed in some cases. The thing is that the X-protocol include commands that allow application change symbol_to_keycode binding in keyboard map inside X-server. Of course these commands changes symbols placement only but doesn't change other data such as action, key behavior or key bound modifiers.
To allow XKB to move this data at symbol moving there is special mechanism - symbol interpretation. Useing this mechanism XKB can move non-symbol data bound to keycode when application requests the symbol moving.
But in some cases such changes can be considered as unwanted. So exceptions set can protect keycode related data against such implicit changes.
This mask can forbid
First of all note that there are two variables for each keycode (modmap and vmodmap) one variable for real modifier and anoter one for virtual modifiers.
The real modifier is used for traditional modifiers set emualtion but virtual modifier can be used as argument for actions bound to this key.
I should say that the virtual modifiers set (base, locked and latched can be changed by appropriate action. Of course this action must has argument that describes what modifiers will be switched on/off. And if you describe such action you can specify modifiers names explicitly or refer to vmodmap (that means "set/unset modifiers bound to this key").
But modifiers in the "emulated traditional modifiers set" changes automaticaly at key press/release. You can guess that the "emulated modifier" for particular key is modifier keeped in the real modifier variable (modmap) of this key.
Also these two variable are used for the virtual_to_real modifier mapping. Remember that the virtual modifier has not any effect while it is not mapped to any real modifier.
Besides group number and modifiers set there is another one set of bit flags in XKB state. But in difference to group and modifiers that are distributed to three variables (base, locked, latched) this set occupate only one variable.
Control flags set contain flags that are used for switching XKB modes and isn't reported to application.
XKB controls (like group number and modifers) can be changed by appropriate action bound to some keys.
You know that besides key keyboard has some indicator LEDs. These indicators management is XKB duty too.
Each indicator can be bound to some component of "XKB state" (modifier, group number or XKB control flag) and so indicator state will reflect state of own XKB state component.
And there are special XKB protocol requests that can be used by application to change some indicator state (to switch on/off). Note that I talk about possibility to switching on/off LED only but not about changeing keyboard state component bound to this lamp.
Therefore each indicator description has some flags that defines:
As I already mentioned above, XKB needs to solve the "compatibility problem" working with application that aren't XKB-aware and that use traditional protocol requests.
Of course XKB can process such requests but the problem is that the XKB has some new terms and mechanisms absent in traditional protocol (core protocol). You guess that the core protocol requests doesn't deal with these mechanisms.
Few other terms.
XKB module allow to unite some keys to one radio-group. It means that all keys states in such group depends on each other. At one key press all other keys become unpressed.
Of course pressed key will stay in pressed state until some other key of group will be pressed. The belonging of concrete key to radio-group can be defined in "key behavior".
In the same place you can specify one additional property for radio-group that defines possibility to release all keys simultaneously. Usual radio-group definition assumes that the one of keys always must be in pressed state. To release it you need to press any another key but in such case this second key become pressed. If radio-group has property "allow to release all keys" you can simply press logicaly pressed key one more time and this key (and all other from group) will become logicaly unpressed.
XKB allow to have up to 127 radio groups.
XKB allow some keys to have alternative scan-code (keycode). It means that in normal state when such key is pressed and keyboard generates its scan-code XKB use this scan-code in usual way. But when overlay mode is switched on XKB replaces this scan-code by alternative one ant then deal with this new code.
Such group of keys that has alternative keycodes is named "overlay group" (or simply overlay). There can be only two such group. The belonging of concrete key to overlay group and alternative keycode itself can be defined in "key behavior".
There are people who has limited mobility of hands (fingers) or need to use some devices to access keyboard.
The problems can occur are:
All these modes are performed by part of XKB module that has name AccessX. Each mode can be switched on/off by change of XKB control flags with the same names.
Also note the AccessX modes switching on itself can be a problem. (Lets imagine that user needs StickyKeys mode but to switch it on he need to press complex key combination). Therefore to switch on some modes the special actions are used:
But to make the XKB recognize such "magic sequences" a special mode (AccessXKeys) must be switched on in its own turn. To activate it you can ...
On the other hand if one of AccessX modes is active but computer is used by different users this mode can disturb some people. Therefore the XKB has special option that allow automatically switch off AccessX modes if keyboard stay not in use long time. And StickyKeys mode (simultaneous key pressing emulation by sequental press) become inactive if you will press some keys really simultaneously.
And finally, AccessX has special mode of additional sound indication of all events such as several timeouts begin and end and LEDs switching. To allow users distinguish these events (especially when more then one AccessX mode is active) the XKB tries to make different sounds (in pitch and duration) for different events as far as hardware allow.
The XKB can emulate mouse events by keyboard. It means that it can be configured to produce events about mouse movement and mouse button pressing instead of key press events.
It can be done by corresponded actions such as "pointer movement", "mouse button press", "mouse mouse button choice".
Also there are two modes of mouse pointer movement - the simple movement and the movement with acceleration. At single press there is not difference between these two modes. But if you will keep key pressed and it begin to autorepeat so in normal mode pointer will be moved on the same number of pixels (on value specified in action arguments). But in accelerated mode size of one step will grow from step to step.
This acceleration process has some additional parameters that are saved in XKB internal variables (are the part of XKB state). (I should note that accelearted mode has own autorepeat parameters - delay between physical key press and autorepeat begin and time interval between autorepeat events). So these numeric parameters are:
Mouse emulation switching on/off and movement mode choice can be performed by two XKB control flags - MouseKeys and MouseKeysAccel.
I should note that by default all needed actions are described in the XKB configuration and are bound to NUMPAD keys. To switch on/off the mouse emulation mode you can use Shift+NumLock keys combination.
It can seems that this part has not relation to keyboard.
I should note that bell control presents in old (core protocol) keyboard module. With special requests to X-server application can change key_click parameters (tone, duration and loudness) and produce this sound when it needs.
The XKB module offers advanced bell features and allows not only cause click sound but play music fragment. Of course to provide such "music accompaniment" is too complex task for keyboard module. First aff all it needs some 'sound database' and the second it has to support many different hardware (sound cards).
Therefore XKB design assumes that there must exists special application ("juke-box") for sound play. And the XKB simply generates special event (instead og click sound) that can be delivered to any application as all other events. Juke-box has to say to X-server at start that it acceps some kind of events (in this case xkb bell-events).
Of course, if such music box presents its ability is not limited with bell sound with different tone/duration play. It would can play many music fragments from own database.
So application working with XKB can request not simple bell but any sound specifying its name. Note that XKB doesn't perform any check of such sound names but simply retranslate them to juke-box.
Of course XKB not only retranslates "sound requests" from applications to juke-box but can request sound for own needs (when it changes own state).