# 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`. - `Measure(&model, view, maxWidth)` returns the natural `width` (at most `maxWidth`) and `height` of the view in logical pixels, rounded up, with text wrapped at `maxWidth`. The size is that of the root's margin box. Use it to size a surface, such as a popup, before creating it. It is a generic method like `Render`. The view is built in a temporary runtime that shares only the style sheet and text engine, so hover, focus, scroll offsets, editors, queued input, `Wake` and the target are untouched, nothing is drawn, and the view receives no events. The shared caches only grow during `Measure` (it does not age them), so a later `Render` is not slowed. There is no surface yet, so the height is indefinite: `Frame.Size` reports an unbounded height (`1<<20`) inside the view, and percentage `height`, `min-height` and `max-height` of the root are treated as `auto` (as for nested boxes) rather than resolved against that value; pixel heights apply. It allocates and shapes text: call it from the owner goroutine when opening a surface, not on every frame and never from inside a view callback. It works before `Resize` and returns an error for a closed Renderer, a nil model or view, a `maxWidth` that is not finite and above zero, or a view that cannot be laid out (the layout error is wrapped). - `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](performance.md). `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.