v0.1.0 d9218d6

frames_test.go RawHistoryFolder

1package wayland
2
3import (
4	"slices"
5	"testing"
6	"time"
7
8	"github.com/bnema/neferwl/internal/ports"
9	"github.com/bnema/purego-libwayland/protocol/wayland"
10)
11
12func TestFramePeriod(t *testing.T) {
13	for _, tc := range []struct {
14		milli int
15		want  time.Duration
16	}{{0, time.Second / 60}, {60000, time.Second / 60}, {165058, 6058476}, {144000, 6944444}} {
17		if got := framePeriod(tc.milli); got != tc.want {
18			t.Errorf("%d: %v want %v", tc.milli, got, tc.want)
19		}
20	}
21}
22
23// Each output is paced at its own refresh; a flip fires its queue and
24// pushes its deadline back; the pacer idles with nothing queued.
25func TestDueFrames(t *testing.T) {
26	fast := &output{place: ports.OutputPlacement{Info: ports.OutputInfo{Name: "DP-2", RefreshMilli: 165000}}}
27	slow := &output{place: ports.OutputPlacement{Info: ports.OutputInfo{Name: "HDMI-A-1", RefreshMilli: 60000}}}
28	s := &Server{outputs: []*output{fast, slow}, frameDue: map[string]time.Time{}, awaiting: map[string][]*wayland.Callback{}}
29	// dueFrames only counts the queued callbacks: nil ones stand for them.
30	queue := func(name string) { s.awaiting[name] = append(s.awaiting[name], nil) }
31	fired := func(fire []string) {
32		for _, name := range fire {
33			delete(s.awaiting, name)
34		}
35	}
36	now := time.Unix(100, 0)
37	if _, _, idle := s.dueFrames(now, nil); !idle {
38		t.Fatal("not idle without callbacks")
39	}
40	// A first callback goes out at once, then one per refresh.
41	queue("DP-2")
42	queue("HDMI-A-1")
43	fire, _, idle := s.dueFrames(now, nil)
44	if len(fire) != 2 || !idle {
45		t.Fatalf("first fire %v idle %v", fire, idle)
46	}
47	fired(fire)
48	queue("DP-2")
49	queue("HDMI-A-1")
50	fire, wait, _ := s.dueFrames(now.Add(time.Millisecond), nil)
51	if len(fire) != 0 || wait != framePeriod(165000)-time.Millisecond {
52		t.Fatalf("early fire %v wait %v", fire, wait)
53	}
54	at := now.Add(framePeriod(165000))
55	fire, wait, _ = s.dueFrames(at, nil)
56	if !slices.Equal(fire, []string{"DP-2"}) || wait != time.Second/60-framePeriod(165000) {
57		t.Fatalf("165 Hz fire %v wait %v", fire, wait)
58	}
59	fired(fire)
60	// A flip fires its output early and pushes its deadline to 1.5 periods.
61	queue("DP-2")
62	flip := at.Add(time.Millisecond)
63	fire, _, _ = s.dueFrames(flip, map[string]bool{"DP-2": true})
64	if !slices.Equal(fire, []string{"DP-2"}) || s.frameDue["DP-2"] != flip.Add(framePeriod(165000)*3/2) {
65		t.Fatalf("flip fire %v due %v", fire, s.frameDue["DP-2"].Sub(flip))
66	}
67	fired(fire)
68	// A queue on an unplugged output moves to the outputless one (60 Hz).
69	s.outputs = []*output{fast}
70	queue("HDMI-A-1")
71	fire, _, _ = s.dueFrames(flip, nil)
72	fired(fire)
73	if _, ok := s.frameDue["HDMI-A-1"]; ok || len(s.awaiting["HDMI-A-1"]) != 0 || !slices.Equal(fire, []string{""}) {
74		t.Fatalf("unplugged: fire %v due %v", fire, s.frameDue)
75	}
76}

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 26

Tags 10

↑↓ moveenter openesc close