1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
|
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.
|