v0.6.1 aa12db3

runtime.md RawHistoryFolder

Immediate runtime

NewRenderer(RendererConfig) opens the GPU named by MainDevice (the dev_t of linux-dmabuf feedback), loads fonts and the optional Styles CSS file, and allocates no images. Formats is the compositor's flattened format and modifier list in preference order; Transparent selects ARGB8888 instead of XRGB8888. Clipboard and IME are optional ports the application implements. The Renderer imports no Wayland library, starts no goroutine and must be used from one owner goroutine; only Wake is safe from any goroutine. Accessibility is not connected.

A client loop forwards events and presents frames:

  • Resize(width, height, scale) sets the logical size and scale; invalid values are ignored. Nothing is drawn before the first Resize.
  • Input(*Input) routes one pointer, key or focus event and reports whether a redraw is needed. Coordinates are logical surface pixels. Keysym carries xkb keysym values and Text the UTF-8 text of the key; Text is valid only during the call. Modifiers is a bit set of ModShift, ModCtrl, ModAlt, ModSuper (held) and ModCapsLock, ModNumLock (latched). Only Shift and Ctrl affect shortcuts and editing; lock bits are ignored, and views do not see modifiers, so an application that shows a lock indicator keeps the lock bits of Input.Modifiers in its model. InputReset drops held state after a lost input queue. Invalidate forces a rebuild.
  • Render(&out, &model, view) builds the view when input or a redraw request is queued and draws it into a free buffer. It returns false, without touching the GPU, when nothing changed or no buffer is free. When it returns true, out describes the frame in physical pixels: DMA-BUF Planes, FourCC, Modifier, acquire and release timelines and points, Damage, Cursor, and InputRects with InputRectsChanged.
  • Released(buffer) returns a buffer to the pool when its ReleaseFD eventfd becomes readable.
  • Pending() reports a built frame waiting for the GPU rather than the compositor. No event announces this: arm a short timer (about 2 ms) and call Render again. Wake() is signaled when another goroutine, for example a finished paste, needs a Render.
  • Close cancels pending pastes and frees GPU resources.

All file descriptors in Output stay owned by the Renderer; duplicate them before handing them to a transport that consumes descriptors. Output.NewBuffer says to import Planes as a new buffer, and NewTimelines says the timeline descriptors are new. Descriptors of retired buffers listed in Output.Retired stay open until the next Render or Close, so the client can stop watching and destroy them first. Output slices are reused and valid until the next Render. Allocation behavior of Render is described in performance.

Frame.SetInputRects stages the clickable region, reported in Output.InputRects only when it changes. Nil restores the whole surface; a non-nil empty slice makes it click-through. Node.Rect places a border-box rectangle relative to a Stack's content box without parsing geometry CSS. It applies only to Stack children; debug builds diagnose other parents. The cursor shape follows the CSS cursor of the hovered element and is reported in Output.Cursor; the client maps it to its own cursor mechanism.

Clipboard reads are asynchronous: paste starts a read and the text is inserted by the next frame. A new paste cancels the previous one. Input-method batches are applied during frame construction.

The unexported runtime constructs views synchronously. A concurrent or re-entrant build never waits: it requests a redraw, posts a wake token and returns false. The in-progress frame commits first; queued input remains for the next build.

The unexported input port platformInput accepts logical pointer motion/press/release/axis/leave, key events, focus-in/out and logical viewport resize/scale. route hit-tests against the last committed layout (reverse paint order and ancestor clips), resolves the result to a frame identity and wakes the next build only when state changes. Target is a committed-child-path helper for tests. A build computes CSS pseudo-state and commits layout, display list and tree together. Scale is used by the renderer only and never affects hit testing: surface coordinates are already logical. NewRenderer installs a text engine from system fonts; headless tests install one explicitly, and without one text commands have no measured glyph runs.

Tab traverses visible, enabled controls in document order and wraps; Shift+Tab reverses. Keyboard focus sets :focus-visible; pointer focus does not. Enter activates focused buttons and checkboxes on initial key press, ignoring repeats. Space sets :active on initial press and activates on release only if focus is unchanged; focus loss/change or Escape cancels it, and repeats are ignored. Disabled controls cannot focus or activate. When a focused control is removed or disabled, focus falls back to none (the next Tab starts at the first available control). The first pressed pointer button owns capture until its matching release, even outside the target; other button presses/releases cannot steal it or change focus. Only primary-button release on the captured control activates it. Pointer leave clears hover but preserves capture until matching release (an out-of-surface release cannot activate); removal or platform focus loss cancels capture. Scroll wheel deltas apply to the nearest scrollable ancestor and clamp to measured content bounds; offsets are discarded when that identity is no longer a laid-out scroll container. Unchanged state does not redraw. Control callbacks run during frame construction; the Renderer calls no application code outside Render.

Compile with -tags nefergui_debug to report duplicate sibling keys, changed unkeyed child types and stale Node use (stale use panics). Without this tag, stale handles are inert. Do not retain a Node across frames. ID is only for CSS, while Key identifies an element within its parent. Unkeyed children are identified by their position and type.

System font discovery indexes family and aspect from font metadata without retaining font files in memory. Text measurement loads and caches only selected faces; CSS family requests and script fallback select faces on demand. User font directories precede system directories, with sorted paths breaking ties. Fonts that fail to load are skipped and reported in catalog diagnostics.

source
1# Immediate runtime
2
3`NewRenderer(RendererConfig)` opens the GPU named by `MainDevice` (the `dev_t` of linux-dmabuf feedback), loads fonts and the optional `Styles` CSS file, and allocates no images. `Formats` is the compositor's flattened format and modifier list in preference order; `Transparent` selects ARGB8888 instead of XRGB8888. `Clipboard` and `IME` are optional ports the application implements. The Renderer imports no Wayland library, starts no goroutine and must be used from one owner goroutine; only `Wake` is safe from any goroutine. Accessibility is not connected.
4
5A client loop forwards events and presents frames:
6
7- `Resize(width, height, scale)` sets the logical size and scale; invalid values are ignored. Nothing is drawn before the first `Resize`.
8- `Input(*Input)` routes one pointer, key or focus event and reports whether a redraw is needed. Coordinates are logical surface pixels. `Keysym` carries xkb keysym values and `Text` the UTF-8 text of the key; `Text` is valid only during the call. `Modifiers` is a bit set of `ModShift`, `ModCtrl`, `ModAlt`, `ModSuper` (held) and `ModCapsLock`, `ModNumLock` (latched). Only Shift and Ctrl affect shortcuts and editing; lock bits are ignored, and views do not see modifiers, so an application that shows a lock indicator keeps the lock bits of `Input.Modifiers` in its model. `InputReset` drops held state after a lost input queue. `Invalidate` forces a rebuild.
9- `Render(&out, &model, view)` builds the view when input or a redraw request is queued and draws it into a free buffer. It returns false, without touching the GPU, when nothing changed or no buffer is free. When it returns true, `out` describes the frame in physical pixels: DMA-BUF `Planes`, `FourCC`, `Modifier`, acquire and release timelines and points, `Damage`, `Cursor`, and `InputRects` with `InputRectsChanged`.
10- `Released(buffer)` returns a buffer to the pool when its `ReleaseFD` eventfd becomes readable.
11- `Pending()` reports a built frame waiting for the GPU rather than the compositor. No event announces this: arm a short timer (about 2 ms) and call `Render` again. `Wake()` is signaled when another goroutine, for example a finished paste, needs a `Render`.
12- `Close` cancels pending pastes and frees GPU resources.
13
14All file descriptors in `Output` stay owned by the Renderer; duplicate them before handing them to a transport that consumes descriptors. `Output.NewBuffer` says to import `Planes` as a new buffer, and `NewTimelines` says the timeline descriptors are new. Descriptors of retired buffers listed in `Output.Retired` stay open until the next `Render` or `Close`, so the client can stop watching and destroy them first. `Output` slices are reused and valid until the next `Render`. Allocation behavior of `Render` is described in [performance](performance.md).
15
16`Frame.SetInputRects` stages the clickable region, reported in `Output.InputRects` only when it changes. Nil restores the whole surface; a non-nil empty slice makes it click-through. `Node.Rect` places a border-box rectangle relative to a Stack's content box without parsing geometry CSS. It applies only to Stack children; debug builds diagnose other parents. The cursor shape follows the CSS `cursor` of the hovered element and is reported in `Output.Cursor`; the client maps it to its own cursor mechanism.
17
18Clipboard reads are asynchronous: paste starts a read and the text is inserted by the next frame. A new paste cancels the previous one. Input-method batches are applied during frame construction.
19
20The unexported `runtime` constructs views synchronously. A concurrent or re-entrant build never waits: it requests a redraw, posts a wake token and returns false. The in-progress frame commits first; queued input remains for the next build.
21
22The unexported input port `platformInput` accepts logical pointer motion/press/release/axis/leave, key events, focus-in/out and logical viewport resize/scale. `route` hit-tests against the last committed layout (reverse paint order and ancestor clips), resolves the result to a frame identity and wakes the next build only when state changes. `Target` is a committed-child-path helper for tests. A build computes CSS pseudo-state and commits layout, display list and tree together. Scale is used by the renderer only and never affects hit testing: surface coordinates are already logical. `NewRenderer` installs a text engine from system fonts; headless tests install one explicitly, and without one text commands have no measured glyph runs.
23
24Tab traverses visible, enabled controls in document order and wraps; Shift+Tab reverses. Keyboard focus sets `:focus-visible`; pointer focus does not. Enter activates focused buttons and checkboxes on initial key press, ignoring repeats. Space sets `:active` on initial press and activates on release only if focus is unchanged; focus loss/change or Escape cancels it, and repeats are ignored. Disabled controls cannot focus or activate. When a focused control is removed or disabled, focus falls back to **none** (the next Tab starts at the first available control). The first pressed pointer button owns capture until its matching release, even outside the target; other button presses/releases cannot steal it or change focus. Only primary-button release on the captured control activates it. Pointer leave clears hover but preserves capture until matching release (an out-of-surface release cannot activate); removal or platform focus loss cancels capture. Scroll wheel deltas apply to the nearest scrollable ancestor and clamp to measured content bounds; offsets are discarded when that identity is no longer a laid-out scroll container. Unchanged state does not redraw. Control callbacks run during frame construction; the Renderer calls no application code outside `Render`.
25
26Compile with `-tags nefergui_debug` to report duplicate sibling keys, changed unkeyed child types and stale Node use (stale use panics). Without this tag, stale handles are inert. Do not retain a Node across frames. `ID` is only for CSS, while `Key` identifies an element within its parent. Unkeyed children are identified by their position and type.
27
28System font discovery indexes family and aspect from font metadata without retaining font files in memory. Text measurement loads and caches only selected faces; CSS family requests and script fallback select faces on demand. User font directories precede system directories, with sorted paths breaking ties. Fonts that fail to load are skipped and reported in catalog diagnostics.

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