detached f8b8aaa

docs(gui): clarify facade methods and profiling measurements

commit
f8b8aaa81ec99f8c0d1869325bf8d7640f8bd16c
author
brice · · 2026-09-30 03:56 UTC
parent
84c1f24
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
3 files · +20 -9
M docs/controls.md +4 -0
@@ -1,5 +1,9 @@
11 # Controls
22
3+Import `github.com/bnema/nefergui`. Public `Frame`, `Node` and event types alias their implementation types, so `go doc` does not list their methods at the root. Inspect signatures with `go doc github.com/bnema/nefergui/internal/ui.Node` (or `.Frame`, `.ButtonEvent`, `.EditEvent`, `.ChangeEvent`). Applications still use the public package; do not import `internal/ui`.
4+
5+`ButtonEvent.Activated()` reports activation; `EditEvent.Changed()` and `.Submitted()` report edits and submission; `ChangeEvent.Changed()` reports value changes. These snapshots can be queried repeatedly without consuming an event.
6+
37 `Text`, `Heading`, `Image`, `Icon`, `Separator`, `Spacer`, `Button`, `Checkbox`, `Radio`, `Slider`, `Input` and `Textarea` build semantic nodes in the immediate frame. `Key` identifies reorderable controls; `ID` and `Class` are CSS metadata. `Image` accepts an existing `image.Image` with bounded intrinsic dimensions. Style is computed via the existing CSS cascade; the caller owns images. CSS types and default accessibility roles are assigned even though a platform accessibility adapter is not yet connected.
48
59 `Button`, `Checkbox`, `Radio` and `Slider` paint their label as text in the control's content box, using its font, `color` and `text-align` (buttons center by default).
@@ -1,5 +1,9 @@
1 # Controls1 # Controls
2 2
3+Import `github.com/bnema/nefergui`. Public `Frame`, `Node` and event types alias their implementation types, so `go doc` does not list their methods at the root. Inspect signatures with `go doc github.com/bnema/nefergui/internal/ui.Node` (or `.Frame`, `.ButtonEvent`, `.EditEvent`, `.ChangeEvent`). Applications still use the public package; do not import `internal/ui`.
4+
5+`ButtonEvent.Activated()` reports activation; `EditEvent.Changed()` and `.Submitted()` report edits and submission; `ChangeEvent.Changed()` reports value changes. These snapshots can be queried repeatedly without consuming an event.
6+
3 `Text`, `Heading`, `Image`, `Icon`, `Separator`, `Spacer`, `Button`, `Checkbox`, `Radio`, `Slider`, `Input` and `Textarea` build semantic nodes in the immediate frame. `Key` identifies reorderable controls; `ID` and `Class` are CSS metadata. `Image` accepts an existing `image.Image` with bounded intrinsic dimensions. Style is computed via the existing CSS cascade; the caller owns images. CSS types and default accessibility roles are assigned even though a platform accessibility adapter is not yet connected.7 `Text`, `Heading`, `Image`, `Icon`, `Separator`, `Spacer`, `Button`, `Checkbox`, `Radio`, `Slider`, `Input` and `Textarea` build semantic nodes in the immediate frame. `Key` identifies reorderable controls; `ID` and `Class` are CSS metadata. `Image` accepts an existing `image.Image` with bounded intrinsic dimensions. Style is computed via the existing CSS cascade; the caller owns images. CSS types and default accessibility roles are assigned even though a platform accessibility adapter is not yet connected.
4 8
5 `Button`, `Checkbox`, `Radio` and `Slider` paint their label as text in the control's content box, using its font, `color` and `text-align` (buttons center by default).9 `Button`, `Checkbox`, `Radio` and `Slider` paint their label as text in the control's content box, using its font, `color` and `text-align` (buttons center by default).
M docs/performance.md +3 -3
@@ -6,7 +6,7 @@ AMD Ryzen 9 7900X3D 12-Core Processor; `CGO_ENABLED=0 GOWORK=off go test -run '^
66
77 | Package / benchmark | Median ns/op | Median B/op | Median allocs/op | Budget ns/op | Budget B/op | Budget allocs/op |
88 |---|---:|---:|---:|---:|---:|---:|
9-| root / DemoFrame | 21,238 | 32,816 | 220 | 45,000 | 66,000 | 500 |
9+| internal/ui / DemoFrame | 21,238 | 32,816 | 220 | 45,000 | 66,000 | 500 |
1010 | render / Prepare | 59,024 | 158,720 | 386 | 125,000 | 320,000 | 800 |
1111 | text / AtlasWarmLookup | 29.07 | 0 | 0 | 60 | 0 | 0 |
1212 | text / RasterDistinct1000 | 4,139,638 | 8,566,137 | 16,784 | 8,300,000 | 17,200,000 | 34,000 |
@@ -37,13 +37,13 @@ A 400-frame demo harness run (960×640, scale 1, input: name Ada then continue)
3737
3838 ## Memory as a dependency
3939
40-An external Go module with a minimal counter view, a 960×640 window, and a private headless NeferWL compositor was profiled on AMD/RADV. Debug readbacks were disabled. Live Go heap was sampled after forced GC; RSS includes shared driver libraries, while PSS apportions shared pages.
40+An external Go module with a minimal counter view, a 960×640 window, and a private headless NeferWL compositor was profiled on AMD/RADV. Baseline: NeferGUI `068ba85`, Go 1.27.1, Mesa/RADV 26.2.3, and NeferWL `1d16b83bf90f9e8189ad21b27772382c96b9f9a8`. A minimal-consumer repeat at `84c1f24` matched retained heap within 0.02 MiB and used identical GPU allocations. Debug readbacks were disabled. Live Go heap was sampled after forced GC; RSS includes shared driver libraries, while PSS apportions shared pages.
4141
4242 | Measurement | Minimal view | Demo view |
4343 |---|---:|---:|
4444 | Live Go heap after 1,000 frames | 5.3 MiB | 5.4 MiB |
4545 | Process RSS / PSS after 1,000 frames | 60 / 43 MiB | 64 / 47 MiB |
46-| Estimated temporary allocations per rendered frame, sampler excluded | about 65 KiB | about 230 KiB |
46+| Estimated temporary allocations per rendered frame, measurement sampler's own allocations excluded | about 65 KiB | about 230 KiB |
4747
4848 The minimal view starts at about 0.75 MiB live Go heap, reaches 5.2 MiB after the first frame, and returns to about 0.9 MiB after closing. No sustained live-heap growth was observed over 1,000–3,000 frames. Driver mappings and Go heap capacity can remain resident after closing; RSS is not a leak measurement on its own.
4949
@@ -6,7 +6,7 @@ AMD Ryzen 9 7900X3D 12-Core Processor; `CGO_ENABLED=0 GOWORK=off go test -run '^
6 6
7 | Package / benchmark | Median ns/op | Median B/op | Median allocs/op | Budget ns/op | Budget B/op | Budget allocs/op |7 | Package / benchmark | Median ns/op | Median B/op | Median allocs/op | Budget ns/op | Budget B/op | Budget allocs/op |
8 |---|---:|---:|---:|---:|---:|---:|8 |---|---:|---:|---:|---:|---:|---:|
9-| root / DemoFrame | 21,238 | 32,816 | 220 | 45,000 | 66,000 | 500 |9+| internal/ui / DemoFrame | 21,238 | 32,816 | 220 | 45,000 | 66,000 | 500 |
10 | render / Prepare | 59,024 | 158,720 | 386 | 125,000 | 320,000 | 800 |10 | render / Prepare | 59,024 | 158,720 | 386 | 125,000 | 320,000 | 800 |
11 | text / AtlasWarmLookup | 29.07 | 0 | 0 | 60 | 0 | 0 |11 | text / AtlasWarmLookup | 29.07 | 0 | 0 | 60 | 0 | 0 |
12 | text / RasterDistinct1000 | 4,139,638 | 8,566,137 | 16,784 | 8,300,000 | 17,200,000 | 34,000 |12 | text / RasterDistinct1000 | 4,139,638 | 8,566,137 | 16,784 | 8,300,000 | 17,200,000 | 34,000 |
@@ -37,13 +37,13 @@ A 400-frame demo harness run (960×640, scale 1, input: name Ada then continue)
37 37
38 ## Memory as a dependency38 ## Memory as a dependency
39 39
40-An external Go module with a minimal counter view, a 960×640 window, and a private headless NeferWL compositor was profiled on AMD/RADV. Debug readbacks were disabled. Live Go heap was sampled after forced GC; RSS includes shared driver libraries, while PSS apportions shared pages.40+An external Go module with a minimal counter view, a 960×640 window, and a private headless NeferWL compositor was profiled on AMD/RADV. Baseline: NeferGUI `068ba85`, Go 1.27.1, Mesa/RADV 26.2.3, and NeferWL `1d16b83bf90f9e8189ad21b27772382c96b9f9a8`. A minimal-consumer repeat at `84c1f24` matched retained heap within 0.02 MiB and used identical GPU allocations. Debug readbacks were disabled. Live Go heap was sampled after forced GC; RSS includes shared driver libraries, while PSS apportions shared pages.
41 41
42 | Measurement | Minimal view | Demo view |42 | Measurement | Minimal view | Demo view |
43 |---|---:|---:|43 |---|---:|---:|
44 | Live Go heap after 1,000 frames | 5.3 MiB | 5.4 MiB |44 | Live Go heap after 1,000 frames | 5.3 MiB | 5.4 MiB |
45 | Process RSS / PSS after 1,000 frames | 60 / 43 MiB | 64 / 47 MiB |45 | Process RSS / PSS after 1,000 frames | 60 / 43 MiB | 64 / 47 MiB |
46-| Estimated temporary allocations per rendered frame, sampler excluded | about 65 KiB | about 230 KiB |46+| Estimated temporary allocations per rendered frame, measurement sampler's own allocations excluded | about 65 KiB | about 230 KiB |
47 47
48 The minimal view starts at about 0.75 MiB live Go heap, reaches 5.2 MiB after the first frame, and returns to about 0.9 MiB after closing. No sustained live-heap growth was observed over 1,000–3,000 frames. Driver mappings and Go heap capacity can remain resident after closing; RSS is not a leak measurement on its own.48 The minimal view starts at about 0.75 MiB live Go heap, reaches 5.2 MiB after the first frame, and returns to about 0.9 MiB after closing. No sustained live-heap growth was observed over 1,000–3,000 frames. Driver mappings and Go heap capacity can remain resident after closing; RSS is not a leak measurement on its own.
49 49
M nefergui.go +13 -6
@@ -23,6 +23,7 @@ import (
2323
2424 // Frame is valid only during one call to the view function. Root builds the
2525 // application element; Diagnostics reports identity problems in debug builds.
26+// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.Frame.
2627 type Frame = ui.Frame
2728
2829 // Node is an ephemeral handle into the current frame. Do not retain it between
@@ -31,14 +32,20 @@ type Frame = ui.Frame
3132 // (Button, Checkbox, Radio, Slider, Input, Textarea, Text, Heading, Image,
3233 // Icon, Separator, Spacer) declare controls. Interactive controls return event
3334 // snapshots.
35+// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.Node.
3436 type Node = ui.Node
3537
36-// Control event values are immutable snapshots; querying them never consumes events.
37-type (
38- ButtonEvent = ui.ButtonEvent
39- EditEvent = ui.EditEvent
40- ChangeEvent = ui.ChangeEvent
41-)
38+// ButtonEvent is an immutable snapshot queried with Activated.
39+// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.ButtonEvent.
40+type ButtonEvent = ui.ButtonEvent
41+
42+// EditEvent is an immutable snapshot queried with Changed and Submitted.
43+// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.EditEvent.
44+type EditEvent = ui.EditEvent
45+
46+// ChangeEvent is an immutable snapshot queried with Changed.
47+// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.ChangeEvent.
48+type ChangeEvent = ui.ChangeEvent
4249
4350 // Option families are sealed: ContainerOption, ButtonOption, EditOption,
4451 // ValueOption and HeadingOption accept the common CSS options (Key, ID,
@@ -23,6 +23,7 @@ import (
23 23
24 // Frame is valid only during one call to the view function. Root builds the24 // Frame is valid only during one call to the view function. Root builds the
25 // application element; Diagnostics reports identity problems in debug builds.25 // application element; Diagnostics reports identity problems in debug builds.
26+// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.Frame.
26 type Frame = ui.Frame27 type Frame = ui.Frame
27 28
28 // Node is an ephemeral handle into the current frame. Do not retain it between29 // Node is an ephemeral handle into the current frame. Do not retain it between
@@ -31,14 +32,20 @@ type Frame = ui.Frame
31 // (Button, Checkbox, Radio, Slider, Input, Textarea, Text, Heading, Image,32 // (Button, Checkbox, Radio, Slider, Input, Textarea, Text, Heading, Image,
32 // Icon, Separator, Spacer) declare controls. Interactive controls return event33 // Icon, Separator, Spacer) declare controls. Interactive controls return event
33 // snapshots.34 // snapshots.
35+// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.Node.
34 type Node = ui.Node36 type Node = ui.Node
35 37
36-// Control event values are immutable snapshots; querying them never consumes events.38+// ButtonEvent is an immutable snapshot queried with Activated.
37-type (39+// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.ButtonEvent.
38- ButtonEvent = ui.ButtonEvent40+type ButtonEvent = ui.ButtonEvent
39- EditEvent = ui.EditEvent41+
40- ChangeEvent = ui.ChangeEvent42+// EditEvent is an immutable snapshot queried with Changed and Submitted.
41-)43+// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.EditEvent.
44+type EditEvent = ui.EditEvent
45+
46+// ChangeEvent is an immutable snapshot queried with Changed.
47+// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.ChangeEvent.
48+type ChangeEvent = ui.ChangeEvent
42 49
43 // Option families are sealed: ContainerOption, ButtonOption, EditOption,50 // Option families are sealed: ContainerOption, ButtonOption, EditOption,
44 // ValueOption and HeadingOption accept the common CSS options (Key, ID,51 // ValueOption and HeadingOption accept the common CSS options (Key, ID,

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 12

↑↓ moveenter openesc close