1// Package nefergui provides a pure-Go immediate-mode GUI for Wayland, rendered with
2// Vulkan and styled with a bounded CSS dialect (see docs/css.md).
3//
4// Run opens a window and calls the view function to build each frame. The view
5// receives a Frame; Frame and its Node handles are valid only during that call.
6// Key identifies a child among its siblings across frames; without a key,
7// position and type determine identity. ID is CSS metadata, not frame identity.
8// Options such as Title, Size, Styles and Transparent configure the window.
9//
10// The frame tree, controls, editors and input routing are implemented in
11// internal/ui; this package is the public facade and re-exports those types.
12//
13// Builds support CGO_ENABLED=0. At runtime, NeferGUI requires libvulkan.so.1,
14// libxkbcommon.so.0 and a Wayland compositor supporting linux-dmabuf and
15// linux-drm-syncobj. See docs/runtime.md and docs/troubleshooting.md.
16package nefergui
17
18import (
19 "context"
20
21 "github.com/bnema/nefergui/internal/ui"
22)
23
24// Frame is valid only during one call to the view function. Root builds the
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.
27type Frame = ui.Frame
28
29// Node is an ephemeral handle into the current frame. Do not retain it between
30// frames. Container methods (Box, Row, Column, Stack, Scroll, Header, Nav,
31// Main, Section, Aside, Footer, Element) return child nodes; control methods
32// (Button, Checkbox, Radio, Slider, Input, Textarea, Text, Heading, Image,
33// Icon, Separator, Spacer) declare controls. Interactive controls return event
34// snapshots.
35// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.Node.
36type Node = ui.Node
37
38// ButtonEvent is an immutable snapshot queried with Activated.
39// Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.ButtonEvent.
40type 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.
44type 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.
48type ChangeEvent = ui.ChangeEvent
49
50// Option families are sealed: ContainerOption, ButtonOption, EditOption,
51// ValueOption and HeadingOption accept the common CSS options (Key, ID,
52// Class, Inline) plus the control-specific options listed on each function.
53type (
54 ContainerOption = ui.ContainerOption
55 ButtonOption = ui.ButtonOption
56 EditOption = ui.EditOption
57 ValueOption = ui.ValueOption
58 HeadingOption = ui.HeadingOption
59 WindowOption = ui.WindowOption
60)
61
62// commonOption belongs to every option family; disabledOption to every
63// interactive control family. Both are concrete internal types, aliased so
64// the constructors below can return them without a second implementation.
65type (
66 commonOption = ui.CommonOption
67 disabledOption = ui.DisabledOption
68)
69
70// Key identifies an element among its siblings across frames.
71func Key(key string) commonOption { return ui.Key(key) }
72
73// ID sets the CSS ID; it does not affect frame identity.
74func ID(id string) commonOption { return ui.ID(id) }
75
76// Class adds a CSS class.
77func Class(class string) commonOption { return ui.Class(class) }
78
79// Inline applies inline CSS declarations.
80func Inline(src string) commonOption { return ui.Inline(src) }
81
82// Disabled blocks focus and interaction on an interactive control.
83func Disabled(v bool) disabledOption { return ui.Disabled(v) }
84
85// Level sets the accessibility heading level (1 through 6).
86func Level(level int) HeadingOption { return ui.Level(level) }
87
88// Placeholder sets the text shown in an empty editor.
89func Placeholder(v string) EditOption { return ui.Placeholder(v) }
90
91// Password masks displayed editor text and blocks copy and cut.
92func Password(v bool) EditOption { return ui.Password(v) }
93
94// Title sets the window title.
95func Title(s string) WindowOption { return ui.Title(s) }
96
97// Size sets the initial logical window size.
98func Size(w, h int) WindowOption { return ui.Size(w, h) }
99
100// Styles loads an author stylesheet from a file path.
101func Styles(s string) WindowOption { return ui.Styles(s) }
102
103// Transparent requests an alpha-capable Wayland surface (opaque by default).
104func Transparent() WindowOption { return ui.Transparent() }
105
106// Layer surface, input and wake configuration. Layer selects a wlr-layer-shell
107// surface instead of an xdg toplevel; OnInput, OnResize and Wake integrate
108// callers that own state outside the view. See internal/ui for details.
109type (
110 LayerConfig = ui.LayerConfig
111 LayerLevel = ui.LayerLevel
112 Anchor = ui.Anchor
113 KeyboardMode = ui.KeyboardMode
114 Rect = ui.Rect
115 InputEvent = ui.InputEvent
116 InputKind = ui.InputKind
117 Modifiers = ui.Modifiers
118)
119
120const (
121 LayerBackground = ui.LayerBackground
122 LayerBottom = ui.LayerBottom
123 LayerTop = ui.LayerTop
124 LayerOverlay = ui.LayerOverlay
125
126 AnchorTop = ui.AnchorTop
127 AnchorBottom = ui.AnchorBottom
128 AnchorLeft = ui.AnchorLeft
129 AnchorRight = ui.AnchorRight
130
131 KeyboardNone = ui.KeyboardNone
132 KeyboardExclusive = ui.KeyboardExclusive
133 KeyboardOnDemand = ui.KeyboardOnDemand
134
135 InputPointerMotion = ui.InputPointerMotion
136 InputPointerPress = ui.InputPointerPress
137 InputPointerRelease = ui.InputPointerRelease
138 InputPointerAxis = ui.InputPointerAxis
139 InputPointerLeave = ui.InputPointerLeave
140 InputKey = ui.InputKey
141 InputFocusIn = ui.InputFocusIn
142 InputFocusOut = ui.InputFocusOut
143 InputReset = ui.InputReset
144
145 ModShift = ui.ModShift
146 ModCtrl = ui.ModCtrl
147)
148
149// Layer makes the window a layer-shell surface.
150func Layer(c LayerConfig) WindowOption { return ui.Layer(c) }
151
152// OnInput receives raw input on the owner loop before control routing; return
153// true to request a redraw.
154func OnInput(fn func(InputEvent) bool) WindowOption { return ui.OnInput(fn) }
155
156// OnResize reports logical size and scale at start and on change only.
157func OnResize(fn func(width, height int, scale float64)) WindowOption { return ui.OnResize(fn) }
158
159// WaylandSurface is the window's Wayland display and wl_surface for OnSurface.
160type WaylandSurface = ui.WaylandSurface
161
162// OnSurface runs fn once after the surface role is configured and before the
163// first buffer; an error aborts Run.
164func OnSurface(fn func(context.Context, WaylandSurface) error) WindowOption { return ui.OnSurface(fn) }
165
166// Wake requests a redraw for each value received on ch.
167func Wake(ch <-chan struct{}) WindowOption { return ui.Wake(ch) }
168
169// Run builds and presents an immediate view on the Wayland session owner loop.
170func Run[T any](ctx context.Context, model *T, view func(*Frame, *T), options ...WindowOption) error {
171 return ui.Run(ctx, model, view, options...)
172}
173
174// RunFrames is a deterministic harness entry: each commit requests a redraw
175// and the loop stops after the given number of committed frames.
176func RunFrames[T any](ctx context.Context, frames int, model *T, view func(*Frame, *T), committed func(uint64) error, options ...WindowOption) error {
177 return ui.RunFrames(ctx, frames, model, view, committed, options...)
178}
179
180// Session lock. RunLock acquires ext-session-lock, covers every output with
181// opaque black through the normal Vulkan/DMA-BUF/explicit-sync path and hosts
182// the caller's view on one output. See docs/session-lock.md.
183type (
184 LockConfig = ui.LockConfig
185 LockState = ui.LockState
186 LockStatus = ui.LockStatus
187 SecretBuffer = ui.SecretBuffer
188)
189
190const (
191 LockIdle = ui.LockIdle
192 LockBusy = ui.LockBusy
193 LockFailed = ui.LockFailed
194)
195
196// ErrLockFinished reports that the compositor refused or ended the lock.
197var ErrLockFinished = ui.ErrLockFinished
198
199// NewSecretBuffer allocates a caller-owned secret input buffer (1..4096 bytes).
200func NewSecretBuffer(capacity int) *SecretBuffer { return ui.NewSecretBuffer(capacity) }
201
202// RunLock runs a session lock until an unlock requested on LockConfig.Unlock,
203// a failure, or cancellation. It never unlocks on failure or cancellation.
204func RunLock(ctx context.Context, cfg LockConfig) error { return ui.RunLock(ctx, cfg) }