1a66cad3fb
Tested by bru@, jsg@ and others
685 lines
15 KiB
Plaintext
685 lines
15 KiB
Plaintext
XKM File Format Description
|
|
Version 15
|
|
|
|
1. Introduction
|
|
|
|
The XKM file format is the exchange format for XKB keyboard descriptions
|
|
between the server and xkbcomp. Usually, the server forks off xkbcomp,
|
|
xkbcomp compiles the XKM format from the given parameters.
|
|
The resulting XKM file is put into a directory readable by the server and
|
|
then parsed.
|
|
|
|
The XKM format is little more than a binary dump of various XKB-specific
|
|
structures and hence tied to the ABI of the server.
|
|
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
|
|
1.1 About this file format description
|
|
|
|
This description was produced by analyzing the XKM parsing code. Parts of
|
|
the file description present in the original format specification may be
|
|
missing. This description thus cannot be a reference document for XKM
|
|
implementations.
|
|
|
|
No description of the meaning of the various fields is given here. Refer to
|
|
the XKB protocol specification for more details.
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
|
|
2. Notations used in this document
|
|
|
|
Notation for structures:
|
|
|
|
┌───
|
|
Name of struct
|
|
name of field: type or fixed value of field
|
|
name of field: type or fixed value of field
|
|
└───
|
|
|
|
Data types are identical to those used in the X Protocol specification
|
|
except where noted otherwise. Structs specific to XKM are prefixed with XKM,
|
|
defines specific to the XKB protocol specification are prefixed with Xkb and
|
|
their value is equivalent to that in the protocol specification.
|
|
|
|
Multiple instances of a given type are denoted in the following form:
|
|
name of field: LISTofFIELDTYPE
|
|
|
|
Length specifiers for such fields are usually prefixed with num_. For
|
|
example, a struct containing a num_foo of 8 and a 'foo' field contains 8
|
|
structures of type 'foo'.
|
|
|
|
Variable length padding is specified as pad(x), where x is the length of the
|
|
data to be padded out to a multiple of 4 bytes. For example, given an x of
|
|
10, pad(x) would be the remaining 2 bytes to pad the whole struct to 12
|
|
bytes.
|
|
|
|
A special notation is a variable content struct. In this case, the contents
|
|
of the struct depend on the value of one or more specific fields.
|
|
┌───
|
|
Name of struct
|
|
field: type or fixed value of field
|
|
field: type or fixed value of field
|
|
───
|
|
field ⇒ value 1
|
|
⇒
|
|
specific field: type
|
|
specific field: type
|
|
───
|
|
field ⇒ value 2
|
|
⇒
|
|
specific field: type
|
|
specific field: type
|
|
└───
|
|
This notation denotes that if field is of value 1, this struct contains the
|
|
specific fields listed underneath value 1.
|
|
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
|
|
3. XKM Format
|
|
|
|
The XKM format is a binary format with structs usually being padded to a
|
|
multiple of 4 bytes. No provisions for endianess are provided, the parser is
|
|
left to guess the endianess of the XKM file.
|
|
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
3.1 Common data types
|
|
|
|
┌───
|
|
XKMCountedString
|
|
count: CARD16
|
|
string: count * CHAR
|
|
pad: pad(count + 2)
|
|
└───
|
|
|
|
XKMCountedString is used for user-readable identifiers. Prime example are
|
|
the level names and the section names ("complete", "evdev(inet)", etc.)
|
|
|
|
┌───
|
|
XKMGroupBits: CARD8
|
|
group1 0x1
|
|
group2 0x2
|
|
group3 0x4
|
|
group4 0x8
|
|
└───
|
|
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
|
|
3.2 Header and Table of Contents
|
|
|
|
┌───
|
|
XKMHeader
|
|
version: CARD8
|
|
identifier1: 'm'
|
|
identifier2: 'k'
|
|
idenfifier3: 'x'
|
|
└───
|
|
|
|
The XKM file format has a 4 byte header identifying the file and the XKM
|
|
version. The header is followed by the table of contents indicating the
|
|
sections present in this file.
|
|
|
|
┌───
|
|
XKMFileInfo
|
|
type: CARD8
|
|
min_keycode: CARD8
|
|
max_keycode: CARD8
|
|
num_sectioninfo: CARD8
|
|
present: CARD16
|
|
pad: CARD16
|
|
sectioninfo: LISTofXKMSectionInfo
|
|
└───
|
|
|
|
min_keycode and max_keycode specify the keycode range for this keyboard
|
|
descriptions. The core protocol requires min_keycode always be equal to or
|
|
greater than 8.
|
|
|
|
┌───
|
|
XKMSectionInfo
|
|
type: CARD16
|
|
XkmTypesIndex 0
|
|
XkmCompatMapIndex 1
|
|
XkmSymbolsIndex 2
|
|
XkmIndicatorsIndex 3
|
|
XkmKeyNamesIndex 4
|
|
XkmGeometryIndex 5
|
|
XkmVirtualModsIndex 6
|
|
format: CARD16
|
|
size: CARD16
|
|
offset: CARD16
|
|
└───
|
|
|
|
Describes the section found in a chunk of a file. This struct is found
|
|
_twice_ in the file per section, once as part of the XKMFileInfo, once at
|
|
the beginning of the actual section (see offset).
|
|
The type specifies the type of the section, the section is to be parsed
|
|
according to this type.
|
|
Size and offset specify the size in bytes and the offset into the file in
|
|
bytes, respectively.
|
|
|
|
3.3 Sections
|
|
|
|
Each section resides at the offset specified in the XKMFileInfo sectioninfo.
|
|
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
|
|
3.3.1 XKMTypes
|
|
|
|
An XKMTypes section describes the key types defined in a layout. Roughly
|
|
speaking, a key type defines how many levels a given key has and which
|
|
modifiers change to a particular level.
|
|
|
|
┌───
|
|
XKMTypesSection
|
|
section_info: XKMSectionInfo
|
|
name: XKMCountedString
|
|
num_types: CARD16
|
|
pad: CARD16
|
|
types: LISTofXKMKeyType
|
|
└───
|
|
|
|
┌───
|
|
XKMKeyType
|
|
real_mods: CARD8
|
|
num_levels: CARD8
|
|
virt_mods: CARD16
|
|
num_map_entries: CARD8
|
|
num_level_names: CARD8
|
|
perserve: CARD8
|
|
pad: CARD8
|
|
map_entries: LISTofXKMKTMapEntry
|
|
name: XKMCountedString
|
|
mods: LISTofXKMModsDesc
|
|
level_names: LISXTofXKMCountedString
|
|
└───
|
|
|
|
The num_map_entries specifies the number of structs in both map_entries and mods. mods is only present if preserve is TRUE.
|
|
|
|
┌───
|
|
XKMKTMapEntry
|
|
level: CARD8
|
|
real_mods: CARD8
|
|
virt_mods: CARD16
|
|
└───
|
|
|
|
┌───
|
|
XKMModsDesc
|
|
real_mods: CARD8
|
|
pad: CARD8
|
|
virt_mods: CARD16
|
|
└───
|
|
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
3.3.2 XKMCompatMap
|
|
|
|
An XKMCompatMap section describes the actions a keyboard may trigger. This
|
|
ranges from the TerminateServer action to simple modifier bits.
|
|
|
|
┌───
|
|
XKMCompatMap
|
|
section_info: XKMSectionInfo
|
|
name: XKMCountedString
|
|
num_si: CARD16
|
|
group_mask: XKMGroupBits
|
|
pad: CARD8
|
|
si: LISTofXKMSymInterpreterDesc
|
|
groups: LISTofXKMModsDesc
|
|
└───
|
|
|
|
One XKMModsDesc is present for each bit set in group_mask.
|
|
|
|
┌───
|
|
XKMSymInterpretDesc
|
|
sym: CARD32
|
|
mods: CARD8
|
|
match: CARD8
|
|
virtual_mod: CARD8
|
|
flags: CARD8
|
|
action_type: CARD8
|
|
action_data: XKMActionData
|
|
└───
|
|
|
|
Where the action is 7 bytes of CARD8 whose content is determined by
|
|
action_type.
|
|
|
|
┌───
|
|
XKMActionData:
|
|
pad0: CARD8
|
|
pad1: CARD16
|
|
pad2: CARD32
|
|
───
|
|
action_type ⇒ XkbSA_SetMods ||
|
|
action_type ⇒ XkbSA_LatchMods ||
|
|
action_type ⇒ XkbSA_LockMods
|
|
⇒
|
|
flags: CARD8
|
|
mask: CARD8
|
|
real_mods: CARD8
|
|
vmods1: CARD8
|
|
vmods2: CARD8
|
|
pad: CARD16
|
|
───
|
|
action_type ⇒ XkbSA_SetGroup ||
|
|
action_type ⇒ XkbSA_LatchGroup ||
|
|
action_type ⇒ XkbSA_LockGroup
|
|
⇒
|
|
flags: CARD8
|
|
group_XXX: CARD8
|
|
pad0: CARD8
|
|
pad1: CARD32
|
|
───
|
|
action_type ⇒ XkbSA_MovePtr
|
|
⇒
|
|
flags: CARD8
|
|
high_XXX: CARD8
|
|
low_XXX: CARD8
|
|
high_YYY: CARD8
|
|
low_YYY: CARD8
|
|
pad: CARD16
|
|
───
|
|
action_type ⇒ XkbSA_PtrBtn ||
|
|
action_type ⇒ XkbSA_LockPtrBtn
|
|
⇒
|
|
flags: CARD8
|
|
count: CARD8
|
|
button: CARD8
|
|
pad: CARD32
|
|
───
|
|
action_type ⇒ XkbSA_DeviceBtn ||
|
|
action_type ⇒ XkbSA_LockLockPtrBtn
|
|
⇒
|
|
flags: CARD8
|
|
count: CARD8
|
|
button: CARD8
|
|
device: CARD8
|
|
pad0: CARD8
|
|
pad1: CARD16
|
|
───
|
|
action_type ⇒ XkbSA_SetPtrDflt
|
|
⇒
|
|
flags: CARD8
|
|
affect: CARD8
|
|
valueXXX: CARD8
|
|
pad0: CARD32
|
|
───
|
|
action_type ⇒ XkbSA_ISOLock
|
|
⇒
|
|
flags: CARD8
|
|
mask: CARD8
|
|
real_mods: CARD8
|
|
group_XXX: CARD8
|
|
affect: CARD8
|
|
vmods1: CARD8
|
|
vmods1: CARD8
|
|
───
|
|
action_type ⇒ XkbSA_SwitchScreen
|
|
⇒
|
|
flags: CARD8
|
|
screenXXX: CARD8
|
|
pad0: CARD8
|
|
pad1: CARD32
|
|
───
|
|
action_type ⇒ XkbSA_SetControls ||
|
|
action_type ⇒ XkbSA_LockControls
|
|
⇒
|
|
flags: CARD8
|
|
ctrls3: CARD8
|
|
ctrls2: CARD8
|
|
ctrls1: CARD8
|
|
ctrls0: CARD8
|
|
pad: CARD16
|
|
───
|
|
action_type ⇒ XkbSA_RedirectKey
|
|
⇒
|
|
new_key: CARD8
|
|
mods_mask: CARD8
|
|
mods: CARD8
|
|
vmods_mask0: CARD8
|
|
vmods_mask1: CARD8
|
|
vmods0: CARD8
|
|
vmods1: CARD8
|
|
───
|
|
action_type ⇒ XkbSA_DeviceValuator
|
|
⇒
|
|
device: CARD8
|
|
v1_what: CARD8
|
|
v1_idx: CARD8
|
|
v1_value: CARD8
|
|
v2_what: CARD8
|
|
v2_idx: CARD8
|
|
v2_value: CARD8
|
|
pad: CARD8
|
|
───
|
|
action_type ⇒ XkbSA_XFree86Private ||
|
|
action_type ⇒ XkbSA_Terminate
|
|
⇒
|
|
pad0: CARD8
|
|
pad1: CARD16
|
|
pad2: CARD32
|
|
───
|
|
action_type ⇒ XkbSA_ActionMessage
|
|
⇒
|
|
press_msg: BOOL
|
|
release_msg: BOOL
|
|
gen_event: BOOL
|
|
message: 4 * CHAR
|
|
└───
|
|
|
|
Note: XkbSA_ActionMessage is currently unsupported and the contents are
|
|
ignored.
|
|
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
3.3.3 XkmSymbols
|
|
|
|
The symbols in a keymap define the actual keysyms each key may produce.
|
|
|
|
┌───
|
|
XKMSymbols
|
|
section_info: XKMSectionInfo
|
|
name: XKMCountedString
|
|
min_keycode: CARD8
|
|
max_keycode: CARD8
|
|
group_names_mask: XKMGroupBits
|
|
num_vmod_maps: CARD8
|
|
group_names: LISTofXKMCountedString
|
|
keysyms: XKMKeysymMapDesc
|
|
vmod_maps: XKMVModMapDesc
|
|
└───
|
|
One group_name is present for each bit set in group_names_mask.
|
|
The number of keysyms present is max_keycode - min_keycode + 1.
|
|
|
|
┌───
|
|
XKMKeysymMapDesc
|
|
width: CARD8
|
|
num_groups: CARD8
|
|
modifier_map: CARD8
|
|
flags: CARD8
|
|
names: LISTofXKMCountedString
|
|
syms: LISTofCARD32
|
|
behavior: XKMBehaviorDesc
|
|
└───
|
|
|
|
Presence of names is conditional on the XkmKeyHasTypes flag. The number of
|
|
strings is equal to the number of group bits in group_names_mask in the
|
|
preceeding XKMSymbols section.
|
|
The number of elements in syms is equal to width * num_groups.
|
|
Presence of behavior is conditional on the XkmKeyHasBehavior flag.
|
|
|
|
┌───
|
|
XKMKeyBehaviorDesc
|
|
type: CARD8
|
|
data: CARD8
|
|
pad: CARD16
|
|
└───
|
|
|
|
┌───
|
|
XKMVModMapDesc
|
|
key: CARD8
|
|
pad: CARD8
|
|
vmods: CARD16
|
|
└───
|
|
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
|
|
3.3.4 XKMIndicators
|
|
|
|
┌───
|
|
XKMIndicators
|
|
section_info: XKMSectionInfo
|
|
name: XKMCountedString
|
|
num_indicators: CARD8
|
|
pad0: CARD8
|
|
pad1: CARD16
|
|
indicators: LISTofXKMIndicatorMapDesc
|
|
└───
|
|
|
|
┌───
|
|
XKMIndicatorMapDesc
|
|
name: XKMCountedString
|
|
indicator: CARD8
|
|
flags: CARD8
|
|
which_mods: CARD8
|
|
real_mods: CARD8
|
|
vmods: CARD16
|
|
which_groups: CARD8
|
|
groups: CARD8
|
|
ctrls: CARD32
|
|
└───
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
|
|
3.3.5 XKMKeyNames
|
|
|
|
┌───
|
|
XKMKeyNames
|
|
section_info: XKMSectionInfo
|
|
name: XKMCountedString
|
|
min_keycode: CARD8
|
|
max_keycode: CARD8
|
|
num_aliases: CARD8
|
|
pad: CARD8
|
|
keynames: LISTofXKMKeyname
|
|
aliases: LISTofXKMKeyAlias
|
|
└───
|
|
|
|
keynames contains max_keycode - min_keycode + 1 entries.
|
|
|
|
┌───
|
|
XkmKeyname
|
|
name: 4 * CHAR8
|
|
└───
|
|
|
|
┌───
|
|
XkmKeyAlias
|
|
real: XkmKeyname
|
|
alias: XkmKeyname
|
|
└───
|
|
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
|
|
3.3.5 XKMGeometry
|
|
|
|
┌───
|
|
XKMGeometry
|
|
section_info: XKMSectionInfo
|
|
name: XKMCountedString
|
|
width_mm: CARD16
|
|
height_mm: CARD16
|
|
base_color_ndx: CARD8
|
|
label_color_ndx: CARD8
|
|
num_properties: CARD16
|
|
num_colors: CARD16
|
|
num_shapes: CARD16
|
|
num_sections: CARD16
|
|
num_doodads: CARD16
|
|
num_key_aliases: CARD16
|
|
pad: CARD16
|
|
label_font: XKMCountedString
|
|
properties: LISTofXKMGeomProperty
|
|
colors: LISTofXKMCountedString
|
|
shapes: LISTofXKMGeomShape
|
|
sections: LISTofXKMGeomSection
|
|
doodads: LISTofXKMGeomDoodad
|
|
key_aliases: LISTofXKMKeyAlias
|
|
└───
|
|
|
|
┌───
|
|
XKMGeomProperty
|
|
name: XKMCountedString
|
|
value: XKMCountedString
|
|
|
|
└───
|
|
|
|
┌───
|
|
XKMGeomShape
|
|
name: XKMCountedString
|
|
num_outlines: CARD8
|
|
primary_idx: CARD8
|
|
approx_idx: CARD8
|
|
pad: CARD8
|
|
outlines: LISTofXKMOutlineDesc
|
|
└───
|
|
|
|
┌───
|
|
XKMOutlineDesc
|
|
num_points: CARD8
|
|
corner_radius: CARD8
|
|
pad: CARD16
|
|
points: LISTofXKMPointDesc
|
|
└───
|
|
|
|
┌───
|
|
XKMPointDesc
|
|
x: INT16
|
|
y: INT16
|
|
└───
|
|
|
|
┌───
|
|
XKMGeomSection
|
|
name: XKMCountedString
|
|
top: INT16
|
|
left: INT16
|
|
width: CARD16
|
|
height: CARD16
|
|
angle: INT16
|
|
priority: CARD8
|
|
num_rows: CARD8
|
|
num_doodads: CARD8
|
|
num_overlays: CARD8
|
|
pad: CARD16
|
|
rows: LISTofXKMRowDesc
|
|
doodads: LISTofXKMGeomDoodad
|
|
overlays: LISTofXKMGeomOverlay
|
|
└───
|
|
|
|
┌───
|
|
XKMRowDesc
|
|
top: INT16
|
|
left: INT16
|
|
num_keys: CARD8
|
|
vertical: BOOL
|
|
pad: CARD16
|
|
keys: XKMKeyDesc
|
|
└───
|
|
|
|
┌───
|
|
XKMKeyDesc
|
|
name: XKMKeyname
|
|
gap: INT16
|
|
shape_idx: CARD8
|
|
color_idx: CARD8
|
|
└───
|
|
|
|
┌───
|
|
XKMGeomDoodad
|
|
name: XKMCountedString
|
|
type: CARD8
|
|
priority: CARD8
|
|
top: INT16
|
|
left: INT16
|
|
pad1: CARD16
|
|
pad2: CARD32
|
|
pad3: CARD32
|
|
───
|
|
type ⇒ XkbOutlineDoodad ||
|
|
type ⇒ XkbSolideDoodad
|
|
⇒
|
|
type: CARD8
|
|
priority: CARD8
|
|
top: INT16
|
|
left: INT16
|
|
angle: INT16
|
|
color_idx: CARD8
|
|
shape_idx: CARD8
|
|
pad0: CARD16
|
|
pad1: CARD32
|
|
───
|
|
type ⇒ XkbTextDoodad
|
|
⇒
|
|
type: CARD8
|
|
priority: CARD8
|
|
top: INT16
|
|
left: INT16
|
|
angle: INT16
|
|
width: CARD16
|
|
height: CARD16
|
|
color_idx: CARD8
|
|
pad0: CARD8
|
|
pad1: CARD16
|
|
text: XKMCountedString
|
|
font: XKMCountedString
|
|
───
|
|
type ⇒ XkbIndicatorDoodad
|
|
⇒
|
|
type: CARD8
|
|
priority: CARD8
|
|
top: INT16
|
|
left: INT16
|
|
shape_idx: CARD8
|
|
on_color_idx: CARD8
|
|
off_color_idx: CARD8
|
|
pad0: CARD8
|
|
pad1: CARD16
|
|
pad2: CARD32
|
|
───
|
|
type ⇒ XkbLogoDoodad
|
|
⇒
|
|
type: CARD8
|
|
priority: CARD8
|
|
top: INT16
|
|
left: INT16
|
|
angle: INT16
|
|
color_idx: CARD8
|
|
shape_idx: CARD8
|
|
pad0: CARD16
|
|
pad1: CARD32
|
|
logo_name: XKMCountedString
|
|
└───
|
|
|
|
WARNING: XKMGeomDoodad has variable length depending on the type.
|
|
NOTE: The current server implementation does not use all fields of all
|
|
structures.
|
|
|
|
┌───
|
|
XKMOverlayDesc
|
|
name: XKMCountedString
|
|
num_rows: CARD8
|
|
pad0: CARD8
|
|
pad1: CARD16
|
|
rows: LISTofXKMOverlayRowDesc
|
|
└───
|
|
|
|
┌───
|
|
XKMOverlayRowDesc
|
|
name: XKMCountedString
|
|
row_under: CARD8
|
|
num_keys: CARD8
|
|
pad: CARD16
|
|
keys: LISTofXKMOverlayKeyDesc
|
|
└───
|
|
|
|
┌───
|
|
XKMOverlayKeyDesc
|
|
over: XKMKeyname
|
|
under: XKMKeyname
|
|
└───
|
|
|
|
❧❧❧❧❧❧❧❧❧❧❧
|
|
|
|
3.3.6 XKMVirtualMods
|
|
|
|
┌───
|
|
XKMOverlayRowDesc
|
|
section_info: XKMSectionInfo
|
|
name: XKMCountedString
|
|
bound_mask: SETofVMODBITS
|
|
named_mask: SETofVMODBITS
|
|
vmods: LISTofCARD8
|
|
pad: pad(vmods)
|
|
names: LISTofXKMCountedString
|
|
└───
|
|
|
|
VMODBITS: CARD16
|
|
|
|
Number of elements in vmods is equal to the number of bits set in
|
|
bound_mask. The padding completes vmods to a multiple of 4 byte units.
|
|
Number of elements in names is equal to the number of bits set in
|
|
named_mask.
|