Skip to main content

Crate kui_native

Crate kui_native 

Source
Expand description

Batteries-included runner: winit windows + wgpu renderers around one kui_core::Core per window, driving the Elm-ish loop — input becomes UiEvents routed to App::on_event (host) or extensions by origin, then App::view rebuilds each window’s frame.

One event loop, any number of windows (docs/adr/0004-multi-window.md). The launcher opens the main window; a frame that declares another (Ui::window) has the core queue a WindowCommand::Open, and the runner opens it as a [Pane] — a window, its surface, its Core and the per-window input state — on the same Session and the same GPU device. App::view runs once per pane per frame, with Ui::window_name saying which; events carry the pane’s WindowId.

Re-exports§

pub use wgpu;

Modules§

access
Accessibility as data (see docs/adr/0001-accessibility-as-data.md).
anim
Transitions: retained tweens keyed by node identity. A node that declares NodeSpec::transition has its animatable spec values (sizing amounts, colors, radius, opacity, shadow) eased from whatever they were last frame toward what the view declares this frame — the inputs to layout animate, so a subtree lays out consistently every frame instead of children snapping to a target size inside a still-moving parent.
atlas
CPU-side glyph atlas: a single RGBA page with shelf packing. Renderers mirror it to a texture; dirty/epoch tell them when to re-upload.
audio
The audio device behind the core’s AudioCommands. The core queues commands as data (Core::take_audio_commands); the shell hands them here after every input dispatch and every frame, and polls finished playbacks back into the core (Core::audio_ended) so tagged ones become sound events. It answers the other way too: a Stop whose handle was still playing goes back as Core::audio_truncated, since whether a sound was still running is the one thing the core cannot see, and a play the device refuses goes back as Core::audio_refused: it never starts and so never ends, so the view has to hear about it or wait forever.
calc
Size expressions (backlog F109): CSS’s min(), max() and clamp() over lengths and percentages, resolved by layout against the parent’s content box — the same box a Percent sizing takes its cut of.
cells
A cell grid: what a terminal draws (backlog C20). One node holds rows × cols cells — a character, a foreground, a background, a few attribute bits — and its emission is a table walk: a glyph is looked up by character and style variant in a cache that was filled by shaping that one character once, placed at col × cell_w, and never shaped again. So a pane whose every cell is new every frame costs the same as one that never changes, which is the property the text runs a terminal could otherwise be built from do not have (see benches/stream.rs).
color
cursor
Pointer shape as declared data. A view says what the pointer is over a node with the cursor prop — a button is a hand because it declared one, a handle a grab because it declared one — and the core resolves which declaration is under the pointer per frame (crate::runtime::Core::cursor_shape), which the frame driver hands to the real window. Nothing is inferred from what a node does: an on_click node with no cursor is the plain arrow, as a native button is, and so is an on_drag node. The one shape the core implies is the I-beam over an editor or a selection scope, the way every desktop marks text that can be taken. The stock button declares Pointer for itself, so <button> is a hand in every binding without the app saying so.
deco
Decoration lines that are not a rect (backlog K4): the wavy and dotted underlines a text, a span or a cell asks for. A solid line is one Solid quad, as it always was; these are runs of QuadKind::Segment — the capsule the backend already draws for a line node (ADR 0010) — so no backend, header or protocol learns a kind. A wave is a zigzag of short pieces whose round caps soften the corners; a dotted line is a row of zero-length pieces, which the capsule SDF draws as dots. Both are sized from the stroke the face recommends, so they scale with the text and the display.
depart
Exit transitions: a subtree the view stopped declaring, kept as a picture and played out.
diag
Diagnostics as data. The misconfigurations that fail silently — a grow weight with nothing to split against, a transition on a positional key under a sibling list that changes, two nodes sharing one key — all look like “the feature is broken” from the outside. The core can see them, so it reports them the way it reports everything else: as plain data a driver drains (crate::Core::take_warnings). The windowed runners print them; a headless test asserts on them, or on their absence.
dialog
File dialogs as an ask (backlog C51): the app asks for an Open, a Save or a folder, the host shows the platform’s own dialog, and the answer comes back as one event — {kind:"files", paths, tag}, the payload shape a drop zone’s drop carries (ADR 0031), paths empty for a dialog the user cancelled.
display
The renderer boundary: a flat list of quads in physical pixels. A backend needs exactly two abilities — draw these quads, and mirror the glyph atlas to a texture. Everything else (layout, shaping, styling) happened already.
edit
Editable text: retained editor state keyed by widget Key, built on cosmic-text’s Editor so cursor motion, selection, and click-to-position all come from the same shaping truth the rest of the text stack uses. Edits arrive as data (InputEvent::Text / InputEvent::Key) routed to the focused editor; hosts read text back with Core::edit_text.
enter
Entrance transitions: where a node’s animatable slots start from the first frame it is seen. A transition never animates in from nowhere — a node’s first sight snaps, so a view that wants a slide-in used to draw the node off screen for a frame and move it on the next. NodeSpec::enter states that starting point as data instead: on first sight the slots it names (dx/dy for the laid-out position, plus width, height, bg and radius in the forms the props themselves take) start there and ease to what the view declares, on the node’s transition.
env
Host environment facts pushed into the core by the frame driver — the inbound mirror of events-as-data. The core never touches a window; the driver (runner, FFI host) reports what it knows and views read it.
event
Typed readings of the core’s own event payloads (backlog DX7).
fragment
A fragment: WGSL an app registers, validated here so a frame never sees a source that cannot compile (docs/adr/0015-a-fragment-element-and-the-painter-it-is-not.md).
geom
input
Input handling and event production. Hit regions come from the previous frame’s layout (the standard immediate-mode trade); events leave as plain data tagged with the origin that declared them, so the runner can route to the host app or an extension without knowing what either looks like.
key
Stable widget identity. Keys are content-addressed hashes of the path from the root (scope keys mixed with labels or sibling indices), so the same logical widget gets the same key every frame — and scripts can reproduce a key from strings alone, with no allocation event tying identity to a slot.
keyframes
Keyframes: CSS @keyframes for a node’s animatable slots. A node with NodeSpec::keyframes cycles those slots through the stops over its transition’s duration, in the transition’s repeat direction, held back by its delay_ms — CSS’s animation-* family on a kui node.
layout
Clay-style flex layout over the flat tree, five passes:
line
Strokes: what a line node draws (docs/adr/0010-a-segment-primitive.md).
menu
Context menus as data: what an item is, what the window has open, and what a host has to do about the items the core cannot finish on its own (docs/adr/0017-selection-as-a-scope.md, decision 5).
message
Typed messages over the plain-data payload (backlog C50).
metrics
The sizes the stock widgets are built from, as one struct beside the palette (backlog T2, the axis ADR 0019 scoped itself out of).
resources
Long-lived, host-registered resources. Slotmap keys give typed handles with generational use-after-free protection, and convert to/from u64 (KeyData::as_ffi) so they cross the scripting boundary as plain integers with the generation check intact on the way back.
runtime
The Core: one window. It owns everything that survives across frames and belongs to this window alone (interaction state, scroll and edit stores, focus) plus the reusable per-frame tree — and the frame-builder state itself. Builder state living here (not in a borrowing wrapper) is what lets flat C bindings drive a frame through one opaque pointer; the Rust Ui is a thin safe façade.
schema
The prop schema: the single source of truth for the per-node surface every frontend lowers into. One PROPS row declares a prop’s name, wire id, value kind, apply function, and doc — and every binding interprets that row instead of restating it:
scroll
Retained scroll state: offsets keyed by widget Key, surviving the per-frame tree rebuild. The layout pass clamps each offset to the current content overflow, so state stays valid as content changes — and, at the same moment, records the geometry it clamped against, which is the only copy of it that outlives the frame (Core::scroll_geometry).
select
The window’s text selection outside an editor: what a selectable node scopes, what a press-drag across it produces, and what a copy reads (docs/adr/0017-selection-as-a-scope.md).
session
What a window does not own alone.
slider
A slider’s arithmetic (docs/adr/0034-stock-controls-over-the-roles.md, decision 4): what value a pointer position, an arrow, a Page key or Home / End means on a node whose role is Slider and that declared on_change. Every slider that followed the pointer did the first half of this in the app and every one that answered the keyboard did the second; none in this repo did both.
slot
Slots: the place a host declares in its own view for an extension to fill, with parameters in and replies out (docs/adr/0014-slots-an-extension-fills-in-place.md).
slots
The animatable slots an entrance or a keyframe stop may name — width, height, bg, radius, opacity — as one value. crate::enter::Enter (where a node starts on first sight) and crate::keyframes::Keyframe (a stop in a cycle) are this plus one field each; before this module the five slots were two structs with the same builders and the same parse arms, and every consumer packed them into a tween’s four lanes by hand. A sixth animatable slot is one field here, one arm in parse_field, one case in lanes — and nothing in the two structs that carry it.
spec
Node configuration: plain data, trivially constructible from any language.
stats
Frame timing samples for the latency graph. The core only stores data — whoever drives the frame loop (the runner, an FFI host) measures and pushes; widgets::latency_graph renders it with ordinary primitives.
testing
A headless driver for an App (backlog DX11). A headless driver for an App: a Core, a viewport, the app’s extensions, and the inputs a test needs to press its keys, click its nodes and read what it drew — through the real view and on_event, with no window (backlog DX11).
text
Core-owned text stack. Shaping and line layout run through cosmic-text and are cached across frames keyed by (content, style, scale) — the layout pass measures through this cache, so shaping survives resizes and static text costs a hash lookup per frame. Rasterization feeds the shared glyph atlas; renderers only ever see positioned atlas quads.
theme
The named colours a view paints with, derived from what the OS said — docs/adr/0019-a-theme-derived-from-appearance-and-accent.md.
tokens
Tokens: named colours and lengths an app declares beside the theme and the metrics, and references a colour or length prop by name (docs/adr/0027-tokens-beside-the-theme.md).
tree
Per-frame UI tree: flat arrays rebuilt every frame, capacities retained. Nodes are stored in DFS preorder (a parent always precedes its children, and preorder equals paint order), linked via first_child/next_sibling.
ui
The Rust frame builder: a thin safe façade over Core’s flat builder methods (which are also the FFI surface). It never captures user state, so view(&state) and update(&mut state) can’t conflict.
value
Dynamic values: the payload type for events crossing the host/extension boundary. Everything in the IR that scripts can produce or consume is expressible as a Value.
widgets
Opinionated helpers composed purely from primitives — the pattern custom widgets should follow (composition over traits, state by key), which is what keeps them reachable from scripting frontends.
window
Windows as data. A node can declare a chrome role (drag handle, close/minimize/maximize button); interacting with it produces WindowCommands that the frame driver drains and applies to the real window. A frame can declare that a window exists (Core::declare_window, docs/adr/0004-multi-window.md): the core diffs the declared set and the same queue carries the WindowCommand::Open / WindowCommand::Close the diff produces. A declared window is a WindowKind::Normal one or a WindowKind::Popup — borderless, owned, anchored, non-activating — and a driver reports a popup dismissed the way it reports one closed (DismissReason). Host window facts flow back in through WindowEnv on Env. The core never touches a window — headless drivers just never drain.

Structs§

Accel
A keyboard shortcut, parsed out of the string an item declares.
AccessNode
One semantic node of a frame.
AccessRequest
A request from assistive technology, delivered as crate::InputEvent::Access.
AccessRun
One visual line (or a piece of one) of an editor’s text, with what a screen reader needs to read it by character and word and to place a caret: every character’s byte length, x position and width. A line that continues into another ends with its "\n", counted as a character of zero width. Runs longer than RUN_CHARS characters are split, so indices fit the platform’s byte-sized ones.
AccessTree
The semantic nodes of a finished frame, in tree order (a parent always precedes its descendants; the root comes first).
Announcement
One thing to say once, with no node behind it: “Saved”, “3 results”. Queued by Core::announce and drained by Core::take_announcements, the way window commands, audio commands and warnings are — an announcement is an event on a timeline, and the frame’s tree has no place to keep one (see docs/adr/0008-live-regions-and-announcements.md).
AudioEnv
What the driver’s audio output is doing, for views to read. A fact, not a verb: nothing here lets a view close the device, which stays the driver’s decision (it closes an idle one itself, after a while).
AudioSpec
What an audio node declares each frame (Core::audio_node).
AudioStore
Playback bookkeeping on the session: the command queue, the tagged playbacks awaiting their ended event, and the audio nodes’ retained playbacks. The queue and the ids are the session’s, because the process has one device; the mounts are keyed by window as well as by node, because each is reconciled against one window’s frame (finish_frame hands in the window it finished, and only that window’s slice is diffed).
BarMenu
One menu of the bar: what the bar reads, and what drops out of it.
Bounce
How far a spring overshoots, 0 (glides in, no overshoot) to MAX_BOUNCE (rings a while): the one number that shapes a spring besides its duration. A bounce b is a damping ratio of 1 - b (SwiftUI’s Spring(duration:bounce:)).
ButtonEvent
A {kind:"button"} event: a non-primary button an onButton node claimed, captured by it from press to release (backlog F105).
Buttons
Which of the non-primary buttons a node’s on_button claims (backlog F105): Buttons::SECONDARY, Buttons::MIDDLE and Buttons::OTHER (every button past the named three), or-ed together. A node declaring on_button claims Buttons::ALL unless it says otherwise. The primary button is never in it: that one presses, drags and clicks for every node.
Calc
An expression that depends on the room, by its place in the table. Copy, so a Sizing holding one still is.
Cell
One cell: a character, its colours as 0xRRGGBBAA (a background of 0 is none, an underline colour of 0 the foreground’s), and attribute bits. Sixteen bytes, so a 200×50 pane is a 160 KB slice a frame.
CellEnd
One end of a selection in a cell grid: an absolute line (the grid’s origin_line plus the row) and a column. Absolute because a grid is one screenful of an app’s own history, so a row number means a different line after every scroll (ADR 0017, decision 4).
CellGrid
A grid to draw: the cells in row-major order (rows × cols of them; fewer draw as blank), the style the glyphs are shaped in (size, line_height as the cell height, family / font), and the cursor.
CellSelection
A selection inside one cells grid.
CellStore
The frame’s grids and the glyph tables they draw from. The frame before it is kept too, the way the text store keeps its places: a host that reads the selection from inside its own view is asking about a frame that has not been built yet.
CellsId
Index into the frame’s grid list.
Clip
The clip a node inherits: a rect, and the radii to round its corners by.
ClipboardMarks
What the pasteboard said about the text a paste brought back (backlog F84): the markers password managers set on a copied secret, after the convention at nspasteboard.org that 1Password, Bitwarden, KeePassXC and the macOS clipboard managers follow. Read by the driver, which owns the clipboard, and handed over with the text as InputEvent::Paste.
Color
Core
DepartStore
The departing subtrees, bounded (see MAX_NODES).
DisplayList
Drag
A {kind:"drag"} event: an onDrag node’s pointer capture.
Edges
Per-side lengths: padding, borders.
EditOptions
Endpoint
Enter
Where a node’s slots start on first sight. Every field is optional: a slot enter doesn’t name simply snaps as it always did. Derefs to its Slots, so enter.bg reads the slot.
Env
What the host knows about the display/window. Defaults are safe for headless drivers (tests, benches) that never set anything.
Extensions
The runner’s extensions, each under the namespace the host gave it. Origins are positions here: the host is OriginId::HOST and the extension at index i is OriginId(i + 1), which is what an event’s origin indexes back into.
FileDialog
An Open, Save or folder dialog, as an app asks for one.
FileFilter
One entry of a dialog’s file-type menu: Images over png, jpg. Extensions are without the dot.
FloatConfig
Takes a node out of flex flow: it doesn’t consume space in its parent, sizes Grow/Percent against its anchor, is positioned by attach points, and escapes ancestor clips unless FloatConfig::clip keeps it in its parent’s. It paints as a layer of its own — above the in-flow tree and every float that opened before it, under every one that opened after — and takes input in the same order (docs/adr/0023-layers-stack-in-the-order-they-open.md).
FontFeatures
The OpenType features a style asks the shaper for (backlog C23): up to FontFeatures::MAX four-letter tags with a value each — liga 0 to keep a coding font from joining ->, tnum 1 for tabular figures in a gutter, ss01 1 for a stylistic set. Plain data and Copy, since a TextStyle is; the spelling every binding shares is FontFeatures::parse’s.
FontId
A registered font (Core::add_font_data / add_system_font), used through TextStyle::font.
FragmentDraw
What a QuadKind::Fragment quad points at: which registered WGSL paints it, and the sixteen numbers that frame passes it.
FragmentDrawId
Where a node’s Draw lives in the frame’s FragmentList.
FragmentId
A registered WGSL fragment function (Core::add_fragment), drawn by a fragment node (docs/adr/0015-a-fragment-element-and-the-painter-it-is-not.md).
FragmentList
The frame’s fragment draws, one per fragment node, indexed by the FragmentDrawId the node’s NodeContent carries.
FragmentRef
What a fragment node names: the function, and the image it reads through kui_sample if it declared one (backlog V1, ADR 0025 decision 7). Every fragment door takes impl Into<FragmentRef>, so a bare FragmentId is the no-image form and id.with_image(img) the other; nothing else about the node changes.
FrameCause
Why a frame was drawn: every reason that reached the window between the start of the last frame and the start of this one (backlog F111). Read from a view as Core::frame_cause. A set, because a frame answers everything that asked since the last one — a keystroke and the caret’s blink, a wheel and the transition it started.
FrameHolder
One thing that holds an owed frame, named for a person: see OwedBy.
FrameRequest
Where a frame was asked for: a Core::request_frame call, or one the core makes for itself.
FrameSample
One frame’s cost in milliseconds, split by phase.
FrameStats
Fixed-size ring of recent frame samples, and the count of every frame ever pushed through it.
Handles
How a binding spells the handles inside a readback — a node key, a resource id — when a shape crosses as a Value (backlog AR1). The shape is the core’s; the spelling of a 64-bit handle is not, because a JS number cannot hold one and a Lua integer can: Node writes sixteen hex digits, the way its key/font/sound arguments already read, and Lua writes the integer its key arguments already are. C reads the structs and never sees a Value.
Hover
A {kind:"hover"} event: an onHover node entered or left.
ImageId
ImageOpts
How an image node meets the pixels it shows — the two per-node rows ADR 0025 decision 4 gives it. Carried on the node’s content rather than on NodeSpec, so a box pays nothing for a row only an image reads.
Key
KeyLocks
What the lock keys hold at a press: Caps Lock and Num Lock on or off. Not a modifier held — KeyMods is only what is down, which accelerators and chords compare exactly — but state a press was made under, which a terminal speaking kitty’s keyboard protocol reports and a keypad reading needs (its 1 is an End with Num Lock off).
KeyMods
Physical modifier state. Unlike Mods — which abstracts platform conventions for the input widget (word, doc) — nothing here is normalized: an app binding Ctrl-w needs to know it was Control and not Command.
KeyPress
One key press, delivered to whatever holds key focus. Carries both the binding view (code + mods) and the typing view (text), so an app can serve a modal keymap and an insert mode from the same event.
Keyframe
One stop. Every field is optional: at resolves by position, and a slot a stop doesn’t name is left to its neighbours. Derefs to its Slots, so stop.bg reads the slot.
Launcher
Layout
A {kind:"layout"} event: an onLayout node’s placed rect.
LineId
Index into the frame’s line list.
LineStore
The frame’s strokes, and the previous frame’s while an exit needs it.
Locale
A language tag as the host reports it — "en", "en-US", "zh-Hans-CN". Carried inline rather than as a String so Env stays Copy: a view reads ui.env() every frame, and a tag that allocated would allocate on every one of them.
Menu
The menu a window has open: its items, where it opened, and what it is about. One per window — opening a second closes the first, the way one selection closes the last.
MenuBar
The application menu: what a frame declares, in order (Core::declare_menu_bar).
MenuItem
One row of a menu.
Metrics
The sizes the stock widgets are built from. Plain data and Copy: a view reads it off ui.metrics() and may keep or change its own copy, and Core::set_metrics makes one the frame’s.
Min
A lower clamp on one axis: a number of logical px, or the node’s own fit size on that axis (minWidth: "fit", Min::FIT). FIT is what lets a Grow child keep a content floor — CSS’s flex: 1 0 auto: the tabs of an i3-style bar split the bar evenly while they fit and sit at their label’s width, scrolling, once they do not. Layout resolves it to a number in the fit pass of its axis (layout::fit_widths / fit_heights), so every later clamp reads one; until then it clamps like no floor at all.
Mods
Modifier state for editing keys. word is Alt/Option (word-wise motion), doc is the platform primary modifier (line/document-wise motion).
NameRefs
A lookup plus the names it could not answer — the shape every by-name lowering wants (Lua’s props, a keyframe stop or an entrance in any binding, since those cross as plain data with the name still in them), so the one miss policy (ADR 0027 decision 4, backlog AR14) is written once: a $name that resolves to nothing, or to the other kind, is None — the slot is left at the row’s default, the way the prop would be if it were not declared — and the miss is remembered for the caller to raise as unknown-token once the lookup’s borrow of the core is handed back (Core::warn_unknown_token).
NodeInfo
One node of the last finished frame.
NodeSpec
Full per-node configuration. This — not any Rust trait — is the contract every frontend (Rust builders, Lua, serialized UI) lowers into.
OpRange
Where a derived token’s steps are in Tokens’ chain: the table owns the ops, so the token stays Copy.
OriginId
Which frontend produced a node: 0 is the host app, extensions get 1+.
Owed
What a frame left owed, by kind: Core::owed. any() is what Core::animating answers; beyond_cycles() is the same with a keyframe cycle — which never ends — left out (backlog F64).
OwedBy
Who holds the frame the last one left owed: Core::owed, named (backlog F111). Each list is empty when its kind in crate::Owed is false, and names what made it true when it is.
PadShorthand
The pad shorthand family as declared — any subset of the seven names, each None when the frontend did not see it. PadShorthand::resolve decides what a missing edge falls back to; a binding only reports what it found.
PlayOptions
How to start a playback (Core::play).
PlaybackId
One playback instance. Allocated by the core when the play command is queued, so callers get it synchronously without a driver round trip; 0 is never issued.
PumpRunner
A windowed runner driven from outside: same [Shell] as Launcher::run (input mapping, IME, clipboard, chrome, caret blink), but the host calls pump on its own cadence instead of parking in run_app.
Quad
RangeEnd
One end of the range an app is asked to fill in (Core::selection_range): the data index of the row it is in, and the byte inside that row’s own text. An end outside every virtualised row has no index — it is text the core built and can answer for itself.
Rect
Renderer
Resources
One session’s registry. The maps are secondary to the process-wide [Mint] (see the module doc), so a lookup that misses is a handle this session never registered or has since removed — never somebody else’s entry.
Scroll
A {kind:"scroll"} event: the wheel over an onScroll node.
ScrollGeometry
What the last layout resolved for a scroll container: where the container landed, how big its content came out, and the offset it clamped. All logical px, in the same viewport coordinates on_layout reports.
ScrollState
A scroll view’s offsets and range (logical px).
Scrollbar
A scrolling node’s bars, per node. Every field’s default is the stock bar — the theme’s scrollbar / scrollbar_active colours, 4 px at rest and 6 px under the pointer, always drawn while the content overflows — so a binding that sets none of the four rows gets exactly what it always had. The bars are overlays and take no layout space whatever their width; the grabbable track is at least as wide as the active thumb plus its inset.
Selection
The window’s selection: a scope and two ends of it. anchor is where the press landed and focus is where the pointer is now, so the pair is directed — dragging back past the anchor selects the other way without the two swapping, which is what keeps a drag from feeling like it jumps when it crosses its own start.
Session
The font database, registries and audio store a set of windows share. Cloning one clones the handle, not the contents: that is how a second Core joins (Core::new_in(&session)).
SessionId
Which Session a registry — and so every handle it minted — belongs to. Process-wide unique, from a counter; never serialized, so the number means nothing across runs and is only ever compared or printed.
Shadow
One outer drop shadow: the node’s rounded rect, moved by dx/dy, grown by spread and its edge blurred over blur, painted in color behind the node. CSS’s box-shadow without the inset and multi-shadow forms.
SharedAudio
A window’s handle to the session’s audio store — Core‘s audio field. The process has one audio device, so the playbacks and the command queue are the session’s and not this window’s: whichever window’s driver drains the queue applies every window’s sounds. The audio nodes’ mounts are per window inside it (see the module doc), which is why the readers here take one.
SharedResources
A window’s handle to the session’s resource registry — Core’s resources field. A font, image or sound registered through one is registered for every window in the session, and draws in all of them.
Size
Slot
Which slot an extension is filling, handed to Extension::view.
SoundId
A registered sound (Core::add_sound): encoded file bytes the driver’s audio backend decodes. Played through Core::play, an audio node, or NodeSpec::click_sound / hover_sound.
Span
One styled run inside a rich-text paragraph. Spans are shaped and wrapped together as a single flow; plain data, so every frontend can build them.
Stroke
How a line is drawn: a width, a colour, and whether the points are the corners of a polyline or the knots of a curve through them.
SystemEnv
The user’s OS settings, as the host reports them. Not window facts and not display facts: things the person chose once, in a settings app, that a view is expected to honour. The core acts on two of them in one way: appearance and accent derive the theme (ADR 0019), so the stock widgets and a <text> with no colour follow the OS — and nothing else moves. Reduced motion does not shorten an animation and a dark appearance repaints none of the app’s own colours: the view decides, because only it knows which of its colours is the background and which of its animations carries meaning.
SystemFont
One family of the font database — installed or loaded — as its faces describe it, from what the database read off each face’s tables when it was scanned: nothing is loaded or shaped to answer (backlog F97). What Core::system_fonts lists, one per family.
TextHit
Where a point landed in the text a keyed node drew: a byte offset and the visual row it is on. byte is a caret position: between two characters, past the last one at the end, and cosmic-text’s rule for which side of a glyph the point fell on. For a node holding several text runs the offset runs across them in tree order, the way the access tree reads a line. line is the visual row within the node, 0-based, counted across every run the key covers by where the rows sit: a line row of three inline runs is one row, a run that wrapped is as many as it wrapped to, and two runs stacked are two — not the wrapped line within one run’s buffer, which is what it was until backlog AR30, and not the ordinal role="line" node a pointer event’s line names (that one counts rows of the editor, this one rows of the text asked about).
TextInput
A {kind:"text"} event: what a focused key sink or editor was given to insert.
TextMetrics
What a piece of text measures, in logical px at the current scale — the same numbers layout uses for a text node with that content and style, so a view can size a column to its widest label or pick a tier that fits without hand-tuned magic numbers.
TextPos
A position in an editor’s text: a run and a character index into it (character == char count is the end of the run).
TextStyle
Theme
Every colour the stock widgets and the core’s own chrome paint with, as roles rather than values. Plain data and Copy: a view reads it off ui.theme() and may keep, mutate or replace its own copy.
TokenLookup
A frame’s view of the tokens a lowering can reference: the running origin’s table over the host’s, and the roles in front of both. Borrowed from the core for the length of a lowering (crate::Core::token_lookup).
Tokens
One origin’s declared tokens, in declaration order. Built with the chaining constructors and handed to crate::Core::set_tokens whole; each call replaces the caller’s table.
Transition
How a node’s animatable values move when the view changes them.
Ui
UiEvent
An event produced by the UI, ready for routing.
Unresolved
Why a derived token was dropped at declaration: the name it was given and the source or operand that resolved to no colour token declared before it and no theme role.
Vec2
Vec2Offset
Plain offset pair (kept separate from geometry to stay Copy + FFI-flat).
Waker
A handle into the event loop that any thread may hold: wake asks for a frame from wherever the app’s data arrived. Cheap to clone, and harmless after the loop has ended (a wake nobody hears is dropped).
Warning
A silent misconfiguration the core noticed while finishing a frame.
WindowConfig
What a frame says about a window it declares (Core::declare_window). Plain data by ADR 0004 decision 5 — no title, no callbacks — so a WindowCommand stays Copy and equality is derived, which is how the diff tells two declarations of one name apart.
WindowEnv
What the host knows about its window, pushed into Env by the frame driver. Views (e.g. widgets::titlebar) read this to adapt: reserve space for native controls, pick the maximize/restore glyph, or render nothing at all under native decorations.
WindowId
Which OS window something belongs to: an opaque integer the core’s declaration diff assigns when it opens a window, not a handle an app builds. WindowId::MAIN is 0 — the window the launcher opens, which is always live. Apps name windows with a stable string (Core::declare_window); the id is how the driver and the events refer to the surface that string opened.

Enums§

AccessAction
What assistive technology can ask of a node. Each node advertises the subset it supports (AccessNode::actions), and a request for one arrives as crate::InputEvent::Access.
Align
Where children sit along an axis, and where a float attaches.
Appearance
The OS light/dark setting. Unknown is a real answer — a host with no way to ask says it, and a view that has one palette per appearance picks its own default for it rather than being handed a guess.
Assistive
Whether assistive technology is listening: the difference between an alert that blinks and one that announces (backlog F48). Listening is “an accessibility client has asked this window for its tree”, which is the one signal the platform adapters give and the moment the runner starts deriving trees (ADR 0016 measures its cache from there). None is “the bridge is up and nobody has asked”; Unknown is “there is no bridge” — a headless core, a driver built without the accesskit feature, a C host that never called the setter.
AudioCommand
An audio intent for the frame driver. Durations are ms; volumes are linear amplitude. Drivers ignore playbacks they no longer hold.
AudioDevice
The output device’s state. Closed is the default and what a headless driver reports; Opening is the ~90 ms the open takes on its own thread; Failed is a device that refused to open, after which commands are dropped.
Bound
What a minWidth / maxWidth / minHeight / maxHeight declares: px, the node’s own fit size (a min only), or a size expression that layout resolves against the parent’s content box when it sizes the node (backlog F109). Until then a calc bound clamps like none, as a percentage clamp does in CSS’s intrinsic sizing.
ButtonPhase
Which part of a held non-primary button an event reports (backlog F105).
CellCursor
How the grid’s cursor is drawn, in the colour given with it.
Chrome
Who draws the window chrome.
ColorOp
One step of a derived token’s recipe, as declared: a verb and its operands, a colour named by its token or role. Each is a method the core already paints with — lift and darken are Color::mix toward white and black, raise is Theme::raise (toward the front of whichever base is in effect), alpha is Color::with_alpha, mix is Color::mix toward another token, and readable is Color::toward_contrast toward black or white — whichever reads on the named colour — until it clears the ratio on it.
ColorToken
A colour token: one value per base, or a recipe over an earlier token or a theme role (ADR 0028). ColorToken::same is the unthemed case, and what a declaration with one colour builds; a derived one is built by Tokens::derive, since its source is an index into the table that holds it.
Content
What a node opened through Core::open_from holds: a box (left open for its children), a fragment (likewise), a cells grid or a stroke (leaves, closed by the door).
CopyRequest
What asking for a copy answered (Core::request_copy).
CursorShape
The shape the pointer takes. Spelled the way CSS and the platform toolkits do, so a driver maps it one-to-one (winit’s CursorIcon, the Web’s cursor, GTK’s names) instead of interpreting it.
DevtoolsDock
Where the panel sits. The header has a button per placement, and Ctrl+Shift+D walks them in Dock::ALL’s order.
Dir
DismissReason
Why a window was asked to go away (Core::dismiss_window): the same two reasons ADR 0003 gave a modal node, one level up.
DragPhase
Which part of a drag an event reports.
Easing
Easing curve for a Transition.
EditKey
Editing keys, decoupled from any windowing library’s key codes.
FileDialogMode
What a dialog picks.
FloatAnchor
What a floating node is positioned against.
FontFamily
FragmentImage
Where a fragment’s image row lands for one frame: nowhere, in the glyph atlas the fragment pipeline already has bound, or in a texture of the image’s own that the backend binds in the atlas’s place for that one quad — the same swap a QuadKind::Texture quad asks for. The core decides between the last two on the image’s backing, so a backend meets the same two cases it already draws.
Grain
What a drag-select moves by. A press sets it from the click count the driver counted, the way every text UI does: one click drags by characters, two by words, three by whole runs.
HoverBy
What moved to change the hover (backlog DX20).
HoverPhase
Which half of a hover an event reports.
ImageBacking
Where a registered image’s pixels are kept for drawing (docs/adr/0025-the-image-is-the-canvas.md, decision 2). The core decides on the two facts that matter — whether the image fits an atlas page, and whether its pixels were ever replaced — and the app never chooses.
ImageFit
The fit row: how the pixels meet the node’s box. The box itself — its layout, its hit region, its access rect — is the same in every mode; only what is painted inside it moves.
InputEvent
KeyCode
A physical key press: the full keyboard, decoupled from any windowing library. EditKey is the input widget’s closed navigation vocabulary; this is what apps that own their own text model bind against — an editor with modal keymaps, a game, a scripted panel.
KeyLocation
Where on the keyboard a key sits, for the keys that have twins: the left or right Shift, Ctrl, Alt or Super, and the keypad’s digits, operators, Enter and (with Num Lock off) arrows beside the main block’s. Everything else is Standard. code stays what the key is — the keypad’s 1 is Char('1'), its Enter is Enter — so a keymap that does not care reads nothing new, and one that does (a terminal speaking kitty’s keyboard protocol, a game) reads this.
KeyPhase
Which half of a key’s life an event reports. Both halves arrive as one {kind="key"} payload — the way a drag’s three phases and a hover’s two do — so an app binds one handler and matches phase.
LayoutScript
Which alphabet the layout a press was typed on writes, as the platform answers it: what decides whose ASCII a keymap matches (backlog F115).
Live
How urgently a reader should read a change it was not asked to read: ARIA’s aria-live, AccessKit’s Live. Declared on the node holding the text (live prop) and, for a one-off with no node behind it, the politeness of a Announcement. See docs/adr/0008-live-regions-and-announcements.md.
MenuAction
What choosing an item leaves for the host to do, drained with crate::runtime::Core::take_menu_actions the way window and audio commands are.
MenuRole
What an item means, as far as anything outside the app is concerned.
MessageError
Why a payload is not the message it was read as.
MotionPref
The OS reduce-motion setting: Reduced is “the user asked for less animation”, Full is “the user did not”, Unknown is “nobody asked the OS”. Spelled as what the user wants rather than as a reduce_motion boolean because the third reading has no place in a boolean, and a missing answer is not the same as a “no”.
MouseButton
Which button a press came from — driver-facing rather than shaped after any one windowing library, so every driver maps its own vocabulary onto this one.
NodeKind
What kind of node a snapshot row is.
OptionAsAlt
Which Option keys act as Alt on macOS (backlog F113) — what a frame declares with crate::Ui::option_as_alt. On a Mac, Option composes: ⌥m types “µ”, and ⌥u, ⌥e, ⌥i, ⌥n and ⌥are *dead keys* that start an accent and wait for the next key, so the press never arrives as a key at all and a keymap that bindsnever hears it. An Option key named here is Alt instead: it composes nothing, types nothing, and every key under it arrives as a chord of the key the layout prints unmodified — what a terminal's "Option as Meta" and an editor's Alt bindings want.None, the default, is the Mac's own behaviour; one side leaves the other composing, so a user keeps ü` on the right Option while the left one is Alt. Other platforms have no such composition on Alt and read nothing here.
Orientation
How a container arranges its items, for the platform to announce (AXOrientation, UIA’s Orientation). Derived from the container’s dir and never declared: the layout is what arranges the items, so a row that says it is a column would be a fact with two owners (see docs/adr/0007-composite-keyboard-patterns.md, decision 7). It is an announcement and not a gate — the arrows move both ways whatever this says — so a container whose visual arrangement does not match its dir costs a less precise announcement rather than a dead keyboard.
Overscroll
What a scroll gesture that starts over a scroller already at its limit does (backlog F107) — CSS’s overscroll-behavior, spelled by the overscroll row (crate::schema::OVERSCROLLS, in this order).
QuadKind
RenderError
A frame that produced no image, mapped from CurrentSurfaceTexture.
Repeat
How keyframes cycle: CSS’s animation-direction, always infinite.
Role
What a node is to assistive technology. Most of these a view declares (role prop; schema::ROLES is that list, and the wire order); the ones the core derives from a node’s content and behaviour instead are schema::DERIVED_ONLY, which says what derives each. Every variant is on one list or the other — schema’s every_role_is_declarable_or_derived fails when a new one is on neither.
Sampling
The sampling row: how a backend reads texels between pixel centres.
ScrollAxes
Which axes an on_scroll node takes (backlog F107), spelled by the scrollAxes row (crate::schema::SCROLL_AXES, in this order).
ScrollAxis
ScrollbarMode
When a scrolling node’s bars are drawn. Spelled by the scrollbar row (crate::schema::SCROLLBARS, in this order).
SizeExpr
A parsed expression: lengths in logical px, percentages as fractions.
Sizing
TextAa
How outline glyphs are antialiased.
TextWrap
How a text node breaks lines at its width.
ThemeSource
Where a Core’s theme comes from, re-read at the start of every frame. Derived is the default.
TokenError
Why a name did not resolve.
TokenKind
What kind of value a token holds, and which prop slots it fits.
TokenRef
Where a name resolved to: a role, or an app token by index.
UnderlineStyle
The shape of an underline (backlog K4): the face’s line, a wave under a diagnostic, dots. Where it goes and how thick it is are the face’s recommendation either way; a wave is three strokes tall around the line’s centre with a six-stroke period, dots two strokes across and four apart (crate::deco).
Value
Why
Why a one-shot playback was cut off — what diag::TRUNCATED_PLAYBACK reports once the driver confirms the sound was still running.
WindowButton
WindowCommand
A window-level intent for the frame driver, drained via Core::take_window_commands after each input dispatch and each frame. Three things produce one: input on a chrome node, the declared set’s diff, and an app asking directly (Core::set_window_size, Core::focus_window, Core::push_window_command). A headless driver never drains, which is the whole of “the core never touches a window”.
WindowKind
What kind of OS surface a declared window is (docs/adr/0004-multi-window.md, decision 9).
WindowRole
Role a node plays in window chrome (set via NodeSpec::window_drag / NodeSpec::window_button). Chrome nodes never emit UiEvents — their interactions become WindowCommands for the driver instead.

Constants§

ANY_SLOT
Splits a full slot name at its last separator into (namespace, name); a name with none has the empty namespace. The one entry in Extension::slots that means “every name the host declares under my namespace”: for an extension that learns its slots after it loads. fill matches any declared name against it and finish has nothing to warn about for it (backlog K1).
DEFAULT_TEXT_CACHE_BYTES
The default byte budget for the shaped-text cache (backlog C16). Sized so a screenful of code never meets it — two panes of 55 highlighted lines are ~900 short entries, a few megabytes — and a pane streaming new text meets it within seconds, which is when the clock alone let the cache reach gigabytes. Core::set_text_cache_budget changes it.
FLOAT_PRESETS
The float preset names, in wire order: the index of a name here is what the binary protocol writes for it and what KUI_FLOAT_* counts from.
LONG_LINE_BYTES
A non-wrapping text at least this long is shaped in chunks (backlog C19): a minified bundle, a log line with a blob in it, a base64 field. Shorter text takes the path it always took, so nothing below the line moves. Bytes, not characters, for the same reason a step line carries integers: every binding can count them.
MAX_BOUNCE
The most bounce a spring takes: at 1 it would never settle, and past 0.9 it rings for seconds.
MAX_UNDECLARED_EDITS
How many undeclared editors the store keeps before the longest undeclared one is dropped (backlog F26). A declared editor is never evicted, however many there are: retention across absence is what the <edit> row promises, so this is a ceiling, not a prune.
MAX_UNDECLARED_SCROLLS
How many undeclared scroll entries the store keeps before the longest undeclared one is dropped (backlog F26). An entry a layout resolved in the frame that just ended is never evicted, however many there are.
NAMESPACE_SEPARATOR
What separates a namespace from a slot name in a full name. A namespace may contain it (the host chooses namespaces, and "left/fs" is a fine one); a slot name an extension lists may not, so a full name splits at its last one.
NO_CLIP
A clip that clips nothing.
NO_CLIP_ID
The entry every frame’s clip table starts with: Clip::NONE in physical pixels. Emission seeds it before any quad is made, so a quad that is clipped by nothing — most quads of most frames — names this without interning anything.
OVERFLOW_CLIP
overflow as bits: the C struct’s field, the binary wire’s payload and what the clip / scrollX / scrollY booleans OR together. One set of values so a binding cannot invent its own numbering.
OVERFLOW_SCROLL_X
OVERFLOW_SCROLL_Y
ROOT_SLOT
The reserved slot name an extension listing none fills.

Traits§

App
Extension
A frontend that draws into the shared tree each frame — the trait the runner uses to host Lua (or any other) extensions without knowing what they are. Origins are assigned by the runner.
Fill
What fills slots: the runner’s extension list, or a test’s stand-in. A frame begun with Core::frame_with carries one; Ui::slot calls Fill::fill at the position the host declared, and Ui::finish calls Fill::finish once the host’s view is done.
MessageField
A type a message field can hold: to a Value and back. Implemented for the numbers, bool, String, Value itself, Option (absent or null is None) and Vec; #[derive(Message)] implements it for the type it derives, so one message can carry another.

Functions§

app
Entry point: kui_native::app("title").custom_titlebar().run(my_app).
full_name
namespace/name, or name alone when the namespace is empty.
run
split_name

Type Aliases§

ClipId
An index into DisplayList::clips. Every quad has one; there is no “no clip” value, because a frame that clips nothing still names an entry — Clip::NONE scaled — and a backend that reads it needs no special case.

Derive Macros§

Message
#[derive(Message)] (backlog C50), with the derive feature; kui-native turns it on. From a crate that depends on kui-core alone, say #[message(crate = "kui_core")] — the generated code reaches ::kui unless told otherwise.