1package xkb
2
3import (
4 "strings"
5 "testing"
6 "time"
7
8 "github.com/bnema/neferwl/internal/ports"
9)
10
11func newTest(t *testing.T, layout string) *Keymap {
12 t.Helper()
13 k, err := New(RMLVO{Layout: layout})
14 if err != nil {
15 if strings.Contains(err.Error(), "libxkbcommon.so.0") {
16 t.Skipf("xkbcommon unavailable: %v", err)
17 }
18 t.Fatal(err)
19 }
20 t.Cleanup(k.Close)
21 return k
22}
23
24func TestKeymap(t *testing.T) {
25 k := newTest(t, "us")
26 if !strings.Contains(k.String(), "xkb_keymap") {
27 t.Fatal("missing keymap text")
28 }
29 if ev := k.Key(30, true, 123*time.Millisecond); ev.Keysym != "a" || ev.Keycode != 30 || !ev.Pressed || ev.Time != 123*time.Millisecond {
30 t.Fatalf("A: %+v", ev)
31 }
32 k.Key(30, false, 0)
33 k.Key(42, true, 0)
34 if ev := k.Key(30, true, 0); ev.Keysym != "A" || ev.Mods&ports.ModShift == 0 || ev.State.Depressed == 0 {
35 t.Fatalf("shift A: %+v", ev)
36 }
37 k.Key(42, false, 0)
38 if ev := k.Key(30, false, 0); ev.Mods&ports.ModShift != 0 {
39 t.Fatalf("shift release: %+v", ev)
40 }
41 for _, tt := range []struct {
42 name string
43 code uint32
44 shift, ok bool
45 }{{"a", 30, false, true}, {"A", 30, true, true}, {"Return", 28, false, true}, {"nope", 0, false, false}} {
46 code, shift, ok := k.KeycodeFor(tt.name)
47 if code != tt.code || shift != tt.shift || ok != tt.ok {
48 t.Errorf("%s: %d %v %v", tt.name, code, shift, ok)
49 }
50 }
51 fr := newTest(t, "fr")
52 if code, _, ok := fr.KeycodeFor("a"); !ok || code != 16 {
53 t.Errorf("fr a: %d %v", code, ok)
54 }
55}
56
57func TestKeyLevels(t *testing.T) {
58 // With Shift held, Base still reports the unshifted keysym.
59 k := newTest(t, "us")
60 k.Key(42, true, 0)
61 if ev := k.Key(2, true, 0); ev.Keysym != "exclam" || ev.Base != "1" {
62 t.Fatalf("shift 1: %+v", ev)
63 }
64 if ev := k.Key(2, false, 0); ev.Base != "" {
65 t.Fatalf("release carries levels: %+v", ev)
66 }
67}