detached e79265d

merge: purego-xkbcommon bindings (Veya P1)

commit
e79265dfcdc2120f43bd7b7b6b0a3f906cc2c724
author
brice · · 2026-09-28 07:11 UTC
merge of
a7f62f3 + 30529e3 · diff against the first parent
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
23 files · +19672 -1
A LICENSE +21 -0
@@ -0,0 +1,21 @@
1+MIT License
2+
3+Copyright (c) 2026 purego-xkbcommon contributors
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy
6+of this software and associated documentation files (the "Software"), to deal
7+in the Software without restriction, including without limitation the rights
8+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+copies of the Software, and to permit persons to whom the Software is
10+furnished to do so, subject to the following conditions:
11+
12+The above copyright notice and this permission notice shall be included in all
13+copies or substantial portions of the Software.
14+
15+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+SOFTWARE.
M README.md +18 -1
@@ -1,3 +1,20 @@
11 # purego-xkbcommon
22
3-Pure Go (no cgo) bindings for libxkbcommon, loaded at runtime with purego.
3+Go 1.27 bindings for Linux `libxkbcommon.so.0`, without cgo or X11. The safe package owns native references; the `raw` package exposes generated ABI constants, types, and function registrations. Install libxkbcommon at runtime and xkeyboard-config for rules-based keymaps. The loader reports missing libraries and required symbols via `Available`.
4+
5+```go
6+ctx, err := xkbcommon.NewContext()
7+if err != nil { return err }
8+defer ctx.Close()
9+keymap, err := ctx.NewKeymapRules("evdev", "pc105", "fr", "", "")
10+if err != nil { return err }
11+defer keymap.Close()
12+state, err := keymap.NewState()
13+if err != nil { return err }
14+defer state.Close()
15+text, err := state.UTF8(xkbcommon.WaylandKeycode(evdevKeycode))
16+```
17+
18+Use `NewKeymapFD(fd, size)` for Wayland `xkb_v1` keymaps; it copies exactly `size` bytes with `pread` (at most 16 MiB), fails on a short read, and accepts an optional trailing NUL. **The caller retains and must close the FD**, on success and failure. `UpdateMask` accepts Wayland modifier masks and group indices. `ComposeState.Feed` and `Status` distinguish composing, composed, cancelled, and ignored keysyms; use `UTF8` only for a composed result. Objects retain their native parents; close each object, in any order. Do not copy value structs containing a mutex.
19+
20+Pinned upstream headers and licenses are in `upstream/`; `upstream/METADATA` and `SHA256SUMS` identify their exact source. Run `GOWORK=off go generate ./...` to regenerate `raw/generated.go`; consumers do not run generation. The generator checks the selected ABI declarations against the headers. `github.com/bnema/purego v0.13.0-bnema.1` matches purego-vulkan and supports `Dlopen`, `Dlsym`, and `RegisterFunc` with cgo disabled.
A cmd/xkbgen/main.go +12 -0
@@ -0,0 +1,12 @@
1+package main
2+
3+import (
4+ "github.com/bnema/purego-xkbcommon/internal/gen"
5+ "log"
6+)
7+
8+func main() {
9+ if err := gen.Generate("."); err != nil {
10+ log.Fatal(err)
11+ }
12+}
A generate.go +3 -0
@@ -0,0 +1,3 @@
1+package xkbcommon
2+
3+//go:generate go run ./cmd/xkbgen
A go.mod +5 -0
@@ -0,0 +1,5 @@
1+module github.com/bnema/purego-xkbcommon
2+
3+go 1.27
4+
5+require github.com/bnema/purego v0.13.0-bnema.1
A go.sum +2 -0 generated file: collapsed
A internal/gen/gen.go +120 -0
@@ -0,0 +1,120 @@
1+// Package gen generates the deliberately bounded libxkbcommon ABI subset.
2+package gen
3+
4+import (
5+ "fmt"
6+ "go/format"
7+ "os"
8+ "regexp"
9+ "strconv"
10+ "strings"
11+)
12+
13+var comments = regexp.MustCompile(`(?s)/\*.*?\*/|//[^\n]*`)
14+
15+func clean(s string) string { return comments.ReplaceAllString(s, "") }
16+func declared(h, name string) bool {
17+ re := regexp.MustCompile(`(?m)\b` + regexp.QuoteMeta(name) + `\s*\([^;{}]*\)\s*;`)
18+ return re.MatchString(clean(h))
19+}
20+
21+var def = regexp.MustCompile(`(?m)^\s*#define\s+(XKB_(?:KEY_|MOD_NAME_|VMOD_NAME_|LED_NAME_)[A-Za-z0-9_]+)\s+("[^"]*"|0x[0-9a-fA-F]+|[0-9]+)\b?`)
22+var en = regexp.MustCompile(`(?s)enum\s+xkb_[a-z_]+\s*\{([^}]*)\}`)
23+var item = regexp.MustCompile(`^\s*(XKB_[A-Z][A-Z0-9_]*)(?:\s*=\s*(.+))?$`)
24+
25+func constants(h string) string {
26+ h = clean(h)
27+ var b strings.Builder
28+ for _, e := range en.FindAllStringSubmatch(h, -1) {
29+ last := int64(-1)
30+ for _, part := range strings.Split(e[1], ",") {
31+ m := item.FindStringSubmatch(strings.TrimSpace(part))
32+ if m == nil {
33+ continue
34+ }
35+ expr := strings.TrimSpace(m[2])
36+ if expr == "" {
37+ last++
38+ expr = strconv.FormatInt(last, 10)
39+ } else if n, err := strconv.ParseInt(expr, 0, 64); err == nil {
40+ last = n
41+ } else if v := regexp.MustCompile(`^\(1 << (\d+)\)$`).FindStringSubmatch(expr); v != nil {
42+ shift, _ := strconv.Atoi(v[1])
43+ last = 1 << shift
44+ } else {
45+ continue
46+ }
47+ fmt.Fprintf(&b, "%s = %s\n", m[1], expr)
48+ }
49+ }
50+ for _, m := range def.FindAllStringSubmatch(h, -1) {
51+ fmt.Fprintf(&b, "%s = %s\n", m[1], m[2])
52+ }
53+ return b.String()
54+}
55+
56+// Functions describes the bound ABI; each name is checked against the pinned headers.
57+// Pointers are uintptr to avoid GC passing Go pointers to native code unexpectedly.
58+var Functions = []struct{ Name, Signature string }{
59+ {"xkb_context_new", "func(uint32) uintptr"}, {"xkb_context_ref", "func(uintptr) uintptr"}, {"xkb_context_unref", "func(uintptr)"},
60+ {"xkb_keymap_new_from_names", "func(uintptr, uintptr, uint32) uintptr"}, {"xkb_keymap_new_from_string", "func(uintptr, uintptr, uint32, uint32) uintptr"}, {"xkb_keymap_new_from_buffer", "func(uintptr, uintptr, uintptr, uint32, uint32) uintptr"},
61+ {"xkb_keymap_ref", "func(uintptr) uintptr"}, {"xkb_keymap_unref", "func(uintptr)"}, {"xkb_keymap_get_as_string", "func(uintptr,uint32) uintptr"},
62+ {"xkb_keymap_mod_get_index", "func(uintptr,uintptr) uint32"}, {"xkb_keymap_num_layouts", "func(uintptr) uint32"},
63+ {"xkb_state_new", "func(uintptr) uintptr"}, {"xkb_state_ref", "func(uintptr) uintptr"}, {"xkb_state_unref", "func(uintptr)"},
64+ {"xkb_state_update_mask", "func(uintptr,uint32,uint32,uint32,uint32,uint32,uint32) uint32"},
65+ {"xkb_state_serialize_layout", "func(uintptr,uint32) uint32"}, {"xkb_state_serialize_mods", "func(uintptr,uint32) uint32"},
66+ {"xkb_state_key_get_one_sym", "func(uintptr,uint32) uint32"}, {"xkb_state_key_get_utf8", "func(uintptr,uint32,uintptr,uintptr) int32"},
67+ {"xkb_keysym_get_name", "func(uint32,uintptr,uintptr) int32"}, {"xkb_keysym_from_name", "func(uintptr,uint32) uint32"},
68+ {"xkb_compose_table_new_from_locale", "func(uintptr,uintptr,uint32) uintptr"}, {"xkb_compose_table_ref", "func(uintptr) uintptr"}, {"xkb_compose_table_unref", "func(uintptr)"},
69+ {"xkb_compose_state_new", "func(uintptr,uint32) uintptr"}, {"xkb_compose_state_ref", "func(uintptr) uintptr"}, {"xkb_compose_state_unref", "func(uintptr)"},
70+ {"xkb_compose_state_feed", "func(uintptr,uint32) uint32"}, {"xkb_compose_state_get_status", "func(uintptr) uint32"},
71+ {"xkb_compose_state_reset", "func(uintptr)"}, {"xkb_compose_state_get_utf8", "func(uintptr,uintptr,uintptr) int32"}, {"xkb_compose_state_get_one_sym", "func(uintptr) uint32"},
72+}
73+
74+func field(name string) string { return strings.ToUpper(name[:1]) + name[1:] }
75+func Generate(root string) error {
76+ h1, err := os.ReadFile(root + "/upstream/xkbcommon.h")
77+ if err != nil {
78+ return err
79+ }
80+ h2, err := os.ReadFile(root + "/upstream/xkbcommon-compose.h")
81+ if err != nil {
82+ return err
83+ }
84+ hdr := string(h1) + "\n" + string(h2)
85+ var b strings.Builder
86+ b.WriteString("// Code generated by go generate; DO NOT EDIT.\npackage raw\n\n")
87+ b.WriteString("// Opaque C handles and scalar typedefs.\ntype Context uintptr\ntype Keymap uintptr\ntype State uintptr\ntype ComposeTable uintptr\ntype ComposeState uintptr\ntype Keycode uint32\ntype Keysym uint32\ntype LayoutIndex uint32\ntype ModIndex uint32\ntype ModMask uint32\ntype LayoutMask uint32\n")
88+ b.WriteString("// RuleNames matches struct xkb_rule_names (five const char pointers).\ntype RuleNames struct { Rules, Model, Layout, Variant, Options uintptr }\n")
89+ b.WriteString("const (\n" + constants(hdr))
90+ for _, f := range []string{"xkbcommon-keysyms.h", "xkbcommon-names.h"} {
91+ data, e := os.ReadFile(root + "/upstream/" + f)
92+ if e != nil {
93+ return e
94+ }
95+ b.WriteString(constants(string(data)))
96+ }
97+ b.WriteString(")\n\n// Funcs holds resolved library functions.\ntype Funcs struct {\n")
98+ for _, f := range Functions {
99+ if !declared(hdr, f.Name) {
100+ return fmt.Errorf("missing pinned declaration: %s", f.Name)
101+ }
102+ fmt.Fprintf(&b, "%s %s\n", field(f.Name), f.Signature)
103+ }
104+ b.WriteString("}\n\n// Symbols is the complete required symbol set.\nvar Symbols = []string{\n")
105+ for _, f := range Functions {
106+ fmt.Fprintf(&b, "%q,\n", f.Name)
107+ }
108+ b.WriteString("}\n\n// Register registers prevalidated addresses in a Funcs value.\nfunc Register(f *Funcs, register func(any,uintptr)) {\n")
109+ for _, f := range Functions {
110+ fmt.Fprintf(&b, "register(&f.%s, addresses[%q])\n", field(f.Name), f.Name)
111+ }
112+ b.WriteString("}\n")
113+ // address map is passed in, not a global mutable singleton.
114+ s := strings.Replace(b.String(), "func Register(f *Funcs, register func(any,uintptr))", "func Register(f *Funcs, addresses map[string]uintptr, register func(any,uintptr))", 1)
115+ formatted, err := format.Source([]byte(s))
116+ if err != nil {
117+ return fmt.Errorf("format generated file: %w", err)
118+ }
119+ return os.WriteFile(root+"/raw/generated.go", formatted, 0644)
120+}
A internal/gen/gen_test.go +25 -0
@@ -0,0 +1,25 @@
1+package gen
2+
3+import (
4+ "strings"
5+ "testing"
6+)
7+
8+func TestDeclarations(t *testing.T) {
9+ h := "/* xkb_fake(void); */\nXKB_EXPORT struct xkb_context *\nxkb_context_new(enum xkb_context_flags flags);"
10+ if !declared(h, "xkb_context_new") || declared(h, "xkb_fake") {
11+ t.Fatal("incorrect declaration selection")
12+ }
13+ if declared(h, "xkb_context_unref") {
14+ t.Fatal("missing declaration accepted")
15+ }
16+}
17+func TestConstants(t *testing.T) {
18+ h := "enum xkb_test { XKB_A = (1 << 2), XKB_B, XKB_C = 0x10 };\n#define XKB_MOD_NAME_SHIFT \"Shift\"\n#define XKB_KEY_dead_acute 0xfe51\n"
19+ got := constants(h)
20+ for _, want := range []string{"XKB_A = (1 << 2)", "XKB_B = 5", "XKB_C = 0x10", "XKB_MOD_NAME_SHIFT = \"Shift\"", "XKB_KEY_dead_acute = 0xfe51"} {
21+ if !strings.Contains(got, want) {
22+ t.Fatalf("missing %s in %s", want, got)
23+ }
24+ }
25+}
A loader.go +50 -0
@@ -0,0 +1,50 @@
1+package xkbcommon
2+
3+import (
4+ "fmt"
5+ "sync"
6+
7+ "github.com/bnema/purego"
8+ "github.com/bnema/purego-xkbcommon/raw"
9+)
10+
11+var loader struct {
12+ sync.Once
13+ f raw.Funcs
14+ err error
15+}
16+
17+// resolveLibrary keeps path and required symbols injectable for diagnostic tests.
18+// On success it leaves the library open for the lifetime of registered functions.
19+func resolveLibrary(path string, symbols []string) (map[string]uintptr, error) {
20+ lib, err := purego.Dlopen(path, purego.RTLD_NOW|purego.RTLD_LOCAL)
21+ if err != nil {
22+ return nil, fmt.Errorf("xkbcommon: load %s: %w", path, err)
23+ }
24+ addresses := make(map[string]uintptr, len(symbols))
25+ for _, name := range symbols {
26+ address, e := purego.Dlsym(lib, name)
27+ if e != nil || address == 0 {
28+ _ = purego.Dlclose(lib)
29+ return nil, fmt.Errorf("xkbcommon: incompatible %s: missing %s: %v", path, name, e)
30+ }
31+ addresses[name] = address
32+ }
33+ return addresses, nil
34+}
35+
36+// Available resolves the SONAME and every required symbol, reporting the first
37+// incompatible symbol rather than failing later in a keyboard event callback.
38+func Available() error {
39+ loader.Do(func() {
40+ addresses, err := resolveLibrary("libxkbcommon.so.0", raw.Symbols)
41+ if err != nil {
42+ loader.err = err
43+ return
44+ }
45+ raw.Register(&loader.f, addresses, purego.RegisterFunc)
46+ // Intentionally keep the library open: registered function pointers and live
47+ // native objects remain valid for the process lifetime.
48+ })
49+ return loader.err
50+}
A raw/generated.go +2834 -0 large diff (2834 lines changed): collapsed
A testdata/keymaps/de.xkb +2090 -0 large diff (2090 lines changed): collapsed
A testdata/keymaps/fr.xkb +2084 -0 large diff (2084 lines changed): collapsed
A testdata/keymaps/us.xkb +2081 -0 large diff (2081 lines changed): collapsed
A testdata/keymaps/us_fr.xkb +2227 -0
@@ -0,0 +1,2227 @@
1+xkb_keymap {
2+xkb_keycodes "evdev_aliases(qwerty)" {
3+ minimum = 8;
4+ maximum = 709;
5+ <ESC> = 9;
6+ <AE01> = 10;
7+ <AE02> = 11;
8+ <AE03> = 12;
9+ <AE04> = 13;
10+ <AE05> = 14;
11+ <AE06> = 15;
12+ <AE07> = 16;
13+ <AE08> = 17;
14+ <AE09> = 18;
15+ <AE10> = 19;
16+ <AE11> = 20;
17+ <AE12> = 21;
18+ <BKSP> = 22;
19+ <TAB> = 23;
20+ <AD01> = 24;
21+ <AD02> = 25;
22+ <AD03> = 26;
23+ <AD04> = 27;
24+ <AD05> = 28;
25+ <AD06> = 29;
26+ <AD07> = 30;
27+ <AD08> = 31;
28+ <AD09> = 32;
29+ <AD10> = 33;
30+ <AD11> = 34;
31+ <AD12> = 35;
32+ <RTRN> = 36;
33+ <LCTL> = 37;
34+ <AC01> = 38;
35+ <AC02> = 39;
36+ <AC03> = 40;
37+ <AC04> = 41;
38+ <AC05> = 42;
39+ <AC06> = 43;
40+ <AC07> = 44;
41+ <AC08> = 45;
42+ <AC09> = 46;
43+ <AC10> = 47;
44+ <AC11> = 48;
45+ <TLDE> = 49;
46+ <LFSH> = 50;
47+ <BKSL> = 51;
48+ <AB01> = 52;
49+ <AB02> = 53;
50+ <AB03> = 54;
51+ <AB04> = 55;
52+ <AB05> = 56;
53+ <AB06> = 57;
54+ <AB07> = 58;
55+ <AB08> = 59;
56+ <AB09> = 60;
57+ <AB10> = 61;
58+ <RTSH> = 62;
59+ <KPMU> = 63;
60+ <LALT> = 64;
61+ <SPCE> = 65;
62+ <CAPS> = 66;
63+ <FK01> = 67;
64+ <FK02> = 68;
65+ <FK03> = 69;
66+ <FK04> = 70;
67+ <FK05> = 71;
68+ <FK06> = 72;
69+ <FK07> = 73;
70+ <FK08> = 74;
71+ <FK09> = 75;
72+ <FK10> = 76;
73+ <NMLK> = 77;
74+ <SCLK> = 78;
75+ <KP7> = 79;
76+ <KP8> = 80;
77+ <KP9> = 81;
78+ <KPSU> = 82;
79+ <KP4> = 83;
80+ <KP5> = 84;
81+ <KP6> = 85;
82+ <KPAD> = 86;
83+ <KP1> = 87;
84+ <KP2> = 88;
85+ <KP3> = 89;
86+ <KP0> = 90;
87+ <KPDL> = 91;
88+ <LVL3> = 92;
89+ <ZEHA> = 93;
90+ <LSGT> = 94;
91+ <FK11> = 95;
92+ <FK12> = 96;
93+ <AB11> = 97;
94+ <KATA> = 98;
95+ <HIRA> = 99;
96+ <HENK> = 100;
97+ <HKTG> = 101;
98+ <MUHE> = 102;
99+ <JPCM> = 103;
100+ <KPEN> = 104;
101+ <RCTL> = 105;
102+ <KPDV> = 106;
103+ <PRSC> = 107;
104+ <RALT> = 108;
105+ <LNFD> = 109;
106+ <HOME> = 110;
107+ <UP> = 111;
108+ <PGUP> = 112;
109+ <LEFT> = 113;
110+ <RGHT> = 114;
111+ <END> = 115;
112+ <DOWN> = 116;
113+ <PGDN> = 117;
114+ <INS> = 118;
115+ <DELE> = 119;
116+ <I120> = 120;
117+ <MUTE> = 121;
118+ <VOL-> = 122;
119+ <VOL+> = 123;
120+ <POWR> = 124;
121+ <KPEQ> = 125;
122+ <I126> = 126;
123+ <PAUS> = 127;
124+ <I128> = 128;
125+ <I129> = 129;
126+ <HNGL> = 130;
127+ <HJCV> = 131;
128+ <AE13> = 132;
129+ <LWIN> = 133;
130+ <RWIN> = 134;
131+ <COMP> = 135;
132+ <STOP> = 136;
133+ <AGAI> = 137;
134+ <PROP> = 138;
135+ <UNDO> = 139;
136+ <FRNT> = 140;
137+ <COPY> = 141;
138+ <OPEN> = 142;
139+ <PAST> = 143;
140+ <FIND> = 144;
141+ <CUT> = 145;
142+ <HELP> = 146;
143+ <I147> = 147;
144+ <I148> = 148;
145+ <I149> = 149;
146+ <I150> = 150;
147+ <I151> = 151;
148+ <I152> = 152;
149+ <I153> = 153;
150+ <I154> = 154;
151+ <I155> = 155;
152+ <I156> = 156;
153+ <I157> = 157;
154+ <I158> = 158;
155+ <I159> = 159;
156+ <I160> = 160;
157+ <I161> = 161;
158+ <I162> = 162;
159+ <I163> = 163;
160+ <I164> = 164;
161+ <I165> = 165;
162+ <I166> = 166;
163+ <I167> = 167;
164+ <I168> = 168;
165+ <I169> = 169;
166+ <I170> = 170;
167+ <I171> = 171;
168+ <I172> = 172;
169+ <I173> = 173;
170+ <I174> = 174;
171+ <I175> = 175;
172+ <I176> = 176;
173+ <I177> = 177;
174+ <I178> = 178;
175+ <I179> = 179;
176+ <I180> = 180;
177+ <I181> = 181;
178+ <I182> = 182;
179+ <I183> = 183;
180+ <I184> = 184;
181+ <I185> = 185;
182+ <I186> = 186;
183+ <I187> = 187;
184+ <I188> = 188;
185+ <I189> = 189;
186+ <I190> = 190;
187+ <FK13> = 191;
188+ <FK14> = 192;
189+ <FK15> = 193;
190+ <FK16> = 194;
191+ <FK17> = 195;
192+ <FK18> = 196;
193+ <FK19> = 197;
194+ <FK20> = 198;
195+ <FK21> = 199;
196+ <FK22> = 200;
197+ <FK23> = 201;
198+ <FK24> = 202;
199+ <LVL5> = 203;
200+ <ALT> = 204;
201+ <META> = 205;
202+ <SUPR> = 206;
203+ <HYPR> = 207;
204+ <I208> = 208;
205+ <I209> = 209;
206+ <I210> = 210;
207+ <I211> = 211;
208+ <I212> = 212;
209+ <I213> = 213;
210+ <I214> = 214;
211+ <I215> = 215;
212+ <I216> = 216;
213+ <I217> = 217;
214+ <I218> = 218;
215+ <I219> = 219;
216+ <I220> = 220;
217+ <I221> = 221;
218+ <I222> = 222;
219+ <I223> = 223;
220+ <I224> = 224;
221+ <I225> = 225;
222+ <I226> = 226;
223+ <I227> = 227;
224+ <I228> = 228;
225+ <I229> = 229;
226+ <I230> = 230;
227+ <I231> = 231;
228+ <I232> = 232;
229+ <I233> = 233;
230+ <I234> = 234;
231+ <I235> = 235;
232+ <I236> = 236;
233+ <I237> = 237;
234+ <I238> = 238;
235+ <I239> = 239;
236+ <I240> = 240;
237+ <I241> = 241;
238+ <I242> = 242;
239+ <I243> = 243;
240+ <I244> = 244;
241+ <I245> = 245;
242+ <I246> = 246;
243+ <I247> = 247;
244+ <I248> = 248;
245+ <I249> = 249;
246+ <I250> = 250;
247+ <I251> = 251;
248+ <I252> = 252;
249+ <I253> = 253;
250+ <I254> = 254;
251+ <I255> = 255;
252+ <I256> = 256;
253+ <I360> = 360;
254+ <I361> = 361;
255+ <I362> = 362;
256+ <I363> = 363;
257+ <I364> = 364;
258+ <I365> = 365;
259+ <I366> = 366;
260+ <I367> = 367;
261+ <I368> = 368;
262+ <I369> = 369;
263+ <I370> = 370;
264+ <I371> = 371;
265+ <I372> = 372;
266+ <I373> = 373;
267+ <I374> = 374;
268+ <I375> = 375;
269+ <I376> = 376;
270+ <I377> = 377;
271+ <I378> = 378;
272+ <I379> = 379;
273+ <I380> = 380;
274+ <I381> = 381;
275+ <I382> = 382;
276+ <I383> = 383;
277+ <I384> = 384;
278+ <I385> = 385;
279+ <I386> = 386;
280+ <I387> = 387;
281+ <I388> = 388;
282+ <I389> = 389;
283+ <I390> = 390;
284+ <I391> = 391;
285+ <I392> = 392;
286+ <I393> = 393;
287+ <I394> = 394;
288+ <I395> = 395;
289+ <I396> = 396;
290+ <I397> = 397;
291+ <I398> = 398;
292+ <I399> = 399;
293+ <I400> = 400;
294+ <I401> = 401;
295+ <I402> = 402;
296+ <I403> = 403;
297+ <I404> = 404;
298+ <I405> = 405;
299+ <I406> = 406;
300+ <I407> = 407;
301+ <I408> = 408;
302+ <I409> = 409;
303+ <I410> = 410;
304+ <I411> = 411;
305+ <I412> = 412;
306+ <I413> = 413;
307+ <I414> = 414;
308+ <I415> = 415;
309+ <I416> = 416;
310+ <I417> = 417;
311+ <I418> = 418;
312+ <I419> = 419;
313+ <I420> = 420;
314+ <I421> = 421;
315+ <I422> = 422;
316+ <I423> = 423;
317+ <I424> = 424;
318+ <I425> = 425;
319+ <I426> = 426;
320+ <I427> = 427;
321+ <I428> = 428;
322+ <I429> = 429;
323+ <I430> = 430;
324+ <I431> = 431;
325+ <I432> = 432;
326+ <I433> = 433;
327+ <I434> = 434;
328+ <I435> = 435;
329+ <I436> = 436;
330+ <I437> = 437;
331+ <I438> = 438;
332+ <I439> = 439;
333+ <I440> = 440;
334+ <I441> = 441;
335+ <I442> = 442;
336+ <I443> = 443;
337+ <I444> = 444;
338+ <I445> = 445;
339+ <I446> = 446;
340+ <I447> = 447;
341+ <I448> = 448;
342+ <I449> = 449;
343+ <I450> = 450;
344+ <I452> = 452;
345+ <I453> = 453;
346+ <I454> = 454;
347+ <I455> = 455;
348+ <I456> = 456;
349+ <I457> = 457;
350+ <I458> = 458;
351+ <I459> = 459;
352+ <I472> = 472;
353+ <I473> = 473;
354+ <I474> = 474;
355+ <I475> = 475;
356+ <I476> = 476;
357+ <I477> = 477;
358+ <I478> = 478;
359+ <I479> = 479;
360+ <I480> = 480;
361+ <I481> = 481;
362+ <I482> = 482;
363+ <I483> = 483;
364+ <I484> = 484;
365+ <I485> = 485;
366+ <I486> = 486;
367+ <I487> = 487;
368+ <I488> = 488;
369+ <I489> = 489;
370+ <I490> = 490;
371+ <I491> = 491;
372+ <I492> = 492;
373+ <I493> = 493;
374+ <I505> = 505;
375+ <I506> = 506;
376+ <I507> = 507;
377+ <I508> = 508;
378+ <I509> = 509;
379+ <I510> = 510;
380+ <I511> = 511;
381+ <I512> = 512;
382+ <I513> = 513;
383+ <I514> = 514;
384+ <I520> = 520;
385+ <I521> = 521;
386+ <I522> = 522;
387+ <I523> = 523;
388+ <I524> = 524;
389+ <I525> = 525;
390+ <I526> = 526;
391+ <I527> = 527;
392+ <I528> = 528;
393+ <I529> = 529;
394+ <I530> = 530;
395+ <I531> = 531;
396+ <I532> = 532;
397+ <I533> = 533;
398+ <I534> = 534;
399+ <I535> = 535;
400+ <I536> = 536;
401+ <I537> = 537;
402+ <I538> = 538;
403+ <I539> = 539;
404+ <I540> = 540;
405+ <I541> = 541;
406+ <I542> = 542;
407+ <I543> = 543;
408+ <I544> = 544;
409+ <I545> = 545;
410+ <I546> = 546;
411+ <I547> = 547;
412+ <I548> = 548;
413+ <I549> = 549;
414+ <I550> = 550;
415+ <I568> = 568;
416+ <I569> = 569;
417+ <I570> = 570;
418+ <I584> = 584;
419+ <I585> = 585;
420+ <I586> = 586;
421+ <I587> = 587;
422+ <I588> = 588;
423+ <I589> = 589;
424+ <I590> = 590;
425+ <I591> = 591;
426+ <I592> = 592;
427+ <I593> = 593;
428+ <I594> = 594;
429+ <I595> = 595;
430+ <I596> = 596;
431+ <I597> = 597;
432+ <I598> = 598;
433+ <I599> = 599;
434+ <I600> = 600;
435+ <I601> = 601;
436+ <I602> = 602;
437+ <I603> = 603;
438+ <I604> = 604;
439+ <I605> = 605;
440+ <I606> = 606;
441+ <I616> = 616;
442+ <I617> = 617;
443+ <I618> = 618;
444+ <I619> = 619;
445+ <I620> = 620;
446+ <I621> = 621;
447+ <I622> = 622;
448+ <I623> = 623;
449+ <I624> = 624;
450+ <I625> = 625;
451+ <I626> = 626;
452+ <I627> = 627;
453+ <I628> = 628;
454+ <I629> = 629;
455+ <I630> = 630;
456+ <I631> = 631;
457+ <I632> = 632;
458+ <I633> = 633;
459+ <I634> = 634;
460+ <I635> = 635;
461+ <I636> = 636;
462+ <I637> = 637;
463+ <I638> = 638;
464+ <I639> = 639;
465+ <I640> = 640;
466+ <I641> = 641;
467+ <I642> = 642;
468+ <I643> = 643;
469+ <I644> = 644;
470+ <I645> = 645;
471+ <I646> = 646;
472+ <I647> = 647;
473+ <I648> = 648;
474+ <I649> = 649;
475+ <I650> = 650;
476+ <I651> = 651;
477+ <I652> = 652;
478+ <I653> = 653;
479+ <I654> = 654;
480+ <I655> = 655;
481+ <I656> = 656;
482+ <I657> = 657;
483+ <I664> = 664;
484+ <I665> = 665;
485+ <I666> = 666;
486+ <I667> = 667;
487+ <I668> = 668;
488+ <I669> = 669;
489+ <I670> = 670;
490+ <I671> = 671;
491+ <I672> = 672;
492+ <I673> = 673;
493+ <I674> = 674;
494+ <I675> = 675;
495+ <I676> = 676;
496+ <I677> = 677;
497+ <I678> = 678;
498+ <I679> = 679;
499+ <I680> = 680;
500+ <I681> = 681;
501+ <I682> = 682;
502+ <I683> = 683;
503+ <I684> = 684;
504+ <I685> = 685;
505+ <I686> = 686;
506+ <I687> = 687;
507+ <I688> = 688;
508+ <I689> = 689;
509+ <I690> = 690;
510+ <I691> = 691;
511+ <I692> = 692;
512+ <I693> = 693;
513+ <I696> = 696;
514+ <I697> = 697;
515+ <I698> = 698;
516+ <I699> = 699;
517+ <I700> = 700;
518+ <I701> = 701;
519+ <I704> = 704;
520+ <I705> = 705;
521+ <I706> = 706;
522+ <I707> = 707;
523+ <I708> = 708;
524+ <I709> = 709;
525+ indicator 1 = "Caps Lock";
526+ indicator 2 = "Num Lock";
527+ indicator 3 = "Scroll Lock";
528+ indicator 4 = "Compose";
529+ indicator 5 = "Kana";
530+ indicator 6 = "Sleep";
531+ indicator 7 = "Suspend";
532+ indicator 8 = "Mute";
533+ indicator 9 = "Misc";
534+ indicator 10 = "Mail";
535+ indicator 11 = "Charging";
536+ indicator 12 = "Shift Lock";
537+ indicator 13 = "Group 2";
538+ indicator 14 = "Mouse Keys";
539+ alias <AC12> = <BKSL>;
540+ alias <ALGR> = <RALT>;
541+ alias <MENU> = <COMP>;
542+ alias <HZTG> = <TLDE>;
543+ alias <LMTA> = <LWIN>;
544+ alias <RMTA> = <RWIN>;
545+ alias <OUTP> = <I235>;
546+ alias <KITG> = <I236>;
547+ alias <KIDN> = <I237>;
548+ alias <KIUP> = <I238>;
549+ alias <I121> = <MUTE>;
550+ alias <I122> = <VOL->;
551+ alias <I123> = <VOL+>;
552+ alias <I124> = <POWR>;
553+ alias <I125> = <KPEQ>;
554+ alias <I127> = <PAUS>;
555+ alias <I130> = <HNGL>;
556+ alias <I131> = <HJCV>;
557+ alias <I132> = <AE13>;
558+ alias <I133> = <LWIN>;
559+ alias <I134> = <RWIN>;
560+ alias <I135> = <COMP>;
561+ alias <I136> = <STOP>;
562+ alias <I137> = <AGAI>;
563+ alias <I138> = <PROP>;
564+ alias <I139> = <UNDO>;
565+ alias <I140> = <FRNT>;
566+ alias <I141> = <COPY>;
567+ alias <I142> = <OPEN>;
568+ alias <I143> = <PAST>;
569+ alias <I144> = <FIND>;
570+ alias <I145> = <CUT>;
571+ alias <I146> = <HELP>;
572+ alias <I191> = <FK13>;
573+ alias <I192> = <FK14>;
574+ alias <I193> = <FK15>;
575+ alias <I194> = <FK16>;
576+ alias <I195> = <FK17>;
577+ alias <I196> = <FK18>;
578+ alias <I197> = <FK19>;
579+ alias <I198> = <FK20>;
580+ alias <I199> = <FK21>;
581+ alias <I200> = <FK22>;
582+ alias <I201> = <FK23>;
583+ alias <I202> = <FK24>;
584+ alias <MDSW> = <LVL5>;
585+ alias <KPPT> = <I129>;
586+ alias <LatQ> = <AD01>;
587+ alias <LatW> = <AD02>;
588+ alias <LatE> = <AD03>;
589+ alias <LatR> = <AD04>;
590+ alias <LatT> = <AD05>;
591+ alias <LatY> = <AD06>;
592+ alias <LatU> = <AD07>;
593+ alias <LatI> = <AD08>;
594+ alias <LatO> = <AD09>;
595+ alias <LatP> = <AD10>;
596+ alias <LatA> = <AC01>;
597+ alias <LatS> = <AC02>;
598+ alias <LatD> = <AC03>;
599+ alias <LatF> = <AC04>;
600+ alias <LatG> = <AC05>;
601+ alias <LatH> = <AC06>;
602+ alias <LatJ> = <AC07>;
603+ alias <LatK> = <AC08>;
604+ alias <LatL> = <AC09>;
605+ alias <LatZ> = <AB01>;
606+ alias <LatX> = <AB02>;
607+ alias <LatC> = <AB03>;
608+ alias <LatV> = <AB04>;
609+ alias <LatB> = <AB05>;
610+ alias <LatN> = <AB06>;
611+ alias <LatM> = <AB07>;
612+};
613+
614+xkb_types "complete" {
615+ virtual_modifiers NumLock,Alt,LevelThree,Super,LevelFive,Meta,Hyper=0x4000,ScrollLock=0x8000;
616+
617+ type "ONE_LEVEL" {
618+ modifiers= none;
619+ level_name[1]= "Any";
620+ };
621+ type "TWO_LEVEL" {
622+ modifiers= Shift;
623+ map[Shift]= 2;
624+ level_name[1]= "Base";
625+ level_name[2]= "Shift";
626+ };
627+ type "ALPHABETIC" {
628+ modifiers= Shift+Lock;
629+ map[Shift]= 2;
630+ map[Lock]= 2;
631+ level_name[1]= "Base";
632+ level_name[2]= "Caps";
633+ };
634+ type "PC_ALT_LEVEL2" {
635+ modifiers= Alt;
636+ map[Alt]= 2;
637+ level_name[1]= "Base";
638+ level_name[2]= "Alt";
639+ };
640+ type "PC_SUPER_LEVEL2" {
641+ modifiers= Super;
642+ map[Super]= 2;
643+ level_name[1]= "Base";
644+ level_name[2]= "Super";
645+ };
646+ type "PC_SHIFT_SUPER_LEVEL2" {
647+ modifiers= Shift+Super;
648+ map[Shift+Super]= 2;
649+ map[Shift]= 1;
650+ preserve[Shift]= Shift;
651+ map[Super]= 1;
652+ preserve[Super]= Super;
653+ level_name[1]= "Base";
654+ level_name[2]= "Super";
655+ };
656+ type "PC_CONTROL_LEVEL2" {
657+ modifiers= Control;
658+ map[Control]= 2;
659+ level_name[1]= "Base";
660+ level_name[2]= "Control";
661+ };
662+ type "PC_CONTROL_SUPER_LEVEL2" {
663+ modifiers= Control+Super;
664+ map[Control+Super]= 2;
665+ map[Control]= 1;
666+ preserve[Control]= Control;
667+ map[Super]= 1;
668+ preserve[Super]= Super;
669+ level_name[1]= "Base";
670+ level_name[2]= "Control + Super";
671+ };
672+ type "CTRL+ALT" {
673+ modifiers= Shift+Control+Alt+LevelThree;
674+ map[Shift]= 2;
675+ map[LevelThree]= 3;
676+ map[Shift+LevelThree]= 4;
677+ map[Control]= 1;
678+ preserve[Control]= Control;
679+ map[Shift+Control]= 2;
680+ preserve[Shift+Control]= Control;
681+ map[Control+LevelThree]= 3;
682+ preserve[Control+LevelThree]= Control;
683+ map[Shift+Control+LevelThree]= 4;
684+ preserve[Shift+Control+LevelThree]= Control;
685+ map[Alt]= 1;
686+ preserve[Alt]= Alt;
687+ map[Shift+Alt]= 2;
688+ preserve[Shift+Alt]= Alt;
689+ map[Alt+LevelThree]= 3;
690+ preserve[Alt+LevelThree]= Alt;
691+ map[Shift+Alt+LevelThree]= 4;
692+ preserve[Shift+Alt+LevelThree]= Alt;
693+ map[Control+Alt]= 5;
694+ map[Shift+Control+Alt]= 2;
695+ preserve[Shift+Control+Alt]= Control+Alt;
696+ map[Control+Alt+LevelThree]= 3;
697+ preserve[Control+Alt+LevelThree]= Control+Alt;
698+ map[Shift+Control+Alt+LevelThree]= 4;
699+ preserve[Shift+Control+Alt+LevelThree]= Control+Alt;
700+ level_name[1]= "Base";
701+ level_name[2]= "Shift";
702+ level_name[3]= "AltGr";
703+ level_name[4]= "Shift AltGr";
704+ level_name[5]= "Ctrl+Alt";
705+ };
706+ type "THREE_LEVEL" {
707+ modifiers= Shift+LevelThree;
708+ map[Shift]= 2;
709+ map[LevelThree]= 3;
710+ map[Shift+LevelThree]= 3;
711+ level_name[1]= "Base";
712+ level_name[2]= "Shift";
713+ level_name[3]= "Level3";
714+ };
715+ type "FOUR_LEVEL" {
716+ modifiers= Shift+LevelThree;
717+ map[Shift]= 2;
718+ map[LevelThree]= 3;
719+ map[Shift+LevelThree]= 4;
720+ level_name[1]= "Base";
721+ level_name[2]= "Shift";
722+ level_name[3]= "AltGr";
723+ level_name[4]= "Shift AltGr";
724+ };
725+ type "FOUR_LEVEL_ALPHABETIC" {
726+ modifiers= Shift+Lock+LevelThree;
727+ map[Shift]= 2;
728+ map[Lock]= 2;
729+ map[LevelThree]= 3;
730+ map[Shift+LevelThree]= 4;
731+ map[Lock+LevelThree]= 4;
732+ map[Shift+Lock+LevelThree]= 3;
733+ level_name[1]= "Base";
734+ level_name[2]= "Shift";
735+ level_name[3]= "AltGr";
736+ level_name[4]= "Shift AltGr";
737+ };
738+ type "FOUR_LEVEL_SEMIALPHABETIC" {
739+ modifiers= Shift+Lock+LevelThree;
740+ map[Shift]= 2;
741+ map[Lock]= 2;
742+ map[LevelThree]= 3;
743+ map[Shift+LevelThree]= 4;
744+ map[Lock+LevelThree]= 3;
745+ preserve[Lock+LevelThree]= Lock;
746+ map[Shift+Lock+LevelThree]= 4;
747+ preserve[Shift+Lock+LevelThree]= Lock;
748+ level_name[1]= "Base";
749+ level_name[2]= "Shift";
750+ level_name[3]= "AltGr";
751+ level_name[4]= "Shift AltGr";
752+ };
753+ type "FOUR_LEVEL_KEYPAD" {
754+ modifiers= Shift+NumLock+LevelThree;
755+ map[Shift]= 1;
756+ preserve[Shift]= Shift;
757+ map[NumLock]= 2;
758+ map[LevelThree]= 3;
759+ map[Shift+NumLock]= 2;
760+ preserve[Shift+NumLock]= Shift;
761+ map[Shift+LevelThree]= 4;
762+ map[NumLock+LevelThree]= 3;
763+ map[Shift+NumLock+LevelThree]= 4;
764+ level_name[1]= "Base";
765+ level_name[2]= "NumLock";
766+ level_name[3]= "AltGr";
767+ level_name[4]= "Shift AltGr";
768+ };
769+ type "FOUR_LEVEL_MIXED_KEYPAD" {
770+ modifiers= Shift+NumLock+LevelThree;
771+ map[Shift]= 1;
772+ preserve[Shift]= Shift;
773+ map[NumLock]= 2;
774+ map[LevelThree]= 3;
775+ map[Shift+NumLock]= 2;
776+ preserve[Shift+NumLock]= Shift;
777+ map[Shift+LevelThree]= 4;
778+ map[NumLock+LevelThree]= 3;
779+ map[Shift+NumLock+LevelThree]= 4;
780+ level_name[1]= "Base";
781+ level_name[2]= "NumLock";
782+ level_name[3]= "AltGr";
783+ level_name[4]= "Shift AltGr";
784+ };
785+ type "FOUR_LEVEL_LOCKABLE_LEVEL2" {
786+ modifiers= Shift+LevelThree+LevelFive;
787+ map[Shift]= 2;
788+ map[LevelFive]= 2;
789+ map[LevelThree]= 3;
790+ map[Shift+LevelThree]= 4;
791+ map[LevelThree+LevelFive]= 3;
792+ map[Shift+LevelThree+LevelFive]= 4;
793+ level_name[1]= "Base";
794+ level_name[2]= "Digit";
795+ level_name[3]= "AltGr";
796+ level_name[4]= "Shift AltGr";
797+ };
798+ type "FOUR_LEVEL_X" {
799+ modifiers= Shift+Control+Alt+LevelThree;
800+ map[Shift]= 1;
801+ preserve[Shift]= Shift;
802+ map[LevelThree]= 2;
803+ map[Control]= 1;
804+ preserve[Control]= Control;
805+ map[Alt]= 1;
806+ preserve[Alt]= Alt;
807+ map[Shift+LevelThree]= 3;
808+ map[Shift+Control]= 1;
809+ preserve[Shift+Control]= Shift+Control;
810+ map[Shift+Alt]= 1;
811+ preserve[Shift+Alt]= Shift+Alt;
812+ map[Control+LevelThree]= 2;
813+ preserve[Control+LevelThree]= Control;
814+ map[Alt+LevelThree]= 2;
815+ preserve[Alt+LevelThree]= Alt;
816+ map[Control+Alt]= 4;
817+ map[Shift+Control+LevelThree]= 3;
818+ preserve[Shift+Control+LevelThree]= Control;
819+ map[Shift+Alt+LevelThree]= 3;
820+ preserve[Shift+Alt+LevelThree]= Alt;
821+ map[Shift+Control+Alt]= 4;
822+ preserve[Shift+Control+Alt]= Shift;
823+ map[Control+Alt+LevelThree]= 2;
824+ preserve[Control+Alt+LevelThree]= Control+Alt;
825+ map[Shift+Control+Alt+LevelThree]= 3;
826+ preserve[Shift+Control+Alt+LevelThree]= Control+Alt;
827+ level_name[1]= "Base";
828+ level_name[2]= "AltGr";
829+ level_name[3]= "Shift AltGr";
830+ level_name[4]= "Ctrl+Alt";
831+ };
832+ type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" {
833+ modifiers= Shift+Lock+LevelThree;
834+ map[Shift]= 2;
835+ map[Lock]= 4;
836+ preserve[Lock]= Lock;
837+ map[LevelThree]= 3;
838+ map[Shift+LevelThree]= 4;
839+ map[Lock+LevelThree]= 3;
840+ preserve[Lock+LevelThree]= Lock;
841+ map[Shift+Lock+LevelThree]= 3;
842+ level_name[1]= "Base";
843+ level_name[2]= "Shift";
844+ level_name[3]= "AltGr";
845+ level_name[4]= "Caps / Shift AltGr";
846+ };
847+ type "FOUR_LEVEL_PLUS_LOCK" {
848+ modifiers= Shift+Lock+LevelThree;
849+ map[Shift]= 2;
850+ map[LevelThree]= 3;
851+ map[Shift+LevelThree]= 4;
852+ map[Lock]= 5;
853+ map[Shift+Lock]= 2;
854+ map[Lock+LevelThree]= 3;
855+ map[Shift+Lock+LevelThree]= 4;
856+ level_name[1]= "Base";
857+ level_name[2]= "Shift";
858+ level_name[3]= "AltGr";
859+ level_name[4]= "Shift AltGr";
860+ level_name[5]= "Lock";
861+ };
862+ type "EIGHT_LEVEL" {
863+ modifiers= Shift+LevelThree+LevelFive;
864+ map[Shift]= 2;
865+ map[LevelThree]= 3;
866+ map[Shift+LevelThree]= 4;
867+ map[LevelFive]= 5;
868+ map[Shift+LevelFive]= 6;
869+ map[LevelThree+LevelFive]= 7;
870+ map[Shift+LevelThree+LevelFive]= 8;
871+ level_name[1]= "Base";
872+ level_name[2]= "Shift";
873+ level_name[3]= "AltGr";
874+ level_name[4]= "Shift AltGr";
875+ level_name[5]= "X";
876+ level_name[6]= "X Shift";
877+ level_name[7]= "X AltGr";
878+ level_name[8]= "X Shift AltGr";
879+ };
880+ type "EIGHT_LEVEL_ALPHABETIC" {
881+ modifiers= Shift+Lock+LevelThree+LevelFive;
882+ map[Shift]= 2;
883+ map[Lock]= 2;
884+ map[LevelThree]= 3;
885+ map[Shift+LevelThree]= 4;
886+ map[Lock+LevelThree]= 4;
887+ map[Shift+Lock+LevelThree]= 3;
888+ map[LevelFive]= 5;
889+ map[Shift+LevelFive]= 6;
890+ map[Lock+LevelFive]= 6;
891+ map[Shift+Lock+LevelFive]= 5;
892+ map[LevelThree+LevelFive]= 7;
893+ map[Shift+LevelThree+LevelFive]= 8;
894+ map[Lock+LevelThree+LevelFive]= 8;
895+ map[Shift+Lock+LevelThree+LevelFive]= 7;
896+ level_name[1]= "Base";
897+ level_name[2]= "Shift";
898+ level_name[3]= "AltGr";
899+ level_name[4]= "Shift AltGr";
900+ level_name[5]= "X";
901+ level_name[6]= "X Shift";
902+ level_name[7]= "X AltGr";
903+ level_name[8]= "X Shift AltGr";
904+ };
905+ type "EIGHT_LEVEL_SEMIALPHABETIC" {
906+ modifiers= Shift+Lock+LevelThree+LevelFive;
907+ map[Shift]= 2;
908+ map[Lock]= 2;
909+ map[LevelThree]= 3;
910+ map[Shift+LevelThree]= 4;
911+ map[Lock+LevelThree]= 3;
912+ preserve[Lock+LevelThree]= Lock;
913+ map[Shift+Lock+LevelThree]= 4;
914+ preserve[Shift+Lock+LevelThree]= Lock;
915+ map[LevelFive]= 5;
916+ map[Shift+LevelFive]= 6;
917+ map[Lock+LevelFive]= 6;
918+ map[Shift+Lock+LevelFive]= 5;
919+ map[LevelThree+LevelFive]= 7;
920+ map[Shift+LevelThree+LevelFive]= 8;
921+ map[Lock+LevelThree+LevelFive]= 7;
922+ preserve[Lock+LevelThree+LevelFive]= Lock;
923+ map[Shift+Lock+LevelThree+LevelFive]= 8;
924+ preserve[Shift+Lock+LevelThree+LevelFive]= Lock;
925+ level_name[1]= "Base";
926+ level_name[2]= "Shift";
927+ level_name[3]= "AltGr";
928+ level_name[4]= "Shift AltGr";
929+ level_name[5]= "X";
930+ level_name[6]= "X Shift";
931+ level_name[7]= "X AltGr";
932+ level_name[8]= "X Shift AltGr";
933+ };
934+ type "EIGHT_LEVEL_WITH_LEVEL5_LOCK" {
935+ modifiers= Shift+NumLock+LevelThree+LevelFive;
936+ map[Shift]= 2;
937+ map[LevelThree]= 3;
938+ map[Shift+LevelThree]= 4;
939+ map[LevelFive]= 5;
940+ map[Shift+LevelFive]= 6;
941+ preserve[Shift+LevelFive]= Shift;
942+ map[LevelThree+LevelFive]= 7;
943+ map[Shift+LevelThree+LevelFive]= 8;
944+ map[NumLock]= 5;
945+ map[Shift+NumLock]= 6;
946+ preserve[Shift+NumLock]= Shift;
947+ map[NumLock+LevelThree]= 7;
948+ map[Shift+NumLock+LevelThree]= 8;
949+ map[Shift+NumLock+LevelFive]= 2;
950+ map[NumLock+LevelThree+LevelFive]= 3;
951+ map[Shift+NumLock+LevelThree+LevelFive]= 4;
952+ level_name[1]= "Base";
953+ level_name[2]= "Shift";
954+ level_name[3]= "AltGr";
955+ level_name[4]= "Shift AltGr";
956+ level_name[5]= "X";
957+ level_name[6]= "X Shift";
958+ level_name[7]= "X AltGr";
959+ level_name[8]= "X Shift AltGr";
960+ };
961+ type "EIGHT_LEVEL_ALPHABETIC_WITH_LEVEL5_LOCK" {
962+ modifiers= Shift+Lock+NumLock+LevelThree+LevelFive;
963+ map[Shift]= 2;
964+ map[LevelThree]= 3;
965+ map[Shift+LevelThree]= 4;
966+ map[LevelFive]= 5;
967+ map[Shift+LevelFive]= 6;
968+ preserve[Shift+LevelFive]= Shift;
969+ map[LevelThree+LevelFive]= 7;
970+ map[Shift+LevelThree+LevelFive]= 8;
971+ map[NumLock]= 5;
972+ map[Shift+NumLock]= 6;
973+ preserve[Shift+NumLock]= Shift;
974+ map[NumLock+LevelThree]= 7;
975+ map[Shift+NumLock+LevelThree]= 8;
976+ map[Shift+NumLock+LevelFive]= 2;
977+ map[NumLock+LevelThree+LevelFive]= 3;
978+ map[Shift+NumLock+LevelThree+LevelFive]= 4;
979+ map[Lock]= 2;
980+ map[Lock+LevelThree]= 3;
981+ map[Shift+Lock+LevelThree]= 4;
982+ map[Lock+LevelFive]= 5;
983+ map[Shift+Lock+LevelFive]= 6;
984+ map[Lock+LevelThree+LevelFive]= 7;
985+ map[Shift+Lock+LevelThree+LevelFive]= 8;
986+ map[Lock+NumLock]= 5;
987+ map[Shift+Lock+NumLock]= 6;
988+ map[Lock+NumLock+LevelThree]= 7;
989+ map[Shift+Lock+NumLock+LevelThree]= 8;
990+ map[Lock+NumLock+LevelFive]= 2;
991+ map[Lock+NumLock+LevelThree+LevelFive]= 3;
992+ map[Shift+Lock+NumLock+LevelThree+LevelFive]= 4;
993+ level_name[1]= "Base";
994+ level_name[2]= "Shift";
995+ level_name[3]= "AltGr";
996+ level_name[4]= "Shift AltGr";
997+ level_name[5]= "X";
998+ level_name[6]= "X Shift";
999+ level_name[7]= "X AltGr";
1000+ level_name[8]= "X Shift AltGr";
1001+ };
1002+ type "EIGHT_LEVEL_BY_CTRL" {
1003+ modifiers= Shift+Lock+Control+LevelThree;
1004+ map[Shift]= 2;
1005+ map[Lock]= 2;
1006+ map[LevelThree]= 3;
1007+ map[Shift+LevelThree]= 4;
1008+ map[Lock+LevelThree]= 4;
1009+ map[Shift+Lock+LevelThree]= 3;
1010+ map[Control]= 5;
1011+ map[Shift+Control]= 6;
1012+ map[Lock+Control]= 6;
1013+ map[Shift+Lock+Control]= 5;
1014+ map[Control+LevelThree]= 7;
1015+ map[Shift+Control+LevelThree]= 8;
1016+ map[Lock+Control+LevelThree]= 8;
1017+ map[Shift+Lock+Control+LevelThree]= 7;
1018+ level_name[1]= "Base";
1019+ level_name[2]= "Shift";
1020+ level_name[3]= "Level3";
1021+ level_name[4]= "Shift Level3";
1022+ level_name[5]= "Ctrl";
1023+ level_name[6]= "Shift Ctrl";
1024+ level_name[7]= "Level3 Ctrl";
1025+ level_name[8]= "Shift Level3 Ctrl";
1026+ };
1027+ type "KEYPAD" {
1028+ modifiers= NumLock;
1029+ map[NumLock]= 2;
1030+ level_name[1]= "Base";
1031+ level_name[2]= "Number";
1032+ };
1033+ type "SHIFT+ALT" {
1034+ modifiers= Shift+Alt;
1035+ map[Shift+Alt]= 2;
1036+ level_name[1]= "Base";
1037+ level_name[2]= "Shift+Alt";
1038+ };
1039+};
1040+
1041+xkb_compatibility "complete" {
1042+ virtual_modifiers NumLock,Alt,LevelThree,Super,LevelFive,Meta,Hyper=0x4000,ScrollLock=0x8000;
1043+
1044+ interpret.useModMapMods= AnyLevel;
1045+ interpret.repeat= False;
1046+ interpret ISO_Level2_Latch+Exactly(Shift) {
1047+ useModMapMods=level1;
1048+ action= LatchMods(modifiers=Shift,clearLocks,latchToLock);
1049+ };
1050+ interpret Shift_Lock+AnyOf(Shift+Lock) {
1051+ action= LockMods(modifiers=Shift);
1052+ };
1053+ interpret Num_Lock+AnyOf(all) {
1054+ virtualModifier= NumLock;
1055+ action= LockMods(modifiers=NumLock);
1056+ };
1057+ interpret ISO_Level3_Shift+AnyOf(all) {
1058+ virtualModifier= LevelThree;
1059+ useModMapMods=level1;
1060+ action= SetMods(modifiers=LevelThree,clearLocks);
1061+ };
1062+ interpret ISO_Level3_Latch+AnyOf(all) {
1063+ virtualModifier= LevelThree;
1064+ useModMapMods=level1;
1065+ action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock);
1066+ };
1067+ interpret ISO_Level3_Lock+AnyOf(all) {
1068+ virtualModifier= LevelThree;
1069+ useModMapMods=level1;
1070+ action= LockMods(modifiers=LevelThree);
1071+ };
1072+ interpret Alt_L+AnyOf(all) {
1073+ virtualModifier= Alt;
1074+ action= SetMods(modifiers=modMapMods,clearLocks);
1075+ };
1076+ interpret Alt_R+AnyOf(all) {
1077+ virtualModifier= Alt;
1078+ action= SetMods(modifiers=modMapMods,clearLocks);
1079+ };
1080+ interpret Meta_L+AnyOf(all) {
1081+ virtualModifier= Meta;
1082+ action= SetMods(modifiers=modMapMods,clearLocks);
1083+ };
1084+ interpret Meta_R+AnyOf(all) {
1085+ virtualModifier= Meta;
1086+ action= SetMods(modifiers=modMapMods,clearLocks);
1087+ };
1088+ interpret Super_L+AnyOf(all) {
1089+ virtualModifier= Super;
1090+ action= SetMods(modifiers=modMapMods,clearLocks);
1091+ };
1092+ interpret Super_R+AnyOf(all) {
1093+ virtualModifier= Super;
1094+ action= SetMods(modifiers=modMapMods,clearLocks);
1095+ };
1096+ interpret Hyper_L+AnyOf(all) {
1097+ virtualModifier= Hyper;
1098+ action= SetMods(modifiers=modMapMods,clearLocks);
1099+ };
1100+ interpret Hyper_R+AnyOf(all) {
1101+ virtualModifier= Hyper;
1102+ action= SetMods(modifiers=modMapMods,clearLocks);
1103+ };
1104+ interpret Scroll_Lock+AnyOf(all) {
1105+ virtualModifier= ScrollLock;
1106+ action= LockMods(modifiers=modMapMods);
1107+ };
1108+ interpret ISO_Level5_Shift+AnyOf(all) {
1109+ virtualModifier= LevelFive;
1110+ useModMapMods=level1;
1111+ action= SetMods(modifiers=LevelFive,clearLocks);
1112+ };
1113+ interpret ISO_Level5_Latch+AnyOf(all) {
1114+ virtualModifier= LevelFive;
1115+ useModMapMods=level1;
1116+ action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock);
1117+ };
1118+ interpret ISO_Level5_Lock+AnyOf(all) {
1119+ virtualModifier= LevelFive;
1120+ useModMapMods=level1;
1121+ action= LockMods(modifiers=LevelFive);
1122+ };
1123+ interpret ISO_Group_Shift+AnyOfOrNone(all) {
1124+ action= SetGroup(group=+1);
1125+ };
1126+ interpret ISO_Level3_Shift+AnyOfOrNone(all) {
1127+ action= SetMods(modifiers=LevelThree,clearLocks);
1128+ };
1129+ interpret ISO_Level3_Latch+AnyOfOrNone(all) {
1130+ action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock);
1131+ };
1132+ interpret ISO_Level3_Lock+AnyOfOrNone(all) {
1133+ action= LockMods(modifiers=LevelThree);
1134+ };
1135+ interpret ISO_Group_Latch+AnyOfOrNone(all) {
1136+ action= LatchGroup(group=2);
1137+ };
1138+ interpret ISO_Next_Group+AnyOfOrNone(all) {
1139+ action= LockGroup(group=+1);
1140+ };
1141+ interpret ISO_Prev_Group+AnyOfOrNone(all) {
1142+ action= LockGroup(group=-1);
1143+ };
1144+ interpret ISO_First_Group+AnyOfOrNone(all) {
1145+ action= LockGroup(group=1);
1146+ };
1147+ interpret ISO_Last_Group+AnyOfOrNone(all) {
1148+ action= LockGroup(group=2);
1149+ };
1150+ interpret KP_1+AnyOfOrNone(all) {
1151+ repeat= True;
1152+ action= MovePtr(x=-1,y=+1);
1153+ };
1154+ interpret KP_End+AnyOfOrNone(all) {
1155+ repeat= True;
1156+ action= MovePtr(x=-1,y=+1);
1157+ };
1158+ interpret KP_2+AnyOfOrNone(all) {
1159+ repeat= True;
1160+ action= MovePtr(x=+0,y=+1);
1161+ };
1162+ interpret KP_Down+AnyOfOrNone(all) {
1163+ repeat= True;
1164+ action= MovePtr(x=+0,y=+1);
1165+ };
1166+ interpret KP_3+AnyOfOrNone(all) {
1167+ repeat= True;
1168+ action= MovePtr(x=+1,y=+1);
1169+ };
1170+ interpret KP_Next+AnyOfOrNone(all) {
1171+ repeat= True;
1172+ action= MovePtr(x=+1,y=+1);
1173+ };
1174+ interpret KP_4+AnyOfOrNone(all) {
1175+ repeat= True;
1176+ action= MovePtr(x=-1,y=+0);
1177+ };
1178+ interpret KP_Left+AnyOfOrNone(all) {
1179+ repeat= True;
1180+ action= MovePtr(x=-1,y=+0);
1181+ };
1182+ interpret KP_6+AnyOfOrNone(all) {
1183+ repeat= True;
1184+ action= MovePtr(x=+1,y=+0);
1185+ };
1186+ interpret KP_Right+AnyOfOrNone(all) {
1187+ repeat= True;
1188+ action= MovePtr(x=+1,y=+0);
1189+ };
1190+ interpret KP_7+AnyOfOrNone(all) {
1191+ repeat= True;
1192+ action= MovePtr(x=-1,y=-1);
1193+ };
1194+ interpret KP_Home+AnyOfOrNone(all) {
1195+ repeat= True;
1196+ action= MovePtr(x=-1,y=-1);
1197+ };
1198+ interpret KP_8+AnyOfOrNone(all) {
1199+ repeat= True;
1200+ action= MovePtr(x=+0,y=-1);
1201+ };
1202+ interpret KP_Up+AnyOfOrNone(all) {
1203+ repeat= True;
1204+ action= MovePtr(x=+0,y=-1);
1205+ };
1206+ interpret KP_9+AnyOfOrNone(all) {
1207+ repeat= True;
1208+ action= MovePtr(x=+1,y=-1);
1209+ };
1210+ interpret KP_Prior+AnyOfOrNone(all) {
1211+ repeat= True;
1212+ action= MovePtr(x=+1,y=-1);
1213+ };
1214+ interpret KP_5+AnyOfOrNone(all) {
1215+ repeat= True;
1216+ action= PtrBtn(button=default);
1217+ };
1218+ interpret KP_Begin+AnyOfOrNone(all) {
1219+ repeat= True;
1220+ action= PtrBtn(button=default);
1221+ };
1222+ interpret KP_F2+AnyOfOrNone(all) {
1223+ repeat= True;
1224+ action= SetPtrDflt(affect=button,button=1);
1225+ };
1226+ interpret KP_Divide+AnyOfOrNone(all) {
1227+ repeat= True;
1228+ action= SetPtrDflt(affect=button,button=1);
1229+ };
1230+ interpret KP_F3+AnyOfOrNone(all) {
1231+ repeat= True;
1232+ action= SetPtrDflt(affect=button,button=2);
1233+ };
1234+ interpret KP_Multiply+AnyOfOrNone(all) {
1235+ repeat= True;
1236+ action= SetPtrDflt(affect=button,button=2);
1237+ };
1238+ interpret KP_F4+AnyOfOrNone(all) {
1239+ repeat= True;
1240+ action= SetPtrDflt(affect=button,button=3);
1241+ };
1242+ interpret KP_Subtract+AnyOfOrNone(all) {
1243+ repeat= True;
1244+ action= SetPtrDflt(affect=button,button=3);
1245+ };
1246+ interpret KP_Separator+AnyOfOrNone(all) {
1247+ repeat= True;
1248+ action= PtrBtn(button=default,count=2);
1249+ };
1250+ interpret KP_Add+AnyOfOrNone(all) {
1251+ repeat= True;
1252+ action= PtrBtn(button=default,count=2);
1253+ };
1254+ interpret KP_0+AnyOfOrNone(all) {
1255+ repeat= True;
1256+ action= LockPtrBtn(button=default,affect=lock);
1257+ };
1258+ interpret KP_Insert+AnyOfOrNone(all) {
1259+ repeat= True;
1260+ action= LockPtrBtn(button=default,affect=lock);
1261+ };
1262+ interpret KP_Decimal+AnyOfOrNone(all) {
1263+ repeat= True;
1264+ action= LockPtrBtn(button=default,affect=unlock);
1265+ };
1266+ interpret KP_Delete+AnyOfOrNone(all) {
1267+ repeat= True;
1268+ action= LockPtrBtn(button=default,affect=unlock);
1269+ };
1270+ interpret F25+AnyOfOrNone(all) {
1271+ repeat= True;
1272+ action= SetPtrDflt(affect=button,button=1);
1273+ };
1274+ interpret F26+AnyOfOrNone(all) {
1275+ repeat= True;
1276+ action= SetPtrDflt(affect=button,button=2);
1277+ };
1278+ interpret F27+AnyOfOrNone(all) {
1279+ repeat= True;
1280+ action= MovePtr(x=-1,y=-1);
1281+ };
1282+ interpret F29+AnyOfOrNone(all) {
1283+ repeat= True;
1284+ action= MovePtr(x=+1,y=-1);
1285+ };
1286+ interpret F31+AnyOfOrNone(all) {
1287+ repeat= True;
1288+ action= PtrBtn(button=default);
1289+ };
1290+ interpret F33+AnyOfOrNone(all) {
1291+ repeat= True;
1292+ action= MovePtr(x=-1,y=+1);
1293+ };
1294+ interpret F35+AnyOfOrNone(all) {
1295+ repeat= True;
1296+ action= MovePtr(x=+1,y=+1);
1297+ };
1298+ interpret Pointer_Button_Dflt+AnyOfOrNone(all) {
1299+ action= PtrBtn(button=default);
1300+ };
1301+ interpret Pointer_Button1+AnyOfOrNone(all) {
1302+ action= PtrBtn(button=1);
1303+ };
1304+ interpret Pointer_Button2+AnyOfOrNone(all) {
1305+ action= PtrBtn(button=2);
1306+ };
1307+ interpret Pointer_Button3+AnyOfOrNone(all) {
1308+ action= PtrBtn(button=3);
1309+ };
1310+ interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) {
1311+ action= PtrBtn(button=default,count=2);
1312+ };
1313+ interpret Pointer_DblClick1+AnyOfOrNone(all) {
1314+ action= PtrBtn(button=1,count=2);
1315+ };
1316+ interpret Pointer_DblClick2+AnyOfOrNone(all) {
1317+ action= PtrBtn(button=2,count=2);
1318+ };
1319+ interpret Pointer_DblClick3+AnyOfOrNone(all) {
1320+ action= PtrBtn(button=3,count=2);
1321+ };
1322+ interpret Pointer_Drag_Dflt+AnyOfOrNone(all) {
1323+ action= LockPtrBtn(button=default,affect=both);
1324+ };
1325+ interpret Pointer_Drag1+AnyOfOrNone(all) {
1326+ action= LockPtrBtn(button=1,affect=both);
1327+ };
1328+ interpret Pointer_Drag2+AnyOfOrNone(all) {
1329+ action= LockPtrBtn(button=2,affect=both);
1330+ };
1331+ interpret Pointer_Drag3+AnyOfOrNone(all) {
1332+ action= LockPtrBtn(button=3,affect=both);
1333+ };
1334+ interpret Pointer_EnableKeys+AnyOfOrNone(all) {
1335+ action= LockControls(controls=MouseKeys);
1336+ };
1337+ interpret Pointer_Accelerate+AnyOfOrNone(all) {
1338+ action= LockControls(controls=MouseKeysAccel);
1339+ };
1340+ interpret Pointer_DfltBtnNext+AnyOfOrNone(all) {
1341+ action= SetPtrDflt(affect=button,button=+1);
1342+ };
1343+ interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) {
1344+ action= SetPtrDflt(affect=button,button=-1);
1345+ };
1346+ interpret AccessX_Enable+AnyOfOrNone(all) {
1347+ action= LockControls(controls=AccessXKeys);
1348+ };
1349+ interpret AccessX_Feedback_Enable+AnyOfOrNone(all) {
1350+ action= LockControls(controls=AccessXFeedback);
1351+ };
1352+ interpret RepeatKeys_Enable+AnyOfOrNone(all) {
1353+ action= LockControls(controls=RepeatKeys);
1354+ };
1355+ interpret SlowKeys_Enable+AnyOfOrNone(all) {
1356+ action= LockControls(controls=SlowKeys);
1357+ };
1358+ interpret BounceKeys_Enable+AnyOfOrNone(all) {
1359+ action= LockControls(controls=BounceKeys);
1360+ };
1361+ interpret StickyKeys_Enable+AnyOfOrNone(all) {
1362+ action= LockControls(controls=StickyKeys);
1363+ };
1364+ interpret MouseKeys_Enable+AnyOfOrNone(all) {
1365+ action= LockControls(controls=MouseKeys);
1366+ };
1367+ interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) {
1368+ action= LockControls(controls=MouseKeysAccel);
1369+ };
1370+ interpret Overlay1_Enable+AnyOfOrNone(all) {
1371+ action= LockControls(controls=none);
1372+ };
1373+ interpret Overlay2_Enable+AnyOfOrNone(all) {
1374+ action= LockControls(controls=none);
1375+ };
1376+ interpret AudibleBell_Enable+AnyOfOrNone(all) {
1377+ action= LockControls(controls=AudibleBell);
1378+ };
1379+ interpret Terminate_Server+AnyOfOrNone(all) {
1380+ action= Terminate();
1381+ };
1382+ interpret Alt_L+AnyOfOrNone(all) {
1383+ action= SetMods(modifiers=Alt,clearLocks);
1384+ };
1385+ interpret Alt_R+AnyOfOrNone(all) {
1386+ action= SetMods(modifiers=Alt,clearLocks);
1387+ };
1388+ interpret Meta_L+AnyOfOrNone(all) {
1389+ action= SetMods(modifiers=Meta,clearLocks);
1390+ };
1391+ interpret Meta_R+AnyOfOrNone(all) {
1392+ action= SetMods(modifiers=Meta,clearLocks);
1393+ };
1394+ interpret Super_L+AnyOfOrNone(all) {
1395+ action= SetMods(modifiers=Super,clearLocks);
1396+ };
1397+ interpret Super_R+AnyOfOrNone(all) {
1398+ action= SetMods(modifiers=Super,clearLocks);
1399+ };
1400+ interpret Hyper_L+AnyOfOrNone(all) {
1401+ action= SetMods(modifiers=Hyper,clearLocks);
1402+ };
1403+ interpret Hyper_R+AnyOfOrNone(all) {
1404+ action= SetMods(modifiers=Hyper,clearLocks);
1405+ };
1406+ interpret Shift_L+AnyOfOrNone(all) {
1407+ action= SetMods(modifiers=Shift,clearLocks);
1408+ };
1409+ interpret Shift_R+AnyOfOrNone(all) {
1410+ action= SetMods(modifiers=Shift,clearLocks);
1411+ };
1412+ interpret XF86Switch_VT_1+AnyOfOrNone(all) {
1413+ repeat= True;
1414+ action= SwitchScreen(screen=1,!same);
1415+ };
1416+ interpret XF86Switch_VT_2+AnyOfOrNone(all) {
1417+ repeat= True;
1418+ action= SwitchScreen(screen=2,!same);
1419+ };
1420+ interpret XF86Switch_VT_3+AnyOfOrNone(all) {
1421+ repeat= True;
1422+ action= SwitchScreen(screen=3,!same);
1423+ };
1424+ interpret XF86Switch_VT_4+AnyOfOrNone(all) {
1425+ repeat= True;
1426+ action= SwitchScreen(screen=4,!same);
1427+ };
1428+ interpret XF86Switch_VT_5+AnyOfOrNone(all) {
1429+ repeat= True;
1430+ action= SwitchScreen(screen=5,!same);
1431+ };
1432+ interpret XF86Switch_VT_6+AnyOfOrNone(all) {
1433+ repeat= True;
1434+ action= SwitchScreen(screen=6,!same);
1435+ };
1436+ interpret XF86Switch_VT_7+AnyOfOrNone(all) {
1437+ repeat= True;
1438+ action= SwitchScreen(screen=7,!same);
1439+ };
1440+ interpret XF86Switch_VT_8+AnyOfOrNone(all) {
1441+ repeat= True;
1442+ action= SwitchScreen(screen=8,!same);
1443+ };
1444+ interpret XF86Switch_VT_9+AnyOfOrNone(all) {
1445+ repeat= True;
1446+ action= SwitchScreen(screen=9,!same);
1447+ };
1448+ interpret XF86Switch_VT_10+AnyOfOrNone(all) {
1449+ repeat= True;
1450+ action= SwitchScreen(screen=10,!same);
1451+ };
1452+ interpret XF86Switch_VT_11+AnyOfOrNone(all) {
1453+ repeat= True;
1454+ action= SwitchScreen(screen=11,!same);
1455+ };
1456+ interpret XF86Switch_VT_12+AnyOfOrNone(all) {
1457+ repeat= True;
1458+ action= SwitchScreen(screen=12,!same);
1459+ };
1460+ interpret XF86LogGrabInfo+AnyOfOrNone(all) {
1461+ repeat= True;
1462+ action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00);
1463+ };
1464+ interpret XF86LogWindowTree+AnyOfOrNone(all) {
1465+ repeat= True;
1466+ action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00);
1467+ };
1468+ interpret XF86Next_VMode+AnyOfOrNone(all) {
1469+ repeat= True;
1470+ action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00);
1471+ };
1472+ interpret XF86Prev_VMode+AnyOfOrNone(all) {
1473+ repeat= True;
1474+ action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00);
1475+ };
1476+ interpret ISO_Level5_Shift+AnyOfOrNone(all) {
1477+ action= SetMods(modifiers=LevelFive,clearLocks);
1478+ };
1479+ interpret ISO_Level5_Latch+AnyOfOrNone(all) {
1480+ action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock);
1481+ };
1482+ interpret ISO_Level5_Lock+AnyOfOrNone(all) {
1483+ action= LockMods(modifiers=LevelFive);
1484+ };
1485+ interpret Caps_Lock+AnyOfOrNone(all) {
1486+ action= LockMods(modifiers=Lock);
1487+ };
1488+ interpret Any+Exactly(Lock) {
1489+ action= LockMods(modifiers=Lock);
1490+ };
1491+ interpret Any+AnyOf(all) {
1492+ action= SetMods(modifiers=modMapMods,clearLocks);
1493+ };
1494+ indicator "Caps Lock" {
1495+ whichModState= locked;
1496+ modifiers= Lock;
1497+ };
1498+ indicator "Num Lock" {
1499+ whichModState= locked;
1500+ modifiers= NumLock;
1501+ };
1502+ indicator "Scroll Lock" {
1503+ whichModState= locked;
1504+ modifiers= ScrollLock;
1505+ };
1506+ indicator "Shift Lock" {
1507+ whichModState= locked;
1508+ modifiers= Shift;
1509+ };
1510+ indicator "Group 2" {
1511+ groups= 0xfffffffe;
1512+ };
1513+ indicator "Mouse Keys" {
1514+ controls= MouseKeys;
1515+ };
1516+};
1517+
1518+xkb_symbols "pc_us_fr_2_inet(evdev)" {
1519+ name[1]="English (US)";
1520+ name[2]="French";
1521+
1522+ key <ESC> { [ Escape ] };
1523+ key <AE01> {
1524+ symbols[1]= [ 1, exclam ],
1525+ symbols[2]= [ ampersand, 1, onesuperior, exclamdown ]
1526+ };
1527+ key <AE02> {
1528+ symbols[1]= [ 2, at ],
1529+ symbols[2]= [ eacute, 2, asciitilde, oneeighth ]
1530+ };
1531+ key <AE03> {
1532+ symbols[1]= [ 3, numbersign ],
1533+ symbols[2]= [ quotedbl, 3, numbersign, sterling ]
1534+ };
1535+ key <AE04> {
1536+ symbols[1]= [ 4, dollar ],
1537+ symbols[2]= [ apostrophe, 4, braceleft, dollar ]
1538+ };
1539+ key <AE05> {
1540+ symbols[1]= [ 5, percent ],
1541+ symbols[2]= [ parenleft, 5, bracketleft, threeeighths ]
1542+ };
1543+ key <AE06> {
1544+ symbols[1]= [ 6, asciicircum ],
1545+ symbols[2]= [ minus, 6, bar, fiveeighths ]
1546+ };
1547+ key <AE07> {
1548+ symbols[1]= [ 7, ampersand ],
1549+ symbols[2]= [ egrave, 7, grave, seveneighths ]
1550+ };
1551+ key <AE08> {
1552+ symbols[1]= [ 8, asterisk ],
1553+ symbols[2]= [ underscore, 8, backslash, trademark ]
1554+ };
1555+ key <AE09> {
1556+ symbols[1]= [ 9, parenleft ],
1557+ symbols[2]= [ ccedilla, 9, asciicircum, plusminus ]
1558+ };
1559+ key <AE10> {
1560+ symbols[1]= [ 0, parenright ],
1561+ symbols[2]= [ agrave, 0, at, degree ]
1562+ };
1563+ key <AE11> {
1564+ symbols[1]= [ minus, underscore ],
1565+ symbols[2]= [ parenright, degree, bracketright, questiondown ]
1566+ };
1567+ key <AE12> {
1568+ symbols[1]= [ equal, plus ],
1569+ symbols[2]= [ equal, plus, braceright, dead_ogonek ]
1570+ };
1571+ key <BKSP> { [ BackSpace, BackSpace ] };
1572+ key <TAB> { [ Tab, ISO_Left_Tab ] };
1573+ key <AD01> {
1574+ symbols[1]= [ q, Q ],
1575+ symbols[2]= [ a, A, ae, AE ]
1576+ };
1577+ key <AD02> {
1578+ symbols[1]= [ w, W ],
1579+ symbols[2]= [ z, Z, guillemotleft, less ]
1580+ };
1581+ key <AD03> {
1582+ symbols[1]= [ e, E ],
1583+ symbols[2]= [ e, E, EuroSign, cent ]
1584+ };
1585+ key <AD04> {
1586+ symbols[1]= [ r, R ],
1587+ symbols[2]= [ r, R, paragraph, registered ]
1588+ };
1589+ key <AD05> {
1590+ symbols[1]= [ t, T ],
1591+ symbols[2]= [ t, T, tslash, Tslash ]
1592+ };
1593+ key <AD06> {
1594+ symbols[1]= [ y, Y ],
1595+ symbols[2]= [ y, Y, leftarrow, yen ]
1596+ };
1597+ key <AD07> {
1598+ symbols[1]= [ u, U ],
1599+ symbols[2]= [ u, U, downarrow, uparrow ]
1600+ };
1601+ key <AD08> {
1602+ symbols[1]= [ i, I ],
1603+ symbols[2]= [ i, I, rightarrow, idotless ]
1604+ };
1605+ key <AD09> {
1606+ symbols[1]= [ o, O ],
1607+ symbols[2]= [ o, O, oslash, Oslash ]
1608+ };
1609+ key <AD10> {
1610+ symbols[1]= [ p, P ],
1611+ symbols[2]= [ p, P, thorn, THORN ]
1612+ };
1613+ key <AD11> {
1614+ symbols[1]= [ bracketleft, braceleft ],
1615+ symbols[2]= [ dead_circumflex, dead_diaeresis, dead_diaeresis, dead_abovering ]
1616+ };
1617+ key <AD12> {
1618+ symbols[1]= [ bracketright, braceright ],
1619+ symbols[2]= [ dollar, sterling, currency, dead_macron ]
1620+ };
1621+ key <RTRN> { [ Return ] };
1622+ key <LCTL> { [ Control_L ] };
1623+ key <AC01> {
1624+ symbols[1]= [ a, A ],
1625+ symbols[2]= [ q, Q, at, Greek_OMEGA ]
1626+ };
1627+ key <AC02> {
1628+ symbols[1]= [ s, S ],
1629+ symbols[2]= [ s, S, ssharp, SSHARP ]
1630+ };
1631+ key <AC03> {
1632+ symbols[1]= [ d, D ],
1633+ symbols[2]= [ d, D, eth, ETH ]
1634+ };
1635+ key <AC04> {
1636+ symbols[1]= [ f, F ],
1637+ symbols[2]= [ f, F, dstroke, ordfeminine ]
1638+ };
1639+ key <AC05> {
1640+ symbols[1]= [ g, G ],
1641+ symbols[2]= [ g, G, eng, ENG ]
1642+ };
1643+ key <AC06> {
1644+ symbols[1]= [ h, H ],
1645+ symbols[2]= [ h, H, hstroke, Hstroke ]
1646+ };
1647+ key <AC07> {
1648+ symbols[1]= [ j, J ],
1649+ symbols[2]= [ j, J, dead_hook, dead_horn ]
1650+ };
1651+ key <AC08> {
1652+ symbols[1]= [ k, K ],
1653+ symbols[2]= [ k, K, kra, ampersand ]
1654+ };
1655+ key <AC09> {
1656+ symbols[1]= [ l, L ],
1657+ symbols[2]= [ l, L, lstroke, Lstroke ]
1658+ };
1659+ key <AC10> {
1660+ symbols[1]= [ semicolon, colon ],
1661+ symbols[2]= [ m, M, mu, masculine ]
1662+ };
1663+ key <AC11> {
1664+ symbols[1]= [ apostrophe, quotedbl ],
1665+ symbols[2]= [ ugrave, percent, dead_circumflex, dead_caron ]
1666+ };
1667+ key <TLDE> {
1668+ symbols[1]= [ grave, asciitilde ],
1669+ symbols[2]= [ twosuperior, asciitilde, notsign, notsign ]
1670+ };
1671+ key <LFSH> { [ Shift_L ] };
1672+ key <BKSL> {
1673+ symbols[1]= [ backslash, bar ],
1674+ symbols[2]= [ asterisk, mu, dead_grave, dead_breve ]
1675+ };
1676+ key <AB01> {
1677+ symbols[1]= [ z, Z ],
1678+ symbols[2]= [ w, W, lstroke, Lstroke ]
1679+ };
1680+ key <AB02> {
1681+ symbols[1]= [ x, X ],
1682+ symbols[2]= [ x, X, guillemotright, greater ]
1683+ };
1684+ key <AB03> {
1685+ symbols[1]= [ c, C ],
1686+ symbols[2]= [ c, C, cent, copyright ]
1687+ };
1688+ key <AB04> {
1689+ symbols[1]= [ v, V ],
1690+ symbols[2]= [ v, V, doublelowquotemark, singlelowquotemark ]
1691+ };
1692+ key <AB05> {
1693+ symbols[1]= [ b, B ],
1694+ symbols[2]= [ b, B, leftdoublequotemark, leftsinglequotemark ]
1695+ };
1696+ key <AB06> {
1697+ symbols[1]= [ n, N ],
1698+ symbols[2]= [ n, N, rightdoublequotemark, rightsinglequotemark ]
1699+ };
1700+ key <AB07> {
1701+ symbols[1]= [ m, M ],
1702+ symbols[2]= [ comma, question, dead_acute, dead_doubleacute ]
1703+ };
1704+ key <AB08> {
1705+ symbols[1]= [ comma, less ],
1706+ symbols[2]= [ semicolon, period, U2022, multiply ]
1707+ };
1708+ key <AB09> {
1709+ symbols[1]= [ period, greater ],
1710+ symbols[2]= [ colon, slash, periodcentered, division ]
1711+ };
1712+ key <AB10> {
1713+ symbols[1]= [ slash, question ],
1714+ symbols[2]= [ exclam, section, dead_belowdot, dead_abovedot ]
1715+ };
1716+ key <RTSH> { [ Shift_R ] };
1717+ key <KPMU> {
1718+ type= "CTRL+ALT",
1719+ symbols[1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ]
1720+ };
1721+ key <LALT> { [ Alt_L ] };
1722+ key <SPCE> { [ space ] };
1723+ key <CAPS> { [ Caps_Lock ] };
1724+ key <FK01> {
1725+ type= "CTRL+ALT",
1726+ symbols[1]= [ F1, F1, F1, F1, XF86Switch_VT_1 ]
1727+ };
1728+ key <FK02> {
1729+ type= "CTRL+ALT",
1730+ symbols[1]= [ F2, F2, F2, F2, XF86Switch_VT_2 ]
1731+ };
1732+ key <FK03> {
1733+ type= "CTRL+ALT",
1734+ symbols[1]= [ F3, F3, F3, F3, XF86Switch_VT_3 ]
1735+ };
1736+ key <FK04> {
1737+ type= "CTRL+ALT",
1738+ symbols[1]= [ F4, F4, F4, F4, XF86Switch_VT_4 ]
1739+ };
1740+ key <FK05> {
1741+ type= "CTRL+ALT",
1742+ symbols[1]= [ F5, F5, F5, F5, XF86Switch_VT_5 ]
1743+ };
1744+ key <FK06> {
1745+ type= "CTRL+ALT",
1746+ symbols[1]= [ F6, F6, F6, F6, XF86Switch_VT_6 ]
1747+ };
1748+ key <FK07> {
1749+ type= "CTRL+ALT",
1750+ symbols[1]= [ F7, F7, F7, F7, XF86Switch_VT_7 ]
1751+ };
1752+ key <FK08> {
1753+ type= "CTRL+ALT",
1754+ symbols[1]= [ F8, F8, F8, F8, XF86Switch_VT_8 ]
1755+ };
1756+ key <FK09> {
1757+ type= "CTRL+ALT",
1758+ symbols[1]= [ F9, F9, F9, F9, XF86Switch_VT_9 ]
1759+ };
1760+ key <FK10> {
1761+ type= "CTRL+ALT",
1762+ symbols[1]= [ F10, F10, F10, F10, XF86Switch_VT_10 ]
1763+ };
1764+ key <NMLK> { [ Num_Lock ] };
1765+ key <SCLK> { [ Scroll_Lock ] };
1766+ key <KP7> { [ KP_Home, KP_7 ] };
1767+ key <KP8> { [ KP_Up, KP_8 ] };
1768+ key <KP9> { [ KP_Prior, KP_9 ] };
1769+ key <KPSU> {
1770+ type= "CTRL+ALT",
1771+ symbols[1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ]
1772+ };
1773+ key <KP4> { [ KP_Left, KP_4 ] };
1774+ key <KP5> { [ KP_Begin, KP_5 ] };
1775+ key <KP6> { [ KP_Right, KP_6 ] };
1776+ key <KPAD> {
1777+ type= "CTRL+ALT",
1778+ symbols[1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ]
1779+ };
1780+ key <KP1> { [ KP_End, KP_1 ] };
1781+ key <KP2> { [ KP_Down, KP_2 ] };
1782+ key <KP3> { [ KP_Next, KP_3 ] };
1783+ key <KP0> { [ KP_Insert, KP_0 ] };
1784+ key <KPDL> { [ KP_Delete, KP_Decimal ] };
1785+ key <LVL3> { [ ISO_Level3_Shift ] };
1786+ key <ZEHA> {
1787+ type= "PC_CONTROL_SUPER_LEVEL2",
1788+ symbols[1]= [ F24, XF86TouchpadToggle ]
1789+ };
1790+ key <LSGT> { [ less, greater, bar, brokenbar ] };
1791+ key <FK11> {
1792+ type= "CTRL+ALT",
1793+ symbols[1]= [ F11, F11, F11, F11, XF86Switch_VT_11 ]
1794+ };
1795+ key <FK12> {
1796+ type= "CTRL+ALT",
1797+ symbols[1]= [ F12, F12, F12, F12, XF86Switch_VT_12 ]
1798+ };
1799+ key <KATA> { [ Katakana ] };
1800+ key <HIRA> { [ Hiragana ] };
1801+ key <HENK> { [ Henkan_Mode ] };
1802+ key <HKTG> { [ Hiragana_Katakana ] };
1803+ key <MUHE> { [ Muhenkan ] };
1804+ key <KPEN> { [ KP_Enter ] };
1805+ key <RCTL> { [ Control_R ] };
1806+ key <KPDV> {
1807+ type= "CTRL+ALT",
1808+ symbols[1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ]
1809+ };
1810+ key <PRSC> {
1811+ type= "PC_ALT_LEVEL2",
1812+ symbols[1]= [ Print, Sys_Req ]
1813+ };
1814+ key <RALT> {
1815+ type= "ONE_LEVEL",
1816+ symbols[1]= [ Alt_R ],
1817+ symbols[2]= [ ISO_Level3_Shift ]
1818+ };
1819+ key <LNFD> { [ Linefeed ] };
1820+ key <HOME> { [ Home ] };
1821+ key <UP> { [ Up ] };
1822+ key <PGUP> { [ Prior ] };
1823+ key <LEFT> { [ Left ] };
1824+ key <RGHT> { [ Right ] };
1825+ key <END> { [ End ] };
1826+ key <DOWN> { [ Down ] };
1827+ key <PGDN> { [ Next ] };
1828+ key <INS> { [ Insert ] };
1829+ key <DELE> { [ Delete ] };
1830+ key <MUTE> { [ XF86AudioMute ] };
1831+ key <VOL-> { [ XF86AudioLowerVolume ] };
1832+ key <VOL+> { [ XF86AudioRaiseVolume ] };
1833+ key <POWR> { [ XF86PowerOff ] };
1834+ key <KPEQ> { [ KP_Equal ] };
1835+ key <I126> { [ plusminus ] };
1836+ key <PAUS> {
1837+ type= "PC_CONTROL_LEVEL2",
1838+ symbols[1]= [ Pause, Break ]
1839+ };
1840+ key <I128> { [ XF86LaunchA ] };
1841+ key <I129> { [ KP_Decimal, KP_Decimal ] };
1842+ key <HNGL> { [ Hangul ] };
1843+ key <HJCV> { [ Hangul_Hanja ] };
1844+ key <LWIN> { [ Super_L ] };
1845+ key <RWIN> { [ Super_R ] };
1846+ key <COMP> { [ Menu ] };
1847+ key <STOP> { [ Cancel ] };
1848+ key <AGAI> { [ Redo ] };
1849+ key <PROP> { [ SunProps ] };
1850+ key <UNDO> { [ Undo ] };
1851+ key <FRNT> { [ SunFront ] };
1852+ key <COPY> { [ XF86Copy ] };
1853+ key <OPEN> { [ XF86Open ] };
1854+ key <PAST> { [ XF86Paste ] };
1855+ key <FIND> { [ Find ] };
1856+ key <CUT> { [ XF86Cut ] };
1857+ key <HELP> { [ Help ] };
1858+ key <I147> { [ XF86MenuKB ] };
1859+ key <I148> { [ XF86Calculator ] };
1860+ key <I150> { [ XF86Sleep ] };
1861+ key <I151> { [ XF86WakeUp ] };
1862+ key <I152> { [ XF86Explorer ] };
1863+ key <I153> { [ XF86Send ] };
1864+ key <I155> { [ XF86Xfer ] };
1865+ key <I156> { [ XF86Launch1 ] };
1866+ key <I157> { [ XF86Launch2 ] };
1867+ key <I158> { [ XF86WWW ] };
1868+ key <I159> { [ XF86DOS ] };
1869+ key <I160> { [ XF86ScreenSaver ] };
1870+ key <I161> { [ XF86RotateWindows ] };
1871+ key <I162> { [ XF86TaskPane ] };
1872+ key <I163> { [ XF86Mail ] };
1873+ key <I164> { [ XF86Favorites ] };
1874+ key <I165> { [ XF86MyComputer ] };
1875+ key <I166> { [ XF86Back ] };
1876+ key <I167> { [ XF86Forward ] };
1877+ key <I169> { [ XF86Eject ] };
1878+ key <I170> { [ XF86Eject ] };
1879+ key <I171> { [ XF86AudioNext ] };
1880+ key <I172> { [ XF86AudioPlay, XF86AudioPause ] };
1881+ key <I173> { [ XF86AudioPrev ] };
1882+ key <I174> { [ XF86AudioStop, XF86Eject ] };
1883+ key <I175> { [ XF86AudioRecord ] };
1884+ key <I176> { [ XF86AudioRewind ] };
1885+ key <I177> { [ XF86Phone ] };
1886+ key <I179> { [ XF86Tools ] };
1887+ key <I180> { [ XF86HomePage ] };
1888+ key <I181> { [ XF86Reload ] };
1889+ key <I182> { [ XF86Close ] };
1890+ key <I185> { [ XF86ScrollUp ] };
1891+ key <I186> { [ XF86ScrollDown ] };
1892+ key <I187> { [ parenleft ] };
1893+ key <I188> { [ parenright ] };
1894+ key <I189> { [ XF86New ] };
1895+ key <I190> { [ Redo ] };
1896+ key <FK13> { [ XF86Tools ] };
1897+ key <FK14> { [ XF86Launch5 ] };
1898+ key <FK15> { [ XF86Launch6 ] };
1899+ key <FK16> { [ XF86Launch7 ] };
1900+ key <FK17> { [ XF86Launch8 ] };
1901+ key <FK18> { [ XF86Launch9 ] };
1902+ key <FK19> { [ F19 ] };
1903+ key <FK20> { [ XF86AudioMicMute ] };
1904+ key <FK21> { [ XF86TouchpadToggle ] };
1905+ key <FK22> { [ XF86TouchpadOn ] };
1906+ key <FK23> {
1907+ type= "PC_SHIFT_SUPER_LEVEL2",
1908+ symbols[1]= [ F23, XF86Assistant ]
1909+ };
1910+ key <FK24> {
1911+ type= "PC_CONTROL_SUPER_LEVEL2",
1912+ symbols[1]= [ F24, XF86TouchpadToggle ]
1913+ };
1914+ key <LVL5> { [ ISO_Level5_Shift ] };
1915+ key <ALT> { [ NoSymbol, Alt_L ] };
1916+ key <META> { [ NoSymbol, Meta_L ] };
1917+ key <SUPR> { [ NoSymbol, Super_L ] };
1918+ key <HYPR> { [ NoSymbol, Hyper_L ] };
1919+ key <I208> { [ XF86AudioPlay ] };
1920+ key <I209> { [ XF86AudioPause ] };
1921+ key <I210> { [ XF86Launch3 ] };
1922+ key <I211> { [ XF86Launch4 ] };
1923+ key <I212> { [ XF86LaunchB ] };
1924+ key <I213> { [ XF86Suspend ] };
1925+ key <I214> { [ XF86Close ] };
1926+ key <I215> { [ XF86AudioPlay ] };
1927+ key <I216> { [ XF86AudioForward ] };
1928+ key <I217> { [ XF86AudioBassBoost ] };
1929+ key <I218> { [ Print ] };
1930+ key <I220> { [ XF86WebCam ] };
1931+ key <I221> { [ XF86AudioPreset ] };
1932+ key <I223> { [ XF86Mail ] };
1933+ key <I224> { [ XF86Messenger ] };
1934+ key <I225> { [ XF86Search ] };
1935+ key <I226> { [ XF86Go ] };
1936+ key <I227> { [ XF86Finance ] };
1937+ key <I228> { [ XF86Game ] };
1938+ key <I229> { [ XF86Shop ] };
1939+ key <I231> { [ Cancel ] };
1940+ key <I232> { [ XF86MonBrightnessDown ] };
1941+ key <I233> { [ XF86MonBrightnessUp ] };
1942+ key <I234> { [ XF86AudioMedia ] };
1943+ key <I235> { [ XF86Display ] };
1944+ key <I236> { [ XF86KbdLightOnOff ] };
1945+ key <I237> { [ XF86KbdBrightnessDown ] };
1946+ key <I238> { [ XF86KbdBrightnessUp ] };
1947+ key <I239> { [ XF86Send ] };
1948+ key <I240> { [ XF86Reply ] };
1949+ key <I241> { [ XF86MailForward ] };
1950+ key <I242> { [ XF86Save ] };
1951+ key <I243> { [ XF86Documents ] };
1952+ key <I244> { [ XF86Battery ] };
1953+ key <I245> { [ XF86Bluetooth ] };
1954+ key <I246> { [ XF86WLAN ] };
1955+ key <I247> { [ XF86UWB ] };
1956+ key <I249> { [ XF86Next_VMode ] };
1957+ key <I250> { [ XF86Prev_VMode ] };
1958+ key <I251> { [ XF86MonBrightnessCycle ] };
1959+ key <I252> { [ XF86BrightnessAuto ] };
1960+ key <I253> { [ XF86DisplayOff ] };
1961+ key <I254> { [ XF86WWAN ] };
1962+ key <I255> { [ XF86RFKill ] };
1963+ key <I256> { [ XF86AudioMicMute ] };
1964+ key <I360> { [ XF86OK ] };
1965+ key <I361> { [ XF86Select ] };
1966+ key <I362> { [ XF86GoTo ] };
1967+ key <I363> { [ XF86Clear ] };
1968+ key <I365> { [ XF86Option ] };
1969+ key <I366> { [ XF86Info ] };
1970+ key <I367> { [ XF86Time ] };
1971+ key <I368> { [ XF86VendorLogo ] };
1972+ key <I370> { [ XF86MediaSelectProgramGuide ] };
1973+ key <I371> { [ XF86NextFavorite ] };
1974+ key <I372> { [ XF86Favorites ] };
1975+ key <I373> { [ XF86MediaSelectProgramGuide ] };
1976+ key <I374> { [ XF86MediaSelectHome ] };
1977+ key <I376> { [ XF86MediaLanguageMenu ] };
1978+ key <I377> { [ XF86MediaTitleMenu ] };
1979+ key <I378> { [ XF86Subtitle ] };
1980+ key <I379> { [ XF86CycleAngle ] };
1981+ key <I380> { [ XF86FullScreen ] };
1982+ key <I381> { [ XF86AudioChannelMode ] };
1983+ key <I382> { [ XF86Keyboard ] };
1984+ key <I383> { [ XF86AspectRatio ] };
1985+ key <I384> { [ XF86MediaSelectPC ] };
1986+ key <I385> { [ XF86MediaSelectTV ] };
1987+ key <I386> { [ XF86MediaSelectCable ] };
1988+ key <I387> { [ XF86MediaSelectVCR ] };
1989+ key <I388> { [ XF86MediaSelectVCRPlus ] };
1990+ key <I389> { [ XF86MediaSelectSatellite ] };
1991+ key <I391> { [ XF86CD ] };
1992+ key <I392> { [ XF86MediaSelectTape ] };
1993+ key <I393> { [ XF86MediaSelectRadio ] };
1994+ key <I394> { [ XF86MediaSelectTuner ] };
1995+ key <I395> { [ XF86MediaPlayer ] };
1996+ key <I396> { [ XF86MediaSelectTeletext ] };
1997+ key <I397> { [ XF86DVD ] };
1998+ key <I398> { [ XF86MediaSelectAuxiliary ] };
1999+ key <I400> { [ XF86Audio ] };
2000+ key <I401> { [ XF86Video ] };
2001+ key <I404> { [ XF86Memo ] };
2002+ key <I405> { [ XF86Calendar ] };
2003+ key <I406> { [ XF86Red ] };
2004+ key <I407> { [ XF86Green ] };
2005+ key <I408> { [ XF86Yellow ] };
2006+ key <I409> { [ XF86Blue ] };
2007+ key <I410> { [ XF86ChannelUp ] };
2008+ key <I411> { [ XF86ChannelDown ] };
2009+ key <I417> { [ XF86MediaPlaySlow ] };
2010+ key <I418> { [ XF86AudioRandomPlay ] };
2011+ key <I419> { [ XF86Break ] };
2012+ key <I421> { [ XF86NumberEntryMode ] };
2013+ key <I424> { [ XF86VideoPhone ] };
2014+ key <I425> { [ XF86Game ] };
2015+ key <I426> { [ XF86ZoomIn ] };
2016+ key <I427> { [ XF86ZoomOut ] };
2017+ key <I428> { [ XF86ZoomReset ] };
2018+ key <I429> { [ XF86Word ] };
2019+ key <I430> { [ XF86Editor ] };
2020+ key <I431> { [ XF86Excel ] };
2021+ key <I432> { [ XF86GraphicsEditor ] };
2022+ key <I433> { [ XF86Presentation ] };
2023+ key <I434> { [ XF86Database ] };
2024+ key <I435> { [ XF86News ] };
2025+ key <I436> { [ XF86Voicemail ] };
2026+ key <I437> { [ XF86Addressbook ] };
2027+ key <I438> { [ XF86Messenger ] };
2028+ key <I439> { [ XF86DisplayToggle ] };
2029+ key <I440> { [ XF86SpellCheck ] };
2030+ key <I441> { [ XF86LogOff ] };
2031+ key <I442> { [ dollar ] };
2032+ key <I443> { [ EuroSign ] };
2033+ key <I444> { [ XF86FrameBack ] };
2034+ key <I445> { [ XF86FrameForward ] };
2035+ key <I446> { [ XF86ContextMenu ] };
2036+ key <I447> { [ XF86MediaRepeat ] };
2037+ key <I448> { [ XF8610ChannelsUp ] };
2038+ key <I449> { [ XF8610ChannelsDown ] };
2039+ key <I450> { [ XF86Images ] };
2040+ key <I452> { [ XF86NotificationCenter ] };
2041+ key <I453> { [ XF86PickupPhone ] };
2042+ key <I454> { [ XF86HangupPhone ] };
2043+ key <I455> { [ XF86LinkPhone ] };
2044+ key <I472> { [ XF86Fn ] };
2045+ key <I473> { [ XF86Fn_Esc ] };
2046+ key <I474> { [ XF86Fn_F1 ] };
2047+ key <I475> { [ XF86Fn_F2 ] };
2048+ key <I476> { [ XF86Fn_F3 ] };
2049+ key <I477> { [ XF86Fn_F4 ] };
2050+ key <I478> { [ XF86Fn_F5 ] };
2051+ key <I479> { [ XF86Fn_F6 ] };
2052+ key <I480> { [ XF86Fn_F7 ] };
2053+ key <I481> { [ XF86Fn_F8 ] };
2054+ key <I482> { [ XF86Fn_F9 ] };
2055+ key <I483> { [ XF86Fn_F10 ] };
2056+ key <I484> { [ XF86Fn_F11 ] };
2057+ key <I485> { [ XF86Fn_F12 ] };
2058+ key <I486> { [ XF86Fn_1 ] };
2059+ key <I487> { [ XF86Fn_2 ] };
2060+ key <I488> { [ XF86Fn_D ] };
2061+ key <I489> { [ XF86Fn_E ] };
2062+ key <I490> { [ XF86Fn_F ] };
2063+ key <I491> { [ XF86Fn_S ] };
2064+ key <I492> { [ XF86Fn_B ] };
2065+ key <I493> { [ XF86FnRightShift ] };
2066+ key <I505> { [ braille_dot_1 ] };
2067+ key <I506> { [ braille_dot_2 ] };
2068+ key <I507> { [ braille_dot_3 ] };
2069+ key <I508> { [ braille_dot_4 ] };
2070+ key <I509> { [ braille_dot_5 ] };
2071+ key <I510> { [ braille_dot_6 ] };
2072+ key <I511> { [ braille_dot_7 ] };
2073+ key <I512> { [ braille_dot_8 ] };
2074+ key <I513> { [ braille_dot_9 ] };
2075+ key <I514> { [ braille_dot_1 ] };
2076+ key <I520> { [ XF86Numeric0 ] };
2077+ key <I521> { [ XF86Numeric1 ] };
2078+ key <I522> { [ XF86Numeric2 ] };
2079+ key <I523> { [ XF86Numeric3 ] };
2080+ key <I524> { [ XF86Numeric4 ] };
2081+ key <I525> { [ XF86Numeric5 ] };
2082+ key <I526> { [ XF86Numeric6 ] };
2083+ key <I527> { [ XF86Numeric7 ] };
2084+ key <I528> { [ XF86Numeric8 ] };
2085+ key <I529> { [ XF86Numeric9 ] };
2086+ key <I530> { [ XF86NumericStar ] };
2087+ key <I531> { [ XF86NumericPound ] };
2088+ key <I532> { [ XF86NumericA ] };
2089+ key <I533> { [ XF86NumericB ] };
2090+ key <I534> { [ XF86NumericC ] };
2091+ key <I535> { [ XF86NumericD ] };
2092+ key <I536> { [ XF86CameraFocus ] };
2093+ key <I537> { [ XF86WPSButton ] };
2094+ key <I538> { [ XF86TouchpadToggle ] };
2095+ key <I539> { [ XF86TouchpadOn ] };
2096+ key <I540> { [ XF86TouchpadOff ] };
2097+ key <I541> { [ XF86CameraZoomIn ] };
2098+ key <I542> { [ XF86CameraZoomOut ] };
2099+ key <I543> { [ XF86CameraUp ] };
2100+ key <I544> { [ XF86CameraDown ] };
2101+ key <I545> { [ XF86CameraLeft ] };
2102+ key <I546> { [ XF86CameraRight ] };
2103+ key <I547> { [ XF86AttendantOn ] };
2104+ key <I548> { [ XF86AttendantOff ] };
2105+ key <I549> { [ XF86AttendantToggle ] };
2106+ key <I550> { [ XF86LightsToggle ] };
2107+ key <I568> { [ XF86ALSToggle ] };
2108+ key <I569> { [ XF86RotationLockToggle ] };
2109+ key <I570> { [ XF86RefreshRateToggle ] };
2110+ key <I584> { [ XF86Buttonconfig ] };
2111+ key <I585> { [ XF86Taskmanager ] };
2112+ key <I586> { [ XF86Journal ] };
2113+ key <I587> { [ XF86ControlPanel ] };
2114+ key <I588> { [ XF86AppSelect ] };
2115+ key <I589> { [ XF86Screensaver ] };
2116+ key <I590> { [ XF86VoiceCommand ] };
2117+ key <I591> { [ XF86Assistant ] };
2118+ key <I592> { [ ISO_Next_Group ] };
2119+ key <I593> { [ XF86EmojiPicker ] };
2120+ key <I594> { [ XF86Dictate ] };
2121+ key <I595> { [ XF86CameraAccessEnable ] };
2122+ key <I596> { [ XF86CameraAccessDisable ] };
2123+ key <I597> { [ XF86CameraAccessToggle ] };
2124+ key <I598> { [ XF86Accessibility ] };
2125+ key <I599> { [ XF86DoNotDisturb ] };
2126+ key <I600> { [ XF86BrightnessMin ] };
2127+ key <I601> { [ XF86BrightnessMax ] };
2128+ key <I602> { [ XF86ElectronicPrivacyScreenOn ] };
2129+ key <I603> { [ XF86ElectronicPrivacyScreenOff ] };
2130+ key <I604> { [ XF86ActionOnSelection ] };
2131+ key <I605> { [ XF86ContextualInsert ] };
2132+ key <I606> { [ XF86ContextualQuery ] };
2133+ key <I616> { [ XF86KbdInputAssistPrev ] };
2134+ key <I617> { [ XF86KbdInputAssistNext ] };
2135+ key <I618> { [ XF86KbdInputAssistPrevgroup ] };
2136+ key <I619> { [ XF86KbdInputAssistNextgroup ] };
2137+ key <I620> { [ XF86KbdInputAssistAccept ] };
2138+ key <I621> { [ XF86KbdInputAssistCancel ] };
2139+ key <I622> { [ XF86RightUp ] };
2140+ key <I623> { [ XF86RightDown ] };
2141+ key <I624> { [ XF86LeftUp ] };
2142+ key <I625> { [ XF86LeftDown ] };
2143+ key <I626> { [ XF86RootMenu ] };
2144+ key <I627> { [ XF86MediaTopMenu ] };
2145+ key <I628> { [ XF86Numeric11 ] };
2146+ key <I629> { [ XF86Numeric12 ] };
2147+ key <I630> { [ XF86AudioDesc ] };
2148+ key <I631> { [ XF863DMode ] };
2149+ key <I632> { [ XF86NextFavorite ] };
2150+ key <I633> { [ XF86StopRecord ] };
2151+ key <I634> { [ XF86PauseRecord ] };
2152+ key <I635> { [ XF86VOD ] };
2153+ key <I636> { [ XF86Unmute ] };
2154+ key <I637> { [ XF86FastReverse ] };
2155+ key <I638> { [ XF86SlowReverse ] };
2156+ key <I639> { [ XF86Data ] };
2157+ key <I640> { [ XF86OnScreenKeyboard ] };
2158+ key <I641> { [ XF86PrivacyScreenToggle ] };
2159+ key <I642> { [ XF86SelectiveScreenshot ] };
2160+ key <I643> { [ XF86NextElement ] };
2161+ key <I644> { [ XF86PreviousElement ] };
2162+ key <I645> { [ XF86AutopilotEngageToggle ] };
2163+ key <I646> { [ XF86MarkWaypoint ] };
2164+ key <I647> { [ XF86Sos ] };
2165+ key <I648> { [ XF86NavChart ] };
2166+ key <I649> { [ XF86FishingChart ] };
2167+ key <I650> { [ XF86SingleRangeRadar ] };
2168+ key <I651> { [ XF86DualRangeRadar ] };
2169+ key <I652> { [ XF86RadarOverlay ] };
2170+ key <I653> { [ XF86TraditionalSonar ] };
2171+ key <I654> { [ XF86ClearvuSonar ] };
2172+ key <I655> { [ XF86SidevuSonar ] };
2173+ key <I656> { [ XF86NavInfo ] };
2174+ key <I657> { [ XF86BrightnessAdjust ] };
2175+ key <I664> { [ XF86Macro1 ] };
2176+ key <I665> { [ XF86Macro2 ] };
2177+ key <I666> { [ XF86Macro3 ] };
2178+ key <I667> { [ XF86Macro4 ] };
2179+ key <I668> { [ XF86Macro5 ] };
2180+ key <I669> { [ XF86Macro6 ] };
2181+ key <I670> { [ XF86Macro7 ] };
2182+ key <I671> { [ XF86Macro8 ] };
2183+ key <I672> { [ XF86Macro9 ] };
2184+ key <I673> { [ XF86Macro10 ] };
2185+ key <I674> { [ XF86Macro11 ] };
2186+ key <I675> { [ XF86Macro12 ] };
2187+ key <I676> { [ XF86Macro13 ] };
2188+ key <I677> { [ XF86Macro14 ] };
2189+ key <I678> { [ XF86Macro15 ] };
2190+ key <I679> { [ XF86Macro16 ] };
2191+ key <I680> { [ XF86Macro17 ] };
2192+ key <I681> { [ XF86Macro18 ] };
2193+ key <I682> { [ XF86Macro19 ] };
2194+ key <I683> { [ XF86Macro20 ] };
2195+ key <I684> { [ XF86Macro21 ] };
2196+ key <I685> { [ XF86Macro22 ] };
2197+ key <I686> { [ XF86Macro23 ] };
2198+ key <I687> { [ XF86Macro24 ] };
2199+ key <I688> { [ XF86Macro25 ] };
2200+ key <I689> { [ XF86Macro26 ] };
2201+ key <I690> { [ XF86Macro27 ] };
2202+ key <I691> { [ XF86Macro28 ] };
2203+ key <I692> { [ XF86Macro29 ] };
2204+ key <I693> { [ XF86Macro30 ] };
2205+ key <I696> { [ XF86MacroRecordStart ] };
2206+ key <I697> { [ XF86MacroRecordStop ] };
2207+ key <I698> { [ XF86MacroPresetCycle ] };
2208+ key <I699> { [ XF86MacroPreset1 ] };
2209+ key <I700> { [ XF86MacroPreset2 ] };
2210+ key <I701> { [ XF86MacroPreset3 ] };
2211+ key <I704> { [ XF86KbdLcdMenu1 ] };
2212+ key <I705> { [ XF86KbdLcdMenu2 ] };
2213+ key <I706> { [ XF86KbdLcdMenu3 ] };
2214+ key <I707> { [ XF86KbdLcdMenu4 ] };
2215+ key <I708> { [ XF86KbdLcdMenu5 ] };
2216+ key <I709> { [ XF86PerformanceMode ] };
2217+ modifier_map Shift { <LFSH>, <RTSH> };
2218+ modifier_map Lock { <CAPS> };
2219+ modifier_map Control { <LCTL>, <RCTL> };
2220+ modifier_map Mod1 { <LALT>, <RALT>, <ALT>, <META> };
2221+ modifier_map Mod2 { <NMLK> };
2222+ modifier_map Mod3 { <LVL5> };
2223+ modifier_map Mod4 { <LWIN>, <RWIN>, <SUPR> };
2224+ modifier_map Mod5 { <LVL3> };
2225+};
2226+
2227+};
A upstream/LICENSE +279 -0
@@ -0,0 +1,279 @@
1+The following is a list of all copyright notices and license statements which
2+appear in the xkbcommon source tree, along with the SPDX short license
3+identifiers which source files use to refer to them. To see which parts are
4+covered by which license and copyright, refer to the source files.
5+
6+If making new contributions, the MIT License is vastly preferred.
7+
8+All licenses are derivative of the MIT/X11 license, mostly identical other
9+than no-endorsement clauses (e.g. paragraph 4 of The Open Group's license).
10+
11+These statements are split into two sections: one for the code compiled and
12+distributed as part of the libxkbcommon shared library and the code component
13+of all tests, and another only for the test data under test/data, which is
14+distributed with the xkbcommon source code, but not installed to the system.
15+
16+BEGINNING OF SOFTWARE COPYRIGHT/LICENSE STATEMENTS:
17+
18+
19+-------------------------------------------------------------------------------
20+SPDX full name: MIT License
21+SPDX short identifier: MIT
22+License text:
23+
24+Copyright © 2008-2009 Dan Nicholson <dbn.lists@gmail.com>
25+Copyright © 2009-2012, 2016 Daniel Stone <daniel@fooishbar.org>
26+Copyright © 2012-2014, 2020-2022, 2025 Ran Benita <ran@unusedvar.com>
27+Copyright © 2010-2012, 2016 Intel Corporation
28+Copyright © 2013-2015, 2018-2020 Red Hat, Inc.
29+Copyright © 2023-2024 Pierre Le Marre <dev@wismill.eu>
30+Copyright (c) 1991, Oracle and/or its affiliates.
31+Copyright © 2008-2011 Kristian Høgsberg
32+Copyright © 2010 Francisco Jerez <currojerez@riseup.net>
33+Copyright © 2012 Collabora, Ltd.
34+Copyright © 2015 Kazunobu Kuriyama <kazunobu.kuriyama@nifty.com>
35+Copyright (C) 2011 Joseph Adams <joeyadams3.14159@gmail.com>
36+
37+Permission is hereby granted, free of charge, to any person obtaining a
38+copy of this software and associated documentation files (the "Software"),
39+to deal in the Software without restriction, including without limitation
40+the rights to use, copy, modify, merge, publish, distribute, sublicense,
41+and/or sell copies of the Software, and to permit persons to whom the
42+Software is furnished to do so, subject to the following conditions:
43+
44+The above copyright notice and this permission notice (including the next
45+paragraph) shall be included in all copies or substantial portions of the
46+Software.
47+
48+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
49+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
50+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
51+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
52+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
53+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
54+DEALINGS IN THE SOFTWARE.
55+
56+
57+-------------------------------------------------------------------------------
58+SPDX full name: MIT Open Group variant
59+SPDX short identifier: MIT-open-group
60+License text:
61+
62+Copyright 1985, 1987, 1988, 1990, 1998 The Open Group
63+
64+Permission is hereby granted, free of charge, to any person obtaining a
65+copy of this software and associated documentation files (the "Software"),
66+to deal in the Software without restriction, including without limitation
67+the rights to use, copy, modify, merge, publish, distribute, sublicense,
68+and/or sell copies of the Software, and to permit persons to whom the
69+Software is furnished to do so, subject to the following conditions:
70+
71+The above copyright notice and this permission notice shall be included in
72+all copies or substantial portions of the Software.
73+
74+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
76+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
77+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
78+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
79+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
80+
81+Except as contained in this notice, the names of the authors or their
82+institutions shall not be used in advertising or otherwise to promote the
83+sale, use or other dealings in this Software without prior written
84+authorization from the authors.
85+
86+
87+-------------------------------------------------------------------------------
88+SPDX full name: Historical Permission Notice and Disclaimer
89+SPDX short identifier: HPND
90+License text:
91+
92+Copyright (c) 1993, 1994, 1995, 1996 by Silicon Graphics Computer Systems, Inc.
93+
94+Permission to use, copy, modify, and distribute this
95+software and its documentation for any purpose and without
96+fee is hereby granted, provided that the above copyright
97+notice appear in all copies and that both that copyright
98+notice and this permission notice appear in supporting
99+documentation, and that the name of Silicon Graphics not be
100+used in advertising or publicity pertaining to distribution
101+of the software without specific prior written permission.
102+Silicon Graphics makes no representation about the suitability
103+of this software for any purpose. It is provided "as is"
104+without any express or implied warranty.
105+
106+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
107+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
108+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
109+GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
110+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
111+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
112+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
113+THE USE OR PERFORMANCE OF THIS SOFTWARE.
114+
115+-------------------------------------------------------------------------------
116+SPDX full name: Historical Permission Notice and Disclaimer - sell variant
117+SPDX short identifier: HPND-sell-variant
118+License text:
119+
120+Copyright 1992 by Oki Technosystems Laboratory, Inc.
121+Copyright 1992 by Fuji Xerox Co., Ltd.
122+
123+Permission to use, copy, modify, distribute, and sell this software
124+and its documentation for any purpose is hereby granted without fee,
125+provided that the above copyright notice appear in all copies and
126+that both that copyright notice and this permission notice appear
127+in supporting documentation, and that the name of Oki Technosystems
128+Laboratory and Fuji Xerox not be used in advertising or publicity
129+pertaining to distribution of the software without specific, written
130+prior permission.
131+Oki Technosystems Laboratory and Fuji Xerox make no representations
132+about the suitability of this software for any purpose. It is provided
133+"as is" without express or implied warranty.
134+
135+OKI TECHNOSYSTEMS LABORATORY AND FUJI XEROX DISCLAIM ALL WARRANTIES
136+WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
137+MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL OKI TECHNOSYSTEMS
138+LABORATORY AND FUJI XEROX BE LIABLE FOR ANY SPECIAL, INDIRECT OR
139+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
140+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
141+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
142+OR PERFORMANCE OF THIS SOFTWARE.
143+
144+
145+-------------------------------------------------------------------------------
146+SPDX full name: <none>
147+SPDX short identifier: LicenseRef-digital-equipment-corporation
148+License text:
149+
150+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
151+
152+ All Rights Reserved
153+
154+Permission to use, copy, modify, and distribute this software and its
155+documentation for any purpose and without fee is hereby granted,
156+provided that the above copyright notice appear in all copies and that
157+both that copyright notice and this permission notice appear in
158+supporting documentation, and that the name of Digital not be
159+used in advertising or publicity pertaining to distribution of the
160+software without specific, written prior permission.
161+
162+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
163+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
164+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
165+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
166+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
167+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
168+SOFTWARE.
169+
170+
171+-------------------------------------------------------------------------------
172+
173+
174+
175+END OF SOFTWARE COPYRIGHT/LICENSE STATEMENTS
176+
177+
178+BEGINNING OF LICENSE STATEMENTS ONLY FOR UNDISTRIBUTED DATA FILES IN test/data,
179+derived from xkeyboard-config and libX11 nls/ directory:
180+
181+
182+
183+-------------------------------------------------------------------------------
184+SPDX full name: Historical Permission Notice and Disclaimer - sell variant
185+SPDX short identifier: HPND-sell-variant
186+
187+Copyright 1996 by Joseph Moss
188+Copyright (C) 2002-2007 Free Software Foundation, Inc.
189+Copyright (C) Dmitry Golubev <lastguru@mail.ru>, 2003-2004
190+Copyright (C) 2004, Gregory Mokhin <mokhin@bog.msu.ru>
191+Copyright (C) 2006 Erdal Ronahî
192+
193+Permission to use, copy, modify, distribute, and sell this software and its
194+documentation for any purpose is hereby granted without fee, provided that
195+the above copyright notice appear in all copies and that both that
196+copyright notice and this permission notice appear in supporting
197+documentation, and that the name of the copyright holder(s) not be used in
198+advertising or publicity pertaining to distribution of the software without
199+specific, written prior permission. The copyright holder(s) makes no
200+representations about the suitability of this software for any purpose. It
201+is provided "as is" without express or implied warranty.
202+
203+THE COPYRIGHT HOLDER(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
204+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
205+EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
206+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
207+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
208+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
209+PERFORMANCE OF THIS SOFTWARE.
210+
211+
212+-------------------------------------------------------------------------------
213+SPDX full name: MIT License
214+SPDX short identifier: MIT
215+
216+Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
217+
218+
219+-------------------------------------------------------------------------------
220+SPDX full name: X11 License
221+SPDX short identifier: X11
222+License text:
223+
224+Copyright (c) 1996 X Consortium
225+
226+Permission is hereby granted, free of charge, to any person obtaining
227+a copy of this software and associated documentation files (the
228+"Software"), to deal in the Software without restriction, including
229+without limitation the rights to use, copy, modify, merge, publish,
230+distribute, sublicense, and/or sell copies of the Software, and to
231+permit persons to whom the Software is furnished to do so, subject to
232+the following conditions:
233+
234+The above copyright notice and this permission notice shall be
235+included in all copies or substantial portions of the Software.
236+
237+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
238+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
239+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
240+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
241+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
242+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
243+OTHER DEALINGS IN THE SOFTWARE.
244+
245+Except as contained in this notice, the name of the X Consortium shall
246+not be used in advertising or otherwise to promote the sale, use or
247+other dealings in this Software without prior written authorization
248+from the X Consortium.
249+
250+
251+
252+-------------------------------------------------------------------------------
253+SPDX full name: MIT Open Group variant
254+SPDX short identifier: MIT-open-group
255+
256+Copyright (C) 2004, 2006 Ævar Arnfjörð Bjarmason <avarab@gmail.com>
257+
258+
259+-------------------------------------------------------------------------------
260+SPDX full name: <none>
261+SPDX short identifier: MIT-open-group
262+SPDX short identifier: LicenseRef-anton-zinoviev
263+License text:
264+
265+Copyright (C) 1999, 2000 by Anton Zinoviev <anton@lml.bas.bg>
266+
267+This software may be used, modified, copied, distributed, and sold,
268+in both source and binary form provided that the above copyright
269+and these terms are retained. Under no circumstances is the author
270+responsible for the proper functioning of this software, nor does
271+the author assume any responsibility for damages incurred with its
272+use.
273+
274+Permission is granted to anyone to use, distribute and modify
275+this file in any way, provided that the above copyright notice
276+is left intact and the author of the modification summarizes
277+the changes in this header.
278+
279+This file is distributed without any expressed or implied warranty.
A upstream/METADATA +6 -0
@@ -0,0 +1,6 @@
1+Source: https://github.com/xkbcommon/libxkbcommon
2+Tag: xkbcommon-1.13.2
3+Commit: d1442aaa6b635551182e83c3b55037f4c118c962
4+Files: include/xkbcommon/{xkbcommon.h,xkbcommon-compose.h,xkbcommon-keysyms.h,xkbcommon-names.h}, LICENSE
5+SHA-256: see SHA256SUMS (paths relative to repository root)
6+Note: the keysyms header includes third-party copyright and license notices; preserve it verbatim.
A upstream/SHA256SUMS +5 -0
@@ -0,0 +1,5 @@
1+967e97b28658f0037bbe164a237bdfb0c3ec790e67f6c29372ea5b09306f61f3 upstream/LICENSE
2+6e2d985b3653c3674df87731931b98a68e4dcb72d5ff90e457708e8e16ce818d upstream/xkbcommon-compose.h
3+17e58db5edc299d13b4365adce6c6d805e16642977ffaacf98d9be0c4c7071ff upstream/xkbcommon.h
4+13023369f65a17411606084e3e09557b4886aeb15f89affba4aaa86490a463f3 upstream/xkbcommon-keysyms.h
5+a5b0ed01c8b1816da8b5ed29cf776eb2ad1f707cf03ff74e62e36a5ca9009f61 upstream/xkbcommon-names.h
A upstream/xkbcommon-compose.h +621 -0
@@ -0,0 +1,621 @@
1+/*
2+ * Copyright © 2013 Ran Benita
3+ * SPDX-License-Identifier: MIT
4+ */
5+
6+#ifndef _XKBCOMMON_COMPOSE_H
7+#define _XKBCOMMON_COMPOSE_H
8+
9+#include <xkbcommon/xkbcommon.h>
10+
11+#ifdef __cplusplus
12+extern "C" {
13+#endif
14+
15+/**
16+ * @file
17+ * libxkbcommon Compose API - support for Compose and dead-keys.
18+ */
19+
20+/**
21+ * @defgroup compose Compose and dead-keys support
22+ * Support for Compose and dead-keys.
23+ * @since 0.5.0
24+ *
25+ * @{
26+ */
27+
28+/**
29+ * @page compose-overview Overview
30+ * @parblock
31+ *
32+ * Compose and dead-keys are a common feature of many keyboard input
33+ * systems. They extend the range of the keysyms that can be produced
34+ * directly from a keyboard by using a sequence of key strokes, instead
35+ * of just one.
36+ *
37+ * Here are some example sequences, in the libX11 Compose file format:
38+ *
39+ * <dead_acute> <a> : "á" aacute # LATIN SMALL LETTER A WITH ACUTE
40+ * <Multi_key> <A> <T> : "@" at # COMMERCIAL AT
41+ *
42+ * When the user presses a key which produces the `<dead_acute>` keysym,
43+ * nothing initially happens (thus the key is dubbed a *dead-key*). But
44+ * when the user enters `<a>`, “á” is *composed*, in place of “a”. If
45+ * instead the user had entered a keysym which does not follow
46+ * `<dead_acute>` in any compose sequence, the sequence is said to be
47+ * *cancelled*.
48+ *
49+ * Compose files define many such sequences. For a description of the
50+ * common file format for Compose files, see the `Compose(5)` man page.
51+ *
52+ * A successfully-composed sequence has two results: a keysym and a UTF-8
53+ * string. At least one of the two is defined for each sequence. If only
54+ * a keysym is given, the keysym’s string representation is used for the
55+ * result string (using xkb_keysym_to_utf8()).
56+ *
57+ * This library provides low-level support for Compose file parsing and
58+ * processing. Higher-level APIs (such as libX11’s `Xutf8LookupString(3)`)
59+ * may be built upon it, or it can be used directly.
60+ *
61+ * @endparblock
62+ */
63+
64+/**
65+ * @page compose-conflicting Conflicting Sequences
66+ * @parblock
67+ *
68+ * To avoid ambiguity, a sequence is not allowed to be a prefix of another.
69+ * When such a conflict occurs, the sequence defined last is the one retained.
70+ *
71+ * Sequences of length 1 are allowed.
72+ *
73+ * @endparblock
74+ */
75+
76+/**
77+ * @page compose-cancellation Cancellation Behavior
78+ * @parblock
79+ *
80+ * What should happen when a sequence is cancelled? For example, consider
81+ * there are only the above sequences, and the input keysyms are
82+ * `<dead_acute> <b>`. There are a few approaches:
83+ *
84+ * 1. Swallow the cancelling keysym; that is, no keysym is produced.
85+ * This is the approach taken by libX11.
86+ * 2. Let the cancelling keysym through; that is, `<b>` is produced.
87+ * 3. Replay the entire sequence; that is, `<dead_acute> <b>` is produced.
88+ * This is the approach taken by Microsoft Windows (approximately;
89+ * instead of `<dead_acute>`, the underlying key is used. This is
90+ * difficult to simulate with XKB keymaps).
91+ *
92+ * You can program whichever approach best fits users' expectations.
93+ *
94+ * @endparblock
95+ */
96+
97+/**
98+ * @struct xkb_compose_table
99+ * Opaque Compose table object.
100+ *
101+ * The compose table holds the definitions of the Compose sequences, as
102+ * gathered from Compose files. It is immutable.
103+ */
104+struct xkb_compose_table;
105+
106+/**
107+ * @struct xkb_compose_state
108+ * Opaque Compose state object.
109+ *
110+ * The compose state maintains state for compose sequence matching, such
111+ * as which possible sequences are being matched, and the position within
112+ * these sequences. It acts as a simple state machine wherein keysyms are
113+ * the input, and composed keysyms and strings are the output.
114+ *
115+ * The compose state is usually associated with a keyboard device.
116+ */
117+struct xkb_compose_state;
118+
119+/** Flags affecting Compose file compilation. */
120+enum xkb_compose_compile_flags {
121+ /** Do not apply any flags. */
122+ XKB_COMPOSE_COMPILE_NO_FLAGS = 0
123+};
124+
125+/** The recognized Compose file formats. */
126+enum xkb_compose_format {
127+ /** The classic libX11 Compose text format, described in Compose(5). */
128+ XKB_COMPOSE_FORMAT_TEXT_V1 = 1
129+};
130+
131+/**
132+ * @page compose-locale Compose Locale
133+ * @parblock
134+ *
135+ * Compose files are locale dependent:
136+ * - Compose files are written for a locale, and the locale is used when
137+ * searching for the appropriate file to use.
138+ * - Compose files may reference the locale internally, with directives
139+ * such as `%%L`.
140+ *
141+ * As such, functions like `xkb_compose_table::xkb_compose_table_new_from_locale()`
142+ * require a `locale` parameter. This will usually be the current locale (see
143+ * `locale(7)` for more details). You may also want to allow the user to
144+ * explicitly configure it, so he can use the Compose file of a given
145+ * locale, but not use that locale for other things.
146+ *
147+ * You may query the current locale as follows:
148+ *
149+ * ```c
150+ * const char *locale;
151+ * locale = setlocale(LC_CTYPE, NULL);
152+ * ```
153+ *
154+ * This will only give useful results if the program had previously set
155+ * the current locale using setlocale(3), with `LC_CTYPE` or `LC_ALL`
156+ * and a non-`NULL` argument.
157+ *
158+ * If you prefer not to use the locale system of the C runtime library,
159+ * you may nevertheless obtain the user’s locale directly using
160+ * environment variables, as described in `locale(7)`. For example,
161+ *
162+ * ```c
163+ * const char *locale;
164+ * locale = getenv("LC_ALL");
165+ * if (!locale || !*locale)
166+ * locale = getenv("LC_CTYPE");
167+ * if (!locale || !*locale)
168+ * locale = getenv("LANG");
169+ * if (!locale || !*locale)
170+ * locale = "C";
171+ * ```
172+ *
173+ * Note that some locales supported by the C standard library may not
174+ * have a Compose file assigned.
175+ *
176+ * @endparblock
177+ */
178+
179+/**
180+ * Create a compose table for a given locale.
181+ *
182+ * The locale is used for searching the file-system for an appropriate
183+ * Compose file. The search order is described in Compose(5). It is
184+ * affected by the following environment variables:
185+ *
186+ * 1. `XCOMPOSEFILE` - see Compose(5).
187+ * 2. `XDG_CONFIG_HOME` - before `$HOME/.XCompose` is checked,
188+ * `$XDG_CONFIG_HOME/XCompose` is checked (with a fall back to
189+ * `$HOME/.config/XCompose` if `XDG_CONFIG_HOME` is not defined).
190+ * This is a libxkbcommon extension to the search procedure in
191+ * Compose(5) (since libxkbcommon 1.0.0). Note that other
192+ * implementations, such as libX11, might not find a Compose file in
193+ * this path.
194+ * 3. `HOME` - see Compose(5).
195+ * 4. `XLOCALEDIR` - if set, used as the base directory for the system’s
196+ * X locale files, e.g. `/usr/share/X11/locale`, instead of the
197+ * preconfigured directory.
198+ *
199+ * Since 1.12, system locales not registered in `$XLOCALEDIR` will fallback
200+ * to `en_US.UTF-8`, if missing locale detection is supported by the C standard
201+ * library in use.
202+ *
203+ * @param context
204+ * The library context in which to create the compose table.
205+ * @param locale
206+ * The current locale. See @ref compose-locale.
207+ * \n
208+ * The value is copied, so it is safe to pass the result of `getenv(3)`
209+ * (or similar) without fear of it being invalidated by a subsequent
210+ * `setenv(3)` (or similar).
211+ * @param flags
212+ * Optional flags for the compose table, or 0.
213+ *
214+ * @returns A compose table for the given locale, or `NULL` if the
215+ * compilation failed or a Compose file was not found.
216+ *
217+ * @memberof xkb_compose_table
218+ */
219+XKB_EXPORT struct xkb_compose_table *
220+xkb_compose_table_new_from_locale(struct xkb_context *context,
221+ const char *locale,
222+ enum xkb_compose_compile_flags flags);
223+
224+/**
225+ * Create a new compose table from a Compose file.
226+ *
227+ * @param context
228+ * The library context in which to create the compose table.
229+ * @param file
230+ * The Compose file to compile.
231+ * @param locale
232+ * The current locale. See @ref compose-locale.
233+ * @param format
234+ * The text format of the Compose file to compile.
235+ * @param flags
236+ * Optional flags for the compose table, or 0.
237+ *
238+ * @returns A compose table compiled from the given file, or `NULL` if
239+ * the compilation failed.
240+ *
241+ * @memberof xkb_compose_table
242+ */
243+XKB_EXPORT struct xkb_compose_table *
244+xkb_compose_table_new_from_file(struct xkb_context *context,
245+ FILE *file,
246+ const char *locale,
247+ enum xkb_compose_format format,
248+ enum xkb_compose_compile_flags flags);
249+
250+/**
251+ * Create a new compose table from a memory buffer.
252+ *
253+ * This is just like xkb_compose_table_new_from_file(), but instead of
254+ * a file, gets the table as one enormous string.
255+ *
256+ * @see xkb_compose_table_new_from_file()
257+ * @memberof xkb_compose_table
258+ */
259+XKB_EXPORT struct xkb_compose_table *
260+xkb_compose_table_new_from_buffer(struct xkb_context *context,
261+ const char *buffer, size_t length,
262+ const char *locale,
263+ enum xkb_compose_format format,
264+ enum xkb_compose_compile_flags flags);
265+
266+/**
267+ * Take a new reference on a compose table.
268+ *
269+ * @returns The passed in object.
270+ *
271+ * @memberof xkb_compose_table
272+ */
273+XKB_EXPORT struct xkb_compose_table *
274+xkb_compose_table_ref(struct xkb_compose_table *table);
275+
276+/**
277+ * Release a reference on a compose table, and possibly free it.
278+ *
279+ * @param table The object. If it is `NULL`, this function does nothing.
280+ *
281+ * @memberof xkb_compose_table
282+ */
283+XKB_EXPORT void
284+xkb_compose_table_unref(struct xkb_compose_table *table);
285+
286+/**
287+ * @struct xkb_compose_table_entry
288+ * Opaque Compose table entry object.
289+ *
290+ * Represents a single entry in a Compose file in the iteration API.
291+ * It is immutable.
292+ *
293+ * @sa xkb_compose_table_iterator_new
294+ * @since 1.6.0
295+ */
296+struct xkb_compose_table_entry;
297+
298+/**
299+ * Get the left-hand keysym sequence of a Compose table entry.
300+ *
301+ * For example, given the following entry:
302+ *
303+ * ```
304+ * <dead_tilde> <space> : "~" asciitilde # TILDE
305+ * ```
306+ *
307+ * it will return `{XKB_KEY_dead_tilde, XKB_KEY_space}`.
308+ *
309+ * @param[in] entry The compose table entry object to process.
310+ *
311+ * @param[out] sequence_length Number of keysyms in the sequence.
312+ *
313+ * @returns The array of left-hand side keysyms. The number of keysyms
314+ * is returned in the @p sequence_length out-parameter.
315+ *
316+ * @memberof xkb_compose_table_entry
317+ * @since 1.6.0
318+ */
319+XKB_EXPORT const xkb_keysym_t *
320+xkb_compose_table_entry_sequence(struct xkb_compose_table_entry *entry,
321+ size_t *sequence_length);
322+
323+/**
324+ * Get the right-hand result keysym of a Compose table entry.
325+ *
326+ * For example, given the following entry:
327+ *
328+ * ```
329+ * <dead_tilde> <space> : "~" asciitilde # TILDE
330+ * ```
331+ *
332+ * it will return `XKB_KEY_asciitilde`.
333+ *
334+ * The keysym is optional; if the entry does not specify a keysym,
335+ * returns `XKB_KEY_NoSymbol`.
336+ *
337+ * @memberof xkb_compose_table_entry
338+ * @since 1.6.0
339+ */
340+XKB_EXPORT xkb_keysym_t
341+xkb_compose_table_entry_keysym(struct xkb_compose_table_entry *entry);
342+
343+/**
344+ * Get the right-hand result string of a Compose table entry.
345+ *
346+ * The string is UTF-8 encoded and `NULL`-terminated.
347+ *
348+ * For example, given the following entry:
349+ *
350+ * ```
351+ * <dead_tilde> <space> : "~" asciitilde # TILDE
352+ * ```
353+ *
354+ * it will return `"~"`.
355+ *
356+ * The string is optional; if the entry does not specify a string,
357+ * returns the empty string.
358+ *
359+ * @memberof xkb_compose_table_entry
360+ * @since 1.6.0
361+ */
362+XKB_EXPORT const char *
363+xkb_compose_table_entry_utf8(struct xkb_compose_table_entry *entry);
364+
365+/**
366+ * @struct xkb_compose_table_iterator
367+ * Iterator over a compose table’s entries.
368+ *
369+ * @sa xkb_compose_table_iterator_new()
370+ * @since 1.6.0
371+ */
372+struct xkb_compose_table_iterator;
373+
374+/**
375+ * Create a new iterator for a compose table.
376+ *
377+ * Intended use:
378+ *
379+ * ```c
380+ * struct xkb_compose_table_iterator *iter = xkb_compose_table_iterator_new(compose_table);
381+ * struct xkb_compose_table_entry *entry;
382+ * while ((entry = xkb_compose_table_iterator_next(iter))) {
383+ * // ...
384+ * }
385+ * xkb_compose_table_iterator_free(iter);
386+ * ```
387+ *
388+ * @returns A new compose table iterator, or `NULL` on failure.
389+ *
390+ * @memberof xkb_compose_table_iterator
391+ * @sa xkb_compose_table_iterator_free()
392+ * @since 1.6.0
393+ */
394+XKB_EXPORT struct xkb_compose_table_iterator *
395+xkb_compose_table_iterator_new(struct xkb_compose_table *table);
396+
397+/**
398+ * Free a compose iterator.
399+ *
400+ * @memberof xkb_compose_table_iterator
401+ * @since 1.6.0
402+ */
403+XKB_EXPORT void
404+xkb_compose_table_iterator_free(struct xkb_compose_table_iterator *iter);
405+
406+/**
407+ * Get the next compose entry from a compose table iterator.
408+ *
409+ * The entries are returned in lexicographic order of the left-hand
410+ * side of entries. This does not correspond to the order in which
411+ * the entries appear in the Compose file.
412+ *
413+ * @attention The return value is valid until the next call to this function.
414+ *
415+ * Returns `NULL` in case there is no more entries.
416+ *
417+ * @memberof xkb_compose_table_iterator
418+ * @since 1.6.0
419+ */
420+XKB_EXPORT struct xkb_compose_table_entry *
421+xkb_compose_table_iterator_next(struct xkb_compose_table_iterator *iter);
422+
423+/** Flags for compose state creation. */
424+enum xkb_compose_state_flags {
425+ /** Do not apply any flags. */
426+ XKB_COMPOSE_STATE_NO_FLAGS = 0
427+};
428+
429+/**
430+ * Create a new compose state object.
431+ *
432+ * @param table
433+ * The compose table the state will use.
434+ * @param flags
435+ * Optional flags for the compose state, or 0.
436+ *
437+ * @returns A new compose state, or `NULL` on failure.
438+ *
439+ * @memberof xkb_compose_state
440+ */
441+XKB_EXPORT struct xkb_compose_state *
442+xkb_compose_state_new(struct xkb_compose_table *table,
443+ enum xkb_compose_state_flags flags);
444+
445+/**
446+ * Take a new reference on a compose state object.
447+ *
448+ * @returns The passed in object.
449+ *
450+ * @memberof xkb_compose_state
451+ */
452+XKB_EXPORT struct xkb_compose_state *
453+xkb_compose_state_ref(struct xkb_compose_state *state);
454+
455+/**
456+ * Release a reference on a compose state object, and possibly free it.
457+ *
458+ * @param state The object. If `NULL`, do nothing.
459+ *
460+ * @memberof xkb_compose_state
461+ */
462+XKB_EXPORT void
463+xkb_compose_state_unref(struct xkb_compose_state *state);
464+
465+/**
466+ * Get the compose table which a compose state object is using.
467+ *
468+ * @returns The compose table which was passed to xkb_compose_state_new()
469+ * when creating this state object.
470+ *
471+ * This function does not take a new reference on the compose table; you
472+ * must explicitly reference it yourself if you plan to use it beyond the
473+ * lifetime of the state.
474+ *
475+ * @memberof xkb_compose_state
476+ */
477+XKB_EXPORT struct xkb_compose_table *
478+xkb_compose_state_get_compose_table(struct xkb_compose_state *state);
479+
480+/** Status of the Compose sequence state machine. */
481+enum xkb_compose_status {
482+ /** The initial state; no sequence has started yet. */
483+ XKB_COMPOSE_NOTHING,
484+ /** In the middle of a sequence. */
485+ XKB_COMPOSE_COMPOSING,
486+ /** A complete sequence has been matched. */
487+ XKB_COMPOSE_COMPOSED,
488+ /** The last sequence was cancelled due to an unmatched keysym. */
489+ XKB_COMPOSE_CANCELLED
490+};
491+
492+/** The effect of a keysym fed to xkb_compose_state_feed(). */
493+enum xkb_compose_feed_result {
494+ /** The keysym had no effect - it did not affect the status. */
495+ XKB_COMPOSE_FEED_IGNORED,
496+ /** The keysym started, advanced or cancelled a sequence. */
497+ XKB_COMPOSE_FEED_ACCEPTED
498+};
499+
500+/**
501+ * Feed one keysym to the Compose sequence state machine.
502+ *
503+ * This function can advance into a compose sequence, cancel a sequence,
504+ * start a new sequence, or do nothing in particular. The resulting
505+ * status may be observed with `xkb_compose_state_get_status()`.
506+ *
507+ * Some keysyms, such as keysyms for modifier keys, are ignored - they
508+ * have no effect on the status or otherwise.
509+ *
510+ * The following is a description of the possible status transitions, in
511+ * the format CURRENT STATUS => NEXT STATUS, given a non-ignored input
512+ * keysym `keysym`:
513+ *
514+ @verbatim
515+ NOTHING or CANCELLED or COMPOSED =>
516+ NOTHING if keysym does not start a sequence.
517+ COMPOSING if keysym starts a sequence.
518+ COMPOSED if keysym starts and terminates a single-keysym sequence.
519+
520+ COMPOSING =>
521+ COMPOSING if keysym advances any of the currently possible
522+ sequences but does not terminate any of them.
523+ COMPOSED if keysym terminates one of the currently possible
524+ sequences.
525+ CANCELLED if keysym does not advance any of the currently
526+ possible sequences.
527+ @endverbatim
528+ *
529+ * The current Compose formats do not support multiple-keysyms. Therefore, if
530+ * you are using a function such as `xkb_state::xkb_state_key_get_syms()`
531+ * and it returns more than one keysym, consider feeding `XKB_KEY_NoSymbol`
532+ * instead.
533+ *
534+ * @param state
535+ * The compose state object.
536+ * @param keysym
537+ * A keysym, usually obtained after a key-press event, with a
538+ * function such as `xkb_state::xkb_state_key_get_one_sym()`.
539+ *
540+ * @returns Whether the keysym was ignored. This is useful, for example,
541+ * if you want to keep a record of the sequence matched thus far.
542+ *
543+ * @memberof xkb_compose_state
544+ */
545+XKB_EXPORT enum xkb_compose_feed_result
546+xkb_compose_state_feed(struct xkb_compose_state *state,
547+ xkb_keysym_t keysym);
548+
549+/**
550+ * Reset the Compose sequence state machine.
551+ *
552+ * The status is set to `::XKB_COMPOSE_NOTHING`, and the current sequence
553+ * is discarded.
554+ *
555+ * @memberof xkb_compose_state
556+ */
557+XKB_EXPORT void
558+xkb_compose_state_reset(struct xkb_compose_state *state);
559+
560+/**
561+ * Get the current status of the compose state machine.
562+ *
563+ * @see xkb_compose_status
564+ * @memberof xkb_compose_state
565+ **/
566+XKB_EXPORT enum xkb_compose_status
567+xkb_compose_state_get_status(struct xkb_compose_state *state);
568+
569+/**
570+ * Get the result Unicode/UTF-8 string for a composed sequence.
571+ *
572+ * See @ref compose-overview for more details. This function is only
573+ * useful when the status is `::XKB_COMPOSE_COMPOSED`.
574+ *
575+ * @param[in] state
576+ * The compose state.
577+ * @param[out] buffer
578+ * A buffer to write the string into.
579+ * @param[in] size
580+ * Size of the buffer.
581+ *
582+ * @warning If the buffer passed is too small, the string is truncated
583+ * (though still `NULL`-terminated).
584+ *
585+ * @returns
586+ * The number of bytes required for the string, excluding the `NULL` byte.
587+ * If the sequence is not complete, or does not have a viable result
588+ * string, returns 0, and sets `buffer` to the empty string (if possible).
589+ * @returns
590+ * You may check if truncation has occurred by comparing the return value
591+ * with the size of `buffer`, similarly to the `snprintf(3)` function.
592+ * You may safely pass `NULL` and 0 to `buffer` and `size` to find the
593+ * required size (without the `NULL`-byte).
594+ *
595+ * @memberof xkb_compose_state
596+ **/
597+XKB_EXPORT int
598+xkb_compose_state_get_utf8(struct xkb_compose_state *state,
599+ char *buffer, size_t size);
600+
601+/**
602+ * Get the result keysym for a composed sequence.
603+ *
604+ * See @ref compose-overview for more details. This function is only
605+ * useful when the status is `::XKB_COMPOSE_COMPOSED`.
606+ *
607+ * @returns The result keysym. If the sequence is not complete, or does
608+ * not specify a result keysym, returns `XKB_KEY_NoSymbol`.
609+ *
610+ * @memberof xkb_compose_state
611+ **/
612+XKB_EXPORT xkb_keysym_t
613+xkb_compose_state_get_one_sym(struct xkb_compose_state *state);
614+
615+/** @} */
616+
617+#ifdef __cplusplus
618+} /* extern "C" */
619+#endif
620+
621+#endif /* _XKBCOMMON_COMPOSE_H */
A upstream/xkbcommon-keysyms.h +3545 -0 large diff (3545 lines changed): collapsed
A upstream/xkbcommon-names.h +144 -0
@@ -0,0 +1,144 @@
1+/*
2+ * Copyright © 2012 Intel Corporation
3+ * SPDX-License-Identifier: MIT
4+ *
5+ * Author: Daniel Stone <daniel@fooishbar.org>
6+ */
7+
8+#ifndef _XKBCOMMON_NAMES_H
9+#define _XKBCOMMON_NAMES_H
10+
11+/**
12+ * @file
13+ * @brief Predefined names for common modifiers and LEDs.
14+ */
15+
16+/**
17+ * @defgroup modifier-names Predefined names for common modifiers and LEDs
18+ *
19+ * @{
20+ */
21+
22+/**
23+ * @defgroup real-modifier-names Real modifiers names
24+ *
25+ * [*Real* modifiers][real modifier] names are hardcoded in libxkbcommon.
26+ *
27+ * [real modifier]: @ref real-modifier-def
28+ *
29+ * @{
30+ */
31+#define XKB_MOD_NAME_SHIFT "Shift"
32+#define XKB_MOD_NAME_CAPS "Lock"
33+#define XKB_MOD_NAME_CTRL "Control"
34+#define XKB_MOD_NAME_MOD1 "Mod1"
35+#define XKB_MOD_NAME_MOD2 "Mod2"
36+#define XKB_MOD_NAME_MOD3 "Mod3"
37+#define XKB_MOD_NAME_MOD4 "Mod4"
38+#define XKB_MOD_NAME_MOD5 "Mod5"
39+/** @} */
40+
41+/**
42+ * @defgroup virtual-modifier-names Virtual modifiers names
43+ *
44+ * Common [*virtual* modifiers][virtual modifiers], encoded in [xkeyboard-config]
45+ * in the [compat] and [symbols] files. They have been stable since the beginning
46+ * of the project and are unlikely to ever change.
47+ *
48+ * [virtual modifiers]: @ref virtual-modifier-def
49+ * [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config
50+ * [compat]: @ref the-xkb_compat-section
51+ * [symbols]: @ref the-xkb_symbols-section
52+ *
53+ * @{
54+ */
55+/** @since 1.8.0 */
56+#define XKB_VMOD_NAME_ALT "Alt"
57+/** @since 1.8.0 */
58+#define XKB_VMOD_NAME_HYPER "Hyper"
59+/** @since 1.8.0 */
60+#define XKB_VMOD_NAME_LEVEL3 "LevelThree"
61+/** @since 1.8.0 */
62+#define XKB_VMOD_NAME_LEVEL5 "LevelFive"
63+/** @since 1.8.0 */
64+#define XKB_VMOD_NAME_META "Meta"
65+/** @since 1.8.0 */
66+#define XKB_VMOD_NAME_NUM "NumLock"
67+/** @since 1.8.0 */
68+#define XKB_VMOD_NAME_SCROLL "ScrollLock"
69+/** @since 1.8.0 */
70+#define XKB_VMOD_NAME_SUPER "Super"
71+/** @} */
72+
73+/**
74+ * @defgroup legacy-virtual-modifier-names Legacy virtual modifier names
75+ *
76+ * Usual [*virtual* modifiers][virtual modifiers] mappings to
77+ * [*real* modifiers][real modifiers].
78+ *
79+ * @deprecated Use @ref virtual-modifier-names instead
80+ *
81+ * [virtual modifiers]: @ref virtual-modifier-def
82+ * [real modifiers]: @ref real-modifier-def
83+ *
84+ * @{
85+ */
86+/**
87+ * Usual [*real* modifier][real modifier] for the
88+ * [*virtual* modifier][virtual modifier] `Alt`.
89+ *
90+ * @deprecated Use `::XKB_VMOD_NAME_ALT` instead.
91+ * @since 1.10: deprecated
92+ *
93+ * [virtual modifier]: @ref virtual-modifier-def
94+ * [real modifier]: @ref real-modifier-def
95+ */
96+#define XKB_MOD_NAME_ALT "Mod1"
97+/**
98+ * Usual [*real* modifier][real modifier] for the
99+ * [*virtual* modifier][virtual modifier] `Super`.
100+ *
101+ * @deprecated Use `::XKB_VMOD_NAME_SUPER` instead.
102+ * @since 1.10: deprecated
103+ *
104+ * [virtual modifier]: @ref virtual-modifier-def
105+ * [real modifier]: @ref real-modifier-def
106+ */
107+#define XKB_MOD_NAME_LOGO "Mod4"
108+/**
109+ * Usual [*real* modifier][real modifier] for the
110+ * [*virtual* modifier][virtual modifier] `NumLock`.
111+ *
112+ * @deprecated Use `::XKB_VMOD_NAME_NUM` instead.
113+ * @since 1.10: deprecated
114+ *
115+ * [virtual modifier]: @ref virtual-modifier-def
116+ * [real modifier]: @ref real-modifier-def
117+ */
118+#define XKB_MOD_NAME_NUM "Mod2"
119+/** @} */
120+
121+/**
122+ * @defgroup led-names LEDs names
123+ *
124+ * LEDs names are encoded in [xkeyboard-config], in the [keycodes] and [compat]
125+ * files. They have been stable since the beginning of the project and are
126+ * unlikely to ever change.
127+ *
128+ * [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config
129+ * [keycodes]: @ref the-xkb_keycodes-section
130+ * [compat]: @ref the-xkb_compat-section
131+ *
132+ * @{
133+ */
134+#define XKB_LED_NAME_NUM "Num Lock"
135+#define XKB_LED_NAME_CAPS "Caps Lock"
136+#define XKB_LED_NAME_SCROLL "Scroll Lock"
137+/** @since 1.8.0 */
138+#define XKB_LED_NAME_COMPOSE "Compose"
139+#define XKB_LED_NAME_KANA "Kana"
140+/** @} */
141+
142+/** @} */
143+
144+#endif
A upstream/xkbcommon.h +2598 -0 large diff (2598 lines changed): collapsed
A xkbcommon.go +500 -0
@@ -0,0 +1,500 @@
1+// Package xkbcommon interprets Wayland keyboard maps with libxkbcommon,
2+// loaded at runtime without cgo. Close owned values when they are no longer used.
3+package xkbcommon
4+
5+import (
6+ "errors"
7+ "fmt"
8+ "runtime"
9+ "strings"
10+ "sync"
11+ "syscall"
12+ "unsafe"
13+
14+ "github.com/bnema/purego-xkbcommon/raw"
15+)
16+
17+var ErrClosed = errors.New("xkbcommon: closed handle")
18+
19+func cstr(s string) []byte { return append([]byte(s), 0) }
20+func ptr(b []byte) uintptr {
21+ if len(b) == 0 {
22+ return 0
23+ }
24+ return uintptr(unsafe.Pointer(&b[0]))
25+}
26+func validString(s string) error {
27+ if strings.IndexByte(s, 0) >= 0 {
28+ return errors.New("xkbcommon: embedded NUL")
29+ }
30+ return nil
31+}
32+
33+// Keycodes from wl_keyboard are evdev codes; add 8 before calling State.KeySym or State.UTF8.
34+func WaylandKeycode(evdev uint32) uint32 { return evdev + 8 }
35+
36+type Context struct {
37+ mu sync.Mutex
38+ h uintptr
39+}
40+
41+func NewContext() (*Context, error) {
42+ if err := Available(); err != nil {
43+ return nil, err
44+ }
45+ h := loader.f.Xkb_context_new(0)
46+ if h == 0 {
47+ return nil, errors.New("xkbcommon: create context failed")
48+ }
49+ return &Context{h: h}, nil
50+}
51+func (c *Context) Close() error {
52+ if c == nil {
53+ return nil
54+ }
55+ c.mu.Lock()
56+ defer c.mu.Unlock()
57+ if c.h != 0 {
58+ loader.f.Xkb_context_unref(c.h)
59+ c.h = 0
60+ }
61+ return nil
62+}
63+func (c *Context) retain() (uintptr, error) {
64+ if c == nil {
65+ return 0, ErrClosed
66+ }
67+ c.mu.Lock()
68+ defer c.mu.Unlock()
69+ if c.h == 0 {
70+ return 0, ErrClosed
71+ }
72+ loader.f.Xkb_context_ref(c.h)
73+ return c.h, nil
74+}
75+func releaseContext(h uintptr) { loader.f.Xkb_context_unref(h) }
76+
77+type Keymap struct {
78+ mu sync.Mutex
79+ h, context uintptr
80+}
81+
82+func newKeymap(ctx *Context, build func(uintptr) uintptr) (*Keymap, error) {
83+ h, e := ctx.retain()
84+ if e != nil {
85+ return nil, e
86+ }
87+ k := build(h)
88+ if k == 0 {
89+ releaseContext(h)
90+ return nil, errors.New("xkbcommon: invalid keymap")
91+ }
92+ return &Keymap{h: k, context: h}, nil
93+}
94+
95+// NewKeymapString compiles a NUL-free xkb_v1 text keymap.
96+func (c *Context) NewKeymapString(text string) (*Keymap, error) {
97+ if e := validString(text); e != nil {
98+ return nil, e
99+ }
100+ b := cstr(text)
101+ return newKeymap(c, func(h uintptr) uintptr {
102+ v := loader.f.Xkb_keymap_new_from_string(h, ptr(b), raw.XKB_KEYMAP_FORMAT_TEXT_V1, 0)
103+ runtime.KeepAlive(b)
104+ return v
105+ })
106+}
107+
108+// NewKeymapRules compiles an evdev rules keymap. Empty rules/model/variant/options
109+// use libxkbcommon defaults; layout is e.g. "us", "fr", "de", or "us,de".
110+func (c *Context) NewKeymapRules(rules, model, layout, variant, options string) (*Keymap, error) {
111+ args := []string{rules, model, layout, variant, options}
112+ var b [5][]byte
113+ var n raw.RuleNames
114+ p := []*uintptr{&n.Rules, &n.Model, &n.Layout, &n.Variant, &n.Options}
115+ for i, s := range args {
116+ if e := validString(s); e != nil {
117+ return nil, e
118+ }
119+ if s != "" {
120+ b[i] = cstr(s)
121+ *p[i] = ptr(b[i])
122+ }
123+ }
124+ return newKeymap(c, func(h uintptr) uintptr {
125+ v := loader.f.Xkb_keymap_new_from_names(h, uintptr(unsafe.Pointer(&n)), 0)
126+ runtime.KeepAlive(b)
127+ runtime.KeepAlive(n)
128+ return v
129+ })
130+}
131+
132+// NewKeymapFD copies exactly size bytes from offset zero of a Wayland xkb_v1
133+// keymap FD (at most 16 MiB). A trailing Wayland NUL, if present, is excluded
134+// from the compiled text. The caller retains ownership of fd, even on error.
135+func (c *Context) NewKeymapFD(fd int, size int) (*Keymap, error) {
136+ if fd < 0 || size < 1 || size > 16<<20 {
137+ return nil, errors.New("xkbcommon: invalid keymap FD or size (limit 16 MiB)")
138+ }
139+ var stat syscall.Stat_t
140+ if e := syscall.Fstat(fd, &stat); e != nil {
141+ return nil, fmt.Errorf("xkbcommon: stat keymap FD: %w", e)
142+ }
143+ if stat.Mode&syscall.S_IFMT != syscall.S_IFREG {
144+ return nil, errors.New("xkbcommon: keymap FD is not a regular file")
145+ }
146+ b := make([]byte, size)
147+ for offset := 0; offset < size; {
148+ n, e := syscall.Pread(fd, b[offset:], int64(offset))
149+ offset += n
150+ if e == syscall.EINTR {
151+ continue
152+ }
153+ if e != nil {
154+ return nil, fmt.Errorf("xkbcommon: read keymap FD: %w", e)
155+ }
156+ if n == 0 {
157+ return nil, fmt.Errorf("xkbcommon: read keymap FD: %w", errors.New("short read"))
158+ }
159+ }
160+ if b[len(b)-1] == 0 {
161+ b = b[:len(b)-1]
162+ }
163+ return newKeymap(c, func(h uintptr) uintptr {
164+ v := loader.f.Xkb_keymap_new_from_buffer(h, ptr(b), uintptr(len(b)), raw.XKB_KEYMAP_FORMAT_TEXT_V1, 0)
165+ runtime.KeepAlive(b)
166+ return v
167+ })
168+}
169+func (k *Keymap) Close() error {
170+ if k == nil {
171+ return nil
172+ }
173+ k.mu.Lock()
174+ h, ctx := k.h, k.context
175+ k.h = 0
176+ k.context = 0
177+ if h != 0 {
178+ loader.f.Xkb_keymap_unref(h)
179+ }
180+ k.mu.Unlock()
181+ if ctx != 0 {
182+ releaseContext(ctx)
183+ }
184+ return nil
185+}
186+func (k *Keymap) retain() (uintptr, error) {
187+ if k == nil {
188+ return 0, ErrClosed
189+ }
190+ k.mu.Lock()
191+ defer k.mu.Unlock()
192+ if k.h == 0 {
193+ return 0, ErrClosed
194+ }
195+ loader.f.Xkb_keymap_ref(k.h)
196+ return k.h, nil
197+}
198+func (k *Keymap) ModIndex(name string) (uint32, error) {
199+ if e := validString(name); e != nil {
200+ return 0, e
201+ }
202+ if k == nil {
203+ return 0, ErrClosed
204+ }
205+ b := cstr(name)
206+ k.mu.Lock()
207+ defer k.mu.Unlock()
208+ if k.h == 0 {
209+ return 0, ErrClosed
210+ }
211+ v := loader.f.Xkb_keymap_mod_get_index(k.h, ptr(b))
212+ runtime.KeepAlive(b)
213+ return v, nil
214+}
215+func (k *Keymap) LayoutCount() (uint32, error) {
216+ if k == nil {
217+ return 0, ErrClosed
218+ }
219+ k.mu.Lock()
220+ defer k.mu.Unlock()
221+ if k.h == 0 {
222+ return 0, ErrClosed
223+ }
224+ return loader.f.Xkb_keymap_num_layouts(k.h), nil
225+}
226+func (k *Keymap) NewState() (*State, error) {
227+ h, e := k.retain()
228+ if e != nil {
229+ return nil, e
230+ }
231+ s := loader.f.Xkb_state_new(h)
232+ if s == 0 {
233+ loader.f.Xkb_keymap_unref(h)
234+ return nil, errors.New("xkbcommon: create state failed")
235+ }
236+ return &State{h: s, keymap: h}, nil
237+}
238+
239+type State struct {
240+ mu sync.Mutex
241+ h, keymap uintptr
242+}
243+
244+func (s *State) Close() error {
245+ if s == nil {
246+ return nil
247+ }
248+ s.mu.Lock()
249+ h, k := s.h, s.keymap
250+ s.h = 0
251+ s.keymap = 0
252+ if h != 0 {
253+ loader.f.Xkb_state_unref(h)
254+ }
255+ s.mu.Unlock()
256+ if k != 0 {
257+ loader.f.Xkb_keymap_unref(k)
258+ }
259+ return nil
260+}
261+
262+// UpdateMask accepts depressed/latched/locked modifier masks and layout group indices
263+// in the order supplied by wl_keyboard.modifiers. It returns changed components.
264+func (s *State) UpdateMask(depressed, latched, locked, groupDepressed, groupLatched, groupLocked uint32) (uint32, error) {
265+ if s == nil {
266+ return 0, ErrClosed
267+ }
268+ s.mu.Lock()
269+ defer s.mu.Unlock()
270+ if s.h == 0 {
271+ return 0, ErrClosed
272+ }
273+ return loader.f.Xkb_state_update_mask(s.h, depressed, latched, locked, groupDepressed, groupLatched, groupLocked), nil
274+}
275+func (s *State) Layout() (uint32, error) {
276+ if s == nil {
277+ return 0, ErrClosed
278+ }
279+ s.mu.Lock()
280+ defer s.mu.Unlock()
281+ if s.h == 0 {
282+ return 0, ErrClosed
283+ }
284+ return loader.f.Xkb_state_serialize_layout(s.h, raw.XKB_STATE_LAYOUT_EFFECTIVE), nil
285+}
286+func (s *State) Mods() (uint32, error) {
287+ if s == nil {
288+ return 0, ErrClosed
289+ }
290+ s.mu.Lock()
291+ defer s.mu.Unlock()
292+ if s.h == 0 {
293+ return 0, ErrClosed
294+ }
295+ return loader.f.Xkb_state_serialize_mods(s.h, raw.XKB_STATE_MODS_EFFECTIVE), nil
296+}
297+func (s *State) KeySym(keycode uint32) (uint32, error) {
298+ if s == nil {
299+ return 0, ErrClosed
300+ }
301+ s.mu.Lock()
302+ defer s.mu.Unlock()
303+ if s.h == 0 {
304+ return 0, ErrClosed
305+ }
306+ return loader.f.Xkb_state_key_get_one_sym(s.h, keycode), nil
307+}
308+
309+// sizedUTF8 probes the required byte count (excluding NUL) and retries if it grows.
310+func sizedUTF8(call func(uintptr, uintptr) int32) (string, error) {
311+ n := call(0, 0)
312+ if n < 0 {
313+ return "", errors.New("xkbcommon: UTF-8 conversion failed")
314+ }
315+ if n == 0 {
316+ return "", nil
317+ }
318+ for attempt := 0; attempt < 3; attempt++ {
319+ if n > 1<<20 {
320+ return "", errors.New("xkbcommon: UTF-8 result exceeds 1 MiB")
321+ }
322+ b := make([]byte, int(n)+1)
323+ got := call(ptr(b), uintptr(len(b)))
324+ runtime.KeepAlive(b)
325+ if got < 0 {
326+ return "", errors.New("xkbcommon: UTF-8 conversion failed")
327+ }
328+ if int(got) < len(b) {
329+ return string(b[:got]), nil
330+ }
331+ n = got
332+ }
333+ return "", errors.New("xkbcommon: UTF-8 result changed during sizing")
334+}
335+func (s *State) UTF8(keycode uint32) (string, error) {
336+ if s == nil {
337+ return "", ErrClosed
338+ }
339+ s.mu.Lock()
340+ defer s.mu.Unlock()
341+ if s.h == 0 {
342+ return "", ErrClosed
343+ }
344+ return sizedUTF8(func(p, n uintptr) int32 { return loader.f.Xkb_state_key_get_utf8(s.h, keycode, p, n) })
345+}
346+func KeysymName(sym uint32) (string, error) {
347+ if e := Available(); e != nil {
348+ return "", e
349+ }
350+ return sizedUTF8(func(p, n uintptr) int32 { return loader.f.Xkb_keysym_get_name(sym, p, n) })
351+}
352+func KeysymFromName(name string) (uint32, error) {
353+ if e := Available(); e != nil {
354+ return 0, e
355+ }
356+ if e := validString(name); e != nil {
357+ return 0, e
358+ }
359+ b := cstr(name)
360+ v := loader.f.Xkb_keysym_from_name(ptr(b), 0)
361+ runtime.KeepAlive(b)
362+ return v, nil
363+}
364+
365+type ComposeTable struct {
366+ mu sync.Mutex
367+ h, context uintptr
368+}
369+
370+func (c *Context) NewComposeTable(locale string) (*ComposeTable, error) {
371+ if e := validString(locale); e != nil {
372+ return nil, e
373+ }
374+ ctx, e := c.retain()
375+ if e != nil {
376+ return nil, e
377+ }
378+ b := cstr(locale)
379+ h := loader.f.Xkb_compose_table_new_from_locale(ctx, ptr(b), 0)
380+ runtime.KeepAlive(b)
381+ if h == 0 {
382+ releaseContext(ctx)
383+ return nil, fmt.Errorf("xkbcommon: no compose table for %q", locale)
384+ }
385+ return &ComposeTable{h: h, context: ctx}, nil
386+}
387+func (t *ComposeTable) Close() error {
388+ if t == nil {
389+ return nil
390+ }
391+ t.mu.Lock()
392+ h, ctx := t.h, t.context
393+ t.h = 0
394+ t.context = 0
395+ if h != 0 {
396+ loader.f.Xkb_compose_table_unref(h)
397+ }
398+ t.mu.Unlock()
399+ if ctx != 0 {
400+ releaseContext(ctx)
401+ }
402+ return nil
403+}
404+func (t *ComposeTable) NewState() (*ComposeState, error) {
405+ if t == nil {
406+ return nil, ErrClosed
407+ }
408+ t.mu.Lock()
409+ if t.h == 0 {
410+ t.mu.Unlock()
411+ return nil, ErrClosed
412+ }
413+ table := loader.f.Xkb_compose_table_ref(t.h)
414+ t.mu.Unlock()
415+ h := loader.f.Xkb_compose_state_new(table, 0)
416+ if h == 0 {
417+ loader.f.Xkb_compose_table_unref(table)
418+ return nil, errors.New("xkbcommon: create compose state failed")
419+ }
420+ return &ComposeState{h: h, table: table}, nil
421+}
422+
423+type ComposeState struct {
424+ mu sync.Mutex
425+ h, table uintptr
426+}
427+
428+func (s *ComposeState) Close() error {
429+ if s == nil {
430+ return nil
431+ }
432+ s.mu.Lock()
433+ h, t := s.h, s.table
434+ s.h = 0
435+ s.table = 0
436+ if h != 0 {
437+ loader.f.Xkb_compose_state_unref(h)
438+ }
439+ s.mu.Unlock()
440+ if t != 0 {
441+ loader.f.Xkb_compose_table_unref(t)
442+ }
443+ return nil
444+}
445+func (s *ComposeState) Feed(sym uint32) (uint32, error) {
446+ if s == nil {
447+ return 0, ErrClosed
448+ }
449+ s.mu.Lock()
450+ defer s.mu.Unlock()
451+ if s.h == 0 {
452+ return 0, ErrClosed
453+ }
454+ return loader.f.Xkb_compose_state_feed(s.h, sym), nil
455+}
456+func (s *ComposeState) Status() (uint32, error) {
457+ if s == nil {
458+ return 0, ErrClosed
459+ }
460+ s.mu.Lock()
461+ defer s.mu.Unlock()
462+ if s.h == 0 {
463+ return 0, ErrClosed
464+ }
465+ return loader.f.Xkb_compose_state_get_status(s.h), nil
466+}
467+func (s *ComposeState) UTF8() (string, error) {
468+ if s == nil {
469+ return "", ErrClosed
470+ }
471+ s.mu.Lock()
472+ defer s.mu.Unlock()
473+ if s.h == 0 {
474+ return "", ErrClosed
475+ }
476+ return sizedUTF8(func(p, n uintptr) int32 { return loader.f.Xkb_compose_state_get_utf8(s.h, p, n) })
477+}
478+func (s *ComposeState) KeySym() (uint32, error) {
479+ if s == nil {
480+ return 0, ErrClosed
481+ }
482+ s.mu.Lock()
483+ defer s.mu.Unlock()
484+ if s.h == 0 {
485+ return 0, ErrClosed
486+ }
487+ return loader.f.Xkb_compose_state_get_one_sym(s.h), nil
488+}
489+func (s *ComposeState) Reset() error {
490+ if s == nil {
491+ return ErrClosed
492+ }
493+ s.mu.Lock()
494+ defer s.mu.Unlock()
495+ if s.h == 0 {
496+ return ErrClosed
497+ }
498+ loader.f.Xkb_compose_state_reset(s.h)
499+ return nil
500+}
A xkbcommon_test.go +402 -0
@@ -0,0 +1,402 @@
1+package xkbcommon
2+
3+import (
4+ "errors"
5+ "fmt"
6+ "os"
7+ "os/exec"
8+ "regexp"
9+ "strings"
10+ "testing"
11+ "unsafe"
12+
13+ "github.com/bnema/purego-xkbcommon/raw"
14+)
15+
16+func live(t *testing.T) *Context {
17+ t.Helper()
18+ if err := Available(); err != nil {
19+ if strings.Contains(err.Error(), "load libxkbcommon.so.0") {
20+ t.Skipf("live libxkbcommon.so.0 absent: %v", err)
21+ }
22+ t.Fatal(err)
23+ }
24+ c, e := NewContext()
25+ if e != nil {
26+ t.Fatal(e)
27+ }
28+ t.Cleanup(func() { c.Close() })
29+ return c
30+}
31+func rules(t *testing.T, c *Context, layout string) *Keymap {
32+ t.Helper()
33+ k, e := c.NewKeymapRules("evdev", "pc105", layout, "", "")
34+ if e != nil {
35+ t.Fatalf("rules %s: %v", layout, e)
36+ }
37+ t.Cleanup(func() { k.Close() })
38+ return k
39+}
40+func state(t *testing.T, k *Keymap) *State {
41+ t.Helper()
42+ s, e := k.NewState()
43+ if e != nil {
44+ t.Fatal(e)
45+ }
46+ t.Cleanup(func() { s.Close() })
47+ return s
48+}
49+func TestABI(t *testing.T) {
50+ if unsafe.Sizeof(raw.RuleNames{}) != 5*unsafe.Sizeof(uintptr(0)) {
51+ t.Fatal("rule names ABI")
52+ }
53+ if unsafe.Sizeof(raw.Keycode(0)) != 4 || unsafe.Sizeof(raw.Keysym(0)) != 4 || unsafe.Sizeof(raw.ModMask(0)) != 4 {
54+ t.Fatal("scalar ABI")
55+ }
56+}
57+func TestSymbols(t *testing.T) {
58+ live(t)
59+ if len(raw.Symbols) < 25 {
60+ t.Fatal("incomplete required symbol set")
61+ }
62+}
63+func TestMalformedAndLifetime(t *testing.T) {
64+ c := live(t)
65+ if _, e := c.NewKeymapString("garbage"); e == nil {
66+ t.Fatal("malformed keymap compiled")
67+ }
68+ if _, e := c.NewKeymapString("foo\x00bar"); e == nil {
69+ t.Fatal("embedded NUL")
70+ }
71+ k := rules(t, c, "us")
72+ s := state(t, k)
73+ c.Close()
74+ k.Close()
75+ for i := 0; i < 3; i++ {
76+ c.Close()
77+ k.Close()
78+ }
79+ if _, e := k.NewState(); !errors.Is(e, ErrClosed) {
80+ t.Fatal(e)
81+ }
82+ v, e := s.UTF8(38)
83+ if e != nil || v != "a" {
84+ t.Fatalf("state after parent close: %q %v", v, e)
85+ }
86+ s.Close()
87+ s.Close()
88+ if _, e := s.KeySym(38); !errors.Is(e, ErrClosed) {
89+ t.Fatal(e)
90+ }
91+}
92+func TestFD(t *testing.T) {
93+ c := live(t)
94+ short := keymapFile(t, []byte("short"))
95+ if _, e := c.NewKeymapFD(int(short.Fd()), 4096); e == nil || !strings.Contains(e.Error(), "short read") {
96+ t.Fatalf("truncated keymap: %v", e)
97+ }
98+ if _, e := short.Stat(); e != nil {
99+ t.Fatalf("FD was closed on error: %v", e)
100+ }
101+ for _, size := range []int{0, 16<<20 + 1} {
102+ if _, e := c.NewKeymapFD(int(short.Fd()), size); e == nil {
103+ t.Fatalf("accepted size %d", size)
104+ }
105+ }
106+ if _, e := c.NewKeymapFD(-1, 5); e == nil {
107+ t.Fatal("negative FD")
108+ }
109+ if _, e := exec.LookPath("xkbcli"); e != nil {
110+ t.Skipf("xkbcli compile-keymap reference unavailable: %v", e)
111+ }
112+ out, e := exec.Command("xkbcli", "compile-keymap", "--rules", "evdev", "--model", "pc105", "--layout", "fr", "--output-format", "1").Output()
113+ if e != nil {
114+ t.Fatalf("reference xkbcli: %v", e)
115+ }
116+ f := keymapFile(t, append(out, 0))
117+ other, e := c.NewKeymapFD(int(f.Fd()), len(out)+1)
118+ if e != nil {
119+ t.Fatal(e)
120+ }
121+ other.Close()
122+ if _, e = f.Stat(); e != nil {
123+ t.Fatalf("FD was closed: %v", e)
124+ }
125+ if _, e = c.NewKeymapFD(int(f.Fd()), len(out)+2); e == nil || !strings.Contains(e.Error(), "short read") {
126+ t.Fatalf("truncated keymap: %v", e)
127+ }
128+ if _, e = c.NewKeymapFD(int(f.Fd()), len(out)); e != nil {
129+ t.Fatalf("non-NUL text: %v", e)
130+ }
131+}
132+
133+func keymapFile(t *testing.T, data []byte) *os.File {
134+ t.Helper()
135+ f, e := os.CreateTemp(t.TempDir(), "keymap")
136+ if e != nil {
137+ t.Fatal(e)
138+ }
139+ t.Cleanup(func() { f.Close() })
140+ if _, e = f.Write(data); e != nil {
141+ t.Fatal(e)
142+ }
143+ return f
144+}
145+
146+func TestLoaderDiagnostics(t *testing.T) {
147+ _, e := resolveLibrary("/no/such/libxkbcommon.so", raw.Symbols)
148+ if e == nil || !strings.Contains(e.Error(), "load /no/such/libxkbcommon.so") {
149+ t.Fatalf("missing library: %v", e)
150+ }
151+ if e := Available(); e != nil {
152+ if strings.Contains(e.Error(), "load libxkbcommon.so.0") {
153+ t.Skipf("missing symbol test needs libxkbcommon.so.0: %v", e)
154+ }
155+ t.Fatal(e)
156+ }
157+ _, e = resolveLibrary("libxkbcommon.so.0", []string{"xkb_nonexistent_test_symbol"})
158+ if e == nil || !strings.Contains(e.Error(), "missing xkb_nonexistent_test_symbol") {
159+ t.Fatalf("missing symbol: %v", e)
160+ }
161+}
162+func TestLayoutsAndDifferential(t *testing.T) {
163+ c := live(t)
164+ for _, tc := range []struct {
165+ layout string
166+ code uint32
167+ want string
168+ alt bool
169+ }{{"us", 38, "a", false}, {"fr", 24, "a", false}, {"de", 29, "z", false}, {"de", 26, "€", true}, {"fr", 26, "€", true}} {
170+ t.Run(tc.layout+tc.want, func(t *testing.T) {
171+ k := rules(t, c, tc.layout)
172+ s := state(t, k)
173+ if tc.alt {
174+ idx, e := k.ModIndex("LevelThree")
175+ if e != nil || idx == ^uint32(0) || idx >= 32 {
176+ t.Fatalf("LevelThree: %d %v", idx, e)
177+ }
178+ s.UpdateMask(1<<idx, 0, 0, 0, 0, 0)
179+ }
180+ got, e := s.UTF8(tc.code)
181+ if e != nil || got != tc.want {
182+ t.Fatalf("utf8 %q want %q: %v", got, tc.want, e)
183+ }
184+ sym, e := s.KeySym(tc.code)
185+ if e != nil {
186+ t.Fatal(e)
187+ }
188+ name, e := KeysymName(sym)
189+ if e != nil || name == "" {
190+ t.Fatalf("name %q: %v", name, e)
191+ }
192+ back, e := KeysymFromName(name)
193+ if e != nil || back != sym {
194+ t.Fatalf("name roundtrip %d %d %v", sym, back, e)
195+ }
196+ // Compare safe calls to the independently resolved native entry points for this real rules keymap.
197+ nativeSym := loader.f.Xkb_state_key_get_one_sym(s.h, tc.code)
198+ if nativeSym != sym {
199+ t.Fatalf("native sym %d != %d", nativeSym, sym)
200+ }
201+ nativeN := loader.f.Xkb_state_key_get_utf8(s.h, tc.code, 0, 0)
202+ if nativeN != int32(len(got)) {
203+ t.Fatalf("native bytes %d != %d", nativeN, len(got))
204+ }
205+ })
206+ }
207+ k := rules(t, c, "us,de")
208+ s := state(t, k)
209+ n, e := k.LayoutCount()
210+ if e != nil || n != 2 {
211+ t.Fatalf("layouts %d %v", n, e)
212+ }
213+ s.UpdateMask(0, 0, 0, 0, 0, 1)
214+ group, e := s.Layout()
215+ if e != nil || group != 1 {
216+ t.Fatalf("group %d %v", group, e)
217+ }
218+ v, _ := s.UTF8(29)
219+ if v != "z" {
220+ t.Fatalf("group 1 %q", v)
221+ }
222+ shift, e := k.ModIndex("Shift")
223+ if e != nil || shift >= 32 {
224+ t.Fatalf("shift %d %v", shift, e)
225+ }
226+ s.UpdateMask(1<<shift, 0, 0, 0, 0, 1)
227+ v, _ = s.UTF8(29)
228+ if v != "Z" {
229+ t.Fatalf("shift group 1 %q", v)
230+ }
231+ mods, _ := s.Mods()
232+ if mods&(1<<shift) == 0 {
233+ t.Fatalf("mods %#x", mods)
234+ }
235+}
236+
237+// These expectations are fixed evdev/XKB facts, not values computed by the
238+// binding under test. Every case compiles through the Wayland FD path.
239+func TestFDReferenceKeyEvents(t *testing.T) {
240+ c := live(t)
241+ for _, tc := range []struct {
242+ layout, key, utf8, modifiers string
243+ evdev, group, sym uint32
244+ }{
245+ {"us", "q", "q", "", 16, 0, raw.XKB_KEY_q},
246+ {"us", "Q", "Q", "Shift", 16, 0, raw.XKB_KEY_Q},
247+ {"us", "Q", "Q", "Lock", 16, 0, raw.XKB_KEY_Q},
248+ {"fr", "a", "a", "", 16, 0, raw.XKB_KEY_a},
249+ {"fr", "€", "€", "Mod5", 18, 0, raw.XKB_KEY_EuroSign},
250+ {"de", "z", "z", "", 21, 0, raw.XKB_KEY_z},
251+ {"de", "@", "@", "Mod5", 16, 0, raw.XKB_KEY_at},
252+ {"de", "dead_circumflex", "", "", 41, 0, raw.XKB_KEY_dead_circumflex},
253+ {"us,fr", "a", "a", "", 16, 1, raw.XKB_KEY_a},
254+ } {
255+ t.Run(tc.layout+"/"+tc.key+"/"+tc.modifiers, func(t *testing.T) {
256+ // Wayland-format keymaps pinned in testdata/keymaps were produced by
257+ // `xkbcli compile-keymap --output-format 1` (libxkbcommon 1.13.2), so
258+ // the FD path is always exercised without optional tools.
259+ text, e := os.ReadFile("testdata/keymaps/" + strings.ReplaceAll(tc.layout, ",", "_") + ".xkb")
260+ if e != nil {
261+ t.Fatal(e)
262+ }
263+ f := keymapFile(t, append(text, 0))
264+ k, e := c.NewKeymapFD(int(f.Fd()), len(text)+1)
265+ if e != nil {
266+ t.Fatal(e)
267+ }
268+ t.Cleanup(func() { k.Close() })
269+ s := state(t, k)
270+ var mask uint32
271+ if tc.modifiers != "" {
272+ idx, e := k.ModIndex(tc.modifiers)
273+ if e != nil || idx >= 32 {
274+ t.Fatalf("modifier %s: %d %v", tc.modifiers, idx, e)
275+ }
276+ mask = 1 << idx
277+ }
278+ var depressed, locked uint32
279+ if tc.modifiers == "Lock" {
280+ locked = mask
281+ } else {
282+ depressed = mask
283+ }
284+ if _, e := s.UpdateMask(depressed, 0, locked, 0, 0, tc.group); e != nil {
285+ t.Fatal(e)
286+ }
287+ if group, e := s.Layout(); e != nil || group != tc.group {
288+ t.Fatalf("group %d: %v", group, e)
289+ }
290+ code := WaylandKeycode(tc.evdev)
291+ if sym, e := s.KeySym(code); e != nil || sym != tc.sym {
292+ t.Fatalf("keysym %#x want %#x: %v", sym, tc.sym, e)
293+ }
294+ if v, e := s.UTF8(code); e != nil || v != tc.utf8 {
295+ t.Fatalf("utf8 %q want %q: %v", v, tc.utf8, e)
296+ }
297+ if tc.sym == raw.XKB_KEY_dead_circumflex {
298+ if v, e := s.UTF8(WaylandKeycode(18)); e != nil || v != "e" {
299+ t.Fatalf("compose input e: %q %v", v, e)
300+ }
301+ table, e := c.NewComposeTable("en_US.UTF-8")
302+ if e != nil {
303+ t.Fatal(e)
304+ }
305+ t.Cleanup(func() { table.Close() })
306+ compose, e := table.NewState()
307+ if e != nil {
308+ t.Fatal(e)
309+ }
310+ t.Cleanup(func() { compose.Close() })
311+ if _, e := compose.Feed(tc.sym); e != nil {
312+ t.Fatal(e)
313+ }
314+ if _, e := compose.Feed(raw.XKB_KEY_e); e != nil {
315+ t.Fatal(e)
316+ }
317+ if status, e := compose.Status(); e != nil || status != raw.XKB_COMPOSE_COMPOSED {
318+ t.Fatalf("compose status %d: %v", status, e)
319+ }
320+ if sym, e := compose.KeySym(); e != nil || sym != raw.XKB_KEY_ecircumflex {
321+ t.Fatalf("compose sym %#x: %v", sym, e)
322+ }
323+ if v, e := compose.UTF8(); e != nil || v != "ê" {
324+ t.Fatalf("compose utf8 %q: %v", v, e)
325+ }
326+ }
327+ if _, e := exec.LookPath("xkbcli"); e == nil && tc.group == 0 && tc.modifiers != "Lock" {
328+ args := []string{"how-to-type", "--layout", tc.layout}
329+ if tc.sym == raw.XKB_KEY_dead_circumflex {
330+ args = append(args, "--keysym")
331+ }
332+ out, e := exec.Command("xkbcli", append(args, tc.key)...).Output()
333+ if e != nil {
334+ t.Fatal(e)
335+ }
336+ // The CLI reports XKB keycodes, not evdev codes.
337+ pattern := regexp.MustCompile(`(?m)^\s*` + fmt.Sprint(code) + `\s+\S+\s+\d+\s+.*\[.*\]`)
338+ if !pattern.Match(out) {
339+ t.Fatalf("xkbcli how-to-type lacks keycode %d: %s", code, out)
340+ }
341+ }
342+ })
343+ }
344+}
345+
346+func TestCompose(t *testing.T) {
347+ c := live(t)
348+ table, e := c.NewComposeTable("en_US.UTF-8")
349+ if e != nil {
350+ t.Fatal(e)
351+ }
352+ s, e := table.NewState()
353+ if e != nil {
354+ t.Fatal(e)
355+ }
356+ table.Close()
357+ c.Close()
358+ if _, e = s.Feed(raw.XKB_KEY_dead_acute); e != nil {
359+ t.Fatal(e)
360+ }
361+ status, _ := s.Status()
362+ if status != raw.XKB_COMPOSE_COMPOSING {
363+ t.Fatalf("status %d", status)
364+ }
365+ s.Feed(raw.XKB_KEY_e)
366+ status, _ = s.Status()
367+ if status != raw.XKB_COMPOSE_COMPOSED {
368+ t.Fatalf("status %d", status)
369+ }
370+ v, e := s.UTF8()
371+ if e != nil || v != "é" {
372+ t.Fatalf("compose %q %v", v, e)
373+ }
374+ s.Reset()
375+ s.Feed(raw.XKB_KEY_Multi_key)
376+ s.Feed(raw.XKB_KEY_apostrophe)
377+ s.Feed(raw.XKB_KEY_e)
378+ v, _ = s.UTF8()
379+ if v != "é" {
380+ t.Fatalf("multikey %q", v)
381+ }
382+ s.Close()
383+ s.Close()
384+ table.Close()
385+ if _, e = s.UTF8(); !errors.Is(e, ErrClosed) {
386+ t.Fatal(e)
387+ }
388+}
389+func TestSizing(t *testing.T) {
390+ v, e := sizedUTF8(func(p, n uintptr) int32 { return 0 })
391+ if e != nil || v != "" {
392+ t.Fatalf("%q %v", v, e)
393+ }
394+ _, e = sizedUTF8(func(p, n uintptr) int32 { return -1 })
395+ if e == nil {
396+ t.Fatal("negative result accepted")
397+ }
398+ v, e = KeysymName(raw.XKB_KEY_EuroSign)
399+ if e != nil || v != "EuroSign" {
400+ t.Fatalf("name %q %v", v, e)
401+ }
402+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 2

↑↓ moveenter openesc close