v0.4.0 76bcd84

layerui_test.go RawHistoryFolder

1package layerui
2
3import (
4	"testing"
5
6	"github.com/bnema/neferclient"
7	"github.com/bnema/nefergui"
8	"github.com/stretchr/testify/assert"
9)
10
11func TestPointerInput(t *testing.T) {
12	cases := []struct {
13		ev   neferclient.PointerEvent
14		want nefergui.Input
15		ok   bool
16	}{
17		{neferclient.PointerEvent{Kind: neferclient.PointerEnter, X: 1, Y: 2}, nefergui.Input{Kind: nefergui.InputPointerMotion, X: 1, Y: 2}, true},
18		{neferclient.PointerEvent{Kind: neferclient.PointerMotion, X: 3, Y: 4}, nefergui.Input{Kind: nefergui.InputPointerMotion, X: 3, Y: 4}, true},
19		{neferclient.PointerEvent{Kind: neferclient.PointerLeave, X: 5, Y: 6}, nefergui.Input{Kind: nefergui.InputPointerLeave, X: 5, Y: 6}, true},
20		{neferclient.PointerEvent{Kind: neferclient.PointerButton, X: 7, Y: 8, Button: 0x110, Pressed: true},
21			nefergui.Input{Kind: nefergui.InputPointerPress, X: 7, Y: 8, Button: 0x110, Pressed: true}, true},
22		{neferclient.PointerEvent{Kind: neferclient.PointerButton, X: 7, Y: 8, Button: 0x110},
23			nefergui.Input{Kind: nefergui.InputPointerRelease, X: 7, Y: 8, Button: 0x110}, true},
24		{neferclient.PointerEvent{Kind: neferclient.PointerAxis, DX: 1, DY: -2}, nefergui.Input{Kind: nefergui.InputPointerAxis, DX: 1, DY: -2}, true},
25		{neferclient.PointerEvent{Kind: neferclient.PointerAxisStop}, nefergui.Input{}, false},
26	}
27	for _, c := range cases {
28		got, ok := pointerInput(&c.ev)
29		assert.Equal(t, c.ok, ok, "kind %d", c.ev.Kind)
30		assert.Equal(t, c.want, got, "kind %d", c.ev.Kind)
31	}
32}
33
34func TestKeyInputKeepsKnownModifiersAndText(t *testing.T) {
35	text := []byte("é")
36	ev := neferclient.KeyEvent{Keysym: 0xe9, Pressed: true, Repeat: true, Text: text,
37		Modifiers: neferclient.ModShift | neferclient.ModCtrl | neferclient.ModCapsLock | 1<<7}
38	got := keyInput(&ev)
39	assert.Equal(t, nefergui.InputKey, got.Kind)
40	assert.Equal(t, uint32(0xe9), got.Keysym)
41	assert.True(t, got.Pressed)
42	assert.True(t, got.Repeat)
43	assert.Equal(t, nefergui.ModShift|nefergui.ModCtrl|nefergui.ModCapsLock, got.Modifiers, "unknown bits are dropped")
44	assert.Equal(t, text, got.Text)
45}
46
47func TestInputRegion(t *testing.T) {
48	_, changed := inputRegion(nil, &nefergui.Output{InputRects: []nefergui.Rect{{Width: 1}}})
49	assert.False(t, changed, "unchanged region is not sent")
50
51	got, changed := inputRegion(nil, &nefergui.Output{InputRectsChanged: true})
52	assert.True(t, changed)
53	assert.Nil(t, got, "nil: the whole surface")
54
55	got, _ = inputRegion(nil, &nefergui.Output{InputRectsChanged: true, InputRects: []nefergui.Rect{}})
56	assert.NotNil(t, got, "empty: click-through")
57	assert.Empty(t, got)
58
59	buf := make([]neferclient.Rect, 0, 2)
60	got, _ = inputRegion(buf, &nefergui.Output{InputRectsChanged: true, InputRects: []nefergui.Rect{{X: 1, Y: 2, Width: 3, Height: 4}}})
61	assert.Equal(t, []neferclient.Rect{{X: 1, Y: 2, Width: 3, Height: 4}}, got)
62	assert.Same(t, &buf[:1][0], &got[0], "storage is reused")
63}
64
65// NeferWL sends the preferred scale before the first configure: the size is
66// still unknown (zero for an anchored layer), so OnResize must wait.
67func TestScaleBeforeConfigureIsNotAResize(t *testing.T) {
68	calls := 0
69	l := &loop[int]{cfg: Config{OnResize: func(int, int, float64) { calls++ }}}
70	l.Scale(0, 1.5)
71	assert.Zero(t, calls)
72}
73
74// Both libraries number the shared modifiers the same way, so the bits copy.
75func TestModifierBitsMatch(t *testing.T) {
76	pairs := [][2]uint8{
77		{uint8(neferclient.ModShift), uint8(nefergui.ModShift)},
78		{uint8(neferclient.ModCtrl), uint8(nefergui.ModCtrl)},
79		{uint8(neferclient.ModAlt), uint8(nefergui.ModAlt)},
80		{uint8(neferclient.ModSuper), uint8(nefergui.ModSuper)},
81		{uint8(neferclient.ModCapsLock), uint8(nefergui.ModCapsLock)},
82		{uint8(neferclient.ModNumLock), uint8(nefergui.ModNumLock)},
83	}
84	for _, p := range pairs {
85		assert.Equal(t, p[0], p[1])
86	}
87}

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 2

Tags 9

↑↓ moveenter openesc close