Some applications (notably emacs) allow meaningful use of higher state bits. It is usually assumed

Some applications (notably emacs) allow meaningful use of higher state bits. It is usually assumed

Line 439:

Line 439:

}

}

−

Standard definitions use Super modifier instead of Mod3 in xkb_compatibility.

+

Standard definitions use Super modifier instead of Mod3 in {{ic|xkb_compatibility}}.

−

You can keep that, just make sure modifier_map line is in place.

+

You can keep that, just make sure {{ic|modifier_map}} line is in place.

Keep in mind there is no strict correspondence between ModN and named modifiers like Super, Hyper or even Alt.

Keep in mind there is no strict correspondence between ModN and named modifiers like Super, Hyper or even Alt.

Revision as of 22:15, 20 June 2012

X KeyBoard extension, or XKB, defines the way keyboards codes are handled in X,
and provides access to internal translation tables.
It's the basic mechanism that allows using multiple keyboard layouts in X.

Learning about XKB can be hard without some hands-on experience.
This page is intended to help users to start with XKB by doing some changes to their keymaps.
It's not meant as a complete guide to all XKB features. Instead, it skips over gritty details
and focuses on the most practical things first.

Precautions and preparations

It is possible (and, in fact, easy) to end up disabling some keys on your keyboard for the current X session
while working with XKB.
This includes modifiers, cursor arrows and Enter key, as well as C-A-Backspace and C-A-Fx combinations.
Make sure you have some way to terminate the session without using your keyboard.

While it is rare, changing XKB configuration can sometimes hang or crash X server.
Make sure you can handle it.
Having some way to killall X or reboot the host remotely may be a good idea.

Stop xxkb, or any other layout switching applications. xxkb actively changes XKB state.
Debugging both at the same time is not a good idea.

And finally, be warned: it is very easy to get used to custom layout.

Getting and setting XKB layout

Use xkbcomp [xorg-xkbcomp] to manipulate XKB data. To get current configuration, run

xkbcomp $DISPLAY output.xkb

To upload the data back to the server, run

xkbcomp input.xkb $DISPLAY

Note that without $DISPLAY argument xkbcomp will try to compile .xkb file into (mostly useless) .xkm
file, without uploading anything to the server. It will, however, check the syntax and report errors.

Once the layout is ready, save it as ~/.Xkeymap and make ~/.xinitrc load it on startup:

test -f ~/.Xkeymap && xkbcomp ~/.Xkeymap $DISPLAY

The actual file name is irrelevant. Note that unlike standard system-wide configuration via xorg.conf,
this is a per-user keymap.
Also, there is absolutely no problem changing XKB configuration while X is running.

Basic information on XKB

The core XKB functionality is quite simple, and it's necessary to have a some ideas on
how it works before starting working on the keymaps.

Tools and values

Use xev [xorg-xev] to get keycodes and to check how your keymap works. Sample output:

Note keycode 21, state 0x1 and keysym 0x2b aka plus.
Keycode 21 is what input device supplied to X, typically a physical key index of some sort.
The state represents modifier keys, 0x01 is Shift.
Keycode together with the state value is what X sends to the application in XKeyEvent(3) structure.
Keysym and corresponding string is what the client obtained using XLookupString(3) and friends.

The bits in the state field have pre-defined names: Shift, Lock, Control, Mod1, Mod2,
Mod3, Mod4 and Mod5,
lowest to highest. Thus, Template:Keypress is 0x05, and so on. Client applications typically only check the bits
they need, so an application with normal keyboard keyboard input and Template:Keypress shortcuts usually
makes no distinction between Control and Control+Mod3 states.

Keysyms are numeric, too. A lot of them have names, declared in /usr/include/X11/keysymdef.h
with KP_ prefix. However, the number is what clients actually receive.
Keysyms are only important when an application expects some particular values; typically
that's keys like arrows, Enter, Backspace, F-keys, and various shortcuts.
For the rest, the string in used.

Keycode translation

XKB works mostly at the XLookupString stage,
transforming incoming keycode into keysym according to its own internal state, which is
group and state values:

(keycode, group, state) → keysym

Group typically represents a "layout", as in US-English, French-AZERTY, Russian, Greek etc.
There can be at most 4 groups.

with S being the translation table (actually called xkb_symbols, see below).

Types are used to tell which modifiers affect which keys; essentially it's a way to reduce the third dimension
of S. For example, typical alphanumeric key is only affected by Shift; it's type is set to TWO_LEVEL, and

(state, TWO_LEVEL) → level = ((state >> 0) & 0x01) = state & 0x01

which is either 0 or 1. Thus it's S[keycode][0..4][0..1] instead of S[keycode][0..4][0..256].

Keysyms and states

Generally it is XKB task to provide different keysyms, but states are handled later
by individual applications.

Also, states in XKB have somewhat delayed effect, that is, you must have the state set
prior to pressing a key.

Example: Template:Keypress can be configured to act as backspace in rxvt (application setting). This
way rxvt will receive h keysym with Control bit set in the state value, and if will be clearly
different from Backspace keysym.
Alternatively, XKB can be used to make Template:Keypress combination generate Backspace keysym with Control bit set;
in this case, rxvt will not see any difference between physical Template:Keypress key and Template:Keypress key as
long as Template:Keypress key is pressed.
Making Template:Keypress combination generate Backspace keysym with no Control bit set is an XKB task, too,
but it's much more difficult to implement than Control+Backspace.

Actions

Keysym obtained from the table above can also trigger some action:

(keysym, state) → action

For XKB, setting or locking a modifier bit is an action, and so is any X server interaction
like switching consoles, terminating the server, moving pointer etc.
Actions do not generally affect keysyms, and generating a keysym is not an action.

There's only one possible action for each (keysym, state) pair.

Editing the layout

The .xkb file produced by xkbcomp is a simple text file.
C++ style comments, // till the end of line, are allowed.
Section names, as in xkb_keycodes "name-here", are irrelevant at this point and can be omited.

xkb_keycodes

Keycode definition. The rest of the file doesn't use numeric keycodes, only symbolic keylabels
defined in this section.

It's a good idea to leave only those keys the keyboard in question actually has here.

The labels themselves are arbitrary. They are only used in xkb_symbols section later.

xkb_types

This section comes before xkb_symbols, so take a look, but try not to make changes yet.
Standard types depend a lot on virtual modifiers, which will be explained later.
For now, just find the types you need.
Start with the following: ONE_LEVEL, TWO_LEVEL, ALPHABETIC.

xkb_symbols

<LABL> is keylabel from xkb_keycodes section, GiLj is keysym for group i level j.
The number of keysyms in each group must match the number of levels defined for this type
(xkbcomp will warn you if it doesn't).

Check /usr/include/X11/keysymdef.h for the list of possible keysyms.
Aside from those listed, you can also use Unnnn for Unicode symbol with hex code nnnn, e.g.
U0301 for combining acute accent. Note that a and U0061 are treated differently (for instance,
most applications expect Template:Keypress, not Template:Keypress because their numeric values are different.

Typically this means placing ISO_Next_Group and ISO_Prev_Group
keysyms in correct group/level positions. Note that groups wrap, so if you have two groups and hit
ISO_Next_Group twice, you'll return to the group you started with.

Cyclic switching between two or more layouts with a dedicated key:

key.type = "ONE_LEVEL";
key <RWIN> { [ ISO_Next_Group ] }

If you have more than two layouts and some keys to spare, it may be a better idea to have a dedicated
key for each layout. Example for three layouts:

Note standard definitions have LevelThree instead of Mod5 in xkb_compatibility and xkb_types.
As long as modifier_map above uses Mod5, there is no practical difference, you will end up using Mod5
bit anyway.

As you may find out using xev, this produces Mod5+Left instead of just Left. But that is ok as most
appications ignore state bits they do not use.

Meta, Super and Hyper

Real modifiers

Some applications (notably emacs) allow meaningful use of higher state bits. It is usually assumed
there are modifier keys called Meta, Super and Hyper on the keyboard beside standard Shift, Ctrl and Alt,
which control these bits.

From XKB point of view this means setting Mod2, Mod3, Mod4 and Mod5 modifier bits. Because all
you need is the bits themselves, there's no need to edit types like in the Level3 example above.

Standard definitions use Super modifier instead of Mod3 in xkb_compatibility.
You can keep that, just make sure modifier_map line is in place.

Keep in mind there is no strict correspondence between ModN and named modifiers like Super, Hyper or even Alt.
Mod1 is the only one that is widely used; some applications call it Meta, some Alt. For the others,
check how particular application treats state bits, and/or check Virtual modifiers below.

keysym tracking

At least one application (openbox) is known to track KeyPress/KeyRelease events for Meta_[LR], Super_[LR]
and Hyper_[LR] keysyms instead of relying on the state bits. In such case

Preset configuration

XKB is often configured by specifying XkbTypes/XkbCompat/XkbSymbols,
or XkbModel/XkbLayout (+XkbVariant/XkbOptions), or XkbKeymap, typically in
/etc/X11/xorg.conf or /etc/X11/xorg.conf.d/*.conf, like this:

These values define full XKB map (the one that can be dumped by xkbcomp) by combining
several files from /usr/share/X11/xkb. In fact, equivalent .xkb
file for xkbcomp can be obtained using setxkbmap -print:

Just like with xkbcomp approach, this kind of configuration can be done
on the fly: use setxkbmap without -print option.

The files from /usr/share/X11/xkb are a good source of examples, especially when it
comes to standard keyboard features with nontrivial XKB implementation
(e.g. keypad/NumLock handling). Also, these are the files you have to edit to push
your changes upstream. Check X Keyboard Config Rules [freedesktop.org] before doing it though.

xmodmap

While sometimes used in conjunction with preset configuration,
xmodmap is not directly related to XKB. This tool uses different (pre-XKB)
ideas on how keycodes are processed within X; in particular, xmodmap lacks the notion
of groups and types, so trying to set more than one keysym per key is not likely
to work.

Generally it is not recommended to use xmodmap, except maybe for the simpliest tasks.
XKB-compatible equivalent of xmodmap is xkbcomp; however,
xkbcomp lacks -e option, so it is not that simple.
Anyway, whenever possible, xkbcomp should be preferred.

Indicators

As in "keyboard leds".
Indicator names are used to match the to the physical LEDs in xkb_keycodes section.
Otherwise, they are irrelevant. Indicators not matched to any LED are called "virtual";
xkbvleds [xorg-xkbutils] can be used to check their state. Example:

xkb_keycodes {
indicator 1 = "LED1"; // first physical LED
}

Indicators always reflect specified part of XKB internal state. Two common modes is showing
modifier state:

The values are bitmasks. For groups, bit 1 is group 1, bit 2 is group 2 and so on.

Modifiers and types

At some point it may become necessary to clean up types section, and/or to introduce
unusual types.

Types and modifiers are tightly connected, so it makes a lot of sense to start with
the modifier bits first, before doing anything with the type descriptions.

Decide which bits you will use. There are only eight of them, and of those,
Shift, Control and Mod1 are widely used in applications, and Lock (aka CapsLock)
has pre-defined meaning which also may be hard to override.
The remaining four, however, are fair play.

Warning: four standard types, ONE_LEVEL, TWO_LEVEL, ALPHABETIC and KEYPAD, receive
special treatment in xkbcomp. They may work differently just because they are named
this way. Avoid deleting them. If some changes do not work as expected, try adding a new
type instead.

Using real modifiers in standard types

Depending of your base configuration, there may be a lot of unused standard types
like EIGHT_LEVEL or PC_RCONTROL_LEVEL2.
Remove them now to avoid doing unnecessary work.

Now, some standard types use virtual modifiers. If you decide to use them, check
Virtual modifiers below and skip this section. Otherwise, it's a good idea
to get rid of them completely. Check the types you need, and either replace them
with corresponding real ones, or remove relevant definitions. Example:

Aside from SetMods, you can also use LockMods or LatchMods.
SetMods makes a regular "on while pressed" modifier key.
LockMods makes an "on/off" switch like CapsLock or NumLock.
LatchMods means "on until next keypress" aka sticky modifier

modifier_map

Modifier map is a table that maps each of eight modifier bits to at most
two keys:

modifier_map Mod1 { Alt_L, Alt_R };

In the core protocol, without XKB, it means more or less the same thing
as

XKB does not use modifier map in its original meaning. Within XKB, its
only function is to map virtual modifiers (see below).

However, the table is easily accessible by clients, and there is one
counter-intuitive (but well-known) trick involving it:
modifier map is used to tell which of ModX bits is Alt.
Because of this, it is a good idea to have one modifier mapped
to Alt_L or Alt_R as shown above. Unless you have very good reasons
to do otherwise, it should be Mod1.

Multiple keyboards

XKB allows setting keymap for a single connected physical keyboard only.
This feature can be extremely useful for multi-keyboard setups when keyboards
in question are different; consider a laptop with a full-size USB keyboard attached.

Additionally, xkbwatch shows all (real) modifiers together with their lock/latch status.
Modifiers are also reported by xev. Xxkb can be used to monitor effective group, but
make sure two_state mode is off.

In case interpretations section does not work well, make sure to check for duplicated
"interpret" blocks. Better yet, try commenting out anything related to specific keysym.
See section 9.2 for explanation.

It also makes sense to check what exactly the server got by downloading the keymap back with

xkbcomp $DISPLAY out.xkb

The results tend to be different from the input file. There is no known work-around for this.

Virtual Modifiers

One of the most troublesome parts of XKB, virtual modifiers appear prominently
in all standard keymaps, despite being a relatively minor and mostly useless feature.
The term itself is grossly misleading, and most of the docs do not help much either.

So, first of all: virtual modifiers are not modifiers in the same way real modifiers are.
If anything, it is a way to name some of the real modifiers. They are not 16 more bits
that can be used in level definitions. They are 16 possible names, each referring
to one (or some, or none) of the 8 modifier bits.

Real modifier bits are called Shift, Lock, Control and Mod1-Mod5. There are no
Alt among them. Virtual modifiers were introduced to allow saying something like

#define Alt Mod1

to applications willing to use this information.

It is possible to make a usable layout without defining virtual modifiers at all.
Among standard modifiers, only Alt/Meta actually need such treatment, because
Shift and Control are real modifiers anyway and NumLock is not normally used as a modifier.

Also, unlike most of the keymap-related things that affect any application using
basic Xlib functions, virtual modifiers must be queried explicitly using XKBlib
calls. Not all applications actually do that.

Defining virtual modifiers

The mapping between virtual and real modifiers is defined in a rather weird way
using keysyms as a medium. Refer to XKBproto for some reasons behind this.
Real modifiers M are assigned to a key using

modifier_map M { <keysym> };

Virtual modifiers V can be assigned to a key using

interpret <keysym> { virtualMod = V; };

If a virtual modifier V shares at least one keysym with a real modifier M,
it is bound to M.

Note that virtual modifier names are not pre-defined and must be declared in
xkb_compatibility and xkb_types sections before using them:

Keysym interpretation

Virtual modifiers can be used in interpret <keysym> blocks as if they were
defined to the respective real modifiers. For a virtual modifier V not bound
to any real modifier, this means

#define V

type declaration, and

interpret <key> { }
interpret <key>+V { }

blocks will be treated as duplicates. Only one of them, the last one in the file, will work.
xkbcomp usually gives a warning in cases like this.

Client side notes

Handling XKB virtual modifiers on the client side requires some non-trivial server interaction.
Most applications just do not bother, sticking with 8 real modifiers supplied in XKeyEvent.state.

However, it is possible for an application to obtain virtual modifiers associated with a key press.
Gtk, for instance, has [gdk-keymap-translate-keyboard-state()]
which may or may not be used in particular application.

Let's assume 83 is a "real" code the keyboard can produce. With overlay1 bit off,
the key will produce KP_Left keysym. With overlay1 bit on, it will produce keycode 144
and associated keysym KP_4, taking it from a different xkb_symbols row.

The principal difference between overlays and user-defined types, which can be used to
accomplish similar behavior too, is that overlays change keycode and leave no traces in the state field.
However, overlays are very limited. There are only two control bits, overlay1 and overlay2),
and each key can have only one alternative keycode, so writing

key <KP4> { [ KP_Left ], overlay1=<KO4>, overlay2=<KX4> };

is useless (but xkbcomp won't warn you). Each key has only one "alternative keycode" field,
the choice between overlay1= and overlay2= only determines which of the two bits
enables that alternative keycode.

The only well-know application for overlays is implementing keypad/NumLock, as shown above.
Check /usr/share/X11/xkb/symbols/keypad for a complete example.

Mouse control

XKB allows controlling mouse pointer from keyboard. When set up properly, it can be extremely
useful. However, its usability depends a lot on particular physical keyboard layout and on
user's individual preferences.

From XKB point of view it is relatively simple to implement, one should just trigger
relevant actions. Fairly complete implementation can be found in
/usr/share/X11/xkb/compat/mousekeys.

See Also

[Ivan Pascal XKB docs. One of the oldest and most well-known guides. Focuses a lot on details, and explains some of exotic XKB features.

[XKB protocol specification]. Comprehensive description of all XKB features. Extremely useful for understating how XKB works, includes a good description of virtual modifiers among other things. Some practice with xkbcomp is strongly recommended though, because the features are described on protocol level.