pub struct Core {
pub text: TextSystem,
pub cells: CellStore,
pub atlas: GlyphAtlas,
pub resources: SharedResources,
pub audio: SharedAudio,
pub interaction: Interaction,
pub scroll: ScrollStore,
pub edit: EditStore,
pub anim: AnimStore,
pub depart: DepartStore,
pub stats: FrameStats,
pub env: Env,
/* private fields */
}Expand description
One window’s runtime: the state a runner drives frame by frame.
Construct one with Core::new (a private Session) or
Core::new_in (joining a session another window shares). The public
fields are the stores a runner or a binding reads directly:
resources and audio for registration and playback commands, env
for the host facts a driver pushes, stats for frame timing.
§One frame, in order
Core::set_timewith the frame clock, so transitions advance.Core::framewith the viewport (logical px) and the scale. It begins the frame and returns theUibuilder; build the tree through it.Ui::finishruns layout and emission. The draw data is now inCore::output: theDisplayListand theGlyphAtlasa renderer mirrors to a texture.Core::take_pending_eventsdrains events the frame itself raised (aresize, a hover change under a still pointer); route them like any other.- Between frames, feed input through
Core::handle_input. Each call returns theUiEvents it resolved to, hit-tested against the frame that finished. Core::take_warningsfor misconfigurations the core noticed, andCore::animatingto decide whether to draw another frame without waiting for input.
A headless core needs no window or GPU, so a test can drive it:
use kui_core::{Color, Core, InputEvent, NodeSpec, QuadKind, Size, TextStyle, Vec2};
let mut core = Core::new();
// 1–3: a frame. `frame` begins it, `finish` lays it out and emits.
core.set_time(0.0);
let mut ui = core.frame(Size::new(400.0, 300.0), 1.0);
ui.with_keyed("toolbar", NodeSpec::row().pad(8.0).gap(8.0), |ui| {
// A clickable node needs an accessible name, or `take_warnings`
// reports `control-without-name`.
let button = NodeSpec::row().size(80.0, 32.0).bg(Color::hex(0x3366cc));
ui.leaf_keyed("save", button.on_click("save").label("Save"));
ui.text("Untitled", TextStyle::new(14.0));
});
ui.finish();
// 4: what the frame itself raised (nothing on a first frame).
assert!(core.take_pending_events().is_empty());
// The renderer's view of the frame: quads in physical pixels.
let (list, atlas) = core.output();
assert!(list.quads.iter().any(|q| q.kind == QuadKind::Solid));
atlas.dirty = false; // after uploading `atlas.pixels`
// 5: input, hit-tested against the frame that finished.
core.handle_input(InputEvent::CursorMoved(Vec2::new(20.0, 20.0)));
core.handle_input(InputEvent::mouse_down(1));
let events = core.handle_input(InputEvent::mouse_up());
assert_eq!(events.len(), 1);
assert_eq!(events[0].payload.as_str(), Some("save"));
// 6: diagnostics, and whether another frame is owed.
assert!(core.take_warnings().is_empty());
assert!(!core.animating());A windowed runner does the same with real time, real input and a
renderer consuming Core::output; kui-native is that runner.
Fields§
§text: TextSystemThis window’s shaped-text cache and rasterizer. Not the session’s:
its cache entries are stamped with atlas’s epoch, and TextId
indexes its per-frame list.
cells: CellStoreThe frame’s cell grids and their glyph tables.
atlas: GlyphAtlasThis window’s glyph atlas — the CPU side of its renderer’s texture,
handed out by output.
resources: SharedResourcesThe session’s resource registry. A font, image or sound registered through it is registered for every window in the session.
audio: SharedAudioThe session’s audio store: one device for the process, so playback bookkeeping and the command queue are shared, not per window.
interaction: Interaction§scroll: ScrollStore§edit: EditStore§anim: AnimStoreTransition tweens, keyed by node; see anim. Fed by set_time.
depart: DepartStoreSubtrees the view stopped declaring, played out and then dropped;
see depart. Empty unless something declares exit.
stats: FrameStatsFrame timing pushed by the frame driver; see widgets::latency_graph.
env: EnvHost facts pushed by the frame driver (refresh rate, focus).
Implementations§
Source§impl Core
impl Core
Sourcepub fn set_origin(&mut self, origin: OriginId)
pub fn set_origin(&mut self, origin: OriginId)
Tags subsequently created nodes with an origin (set by the runner before handing the frame to an extension).
Sourcepub fn configure_root(&mut self, spec: NodeSpec)
pub fn configure_root(&mut self, spec: NodeSpec)
Replaces the implicit root’s spec (e.g. to make the top level a row). Root sizing is resolved against the viewport regardless.
Sourcepub fn root_key(&self) -> Key
pub fn root_key(&self) -> Key
The root node’s key — for hover/press queries or set_key_focus when
the root itself declares the interaction (e.g. a root-level key sink).
Sourcepub fn child_key(&self, label: &str) -> Key
pub fn child_key(&self, label: &str) -> Key
The key a child labeled label would get — usable before creating it,
e.g. to check hover state for styling.
Sourcepub fn child_key_indexed(&self, i: u64) -> Key
pub fn child_key_indexed(&self, i: u64) -> Key
The key the ith child gets from auto-keying — what open_indexed
opens with, usable before the node exists.
pub fn is_hovered(&self, key: Key) -> bool
Sourcepub fn is_drop_target(&self, key: Key) -> bool
pub fn is_drop_target(&self, key: Key) -> bool
Whether files dragged in from the OS are over key.
Sourcepub fn drop_target(&self) -> Option<Key>
pub fn drop_target(&self) -> Option<Key>
The zone the dragged files are over, if any — what a driver answers the OS with.
pub fn is_pressed(&self, key: Key) -> bool
Sourcepub fn is_group_hovered(&self, group: u64) -> bool
pub fn is_group_hovered(&self, group: u64) -> bool
Whether any member of hover group group (see
NodeSpec::hover_group) is hovered.
Sourcepub fn is_group_pressed(&self, group: u64) -> bool
pub fn is_group_pressed(&self, group: u64) -> bool
Whether hover group group is pressed (press started on a member,
pointer still over one).
Sourcepub fn take_pending_events(&mut self) -> Vec<UiEvent>
pub fn take_pending_events(&mut self) -> Vec<UiEvent>
Events raised outside handle_input: the resize a changed
viewport produced at begin_frame, and on_hover enter/leave
caused by a finished frame changing what sits under a still cursor.
Frame drivers route these after finish_frame; they also ride along
with the next handle_input result, so a driver that never calls
this merely sees them a little later.
Sourcepub fn modifiers(&self) -> KeyMods
pub fn modifiers(&self) -> KeyMods
Physical modifier state as of the last InputEvent::Modifiers.
Sourcepub fn cursor(&self) -> Option<Vec2>
pub fn cursor(&self) -> Option<Vec2>
Where the pointer is, in this window’s logical viewport
coordinates, as of the last CursorMoved — None once it has
left the window. What a view that follows the pointer reads (the
devtools’ picker outlines the node under it); a control that wants
to react to the pointer declares hoverable or on_hover and
lets the core do the hit test.
pub fn open(&mut self, spec: NodeSpec) -> Key
pub fn open_keyed(&mut self, label: &str, spec: NodeSpec) -> Key
Sourcepub fn label_of(&self, key: Key) -> Option<&str>
pub fn label_of(&self, key: Key) -> Option<&str>
The inverse of Self::key_of: the label key was opened under
— in the frame being built so far, else in the last one — or
None for an auto-keyed node or a key no frame has declared. What
a reader holding a key from an event or from focus() turns back
into the name the view gave it.
Sourcepub fn key_of(&mut self, label: &str) -> Option<Key>
pub fn key_of(&mut self, label: &str) -> Option<Key>
The key of the node opened under label (open_keyed; a key
prop in JSX or a Lua table) in the last finished frame — or, while
a frame is being built, in it so far and then in the last one. The
door for a caller that holds only strings: keys are hashes of the
path from the root, and that path runs through auto-keyed
ancestors nothing outside the build can spell, so “focus the node
I just declared” is this and not child_key. None when no node
declared the label. Labels are unique among siblings, not across a
tree, so two nodes may share one under different parents. A guest
asking from inside its fill is answered from the nodes
it opened and no one else’s — it cannot know what the host or
another guest called theirs, and its env is a reading of its own
view; the host, whose frame it is, from its own first and from
everyone’s when it opened none. Within that, the first in tree
order wins and an ambiguous-key warning says so.
Sourcepub fn open_indexed(&mut self, i: u64, spec: NodeSpec) -> Key
pub fn open_indexed(&mut self, i: u64, spec: NodeSpec) -> Key
open_keyed in the sibling-index namespace: the key auto-keying
would have given the ith child. A list that builds only rows
900..930 opens each with its data index, so row 900 keeps the key
it has when the whole list is built — hover, focus, edit buffers and
tweens follow the row instead of the slot it happens to occupy.
Sourcepub fn row_count(&mut self, n: u64)
pub fn row_count(&mut self, n: u64)
Declares how many indexed rows the open node’s virtual list has,
built or not (rowCount): what Select All inside a selectable
virtual list spans, since the built rows are all the core can see.
widgets::uniform_list and widgets::list
call it on their container; a list composed by hand calls it
inside the container’s with. Nothing, outside any node.
Sourcepub fn open_key(&mut self, key: Key, spec: NodeSpec) -> Key
pub fn open_key(&mut self, key: Key, spec: NodeSpec) -> Key
Opens a node under a key the caller built; see Ui::open_key.
pub fn close(&mut self)
Sourcepub fn hint(&mut self, key: Key, text: impl Into<String>)
pub fn hint(&mut self, key: Key, text: impl Into<String>)
Records the hover hint of the node just opened (the top of the
stack): close floats widgets::hover_hint below it while it is
hovered. The one place that decides when a tooltip shows, so a
binding that parsed the string cannot show it some other way.
Sourcepub fn open_from(&mut self, props: PropsOut, content: Content<'_>) -> Key
pub fn open_from(&mut self, props: PropsOut, content: Content<'_>) -> Key
Opens a node the way a parsed prop list says — under the data
index, the label or the next auto key; taking keyboard focus when
keyFocus asked; floating its tooltip on close while hovered —
with whatever the node holds. The one door for every binding that
lowers props, so the identity match, the focus edge and the hint
are not re-derived per binding per element (they were, eight, five
and four times). A box or a fragment is left open for its children,
and its hint floats as its last child on close; a cells grid, a
line, a polygon and a path are leaves, and theirs floats
beside the leaf, anchored to it (PropsOut::for_leaf, backlog
RG113). Returns the key.
Sourcepub fn configure_root_from(&mut self, props: PropsOut)
pub fn configure_root_from(&mut self, props: PropsOut)
The root the way a parsed prop list says: its title, whether it wants the window on top, its keyboard secure, its Option keys as Alt or its input method off, the windows it declares, its spec, and keyboard focus on it when asked — what a binding’s root op does, once.
pub fn text_node(&mut self, content: &str, style: TextStyle)
Sourcepub fn cells(&mut self, grid: &CellGrid<'_>, spec: NodeSpec)
pub fn cells(&mut self, grid: &CellGrid<'_>, spec: NodeSpec)
A cell grid as one leaf node, sized cols × cell_w by rows × cell_h. spec is the node’s:
an on_key makes it the terminal’s sink, an on_click / on_drag
carry cell: {row, col} on their events.
Sourcepub fn cells_keyed(&mut self, label: &str, grid: &CellGrid<'_>, spec: NodeSpec)
pub fn cells_keyed(&mut self, label: &str, grid: &CellGrid<'_>, spec: NodeSpec)
Self::cells under a declared key.
Sourcepub fn cells_indexed(&mut self, i: u64, grid: &CellGrid<'_>, spec: NodeSpec)
pub fn cells_indexed(&mut self, i: u64, grid: &CellGrid<'_>, spec: NodeSpec)
Self::cells under a data index; see Self::open_indexed.
Sourcepub fn text_edit(
&mut self,
label: &str,
initial: &str,
opts: &EditOptions,
spec: NodeSpec,
) -> Key
pub fn text_edit( &mut self, label: &str, initial: &str, opts: &EditOptions, spec: NodeSpec, ) -> Key
An editable text node. State (buffer, cursor, selection) is retained
by key across frames; edits arrive via handle_input and come back to
the host as “changed”/“submit” events. Read with edit_text.
Sourcepub fn image_node(&mut self, id: ImageId, spec: NodeSpec)
pub fn image_node(&mut self, id: ImageId, spec: NodeSpec)
A registered image (see Resources::add_image). Fit sizing takes
the image’s pixel dimensions as logical px; a Fit height against a
resolved width preserves the aspect ratio. style.radius rounds the
corners. Linear sampling, stretched to the box: Self::image_node_with
takes the two rows that say otherwise.
Sourcepub fn image_node_with(&mut self, id: ImageId, opts: ImageOpts, spec: NodeSpec)
pub fn image_node_with(&mut self, id: ImageId, opts: ImageOpts, spec: NodeSpec)
Self::image_node with its sampling and fit rows: how texels are
read between pixels, and how the pixels
meet a box of another aspect. The box — its layout, hit region and
access rect — is the same in every mode.
Sourcepub fn fragment_node(
&mut self,
frag: impl Into<FragmentRef>,
params: &[f32],
spec: NodeSpec,
) -> Key
pub fn fragment_node( &mut self, frag: impl Into<FragmentRef>, params: &[f32], spec: NodeSpec, ) -> Key
A box a registered WGSL function paints.
An ordinary node in every other respect: it lays out where it is
declared, sizes from spec, rounds by radius, clips, fades with
its subtree’s opacity, takes input like any box, and may hold
children — which paint over it, so a gradient card is a fragment
with a title and buttons inside it.
It has no intrinsic size: unlike an image there is nothing to
measure, so a fragment with no width / height / fill is zero
by zero and draws nothing. Size it.
params is up to sixteen numbers, positional, zero-padded, read by
the shader as four vec4<f32>; more than sixteen are dropped with
a fragment-params-truncated warning. A handle that is not live in
this session draws nothing, as every resource kind does — and so
does one whose image (FragmentId::with_image) is not, which is
the removal order: the image goes, the fragment reading it draws
the fallback, and the handle it kept is a foreign-resource miss
like any other.
Sourcepub fn open_fragment(
&mut self,
frag: impl Into<FragmentRef>,
params: &[f32],
spec: NodeSpec,
) -> Key
pub fn open_fragment( &mut self, frag: impl Into<FragmentRef>, params: &[f32], spec: NodeSpec, ) -> Key
Opens a fragment as a parent: its children paint over it, which is
what a gradient card with a title and buttons in it is. Balance it
with Self::close, or use Ui::fragment_with.
Sourcepub fn fragment_node_keyed(
&mut self,
label: &str,
frag: impl Into<FragmentRef>,
params: &[f32],
spec: NodeSpec,
) -> Key
pub fn fragment_node_keyed( &mut self, label: &str, frag: impl Into<FragmentRef>, params: &[f32], spec: NodeSpec, ) -> Key
Self::fragment_node under a label key, for a fragment that
transitions or exits and needs a stable identity across frames.
Sourcepub fn open_fragment_keyed(
&mut self,
label: &str,
frag: impl Into<FragmentRef>,
params: &[f32],
spec: NodeSpec,
) -> Key
pub fn open_fragment_keyed( &mut self, label: &str, frag: impl Into<FragmentRef>, params: &[f32], spec: NodeSpec, ) -> Key
Self::open_fragment under a label key.
Sourcepub fn open_fragment_indexed(
&mut self,
i: u64,
frag: impl Into<FragmentRef>,
params: &[f32],
spec: NodeSpec,
) -> Key
pub fn open_fragment_indexed( &mut self, i: u64, frag: impl Into<FragmentRef>, params: &[f32], spec: NodeSpec, ) -> Key
Self::open_fragment under a data index; see Self::open_indexed.
Sourcepub fn line_node(&mut self, points: &[Vec2], stroke: Stroke, spec: NodeSpec)
pub fn line_node(&mut self, points: &[Vec2], stroke: Stroke, spec: NodeSpec)
A stroke through points in the parent’s box space: one round-capped
segment for two points, a polyline for more, a smooth curve through
them with Stroke::curve.
Never in layout. The node is a float sized to the stroke’s padded
bounding box, so it takes no room in a row or column, and spec’s
sizing, clamps, padding, gap and alignment are ignored. What spec
carries that matters: transition (the colour eases — it rides in
the bg slot — and slide, enter and exit offsets move the
float), opacity, on_layout (reports the bounding box), a
declared float whose anchor is kept (FloatAnchor::Viewport
reads the points in viewport space), and role / label, which are
honoured like any node’s; without them a line has no access row —
unless it takes input, when it derives one as a box would. Input
is hit by shape: a press within half the stroke’s
width of any piece (at least MIN_STROKE_GRAB wide) hits it, and
a press elsewhere in its box falls through to what is under it.
Fewer than two points draw nothing.
Consecutive segments overlap at their round caps, which is the join: exact for an opaque stroke, and a translucent one double-blends there, the way a faded subtree shows its seams.
Sourcepub fn line_node_keyed(
&mut self,
label: &str,
points: &[Vec2],
stroke: Stroke,
spec: NodeSpec,
)
pub fn line_node_keyed( &mut self, label: &str, points: &[Vec2], stroke: Stroke, spec: NodeSpec, )
Self::line_node under a label key, for a stroke that transitions
or exits and needs a stable identity across frames.
Sourcepub fn line_node_indexed(
&mut self,
i: u64,
points: &[Vec2],
stroke: Stroke,
spec: NodeSpec,
)
pub fn line_node_indexed( &mut self, i: u64, points: &[Vec2], stroke: Stroke, spec: NodeSpec, )
Self::line_node under a data index; see Self::open_indexed.
Sourcepub fn polygon_node(&mut self, points: &[Vec2], spec: NodeSpec)
pub fn polygon_node(&mut self, points: &[Vec2], spec: NodeSpec)
A filled polygon through points in the parent’s box space:
up to
eight vertices, the fill in spec’s bg, painted by the stock
polygon fragment the core registers itself.
Placed exactly as a line is: never in
layout, a float sized to the points’ bounding box inflated by a
logical pixel for the edge ramp, so it takes no room in a row or
column and spec’s sizing, clamps, padding, gap and alignment are
ignored. transition eases the fill through the bg slot, and
slide, enter and exit move the float; a declared float
keeps its anchor; role and label are honoured, and without
them a polygon has no access row unless it takes input, when it
derives one as a box would (a clickable wedge is a button). Input
is hit by shape: a press inside the outline hits it,
one in its box but outside the outline falls through to what is
under. Fewer than three points draw nothing; a ninth and later are
dropped with polygon-points-truncated. The outline may be
concave; a self-intersecting one fills even-odd, its overlaps
unfilled.
Sourcepub fn polygon_node_keyed(
&mut self,
label: &str,
points: &[Vec2],
spec: NodeSpec,
)
pub fn polygon_node_keyed( &mut self, label: &str, points: &[Vec2], spec: NodeSpec, )
Self::polygon_node under a label key.
Sourcepub fn polygon_node_indexed(&mut self, i: u64, points: &[Vec2], spec: NodeSpec)
pub fn polygon_node_indexed(&mut self, i: u64, points: &[Vec2], spec: NodeSpec)
Self::polygon_node under a data index; see Self::open_indexed.
Sourcepub fn path_node(&mut self, path: &Path, spec: NodeSpec)
pub fn path_node(&mut self, path: &Path, spec: NodeSpec)
A path — any outline, SVG’s d — filled with spec’s bg by the
path’s rule and stroked by its stroke if it has one
(docs/adr/0040-a-path-is-a-mask-in-the-atlas.md).
Placed exactly as a line is: never in layout, a float sized to the
outline’s bounding box two logical pixels out (and half the stroke’s
width further), so it takes no room in a row or column and
spec’s sizing, clamps, padding, gap and alignment are ignored.
transition eases the fill through the bg slot, and slide,
enter and exit move the float; a declared float keeps its
anchor; role and label are honoured, and without them a path
has no access row unless it takes input, when it derives one as a
box would. Input is hit by shape: a press inside the outline by
the fill rule hits it, one in its box past the outline falls
through to what is under. A path with no outline draws nothing.
The outline is rasterized once per shape, scale and quarter-pixel position into the glyph atlas and drawn as a glyph-mask quad; the fill bleeds half a pixel so two paths sharing an edge meet without the background showing through. A path whose ops change twice within a few frames, or whose mask is a quarter of the biggest atlas page or more, draws from a texture of its own instead.
Sourcepub fn path_node_keyed(&mut self, label: &str, path: &Path, spec: NodeSpec)
pub fn path_node_keyed(&mut self, label: &str, path: &Path, spec: NodeSpec)
Self::path_node under a label key.
Sourcepub fn path_node_indexed(&mut self, i: u64, path: &Path, spec: NodeSpec)
pub fn path_node_indexed(&mut self, i: u64, path: &Path, spec: NodeSpec)
Self::path_node under a data index; see Self::open_indexed.
Sourcepub fn parse_path(&self, d: &str) -> Result<Path, PathError>
pub fn parse_path(&self, d: &str) -> Result<Path, PathError>
SVG path data to a crate::path::Path, through the one parser
every binding’s d goes through (Path::parse, reached here as
the door the C API’s kui_path_parse is). Err names the byte.
Sourcepub fn path_d_node(
&mut self,
d: &str,
rule: FillRule,
stroke: Option<Stroke>,
turn: Option<Turn>,
spec: NodeSpec,
)
pub fn path_d_node( &mut self, d: &str, rule: FillRule, stroke: Option<Stroke>, turn: Option<Turn>, spec: NodeSpec, )
Self::path_node from SVG path data, parsed by the one parser
every binding goes through; data that does not parse raises
path-malformed under the node’s key and draws nothing.
Sourcepub fn path_d_node_keyed(
&mut self,
label: &str,
d: &str,
rule: FillRule,
stroke: Option<Stroke>,
turn: Option<Turn>,
spec: NodeSpec,
)
pub fn path_d_node_keyed( &mut self, label: &str, d: &str, rule: FillRule, stroke: Option<Stroke>, turn: Option<Turn>, spec: NodeSpec, )
Self::path_d_node under a label key.
Sourcepub fn path_node_d(
&mut self,
key: Key,
d: &str,
rule: FillRule,
stroke: Option<Stroke>,
turn: Option<Turn>,
spec: NodeSpec,
)
pub fn path_node_d( &mut self, key: Key, d: &str, rule: FillRule, stroke: Option<Stroke>, turn: Option<Turn>, spec: NodeSpec, )
Self::path_d_node under a key the caller derived.
Sourcepub fn path_flat_node(
&mut self,
floats: &[f32],
rule: FillRule,
stroke: Option<Stroke>,
turn: Option<Turn>,
spec: NodeSpec,
)
pub fn path_flat_node( &mut self, floats: &[f32], rule: FillRule, stroke: Option<Stroke>, turn: Option<Turn>, spec: NodeSpec, )
Self::path_node from the flat op form — a code, then its
operands, per op, as Path::to_floats writes it and a binding’s
wire carries it. Floats that are not the form (a code that is not
one, an op cut short) raise path-malformed under the node’s key
and draw nothing: one answer in every binding, where it was an
error in one and silence in two (RG112).
Sourcepub fn path_flat_node_keyed(
&mut self,
label: &str,
floats: &[f32],
rule: FillRule,
stroke: Option<Stroke>,
turn: Option<Turn>,
spec: NodeSpec,
)
pub fn path_flat_node_keyed( &mut self, label: &str, floats: &[f32], rule: FillRule, stroke: Option<Stroke>, turn: Option<Turn>, spec: NodeSpec, )
Self::path_flat_node under a label key.
Sourcepub fn path_node_flat(
&mut self,
key: Key,
floats: &[f32],
rule: FillRule,
stroke: Option<Stroke>,
turn: Option<Turn>,
spec: NodeSpec,
)
pub fn path_node_flat( &mut self, key: Key, floats: &[f32], rule: FillRule, stroke: Option<Stroke>, turn: Option<Turn>, spec: NodeSpec, )
Self::path_flat_node under a key the caller derived.
Sourcepub fn rich_text_node(&mut self, spans: &[Span<'_>], base: TextStyle)
pub fn rich_text_node(&mut self, spans: &[Span<'_>], base: TextStyle)
A paragraph of styled spans, shaped and wrapped as one flow.
Source§impl Core
impl Core
Sourcepub fn set_frame_trace(&mut self, on: bool)
pub fn set_frame_trace(&mut self, on: bool)
Turns the trace of why frames run on or off: who
holds each owed frame (Self::owed_by) and whether each frame
changed what is drawn (Self::frame_unchanged). Off by default,
where neither costs anything; on, the holders are taken at the
start of every frame the last one owed — a walk of what is owed
and one of the last frame’s tree to name it — and the display
list is hashed at the end of every frame. Self::frame_cause
is kept either way.
Sourcepub fn frame_trace(&self) -> bool
pub fn frame_trace(&self) -> bool
Whether Self::set_frame_trace turned the trace on.
Sourcepub fn frame_cause(&self) -> FrameCause
pub fn frame_cause(&self) -> FrameCause
Why the frame being built runs: every reason that reached the
window between the start of the last frame and the start of this
one. Between frames, the last frame’s — or, after
Self::begin_frame_cause, the next one’s. See FrameCause.
Sourcepub fn begin_frame_cause(&mut self)
pub fn begin_frame_cause(&mut self)
Starts the next frame’s record now rather than at its
begin_frame: its reasons (Self::frame_cause) and, traced,
who holds it (Self::owed_by) — for a driver whose view runs
before the frame it is for begins. Node’s loop runs
view to a tree and only then hands the tree to a frame, so a
view reading either would read the frame before; the loop calls
this first, and the view reads the frame it is building. The
begin_frame that follows keeps what this took, and a second
call before it is nothing. What reaches the window in between —
input, a note — is the frame after’s, as it is during a build.
Sourcepub fn note_frame_cause(&mut self, cause: FrameCause)
pub fn note_frame_cause(&mut self, cause: FrameCause)
Adds to the next frame’s reasons — the driver’s door, for what it
saw and the core never will: a wake, a resize, a blink, a retry,
an OS event it kept. The input it hands Self::handle_input is
recorded without this.
Sourcepub fn owed_by(&self) -> &OwedBy
pub fn owed_by(&self) -> &OwedBy
Who held the frame the last one left owed, as the frame being
built found them (see OwedBy) — or, after
Self::begin_frame_cause, as the next one will. Empty when the
trace is off.
Sourcepub fn frame_unchanged(&self) -> Option<bool>
pub fn frame_unchanged(&self) -> Option<bool>
Whether the last finished frame drew exactly what the one before
it drew — the same quads, clips, fragments and textures at the
same size and scale — so it changed nothing on screen. None
while the trace is off and for the first frame after it came on.
A frame that draws a fragment is never unchanged: the shader reads
the clock. What the glyph atlas holds is not compared, only where
the quads sample it.
Source§impl Core
impl Core
Sourcepub fn devtools_tab_declare(
&mut self,
name: &str,
label: &str,
slot: Option<&str>,
) -> bool
pub fn devtools_tab_declare( &mut self, name: &str, label: &str, slot: Option<&str>, ) -> bool
Declares a devtools tab this frame. A name
declared already this frame warns duplicate-tab and keeps the
first; returns whether this one stood. The bare door under
Ui::devtools_tab / devtools_tab_with, for a binding that
opens the content itself.
Sourcepub fn devtools_tab_shown(&self, name: &str) -> bool
pub fn devtools_tab_shown(&self, name: &str) -> bool
Whether the host form of tab name is shown this frame — the
panel is on, docked in this (the main) window, and name is the
tab on show. Read before the content is
built, from the session’s state, which is in place while the
host’s view runs.
Sourcepub fn devtools_shown_tab(&self) -> Option<String>
pub fn devtools_shown_tab(&self) -> Option<String>
The tab on show, by name, when it is a declared one — what the
Node and Lua drivers read once a frame to call a tab’s function
child. None for one of the panel’s own,
for the panel off, popped out, or another window’s frame.
Sourcepub fn devtools_tab_open(&mut self, name: &str)
pub fn devtools_tab_open(&mut self, name: &str)
Opens the host form’s content node: a float anchored to the tab’s
body by key, the body’s size, clipped, keyed as the host’s own
child. The caller builds inside and
closes. The bare door under Ui::devtools_tab_with; it does not
declare, and it does not ask whether the tab is on show.
Source§impl Core
impl Core
Sourcepub fn set_devtools(&mut self, on: bool)
pub fn set_devtools(&mut self, on: bool)
Turns the devtools panel on or off for this session. On,
it is drawn where Self::set_devtools_dock says — beside the
host’s tree in the main window by default — and its chords are
live in every window. KUI_DEVTOOLS=1 in the environment is the
same call made by nobody; KUI_DEVTOOLS=bottom (or left,
right, window, off) also says where.
Sourcepub fn devtools_from_env(&mut self) -> bool
pub fn devtools_from_env(&mut self) -> bool
Opens the panel if KUI_DEVTOOLS in the environment asks for it
(1, true, or a placement name), and says whether it did. What
the windowed runners call once, before the first frame — the door
for a program that was never told about the panel — and what a
headless core never reads, so a variable left exported cannot put
a dock into a test’s tree.
Sourcepub fn set_devtools_dock(&mut self, dock: Dock)
pub fn set_devtools_dock(&mut self, dock: Dock)
Where the panel sits; Ctrl+Shift+D moves it from there.
pub fn devtools_dock(&self) -> Dock
Sourcepub fn set_devtools_theme(
&mut self,
base: Option<Appearance>,
accent: Option<Color>,
)
pub fn set_devtools_theme( &mut self, base: Option<Appearance>, accent: Option<Color>, )
Seeds the panel’s theme override — what its T and A chords
cycle from. None for either leaves the app’s own.
Sourcepub fn set_devtools_key(&mut self, key: Accel)
pub fn set_devtools_key(&mut self, key: Accel)
Respells the chord that moves the keyboard into the panel and
back out — and brings the panel back when it is off — from its
default Ctrl+Shift+I: any Accel spelling ("f12",
"mod+shift+d", "⌥⌘I"). The other chords stay Ctrl+Shift+ <letter>; this is the one an app puts in its own help, and the
one whose default an app’s keymap may want for itself. A chord
the app takes is the app’s for good: with F12 set,
Ctrl+Shift+I reaches the app’s sinks like any other press.
Sourcepub fn devtools_key(&self) -> Accel
pub fn devtools_key(&self) -> Accel
The chord that moves the keyboard into the panel, as set or as it defaults.
Sourcepub fn devtools_selected(&self) -> Option<Key>
pub fn devtools_selected(&self) -> Option<Key>
The node the panel’s tree tab has selected: what an inspector in a declared tab reads to say which node it is about. Answered from the session, so it is right inside the host’s view and inside an extension’s fill alike.
Sourcepub fn devtools_hovered(&self) -> Option<Key>
pub fn devtools_hovered(&self) -> Option<Key>
The tree row under the pointer in whichever window draws the tree — the node the main window outlines.
Sourcepub fn devtools_picked(&self) -> Option<Key>
pub fn devtools_picked(&self) -> Option<Key>
The node the picker last saw under the pointer, while picking.
Sourcepub fn set_devtools_selected(&mut self, key: Option<Key>)
pub fn set_devtools_selected(&mut self, key: Option<Key>)
Selects a node in the panel’s tree tab from outside it — an
inspector driving the highlight from its side — and reveals it
there, as the picker does; None clears. The tab does not move:
the caller is drawing in one.
Sourcepub fn set_devtools_pick(&mut self, on: bool)
pub fn set_devtools_pick(&mut self, on: bool)
Raises the panel’s picker from outside it — an inspector in a
declared tab asking “which node?” — or puts it away. Picking happens in
the main window, over the app: the
node under the pointer is devtools_picked while it is up, and
the press lands it in devtools_selected. Raised while a declared
tab is on show, the pick leaves that tab up; raised otherwise — a
tab named through Self::set_devtools_tab but not declared yet
included — it is the Ctrl+Shift+P pick, which shows the tree
tab. A hidden panel comes back docked, as the chord’s does.
Sourcepub fn devtools_picking(&self) -> bool
pub fn devtools_picking(&self) -> bool
Whether the panel’s picker is up.
Sourcepub fn set_devtools_tab(&mut self, name: &str) -> bool
pub fn set_devtools_tab(&mut self, name: &str) -> bool
Shows the panel’s tab named name from outside the panel — what
the strip’s click and Ctrl+Shift+N do, for an app with a command
that jumps to its own tab. name is one of the panel’s
own (facts, events, tree, in any case — the strip labels
them Facts, Events, Tree) or a declared tab’s, exactly as
the app declared it. A declared
name the panel does not list yet is kept and shows once a frame
declares it, as a strip click on it would; the return says whether
the panel lists it now (it lists a declared tab from the first
frame it is on). A hidden panel comes back docked, as the
picker’s does. The panel’s on is not touched: that is
Self::set_devtools’s. Edge-triggered — called once a frame it
would pin the strip against the user’s own clicks.
Sourcepub fn devtools_current_tab(&self) -> String
pub fn devtools_current_tab(&self) -> String
The tab the panel is on, by name: one of its own (facts,
events, tree) or a declared tab’s — what the strip marks,
panel on or off, in any window. A declared name the panel stopped
listing answers the panel’s own tab the strip falls back to.
Unlike Self::devtools_shown_tab, which answers only a declared
tab on show in the main window for a data binding’s function
child, this is the selection itself.
Sourcepub fn set_devtools_legend(&mut self, legend: &[(&str, &str)])
pub fn set_devtools_legend(&mut self, legend: &[(&str, &str)])
The key legend the facts tab shows: (keys, what they do).
Sourcepub fn devtools_window(&self) -> bool
pub fn devtools_window(&self) -> bool
Whether this core draws the panel’s own window — a frame the host builds nothing into.
Source§impl Core
impl Core
Sourcepub fn host_area(&self, window: Size) -> Size
pub fn host_area(&self, window: Size) -> Size
What the dock leaves of a window window big: the
viewport a frame begun at that size lays out into, which
viewport() reports once the frame has begun and a resize
reports when it changes. It takes the window’s size and the dock’s
state and nothing of the frame, so it answers before the first
frame too — what a driver’s window-size reading hands a host that
sizes its model at setup (Node’s KuiWindow.size()).
Sourcepub fn host_rect(&self) -> Rect
pub fn host_rect(&self) -> Rect
Where the current frame laid the host out, in the window’s logical
px: Core::viewport with its origin — x the pane’s width under
a left dock, and zero everywhere else, the whole window with the
panel off, in a window of its own, or in any window but the main
one. The frame’s reading, like viewport(), so it is zero before
the first frame (the pre-frame answer is host_area’s size) and it
is the rect the quads of output() were drawn against: scaled by
scale() into their physical px, it is what separates the host’s
quads from the dock’s — all but the root’s background, which
devtools_configure_root gives the window as well as the app
container, so it fills the whole window beneath the pane. Backlog
F92: the origin reached only the Rust
runner, through devtools_inset, so a Node test could size itself
to the host area but not say that nothing of its own left it.
Sourcepub fn devtools_inset(&self) -> Size
pub fn devtools_inset(&self) -> Size
What a docked pane takes off the main window, in the axis it
takes it: the side column’s width as (w, 0), the bottom strip’s
height as (0, h), and zero with the panel off, in a window of
its own, or asked of any window but the main one. The pane’s
extent as the handle left it, not as the window clamps it — what
a driver adds to the app’s minimum window size while the panel is
docked, so the floor the app declared is a floor on the app and
not on the app less the dock (the pomodoro’s report, 2026-09-12:
a 620×500 minimum with a 340 px dock left the app 280 px, below
the tier it was drawn to fit). Read after a frame, since the
handle’s drag and the placement buttons land in one.
Source§impl Core
impl Core
Sourcepub fn handle_input(&mut self, ev: InputEvent) -> Vec<UiEvent>
pub fn handle_input(&mut self, ev: InputEvent) -> Vec<UiEvent>
Feeds one input event; returns any UI events it resolved to, hit-tested against the previous frame’s layout.
Sourcepub fn press(&mut self, key: KeyPress) -> Vec<UiEvent>
pub fn press(&mut self, key: KeyPress) -> Vec<UiEvent>
One whole key going down: both channels, in the order a window
drives them. The press reaches whatever holds key
focus, and then KeyPress::edit_event asks the core for what
that key means — Escape dismisses a modal, Tab walks the ring,
an arrow nudges a focused slider, a printable character reaches
the focused editor.
This is what a driver with a real keyboard does, so it is what a
headless test should do too. Core::handle_input with a bare
KeyDown is still the way to drive one channel on purpose.
Sourcepub fn release(&mut self, key: KeyPress) -> Vec<UiEvent>
pub fn release(&mut self, key: KeyPress) -> Vec<UiEvent>
The same key coming up. One channel, because only one has a second
half: the editing keys act on the way down. Paired with
Core::press so a held key is a press and a release, and a sink
that asked for key_up hears both.
Sourcepub fn holds_key(&self, key: &KeyPress) -> bool
pub fn holds_key(&self, key: &KeyPress) -> bool
Whether this core delivered key’s press and has not delivered
its release — the one core a KeyUp for it resolves in. What a
driver with more than one core asks before routing a release: a
key pressed in a window and let go while a popup borrowed its
keyboard was released in the popup, which never saw the press, and
the owner held it until it lost focus.
Sourcepub fn access_tree(&mut self) -> &AccessTree
pub fn access_tree(&mut self) -> &AccessTree
The access tree of the last finished frame (see crate::access):
derived on the first call after a frame, then reused. A driver that
never asks pays nothing.
Sourcepub fn release_held_keys(&mut self)
pub fn release_held_keys(&mut self)
Lets go of every key the focused sink is holding, as if the user
had released them: each becomes a {kind="key", phase="up"} on the
sink that took the press. Called when focus moves — a keymap that
armed a mode on the way down has to hear the way up, and the node
it moved to never saw the press — and by drivers when the window
loses the keyboard (Cmd-Tab while a key is down otherwise leaves it
stuck down forever).
Sourcepub fn set_focused(&mut self, focused: bool)
pub fn set_focused(&mut self, focused: bool)
The driver’s report that this window gained or lost the keyboard:
env.focused, plus the one rule that rides on it — a window that
lost the keyboard lets go of every key its sink was holding, since
the OS stops delivering key events to it and the release would
never arrive. The rule lives here rather than in each driver so a
Node test’s setEnv({focused: false}) and a C host’s kui_env_set
do what the windowed runner does, instead of each remembering to.
The synthetic ups are pending, like release_held_keys’s, and so
are the releases of the buttons onButton nodes held.
Sourcepub fn chord_sink(&self) -> Option<Key>
pub fn chord_sink(&self) -> Option<Key>
The sink a chord pressed now would reach, if any: the focused sink, the nearest one above the focused control, or the root’s with nothing focused. What a driver asks before greying a menu row that spells a chord — a sink that would hear ⌘C may do anything with it, so the row stays lit.
Sourcepub fn copy_selection(&self) -> Option<String>
pub fn copy_selection(&self) -> Option<String>
The window’s selected text, for clipboard integration: the
selection in a selectable scope when there is one, else the
focused editor’s. Only one of the two exists at a time — starting
either clears the other
— so this asks in that order rather than merging them.
Sourcepub fn cut_selection(&mut self) -> Option<String>
pub fn cut_selection(&mut self) -> Option<String>
Cuts the focused editor’s selection, returning the removed text.
A cut is an edit like any other, so the editor’s changed is
pending for the caller to route — like a resize, since the
caller is not answering an input event.
Sourcepub fn set_edit_text(&mut self, key: Key, text: &str) -> bool
pub fn set_edit_text(&mut self, key: Key, text: &str) -> bool
Replaces an editor’s text, leaving the caret at the end.
The key need not have an editor behind it yet: an update that
opens a rename field runs a frame ahead of the view that declares
it, so the text is held and seeds the editor the next frame
declares under this key, over its initial. Held for that one
frame — a key nothing declares on it drops its text and raises
crate::diag::EDIT_TEXT_WITHOUT_EDITOR.
Returns whether the text reached an editor now. false is the
held case: nothing on screen changed, and a driver that redraws on
it re-lowers the tree that declares no editor, which is the frame
the hold expires on — so a binding asks for a redraw
only on true.
Sourcepub fn set_edit_text_by_label(&mut self, label: &str, text: &str) -> bool
pub fn set_edit_text_by_label(&mut self, label: &str, text: &str) -> bool
The same call by the name the view declares — an editor’s key
prop / label — for the app that has no key to give: the hex key
comes from an event the node fired, and an editor a rename opens
for the first time has fired none.
A label some frame declared resolves now (Core::key_of) and
this is Core::set_edit_text on that key. One nothing has
declared — a first open, or a second one, since an editor closed
in between was in no recent frame — is held for the next frame
that declares an editor under it, and seeds it there. An editor
retained while its key was off screen takes the text over its
draft, which is what a set_edit_text by key cannot say.
Held for that one frame: a label nothing declares on it drops its
text and raises crate::diag::EDIT_TEXT_WITHOUT_EDITOR.
Returns whether the text reached an editor now, as
Core::set_edit_text does; a label held is false.
Sourcepub fn cursor_shape(&self) -> CursorShape
pub fn cursor_shape(&self) -> CursorShape
The pointer shape for wherever the pointer is now, derived from the
frame’s hit regions (see crate::cursor). Per-frame output like
the window commands, but a query rather than a drain: it is a state,
not a queue, so a driver reads it after each input and each frame and
only touches the window when the answer changes. Headless drivers
never read it, and the core stays device-free.
Source§impl Core
impl Core
Sourcepub fn ime_rect(&self) -> Option<Rect>
pub fn ime_rect(&self) -> Option<Rect>
See the ime_rect field. None when nothing with a caret is
focused: neither a stock editor nor a sink holding a line that
declares one.
Sourcepub fn has_caret(&self) -> bool
pub fn has_caret(&self) -> bool
Whether there is a caret to blink: a focused stock editor’s, or the
caret a line under the focused custom editor declares — unless
that line declares it caret_solid, which is a caret to anchor
the IME and read to assistive technology but not one to blink. A
driver arms its blink clock while this is true and leaves the
caret solid otherwise.
Sourcepub fn caret_stamp(&self) -> u64
pub fn caret_stamp(&self) -> u64
Changes whenever the caret moved or focus changed — the stock
editor’s caret through typing or a click, a custom editor’s
through the caret row it declares — so a driver comparing it
across frames re-arms the blink with the caret solid, the way a
caret that just moved is never mid-blink.
Sourcepub fn caret_visible(&self) -> bool
pub fn caret_visible(&self) -> bool
The blink phase, as the driver last set it: true draws the
caret. The stock editor reads it itself; a custom editor reads it
in view (Ui::caret_visible) and skips its caret node on the
off phase, so the two blink in step — and a window without the
keyboard, where the driver parks it hidden, shows neither.
Headless it stays true.
Sourcepub fn set_caret_visible(&mut self, visible: bool)
pub fn set_caret_visible(&mut self, visible: bool)
Sets the blink phase; the driver’s, on its clock. A frame is the caller’s to ask for.
Source§impl Core
impl Core
Sourcepub fn begin_slot(&mut self, name: &str) -> Option<Key>
pub fn begin_slot(&mut self, name: &str) -> Option<Key>
Declares a slot under its full name at the cursor and returns its
key — parent.str(name), recorded for key_of — or None when it
cannot be declared: outside a frame, or a second time in one
frame, which is the duplicate-slot warning.
An extension may declare one too, and its key nests under the slot
the extension is itself filling, like any of its nodes. Names stay
frame-wide because namespaces are: there is one extension called
todos however deep the thing that loaded it sat, so todos/panel
is one slot and declaring it twice is the same warning wherever
the two declarations came from.
Sourcepub fn slot_declared(&self, name: &str) -> bool
pub fn slot_declared(&self, name: &str) -> bool
Whether the full name name was declared this frame so far — or
is the slot of a devtools tab declared this frame, which counts
whether or not the panel mounted it, so a plugin whose only slot
is a tab is quiet with the panel off.
Sourcepub fn fill(
&mut self,
slot: &Slot<'_>,
origin: OriginId,
f: impl FnOnce(&mut Ui<'_>),
)
pub fn fill( &mut self, slot: &Slot<'_>, origin: OriginId, f: impl FnOnce(&mut Ui<'_>), )
Runs f as the fill of slot under origin: every node it opens
is tagged origin, keyed as a child of slot.key (an extension’s keys depend on the slot’s
full name, which the host’s namespace makes its own, and on
nothing the host built around them), counted from zero, and
closed for it if it returns with any open (decision 5, with the
unbalanced-extension warning). The host’s origin, counter and
namespace are what they were when f returns, so the host’s next
child is keyed as if the fill had not happened.
Sourcepub fn fill_within(
&mut self,
slot: &Slot<'_>,
origin: OriginId,
filler: Option<&mut dyn Fill>,
f: impl FnOnce(&mut Ui<'_>),
)
pub fn fill_within( &mut self, slot: &Slot<'_>, origin: OriginId, filler: Option<&mut dyn Fill>, f: impl FnOnce(&mut Ui<'_>), )
fill, with filler answering the slots the fill itself declares
— what Extensions::fill_one hands in, so an extension can host
extensions of its own (see crate::slot). None is plain fill:
nothing answers, so a slot declared inside draws nothing.
Source§impl Core
impl Core
Sourcepub fn focus_next(&mut self, forward: bool)
pub fn focus_next(&mut self, forward: bool)
Moves keyboard focus to the next / previous focusable node in tree
order (from the last laid-out frame; see access::focusable),
wrapping around; with no current focus, enters the first (or last,
going backwards). What Tab does. The landing node scrolls into
view, and the focus shows (ring or focus_bg), as keyboard focus
should.
Sourcepub fn region(&self) -> Option<Key>
pub fn region(&self) -> Option<Key>
The focus region in effect: the node whose subtree Tab walks, or
None for the main ring.
Sourcepub fn focus_region(&mut self, key: Option<Key>)
pub fn focus_region(&mut self, key: Option<Key>)
Asks to enter a focus region at the end of the frame being built
(None is the main ring): focus lands on what that region last
held if the node is still there, else its ring’s initial_focus,
else the ring’s first stop, and shows. Deferred like
request_focus_step, and for one more reason: the caller that
toggles a dock on and enters it in one update names a node the
last frame did not build. A key the frame does not declare as a
region raises focus-region-without-node and moves nothing.
Sourcepub fn focus_region_by_label(&mut self, label: &str)
pub fn focus_region_by_label(&mut self, label: &str)
focus_region by the label the region’s node declares — the
spelling a caller has for a node that does not exist yet.
Sourcepub fn is_focused(&self, key: Key) -> bool
pub fn is_focused(&self, key: Key) -> bool
Whether key holds keyboard focus — any node (see focus).
Sourcepub fn focus(&self) -> Option<Key>
pub fn focus(&self) -> Option<Key>
The node holding keyboard focus: an editor, an on_key sink, or
a control Tab (or assistive technology, or set_focus) put it on.
Sourcepub fn focus_visible(&self) -> bool
pub fn focus_visible(&self) -> bool
Whether focus got where it is by keyboard or assistive technology
rather than a click — when it shows (the default ring, or the
node’s focus_bg).
Sourcepub fn set_focus(&mut self, key: Option<Key>)
pub fn set_focus(&mut self, key: Option<Key>)
Moves keyboard focus (None blurs) — the app’s door: Ui::focus,
Node’s focus, kui_focus, Lua’s env.set_focus. Any node can be
focused this way; only focusable ones (see access::focusable)
are reached by Tab. A move made here is the app saying where focus
goes, and it stands at the frame’s end against a closing modal’s
restore, the way a keyFocus edge does: the restore is the default for an app that said
nothing, and this is an app that did. The core’s own moves — a
press, a Tab, an autofocus, the restore itself — go through
move_focus and say nothing.
Sourcepub fn request_focus_step(&mut self, forward: bool)
pub fn request_focus_step(&mut self, forward: bool)
Asks for a Tab step (forward) / Shift-Tab step at the end of the
frame being built. focus_next moves focus now, against the last
finished tree — which is what a driver handling a key press between
frames wants, and exactly what a view cannot use, since its own
tree does not exist yet. A view asks with this instead and the step
lands on the frame it is declaring.
Sourcepub fn set_key_focus(&mut self, key: Option<Key>)
pub fn set_key_focus(&mut self, key: Option<Key>)
Declares a node focused this frame (None blurs at once). The
declaration is edge-triggered: the node takes focus on the first
frame it is declared and keeps being declared without effect
afterwards, so a view that repeats it every frame (an app that
owns its keyboard, a keyFocus prop) does not clobber the focus a
Tab press or a click moved. Programmatic focus keeps the modality
of the last input (it shows after keyboard use, not after a
click). To move focus at any time, set_focus.
Source§impl Core
impl Core
Sourcepub fn set_inspect(&mut self, on: bool)
pub fn set_inspect(&mut self, on: bool)
Turns the per-frame snapshot on or off (see the module doc). Off by
default; a devtool that reads Self::nodes turns it on once.
The host’s ask alone: the core’s own devtools panel asks for the
snapshot separately, per frame, while its tree tab shows or it is
picking, and neither ask turns the other off.
Sourcepub fn nodes(&self) -> Vec<NodeInfo>
pub fn nodes(&self) -> Vec<NodeInfo>
The last finished frame’s nodes, in tree order — empty until
Self::set_inspect asked for them and a frame has finished since.
Rects in the host’s viewport coordinates, like every other readback
(layout_of, scroll_geometry, text_hit): under a left dock the
snapshot itself is kept in window px for the panel’s outlines, and
this is the translated copy.
Source§impl Core
impl Core
The menu this window has open, if any.
Tells the core that this host shows menus itself — an NSMenu, a
TrackPopupMenu, whatever the platform has. The core then keeps the
open menu as state and does not
draw it: the host reads menu(), shows it, and reports back with
Self::activate_menu_item or Self::close_menu.
Declared once by the driver, not per menu, because it is a fact about the host and not about any one menu. Off by default: a host that says nothing gets the drawn menu, which is every binding’s starting point and the only thing a headless test can see.
Sourcepub fn set_lookup_available(&mut self, on: bool)
pub fn set_lookup_available(&mut self, on: bool)
Tells the core that this host can show the platform’s definition panel — macOS’s Look Up. The standard Look Up row is then offered where it means something, and a force click over text asks for one; without it the core neither offers nor asks, because an item that does nothing is worse than an item that is not there.
Sourcepub fn lookup_available(&self) -> bool
pub fn lookup_available(&self) -> bool
Whether the host said it can show a definition panel.
Whether the host said it shows menus itself.
The host’s menu reports that item i was chosen: the same path a
press on the drawn menu’s row takes — the core performs what it
can, queues what the host must do, and returns the events the app
hears (one menu event on the node the menu was about).
None when nothing was taken: no menu is open, or row i cannot
be chosen — a disabled row, a separator — in which case the menu
stays open and nothing is posted, since a native menu never reports
such a row and the drawn one has no click on it, so a door that
names one (activateMenuItem(1) over a select whose second option
is disabled) should be answered the way the pointer would be,
rather than handing the app a choice it disabled.
An index past the end closes the menu and posts nothing
(Some and empty), which is what a host reporting a row this build
does not know should do.
Self::activate_menu_item for a row inside a submenu, by its
path: [2, 0] is the first row of the third row’s submenu
(MenuItem::at_path) — what a host whose own menu nests them
(an NSMenu’s submenus) reports (backlog F128). A row that opens a
submenu is refused like a disabled one: the platform opens it and
never reports it chosen. A path that names no row closes the menu
and posts nothing, as an index past the end does.
Sourcepub fn lookup_text(&self) -> Option<String>
pub fn lookup_text(&self) -> Option<String>
What the selection would be looked up as, or None when it is
not something to look up.
A definition panel answers a word or a short phrase. Handed a paragraph it draws the whole thing back over the page as one enormous highlighted strip and then says “No Results Found” — seen in the field, 2026-09-09 — so a selection that spans lines, or runs past 100 characters, is neither offered nor asked about. A force click always passes: it selects one word.
Opens one. A second replaces the first: a window has one menu, the way it has one selection and one focus.
Nothing is drawn here. The next frame draws it, because the menu is state and the frame is a function of state — which is also what makes an app that never pumps another frame after a right-click a bug the app can see rather than a menu that appears out of turn.
Closes it, and every submenu open in it. Returns whether one was open.
The submenus open in the drawn context menu: the row opened at each
level, outermost first — [2] is the third row’s submenu, [2, 0]
that and the submenu of its first row. Empty when none is, and
always while the host shows menus itself (backlog F128).
What choosing an item left for the host: clipboard work, which is the host’s in this library. Drained like the window and audio commands, and empty on every frame of an app whose menus are all its own.
Source§impl Core
impl Core
Declares the application menu for this frame.
Sticky, and diffed: declaring the same bar again costs one
comparison and changes nothing, a different one bumps
Self::menu_bar_revision for the driver to notice, and an empty
MenuBar is how an app takes the bar away. A frame that says
nothing leaves the last declaration standing — which is what lets a
palette window declare no menu and leave the document window’s bar
alone.
Every item’s accelerator is normalized on the way in: a portable
"mod+s" becomes the platform’s own spelling ("⌘S", "Ctrl+S"),
so the drawn bar and the platform’s read the same and the platform’s
can bind the key. A spelling kui cannot parse is left exactly as
written and drawn as written — an app’s own shortcut is the app’s.
The declaration in force, if any frame has made one.
Bumped whenever the declaration changes. A driver keeps the number it last applied and touches the platform only when they differ — the menu-bar analogue of the title diff, and the reason re-declaring an unchanged bar every frame costs nothing.
Tells the core that the platform owns the menu bar — macOS’s, which is not in any window. The drawn bar then draws nothing, and the driver is the one that hands the declaration over and reports what was chosen.
Off by default, like Self::set_native_menus: a host that says
nothing draws its own bar, which is what every headless test and
every binding without a runner sees.
Whether the platform said the menu bar is its.
Which menu of the drawn bar is open, if any. Retained by the core
because it is the one thing the widget cannot derive from the frame
— and always None while the platform draws
the bar, since then the open menu is the platform’s.
The submenus open in the drawn bar’s open menu, as
Self::menu_submenus reads the context menu’s (backlog F128).
Opens one of the drawn bar’s menus, closes it (None), and is what
a press on a title goes through. Public because a keymap is as good
a reason to open the File menu as a click is; out of range closes.
The platform’s menu bar reports that an item was chosen: the same
path a press on the drawn bar’s row takes. The core performs the
standard roles it can, queues what the host must do
(take_menu_actions) and returns the events the app hears.
An index past the end does nothing, which is what a host reporting a row this build does not have should do.
Self::activate_menu_bar_item for a row inside a submenu of menu
menu, by its path (crate::menu::MenuBar::item_at) — what a
platform bar whose menus nest reports (backlog F128). A row that
opens a submenu, a dead row or one under a dead row or menu, or a
path that names none, does nothing.
Source§impl Core
impl Core
Sourcepub fn add_fragment(&mut self, wgsl: &str) -> Option<FragmentId>
pub fn add_fragment(&mut self, wgsl: &str) -> Option<FragmentId>
Registers a WGSL fragment function for a fragment node.
The app writes one function:
fn fragment(in: FragmentIn, params: array<vec4<f32>, 4>) -> vec4<f32>and the core wraps it in the prelude and epilogue that give it the
node’s rounded box, the inherited clip, the group opacity and the
blend (see crate::fragment). None when the source does not
compile, with a fragment-rejected warning carrying naga’s message
in the app’s own line numbers — so a bad shader is a warning at
registration, in a headless test included, and never a blank box in
a window.
Idempotent by source: the same text gets the same handle without validating again, so a view may call this every frame. Registering at startup is still the advice, because the backend builds a pipeline the first time it sees a handle.
Sourcepub fn remove_fragment(&mut self, id: FragmentId)
pub fn remove_fragment(&mut self, id: FragmentId)
Forgets a registered fragment. Nodes still naming it draw nothing, and the next frame any window draws has the backend drop the pipelines it built for it.
Sourcepub fn fragment_module_source(&self, id: FragmentId) -> Option<String>
pub fn fragment_module_source(&self, id: FragmentId) -> Option<String>
The whole WGSL module behind a fragment handle — the app’s source between the core’s prelude and epilogue — which is what a backend compiles. A host rendering the display list itself asks for this rather than assembling its own, so what it compiles is what the core validated.
Sourcepub fn add_font_data(&mut self, data: Vec<u8>) -> Option<FontId>
pub fn add_font_data(&mut self, data: Vec<u8>) -> Option<FontId>
Registers a font from its file bytes (TTF/OTF/TTC); None when the
data holds no usable face — none the font database can read, or
none whose glyphs can be measured (no head, hhea or hmtx).
Shape with it via TextStyle::font.
Sourcepub fn load_font_file(&mut self, path: impl Into<PathBuf>) -> Option<FontId>
pub fn load_font_file(&mut self, path: impl Into<PathBuf>) -> Option<FontId>
Registers a font file (TTF/OTF/TTC) by path, memory-mapped by the
font database; None when it cannot be read or holds no usable
face (see add_font_data). Shape with it
via TextStyle::font.
Sourcepub fn load_fonts_dir(&mut self, dir: impl AsRef<Path>) -> usize
pub fn load_fonts_dir(&mut self, dir: impl AsRef<Path>) -> usize
Loads every font file under dir (recursively) into the font
database, so their families become available to add_system_font
by name; returns how many faces were added. A face whose glyphs
cannot be measured is left out and not counted. A
bundled fonts/ folder next to the app is the usual case.
Sourcepub fn reload_system_fonts(&mut self) -> usize
pub fn reload_system_fonts(&mut self) -> usize
Scans the system’s fonts again and brings this session’s font database up to it: a face installed since the last scan joins it, one uninstalled leaves it. Returns how many faces came and went, 0 when nothing did.
The system’s fonts are scanned once a process, and every session
starts from that scan, so a font the user installs while the app
runs is not seen until something asks. The winit runner
(kui-native) asks itself when macOS or Windows says the installed
fonts changed; a host with its own windowing, or on Linux, where
fontconfig says nothing, calls this when it has reason to think the
set changed (a “fonts” pane opening, the window taking focus back).
It opens every font file on the system — tens of milliseconds on a
Mac’s 1300 faces — so it is not a per-frame call. Sessions made after
it start from the new scan; another
session that already exists keeps what it has until it calls this
too.
Faces still installed keep their handles and their place in every
cache; fonts the app loaded itself (add_font_data,
load_font_file, load_fonts_dir) are not touched. Every window
of the session shapes its text again on its next frame, since
fallback can land on a new face anywhere; every one of them owes
that frame (animating), and each window’s next frame reports a fonts event to
the host, for an app that keeps the font list in its model. A face
whose file was replaced in place, under the same
path, is not read again.
Sourcepub fn add_system_font(&mut self, name: &str) -> Option<FontId>
pub fn add_system_font(&mut self, name: &str) -> Option<FontId>
The handle for a font family by name ("Menlo", "Antonio") —
installed on the system or loaded with load_fonts_dir /
load_font_file; None when no face matches (see
system_font_families). Idempotent: the same family gets the same
handle, so views can call it every frame.
Sourcepub fn set_fallback_fonts(&mut self, fonts: &[FontId])
pub fn set_fallback_fonts(&mut self, fonts: &[FontId])
The families asked, in order, for a character the text’s own
family has no glyph for — before the platform’s fallback list,
whose first choice is the system’s interface face: proportional on
macOS, so a Cyrillic word in a Latin-only monospaced family was
set in San Francisco. An editor names its icon face, the face it
ships and a monospaced one the machine has; a family that has not
got the character is passed over, and after the last the
platform’s list runs as before. For every family and every kind of
text in the session — plain, spans, an editor, a cell grid — and
kept across reload_system_fonts. FontFamily::Mono asks them
straight after its own face, ahead of the machine’s other
monospaced faces, which with no list it walks first (backlog
RG118). A handle that names no font is left out; an empty list is
the platform’s alone.
Not a per-frame call for a list that changes: a new list builds
the font system again over the same faces and every window of the
session shapes its text again: each owes a frame (animating), so
a driver draws the windows the call was not made through as well
(backlog RG118). The same list twice is nothing.
Sourcepub fn fallback_fonts(&self) -> Vec<String>
pub fn fallback_fonts(&self) -> Vec<String>
The families set_fallback_fonts named, in order.
Sourcepub fn remove_font(&mut self, id: FontId)
pub fn remove_font(&mut self, id: FontId)
Forgets a registered font; faces loaded from bytes leave the font database. Styles still naming it shape as sans-serif.
Sourcepub fn font_family(&self, id: FontId) -> Option<&str>
pub fn font_family(&self, id: FontId) -> Option<&str>
The registered family name behind a font handle, if it is live.
Read from this window’s mirror of the session’s fonts (see
session’s module doc), which every registration refreshes and so
does every frame — a font another window registered mid-frame shows
up here on the next one.
Sourcepub fn system_font_families(&self) -> Vec<String>
pub fn system_font_families(&self) -> Vec<String>
Family names of every installed font the core can see (sorted,
deduplicated) — what add_system_font accepts. The names of
system_fonts, which says what each is.
Sourcepub fn system_fonts(&self) -> Vec<SystemFont>
pub fn system_fonts(&self) -> Vec<SystemFont>
Every family the core can see, installed or loaded, one per family
and sorted by name — the families system_font_families names —
with what its faces say they are: monospaced, the weights, an
italic. Read from what the font database recorded
when it scanned each face, so a fonts pane showing the monospaced
ones first costs no file loaded and no glyph shaped. A face whose
glyphs cannot be measured never entered the database,
so a family of only such faces — macOS’s GB18030 Bitmap — is not
listed.
Sourcepub fn add_sound(&mut self, bytes: Vec<u8>) -> SoundId
pub fn add_sound(&mut self, bytes: Vec<u8>) -> SoundId
Registers a sound from its encoded file bytes (wav/ogg/mp3/flac — the driver’s backend decodes; the core only keeps the bytes).
Sourcepub fn remove_sound(&mut self, id: SoundId)
pub fn remove_sound(&mut self, id: SoundId)
Forgets a sound; the driver drops its decoded copy. Playbacks already running keep going.
Sourcepub fn play(&mut self, sound: SoundId, opts: PlayOptions) -> PlaybackId
pub fn play(&mut self, sound: SoundId, opts: PlayOptions) -> PlaybackId
Starts a playback; the returned id addresses it in stop /
set_volume / pause / resume. With a tag in the options, the
playback finishing on its own comes back as
{kind="sound", phase="ended", playback, tag} on the current
origin’s root — the host’s, or the extension’s during its view.
Sourcepub fn stop(&mut self, playback: PlaybackId, fade_ms: f32)
pub fn stop(&mut self, playback: PlaybackId, fade_ms: f32)
Stops a playback, fading over fade_ms (0 = at once). A stopped
playback never reports ended.
Sourcepub fn set_volume(&mut self, playback: PlaybackId, volume: f32, tween_ms: f32)
pub fn set_volume(&mut self, playback: PlaybackId, volume: f32, tween_ms: f32)
Sets a playback’s volume (linear amplitude), tweening over tween_ms.
pub fn pause(&mut self, playback: PlaybackId, fade_ms: f32)
pub fn resume(&mut self, playback: PlaybackId, fade_ms: f32)
Sourcepub fn set_master_volume(&mut self, volume: f32, tween_ms: f32)
pub fn set_master_volume(&mut self, volume: f32, tween_ms: f32)
Sets the master volume (linear amplitude), tweening over tween_ms.
Sourcepub fn audio_node(&mut self, spec: AudioSpec) -> Key
pub fn audio_node(&mut self, spec: AudioSpec) -> Key
An audio node: a playback retained by key for as long as the view
keeps declaring it — present means playing (once, or looped),
gone means stopped; volume / paused changes apply live, a
changed src restarts. The key is auto-assigned from the tree
position; see audio_node_keyed for a stable label. Draws nothing
and takes no layout space. The mount is this window’s: it is
reconciled against this window’s frames, and another window’s
frame declaring nothing leaves it playing.
Sourcepub fn audio_node_keyed(&mut self, label: &str, spec: AudioSpec) -> Key
pub fn audio_node_keyed(&mut self, label: &str, spec: AudioSpec) -> Key
audio_node with a label-derived key (stable across reorders).
Sourcepub fn playback_of(&self, key: Key) -> Option<PlaybackId>
pub fn playback_of(&self, key: Key) -> Option<PlaybackId>
The playback an audio node of this window holds, if it is
mounted — after the frame that declared it has finished.
Sourcepub fn take_audio_commands(&mut self) -> Vec<AudioCommand>
pub fn take_audio_commands(&mut self) -> Vec<AudioCommand>
Drains the audio commands queued since the last drain. Frame drivers apply them to a real device after each input dispatch and after each frame; headless drivers may simply never call.
Sourcepub fn audio_ended(&mut self, playback: PlaybackId)
pub fn audio_ended(&mut self, playback: PlaybackId)
The driver reports a playback finished on its own (not stopped).
A tagged playback becomes an ended event, pending like a resize
(see take_pending_events).
Sourcepub fn audio_truncated(&mut self, playback: PlaybackId, at: f64)
pub fn audio_truncated(&mut self, playback: PlaybackId, at: f64)
The driver reports it stopped a playback that was still running,
at seconds into the sound. When that stop was a one-shot audio
node going away (or changing its src) without
finish, the node is named in a
TRUNCATED_PLAYBACK warning;
anything else — a stop that landed after the sound ended, an
imperative Self::stop, a loop, a released playback — reports
nothing. The driver stays key-blind, as Self::audio_ended is.
Sourcepub fn audio_refused(&mut self, playback: PlaybackId)
pub fn audio_refused(&mut self, playback: PlaybackId)
The driver refused a play: the device’s voices are all held, or
the sound failed to decode. The playback never started, so it can
never report ended — a tagged one gets
{kind="sound", phase="refused", playback, tag} instead, pending
like an ended is, so a view waiting on the sound is unstuck and
can tell the two apart. crate::diag::PLAYBACK_REFUSED is raised
on the node that asked either way, behind the usual diagnostics
gate, so an untagged refusal is not silent.
Sourcepub fn update_image(
&mut self,
id: ImageId,
width: u32,
height: u32,
rgba: Vec<u8>,
) -> bool
pub fn update_image( &mut self, id: ImageId, width: u32, height: u32, rgba: Vec<u8>, ) -> bool
Replaces an image’s pixels in place; see Resources::update_image.
If the image had been drawn from the atlas
its slot is forgotten — one eviction, once — and from here on it is
texture-backed. A foreign or removed handle warns and changes
nothing, and so does a buffer that is not width × height × 4
bytes; the return says whether the pixels were taken.
Sourcepub fn update_image_with(
&mut self,
id: ImageId,
width: u32,
height: u32,
fill: impl FnOnce(&mut [u8]),
) -> bool
pub fn update_image_with( &mut self, id: ImageId, width: u32, height: u32, fill: impl FnOnce(&mut [u8]), ) -> bool
Replaces an image’s pixels by writing them into a buffer the core
recycles; see Resources::update_image_with. fill gets
width × height × 4 bytes holding an earlier frame’s pixels and
writes every one. Where Self::update_image takes a buffer the
app allocated — and frees the one it replaces — this one stops
allocating after a stream’s third update, which on Windows is most
of what a 1080p update cost. Render into fill’s
slice rather than into a buffer of your own to skip the copy too.
fill runs while the session’s resources are borrowed, so it must
not reach them through another window’s Core; that panics.
Sourcepub fn image_pixels(&self, id: ImageId) -> Option<(u32, u32, Arc<Vec<u8>>)>
pub fn image_pixels(&self, id: ImageId) -> Option<(u32, u32, Arc<Vec<u8>>)>
The pixels behind an image handle — its size and a shared handle on
the bytes — for a host that renders the display list itself and
meets a QuadKind::Texture quad. None for a dead or foreign
handle, which is also noted as a miss.
Sourcepub fn remove_image(&mut self, id: ImageId)
pub fn remove_image(&mut self, id: ImageId)
Unregisters an image and forgets its atlas slot — every other window’s atlas forgets its own at that window’s next frame — or, for a texture-backed one, has the next display list any window builds tell the backend to drop the texture.
Sourcepub fn path_texture_count(&self) -> usize
pub fn path_texture_count(&self) -> usize
What the session removed and no display list has carried yet,
onto this frame’s — a backend frees a texture or a pipeline
once, on whichever window draws next, since both are the device’s
and the device is shared. And this window’s own atlas slots for
images the registry no longer holds, when a removal has moved the
revision since this core last looked: the atlas is per window, so
the removing core’s eviction reached only its own.
How many path masks this core draws from textures of their own
rather than the atlas — too big for a page, or animating (ADR
0040, decisions 7 and 8). For a test of which road a path took.
Source§impl Core
impl Core
Sourcepub fn reveal(&mut self, key: Key)
pub fn reveal(&mut self, key: Key)
Scrolls the nearest scrolling ancestor of key so the node is
inside it — what Tab does to the control it lands on, asked for by
name. Already-visible nodes stay put.
The request resolves at the next finish_frame, against the frame
that one lays out — the frame being built if this is called from a
view, the one after it if from an event handler (a frame is
requested, so one comes). That is what lets a view reveal a row it
is declaring for the first time. If that frame does not declare
key, or nothing above it scrolls, it is a no-op — the request is
spent, not held for the frame that might. Two reveals before one
frame into the same container are contradictory, so the last one
wins there; reveals into different containers — a tab strip and
the pane list under it — are not, and each lands.
Traced, the ask is "reveal" at the caller’s line.
Sourcepub fn reveal_label(&mut self, label: &str)
pub fn reveal_label(&mut self, label: &str)
Self::reveal by the label a node declares, resolved when the
frame finishes — against the frame being built, or the next one
when none is — so a view may name a row it is declaring right now,
or one the frame after declares. A label that frame
does not declare raises label-without-node and moves nothing.
Sourcepub fn set_scroll_label(&mut self, label: &str, offset: Vec2)
pub fn set_scroll_label(&mut self, label: &str, offset: Vec2)
Self::set_scroll by label, resolved like Self::reveal_label
but before layout, so the frame that resolves it lays out at the
offset.
Sourcepub fn scroll_offset(&self, key: Key) -> Vec2
pub fn scroll_offset(&self, key: Key) -> Vec2
The retained scroll offset of the container key, as the last
layout clamped it (positive = content moved up / left) — the
target: while a container with a transition eases to it the
content is drawn short of it, where Self::scroll_geometry
says. Zero for a node that never scrolled, and for one that is not
a container at all — the store keeps offsets, not membership.
Sourcepub fn scroll_geometry(&self, key: Key) -> Option<ScrollGeometry>
pub fn scroll_geometry(&self, key: Key) -> Option<ScrollGeometry>
Everything the last layout resolved for the container key: its own
box, its content size, and the clamped offset — None for a key no
layout has ever resolved as a scroll container. While an eased
leg runs the offset is where the content is drawn rather than
the target, sampled at the clock the coming frame reads, so a view
slices the rows that frame shows.
This is what makes a long list affordable. The core culls glyphs by
viewport but builds every child a view declares, so ten thousand rows
cost ten thousand rows; with the offset and the container’s height a
view can declare only the rows that can be seen and two spacers, and
pay for a screenful. widgets::uniform_list is that, done.
Read during a build, it describes the frame before — the tree it came
from is already cleared. That is one frame of lag on the size, so the
frame after a resize slices to the old height; a row or two of
overscan covers it, which is what the widget does. The rect is the
same one an on_layout on that node would post, without the round
trip through the app’s model, and without firing every time an
enclosing container scrolls the whole list past.
Sourcepub fn layout_of(&self, key: Key) -> Option<Rect>
pub fn layout_of(&self, key: Key) -> Option<Rect>
The rect the last frame laid key out at, in logical viewport px —
for a node that declared on_layout, whose rect the core keeps for
the event’s edge trigger anyway. The query
shape of the layout event: the same numbers, read during the next
build with no event, no tag and no model field. None for a key
that did not declare on_layout last frame; read during a build it
describes the previous frame, like Self::scroll_geometry.
Sourcepub fn set_scroll(&mut self, key: Key, offset: Vec2)
pub fn set_scroll(&mut self, key: Key, offset: Vec2)
Sets the container key‘s retained offset, the way the wheel would.
Takes effect at the next layout, which clamps it to that frame’s
overflow: Vec2::ZERO is “jump to the top”, and a large value is
“jump to the end” without knowing the content height. Writing an
offset for a key that never scrolls is harmless; it just never
reads back. Between two frames the write asks for the frame that
lands it; from inside a view it asks for nothing, because the
frame being built is that frame — the positions pass reads the
store after the view has run — and a view writing every frame
would otherwise be a window that never idles (the devtools’ events
list and widgets::list both write this way).
Sourcepub fn shift_scroll(&mut self, key: Key, drawn: Vec2, target: Vec2)
pub fn shift_scroll(&mut self, key: Key, drawn: Vec2, target: Vec2)
Moves key’s scroll state by the content that moved under it:
drawn for where the content is drawn (and an eased leg’s start),
target for the retained offset. No ease is asked or ended, and no
frame is asked for: it is a correction to the frame about to be
laid out — the rows above the window were measured and came out
another height — so it belongs to that frame, whoever calls it. A
variable-height list’s anchor: widgets::list from its view,
the Node and Lua ports from theirs, just before the tree they
return is laid out.
Source§impl Core
impl Core
Sourcepub fn selection(&self) -> Option<Selection>
pub fn selection(&self) -> Option<Selection>
The window’s text selection outside an editor, if it has one.
Sourcepub fn cell_selection(&self) -> Option<CellSelection>
pub fn cell_selection(&self) -> Option<CellSelection>
The window’s selection when it lives in a cells grid.
Sourcepub fn set_cell_selection(&mut self, sel: CellSelection)
pub fn set_cell_selection(&mut self, sel: CellSelection)
Sets it, clearing whatever else the window had selected.
Sourcepub fn cell_at(&mut self, key: Key, point: Vec2) -> Option<CellEnd>
pub fn cell_at(&mut self, key: Key, point: Vec2) -> Option<CellEnd>
Where point lands in the grid key drew, as an absolute line and
a column — the address a cell selection’s end is. None when the
node drew no grid.
Sourcepub fn select_word_in_cells(
&mut self,
key: Key,
point: Vec2,
block: bool,
) -> Option<(u64, usize, usize)>
pub fn select_word_in_cells( &mut self, key: Key, point: Vec2, block: bool, ) -> Option<(u64, usize, usize)>
Selects the word under point in the grid key — a double click
on a terminal. Answers the span it took, as an absolute line and a
half-open column range, so a drag that follows can round to it.
Sourcepub fn select_line_in_cells(
&mut self,
key: Key,
point: Vec2,
block: bool,
) -> Option<(u64, usize, usize)>
pub fn select_line_in_cells( &mut self, key: Key, point: Vec2, block: bool, ) -> Option<(u64, usize, usize)>
Selects the whole row under point — a triple click. Edge to edge,
the way a line in the middle of a linewise selection runs; the
copy is what trims the blanks off the end of it.
Sourcepub fn begin_cell_selection(
&mut self,
key: Key,
point: Vec2,
block: bool,
) -> bool
pub fn begin_cell_selection( &mut self, key: Key, point: Vec2, block: bool, ) -> bool
Starts a cell selection at point in the grid key.
Sourcepub fn extend_cell_selection(&mut self, point: Vec2) -> bool
pub fn extend_cell_selection(&mut self, point: Vec2) -> bool
Moves the live end of a cell selection to point.
Sourcepub fn cell_selection_text(&self) -> Option<String>
pub fn cell_selection_text(&self) -> Option<String>
The selected cells as text: one line per grid row it covers, each with its trailing blanks trimmed — the rule that makes a copied screen paste like text instead of like a rectangle of spaces.
Only what the grid holds: a selection whose ends reach into the scrollback copies the lines on screen, because the lines behind it were never handed to the core.
Sourcepub fn set_selection(&mut self, sel: Selection)
pub fn set_selection(&mut self, sel: Selection)
Sets it. The scope is a node that declared selectable; the two
ends are addresses inside it (a node key and a byte in that node’s
own text). Ends the frame cannot resolve paint nothing rather than
something else, so setting a selection against a tree that has
since changed is safe.
Clears the focused editor’s own selection: there is one selection per window.
Sourcepub fn clear_selection(&mut self) -> bool
pub fn clear_selection(&mut self) -> bool
Drops the selection. Returns whether there was one.
Sourcepub fn select_all_in(&mut self, scope: Key) -> bool
pub fn select_all_in(&mut self, scope: Key) -> bool
Selects every run in scope, first byte to last — what Select All
does inside one. false when the scope drew no text.
Sourcepub fn selection_hit(&self, scope: Key, point: Vec2) -> Option<Endpoint>
pub fn selection_hit(&self, scope: Key, point: Vec2) -> Option<Endpoint>
Where point (logical viewport px) lands inside scope, as the
address a selection end is made of. None when the scope drew
nothing the pointer could land in — an off-screen run is part of
the scope’s text but is under no pointer.
Sourcepub fn selection_text(&self) -> Option<String>
pub fn selection_text(&self) -> Option<String>
The selected text, assembled across every run the selection covers — including runs the frame built but never drew, which is what makes a selection that ran past the bottom of a scroller copy what the reader dragged over.
None with no selection; an empty string when the selection is
empty or its ends no longer resolve.
Sourcepub fn selection_rect(&self) -> Option<Rect>
pub fn selection_rect(&self) -> Option<Rect>
The box the window’s selection occupies, logical viewport px — what a platform panel about that selection is anchored to. The union of the drawn runs it covers, so a selection that runs off the screen is anchored by the part the reader can see.
None with no selection, an empty one, or one whose runs the
frame never drew.
Sourcepub fn selection_anchor(&self) -> Option<Vec2>
pub fn selection_anchor(&self) -> Option<Vec2>
Where a platform panel about the selection should point: the
baseline origin of its first line, logical viewport px. See
TextSystem::scope_selection_anchor.
Sourcepub fn selection_html(&self) -> Option<String>
pub fn selection_html(&self) -> Option<String>
The selection as HTML — the same text selection_text gives, with
the bold, the italic and the span colours it was declared with.
None with no text selection; a cells
selection has no styling to carry and answers None too.
Meant as the second clipboard flavour, beside the plain text and never instead of it: an editor that understands HTML takes the formatting, and everything else takes the words.
Sourcepub fn selection_range(&self) -> Option<(RangeEnd, RangeEnd)>
pub fn selection_range(&self) -> Option<(RangeEnd, RangeEnd)>
The selection’s two ends as the app’s own addresses — the data
index of the virtualised row each is in, and the byte inside that
row’s text — in reading order: from precedes to whichever
way the drag was made, so an app answering a selectionrange ask
can iterate from..=to (the clipboard examples do). None when
there is no selection, or when neither end is in a virtualised row
(nothing to ask about: the core has it all). The directed pair is
Self::selection_ends.
Sourcepub fn selection_ends(&self) -> Option<(RangeEnd, RangeEnd)>
pub fn selection_ends(&self) -> Option<(RangeEnd, RangeEnd)>
The selection’s two ends as the drag made them — the anchor where
the press landed, the focus where the pointer is — each as the
data index of the virtualised row it is in (None outside every
virtualised row) and the byte inside that node’s own text. The
directed pair, unlike Self::selection_range’s: what a test or
a model that mirrors the selection reads, and what says whether a
Shift-press kept the anchor. None with no text
selection; a grid’s is cell_selection.
Sourcepub fn request_copy(&mut self) -> CopyRequest
pub fn request_copy(&mut self) -> CopyRequest
Asks for the selection as text, and says how the answer will come.
CopyRequest::Ready is the ordinary case: everything selected is
text the core shaped, so it hands it over. CopyRequest::Asked
is a selection that reaches rows a virtual list never built — the
core posts {kind:"selectionrange", from:{index, byte}, to:{index, byte}} on the scope and waits for
Self::answer_selection_range, because the rows behind that gap
are the app’s and only the app has them.
The event goes out with the frame’s pending events, so a host that
calls this outside handle_input drains take_pending_events
after it.
Sourcepub fn answer_selection_range(&mut self, text: &str) -> bool
pub fn answer_selection_range(&mut self, text: &str) -> bool
The app’s answer to a selectionrange ask: the text for the range
it was asked about, whole. Queues it for the clipboard the way a
menu’s Copy does, and is ignored when nothing asked — a stale
answer cannot overwrite what somebody copied since.
Sourcepub fn set_clipboard(&mut self, text: impl Into<String>, html: Option<String>)
pub fn set_clipboard(&mut self, text: impl Into<String>, html: Option<String>)
Puts text on the system clipboard — queued as the
MenuAction::SetClipboard a menu’s Copy produces, for the host to
apply at its next drain (the runner’s is after every input and
every frame). html is a second flavour beside the text for a
host that offers one, never in place of it.
Sourcepub fn set_clipboard_secret(&mut self, text: impl Into<String>)
pub fn set_clipboard_secret(&mut self, text: impl Into<String>)
Puts a secret on the system clipboard the way a password manager
does — queued as MenuAction::SetClipboardSecret,
which the runner writes marked concealed and transient, so a
clipboard manager neither shows nor keeps it. What the marks are on
each platform is on the action. The text alone: a secret has no
second flavour to offer.
Sourcepub fn request_paste(&mut self)
pub fn request_paste(&mut self)
Asks for what is on the clipboard — queued as the
MenuAction::Paste a menu’s Paste produces. The host reads the
clipboard and hands the text back as InputEvent::Paste (or a
bare InputEvent::Commit), which reaches a focused editor as
typing and a focused sink as {kind:"text", text, tag}, with
concealed: true / transient: true beside the text
when the pasteboard marked it so — so the app that asked
inserts it the way it inserts a committed IME string, and never
sees the clipboard any other way. The read stays on the driver’s
side, where the permission lives.
One ask at a time: while a paste is outstanding — queued, or taken
by the driver and not yet answered — a second ask is dropped, so a
view that asks on every frame until the answer lands asks once.
The answer is the Paste (or Commit) the driver sends, an empty
one when the clipboard held nothing, and Core::awaiting_paste
reads the state.
Sourcepub fn awaiting_paste(&self) -> bool
pub fn awaiting_paste(&self) -> bool
Whether a paste ask is outstanding: asked and not yet answered
with a Paste or a Commit.
Sourcepub fn request_files(&mut self, dialog: FileDialog) -> bool
pub fn request_files(&mut self, dialog: FileDialog) -> bool
Asks the host for a file dialog: an Open, a Save or
a folder picker, which the host shows as the platform’s own. The
answer is an event, {kind:"files", paths, tag} — the drop
payload’s shape, paths empty when the user cancelled — delivered
to whoever asked: the host from its own view or between frames, the
extension from inside its fill. A host drains the ask with
Core::take_file_requests and answers with InputEvent::Files;
the runner does both.
One ask at a time, as for a paste: while one is outstanding — queued, or taken and not yet answered — another is dropped and this returns false, so a view that asks every frame until the answer lands asks once. Between frames it asks for the frame that hands the ask to the host.
Sourcepub fn awaiting_files(&self) -> bool
pub fn awaiting_files(&self) -> bool
Whether a file dialog asked for is still unanswered.
Sourcepub fn take_file_requests(&mut self) -> Vec<FileDialog>
pub fn take_file_requests(&mut self) -> Vec<FileDialog>
The file dialog asked for and not yet taken — at most one — for the host to show. Taking it keeps the ask outstanding until the answer.
Sourcepub fn begin_selection(&mut self, scope: Key, point: Vec2) -> bool
pub fn begin_selection(&mut self, scope: Key, point: Vec2) -> bool
Starts a selection at point inside scope — the press half of a
drag-select. Both ends land together, so nothing is selected until
the pointer moves.
Sourcepub fn extend_selection(&mut self, point: Vec2) -> bool
pub fn extend_selection(&mut self, point: Vec2) -> bool
Moves the live end of the selection to point — the motion half.
The anchor stays where the press put it, so dragging back past it
selects the other way rather than starting again.
Sourcepub fn keyboard_select(&mut self, scope: Key, key: EditKey, mods: Mods) -> bool
pub fn keyboard_select(&mut self, scope: Key, key: EditKey, mods: Mods) -> bool
A keyboard’s selection in a selectable scope:
Shift with an arrow, Home or End on a focused node inside scope
— the scope itself when it is focusable, a control inside it —
moves the selection’s focus the way the stock editor’s Shift-
motions move its caret: a character (a word with mods.word)
left or right through the scope’s runs in order, Home and End to
the scope’s first and last byte. Nothing selected yet, the anchor
is placed at the scope’s start, so Shift-End from a freshly
focused label selects it whole. Returns whether the selection
changed. Answered from the frame that finished, like a drag; the
endpoints carry their virtual rows like every other selection, so
a copy past the built range asks the app for the text, as any
virtualised selection does. Up and Down are not motions here: a scope has no line
geometry a caret could keep a column in.
Sourcepub fn select_word_at(
&mut self,
scope: Key,
point: Vec2,
) -> Option<(Key, usize, usize)>
pub fn select_word_at( &mut self, scope: Key, point: Vec2, ) -> Option<(Key, usize, usize)>
Selects the word under point inside scope — a double click,
and (on macOS) a force click. Answers the span it took, in the
node’s own bytes, so a drag that follows can round to it.
Sourcepub fn select_run_at(
&mut self,
scope: Key,
point: Vec2,
) -> Option<(Key, usize, usize)>
pub fn select_run_at( &mut self, scope: Key, point: Vec2, ) -> Option<(Key, usize, usize)>
Selects the whole run under point — a triple click, which takes
the line a label is. Answers the span, like select_word_at.
Sourcepub fn select_word_under(&mut self, scope: Key, point: Vec2) -> bool
pub fn select_word_under(&mut self, scope: Key, point: Vec2) -> bool
Selects the word under point in scope, whichever way the scope
addresses itself — what a double click takes, and what a force
click takes before it asks for a definition. false when there
was no word there.
Source§impl Core
impl Core
Sourcepub fn declare_window(&mut self, name: &str, config: WindowConfig)
pub fn declare_window(&mut self, name: &str, config: WindowConfig)
Declares that a window named name exists this frame.
The window opens on the first frame any core declares it — that
frame’s finish_frame queues a crate::WindowCommand::Open with
the id the core assigned and raises {kind:"window", phase:"opened", name, id} — and closes, with a Close and a
phase:"closed", on the first frame none does. Declared every
frame it costs nothing after the first.
config is read on that opening edge and never again: re-declaring
a live window at another size changes nothing, because the user
owns its geometry once it exists. Where two declarations of one
name disagree on that edge, the lowest declaring window’s first
declaration wins and crate::diag::DUPLICATE_WINDOW_CONFIG
says so. A window the user closed (see Self::window_closed)
does not reopen while it is still declared — the declaration has
to stop and start again — and keeps raising
crate::diag::WINDOW_DECLARED_WHILE_CLOSED until it does.
"main" names the window the launcher opened and is always live.
Sourcepub fn window_name(&self) -> Rc<str>
pub fn window_name(&self) -> Rc<str>
The name of the window this core draws: "main" for
WindowId::MAIN, else the name the declaration that opened
env.window.id used. A driver that gave a core an id the session
never opened gets the id spelled out, so the answer is never empty.
Sourcepub fn windows(&self) -> Vec<(WindowId, Rc<str>)>
pub fn windows(&self) -> Vec<(WindowId, Rc<str>)>
Every window of the session that is open right now — main first,
then in the order they opened — as (id, name). What the
declaration diff has asked for, not what the driver has shown:
the two agree once the driver drains its commands.
Sourcepub fn window_closed(&mut self, id: WindowId)
pub fn window_closed(&mut self, id: WindowId)
The driver reports that the OS closed window id — its close
button, a keyboard shortcut, the window manager. The window is gone
and stays gone while its name is still declared (the app has to stop
declaring it and start again to reopen it; see
Self::declare_window); its own declarations leave the union, so
whatever only it declared closes too. Raises {kind:"window", phase:"closed", name, id} for the app, pending like a resize.
Nothing happens for the main window (closing it ends the app) or
for a window the diff already closed.
Sourcepub fn dismiss_window(&mut self, id: WindowId, reason: DismissReason)
pub fn dismiss_window(&mut self, id: WindowId, reason: DismissReason)
The driver reports that window id was asked to go away — a press
landed outside it, or Escape reached it (see
crate::window::DismissReason). Raises {kind:"dismiss", reason, name, id} on the root, pending like a resize, and closes
nothing: only the app can stop declaring the window, and it does
that on the frame it decides to, the way a modal closes. So an app that
graduates a dropdown from a modal float
to a popup window changes its declaration and keeps its handler.
Both facts behind it are the OS’s — a press outside a window lands
in another surface, and a non-activating popup never holds the
keyboard — so the core cannot notice either; a driver reports them
the way it reports a close (Self::window_closed). Nothing
happens for a window the session has not opened.
Sourcepub fn push_window_command(&mut self, cmd: WindowCommand)
pub fn push_window_command(&mut self, cmd: WindowCommand)
Queues a window command as if chrome had produced it, so apps can close/minimize/maximize from a keymap or command line. Drained by the frame driver with the rest.
Sourcepub fn set_window_size(&mut self, window: WindowId, size: Size)
pub fn set_window_size(&mut self, window: WindowId, size: Size)
Asks the driver to resize window to size (logical px). Queued
the way reveal and play queue theirs: a request the driver
applies on its next pump — after this input dispatch if called from
a handler, after this frame if called from a view — and one a
headless driver never applies, since it never drains. The window
answers through the ordinary resize event, with the size it
actually became.
Sourcepub fn focus_window(&mut self, window: WindowId)
pub fn focus_window(&mut self, window: WindowId)
Asks the driver to give window keyboard focus; queued like
Core::set_window_size. Whether the window manager agrees shows
up as env.focused on the frames that follow, not as a reply.
Sourcepub fn take_window_commands(&mut self) -> Vec<WindowCommand>
pub fn take_window_commands(&mut self) -> Vec<WindowCommand>
Drains window intents queued since the last drain — by chrome nodes,
by push_window_command, set_window_size and focus_window — in
the order they were queued. Frame drivers call this after each input
dispatch and each frame and apply the commands to the real window;
headless drivers may simply never call.
Sourcepub fn set_window_title(&mut self, title: &str)
pub fn set_window_title(&mut self, title: &str)
Declares this frame’s window title. Like all frame state it’s data: the driver diffs against what’s applied and only then touches the window. Undeclared frames leave the title alone; last writer wins.
Sourcepub fn window_title(&self) -> Option<&str>
pub fn window_title(&self) -> Option<&str>
The title declared this frame, if any (for the frame driver).
Sourcepub fn set_always_on_top(&mut self, on_top: bool)
pub fn set_always_on_top(&mut self, on_top: bool)
Declares that this frame wants the window above every other app’s:
a floating palette, a picture-in-picture player, a
timer. Frame state like the title, and the driver applies it the
same way — set_window_level when it differs from what is applied,
nothing when it does not — but it defaults to false rather than
“leave as-is”, so a frame that stops declaring it lowers the window
again and a pin button is a toggle on the app’s own state. Whether
the platform has a level to set is env.window.always_on_top: the
driver’s record of what it set, false on Wayland (where winit has
no call for it) however often the app asks — and not a query, so a
level the OS dropped afterwards (a fullscreen space, a tiling
manager) is not reported. A popup’s level is its own whatever its
owner declares.
Sourcepub fn always_on_top(&self) -> bool
pub fn always_on_top(&self) -> bool
Whether this frame asked for the window to stay on top (for the frame driver); false for a frame that never said.
Sourcepub fn set_secure_input(&mut self, on: bool)
pub fn set_secure_input(&mut self, on: bool)
Declares that this frame wants the keyboard to this window kept
from other processes while the window has it — macOS’s Secure
Keyboard Entry, what a terminal turns on at a password prompt.
Frame state like always_on_top: a frame that stops
declaring it turns it off, so an app asks on every frame the
prompt is up and never has to remember to undo it.
The runner owns the platform call and its balance: it enables
secure input only while a window whose frame asked has the
keyboard, and disables it when that window loses the keyboard,
closes, stops asking, or the app exits — Apple’s rule for it,
since while it is on no other process can read the keyboard at
all (a launcher’s hotkey, a text expander, an accessibility tool).
EnableSecureEventInput is process-wide and counted, and the
runner holds at most one count however many windows ask. Nothing
happens on other platforms, which have no such switch.
Sourcepub fn secure_input(&self) -> bool
pub fn secure_input(&self) -> bool
Whether this frame asked for secure keyboard entry (for the frame driver); false for a frame that never said.
Sourcepub fn set_option_as_alt(&mut self, option_as_alt: OptionAsAlt)
pub fn set_option_as_alt(&mut self, option_as_alt: OptionAsAlt)
Declares which Option keys act as Alt in this window on macOS:
a dead key under that Option — ⌥u, ⌥e, ⌥i, ⌥n,
⌥` — then arrives as the chord <A-u> rather than starting an
accent the app never hears, and a key under it types nothing, as
under Control. Frame state like always_on_top, default
OptionAsAlt::None: a frame that stops
declaring it gives the Option keys back to the layout, so an app
declares it on every frame — from a setting, say — and never has
to undo it.
The runner applies it to the window on change and never per frame. A popup never has the keyboard on macOS — its keys come through its owner, which stays key — so the owner’s declaration is the one a popup’s keys are read under. Nothing happens on other platforms, whose Alt composes nothing.
Sourcepub fn option_as_alt(&self) -> OptionAsAlt
pub fn option_as_alt(&self) -> OptionAsAlt
Which Option keys this frame asked to act as Alt (for the frame
driver); None for a frame that never said.
Sourcepub fn set_ime_off(&mut self, off: bool)
pub fn set_ime_off(&mut self, off: bool)
Declares that this window takes the keyboard as keys, with the
platform’s input method off: no composition and no candidate
window, and on a Mac no dead key waiting for the next one and no
press-and-hold — which is an input method too, so a held letter
repeats instead of opening the accent picker, whatever the user’s
ApplePressAndHoldEnabled says. A key’s text is still the
layout’s character; what goes is everything the OS would have
composed from it. What a modal editor’s normal mode wants, where
jjjj is how one moves and a Japanese IME left on eats the
keymap; its insert mode stops declaring it and gets both back.
Frame state like always_on_top, default off: a frame that stops
declaring it gives the window its input method back, so an app
declares it on every frame its mode wants it and never has to
undo it.
The runner applies it to the window on change and never per
frame (winit’s set_ime_allowed); a composition in progress when
it turns off is ended without a commit, as an empty preedit. It
is the window’s, not a node’s: a stock editor focused under it
composes nothing either. A popup’s keys arrive through its owner,
so the owner’s declaration is the one they are read under. On
Windows and Linux the window’s IME is disabled the same way, and
that is all: their dead keys are the layout’s (WM_DEADCHAR, xkb
compose), winit composes them whatever the IME says, and they
still compose.
Source§impl Core
impl Core
Sourcepub fn theme(&self) -> &Theme
pub fn theme(&self) -> &Theme
This window’s palette, as of this frame.
Resolved from Core::theme_source and env.system at the start
of every frame, so it is already right by the time a view runs.
Frame-stable on purpose: every widget in one frame paints from the
same palette, whatever the driver does to env while the view
runs. A host that writes env.system directly and wants the new
answer before its next frame calls Core::refresh_theme; every
env setter a binding exposes already does.
Sourcepub fn refresh_theme(&mut self)
pub fn refresh_theme(&mut self)
Re-resolve the palette from env.system now, rather than at the
start of the next frame. What an env setter calls after writing.
Sourcepub fn set_system(&mut self, system: SystemEnv)
pub fn set_system(&mut self, system: SystemEnv)
Writes what the user set in the OS and re-resolves the palette from
it, so a host that pushes the appearance and reads the theme back
before its next frame sees the answer. The one door for
a binding’s env setter: writing env.system by hand and forgetting
the refresh was a decision each of them had to remember.
Sourcepub fn env_facts(&self) -> EnvFacts
pub fn env_facts(&self) -> EnvFacts
The env reading’s inputs (schema::ENV_FIELDS): the stored env and
the frame’s own facts — viewport, scale, focus — that ride in the
same reading.
Sourcepub fn has_accent(&self) -> bool
pub fn has_accent(&self) -> bool
Whether anyone actually chose the accent — the OS reported one, or the app set or pinned one — as opposed to the palette falling back to kui’s own blue.
The question the accent row asks before it repaints anything:
that row has always meant “the accent colour where there is one,
the bg I declared where there is not”, so a view can name its
own fallback and a host that knows nothing changes nothing. The
theme widened where the accent comes from without widening
whether there is one.
Sourcepub fn theme_source(&self) -> ThemeSource
pub fn theme_source(&self) -> ThemeSource
Where the palette comes from. ThemeSource::Derived by default.
Sourcepub fn set_theme_source(&mut self, source: ThemeSource)
pub fn set_theme_source(&mut self, source: ThemeSource)
Change where the palette comes from. Takes effect on the next
frame, and immediately for anything reading Core::theme after
this call, so a host may set it before its first frame or in a
handler and get the same answer either way.
Sourcepub fn set_theme(&mut self, theme: Theme)
pub fn set_theme(&mut self, theme: Theme)
Pin a palette: this exact Theme, following neither the OS’s
appearance nor its accent. Shorthand for
ThemeSource::Pinned.
Sourcepub fn set_accent(&mut self, accent: Color)
pub fn set_accent(&mut self, accent: Color)
Keep following the OS’s light/dark, but paint this accent instead
of the OS’s. Shorthand for ThemeSource::DerivedWithAccent, and
what an app with a brand colour wants.
Sourcepub fn derive_theme(&mut self)
pub fn derive_theme(&mut self)
Go back to following the OS for both — the default.
Sourcepub fn metrics(&self) -> &Metrics
pub fn metrics(&self) -> &Metrics
The sizes the stock widgets are built from — the palette’s other
axis (crate::metrics). Metrics::default until
the app sets one; nothing in the OS is followed.
Sourcepub fn set_tokens(&mut self, tokens: Tokens)
pub fn set_tokens(&mut self, tokens: Tokens)
Declare the tokens the running origin references by name:
the host’s outside a
fill, the filling extension’s inside one. Replaces that origin’s
table whole, so an app whose lengths change with a viewport tier
declares again on resize. A name a role owns is dropped with a
reserved-token warning, once per name. A derived token whose
source did not resolve is dropped with unknown-token, naming both.
Sourcepub fn tokens_declared(&self, origin: OriginId) -> bool
pub fn tokens_declared(&self, origin: OriginId) -> bool
Whether origin has declared a table — what an extension asks
before declaring the one it was loaded with, so a per-frame view
declares once.
Sourcepub fn token_lookup(&self) -> TokenLookup<'_>
pub fn token_lookup(&self) -> TokenLookup<'_>
What a $name in a prop resolves to this frame: the running
origin’s table over the host’s, the theme’s and metrics’ roles in
front of both. What every binding lowers a reference through.
Sourcepub fn warn_unknown_family(&mut self, name: &str)
pub fn warn_unknown_family(&mut self, name: &str)
A binding lowered a family that names nothing installed or
loaded: raise unknown-family, once per name. The text
shapes as sans, which is what the message says.
Sourcepub fn warn_unknown_token(&mut self, err: &TokenError)
pub fn warn_unknown_token(&mut self, err: &TokenError)
A binding lowered a reference that did not resolve: raise
unknown-token, once per name, saying which slot asked. The slot
keeps its default, which is what the message says.
Sourcepub fn set_metrics(&mut self, metrics: Metrics)
pub fn set_metrics(&mut self, metrics: Metrics)
Makes metrics the frame’s: every stock widget from the next node
on is built from it, and ui.metrics() reads it back. Logical px,
before env.scale; a density is the app’s to choose
(Metrics::compact, Metrics::scaled).
Sourcepub fn new_in(session: &Session) -> Core
pub fn new_in(session: &Session) -> Core
A core joining an existing session: it draws with the same fonts,
images, sounds, shaping caches and glyph atlas as every other core
constructed against session, and plays through the same audio
device. Everything else — tree, focus, scroll, viewport — is this
window’s alone.
Sourcepub fn measure_text(
&mut self,
content: &str,
style: &TextStyle,
max_w: Option<f32>,
) -> TextMetrics
pub fn measure_text( &mut self, content: &str, style: &TextStyle, max_w: Option<f32>, ) -> TextMetrics
Measures content in style without adding a node: its unwrapped
size, or with max_w (logical px) its size once wrapped to that
width — what layout would give a text node with that content and
style, wrap / max_lines / ellipsis included. Logical px at
the scale of the current or last frame (1 before any frame).
Shapes through the text cache, so measuring a string and then
drawing it shapes once.
Sourcepub fn measure_rich_text(
&mut self,
spans: &[Span<'_>],
base: &TextStyle,
max_w: Option<f32>,
) -> TextMetrics
pub fn measure_rich_text( &mut self, spans: &[Span<'_>], base: &TextStyle, max_w: Option<f32>, ) -> TextMetrics
measure_text for a rich-text paragraph.
Sourcepub fn text_hit(&self, key: Key, point: Vec2) -> Option<TextHit>
pub fn text_hit(&self, key: Key, point: Vec2) -> Option<TextHit>
Where a point lands in the text node key drew: a byte offset into
its content and the visual row within that node — counted across
every run the key covers by where the rows sit, so a line row of
inline runs is one row and a wrapped run as many as it wrapped to;
not the ordinal line node a pointer event names
— or None for a key that is not a text node or was not drawn.
A role="none" subtree under the key (a gutter) is
not its text, as the access tree reads it. point is logical
viewport px — the x/y a click or drag event carries — so a
custom editor turns the event into a caret position with one call
instead of measuring prefixes or assuming a cell width. Answered
from the frame that finished: between frames that is the layout the
pointer was over, and during a build it is the last one, since the
node being declared has no layout yet. A wrapped node answers in
the width it was drawn at.
Sourcepub fn caret_rect(&self, key: Key, byte: usize) -> Option<Rect>
pub fn caret_rect(&self, key: Key, byte: usize) -> Option<Rect>
The caret rect for byte byte of the text node key drew: logical
viewport px, zero wide, one line tall — where a caret, an IME
candidate window or a selection edge goes. byte past the content
is the end. Answered from the same frame text_hit is.
Sourcepub fn announce(&mut self, text: &str, live: Live)
pub fn announce(&mut self, text: &str, live: Live)
Says something once, with no node behind it: “Saved”, “3 results”.
Queued for Self::take_announcements, the way play queues an
audio command — an announcement is a consequence of an event, and
the frame’s tree, which is a function of state, has no place to
keep one.
A region whose text changes on screen is the other half, and is
the live prop instead.
Live::Off and an empty string are both no-ops — the first so a
caller can gate politeness without an if, the second because
every platform needs a name to say.
Sourcepub fn take_announcements(&mut self) -> Vec<Announcement>
pub fn take_announcements(&mut self) -> Vec<Announcement>
Drains the announcements queued since the last drain. Windowed runners drain every frame whether or not assistive technology is attached, and discard what they cannot deliver, so a real app never accumulates and nothing is spoken minutes late; headless drivers assert on what comes back.
Sourcepub fn pending_announcements(&self) -> &[Announcement]
pub fn pending_announcements(&self) -> &[Announcement]
Announcements queued and not yet drained (what pending is for
audio commands).
Sourcepub fn take_warnings(&mut self) -> Vec<Warning>
pub fn take_warnings(&mut self) -> Vec<Warning>
Drains the warnings raised since the last drain (see crate::diag):
silent misconfigurations the core noticed while finishing frames,
each distinct (code, node) pair once. Windowed runners print them;
headless tests assert on them.
Sourcepub fn warnings_raised(&self) -> &[Warning]
pub fn warnings_raised(&self) -> &[Warning]
Every warning this core has raised, drained or not, oldest first —
for a reader that is not the driver. The runner drains
Self::take_warnings after every frame and prints them, so a
view that wants to show them (a development overlay) would
otherwise never see one; this is the log the drain leaves behind.
Sourcepub fn warn(&mut self, warning: Warning)
pub fn warn(&mut self, warning: Warning)
Raises a warning a binding built (see crate::diag::unknown_prop):
a frontend sees declarations the tree walk cannot, because a prop
name nothing claims never becomes part of a node. Behind the same
Self::set_diagnostics gate and the same once-per-(code, key)
dedup as the checks, so a binding may raise one per node per frame.
Sourcepub fn set_diagnostics(&mut self, on: bool)
pub fn set_diagnostics(&mut self, on: bool)
Turns the diagnostic checks on or off. A bare Core has them on;
drivers set them for the build they are in (the runner: debug on,
release off; Node loops: off under NODE_ENV=production; a
standalone C context: off until asked).
pub fn diagnostics(&self) -> bool
Sourcepub fn lines_to_px(lines: f32) -> f32
pub fn lines_to_px(lines: f32) -> f32
Wheel line-deltas (e.g. winit’s LineDelta) to logical px.
Sourcepub fn set_subpixel_text(&mut self, on: bool)
pub fn set_subpixel_text(&mut self, on: bool)
Rasterizes outline glyphs as LCD subpixel coverage
(QuadKind::GlyphSubpixel) instead of alpha masks. Drivers set it
from what their renderer can blend per channel; flipping it drops
the glyph atlas so every glyph re-rasterizes in the new mode.
pub fn subpixel_text(&self) -> bool
Sourcepub fn set_text_cache_budget(&mut self, bytes: usize)
pub fn set_text_cache_budget(&mut self, bytes: usize)
The byte budget for the shaped-text cache: every
text a frame draws is shaped once and kept, and past this many
estimated bytes the least recently drawn entries go, down to three
quarters of it, at the start of the next frame. What the last
frame drew is never evicted, so a budget too small for one
screenful costs re-shaping nothing — it only stops keeping what
scrolled away. Default DEFAULT_TEXT_CACHE_BYTES (64 MB): a
terminal streaming new lines lowers it, a document viewer that
wants every page it showed to stay warm raises it. The clock that
empties an idle cache after 300 frames is unchanged.
pub fn text_cache_budget(&self) -> usize
Sourcepub fn text_cache_bytes(&self) -> usize
pub fn text_cache_bytes(&self) -> usize
What the shaped-text cache holds, as the estimate the budget is
charged against (a fixed floor per entry plus a per-glyph rate,
calibrated against a counting allocator; see text.rs).
Sourcepub fn text_cache_len(&self) -> usize
pub fn text_cache_len(&self) -> usize
How many shaped texts the cache holds (a long line’s chunks each count).
Sourcepub fn long_lines(&self) -> usize
pub fn long_lines(&self) -> usize
How many long lines — no-wrap texts past LONG_LINE_BYTES, shaped
in chunks — are held.
Sourcepub fn set_time(&mut self, now_secs: f64)
pub fn set_time(&mut self, now_secs: f64)
The frame clock for transitions: monotonic seconds, any origin. Drivers set it before every frame; a driver that never does gets snapping instead of animation.
Sourcepub fn animating(&self) -> bool
pub fn animating(&self) -> bool
True when the last frame left a transition mid-flight, or a view
asked for another frame — drivers schedule one without waiting for
input. One bool over every source; owed is the
same reading by kind.
Sourcepub fn owed(&self) -> Owed
pub fn owed(&self) -> Owed
What the last frame left owed, by kind. To a driver
the kinds are one — it schedules the frame either way — but a
test that wants to know whether the transitions have run out
under a keyframe cycle that never will reads cycle apart from
the rest: Owed::beyond_cycles is that wait’s predicate.
Sourcepub fn request_frame(&mut self)
pub fn request_frame(&mut self)
Asks the driver for one more frame right after this one. A view that sets up a transition by drawing a starting state (a new split drawn collapsed so it can slide open) needs the next frame to come without waiting for input — the starting state itself snaps, so nothing is mid-flight yet to request it.
Traced (Self::set_frame_trace), the calling line is kept as
the frame’s cause::FrameRequest, which is why this tracks its
caller.
Sourcepub fn frame(&mut self, viewport: Size, scale: f32) -> Ui<'_>
pub fn frame(&mut self, viewport: Size, scale: f32) -> Ui<'_>
Starts a frame. Build the tree through the returned Ui (or the
Core builder methods directly), then Ui::finish — the one door
out of a frame, which runs the extension fills, the devtools panel
and the open menu before layout. A driver holding a bare Core
mid-frame finishes through Ui::wrap(core).finish().
Sourcepub fn frame_with<'a>(
&'a mut self,
viewport: Size,
scale: f32,
filler: &'a mut dyn Fill,
) -> Ui<'a>
pub fn frame_with<'a>( &'a mut self, viewport: Size, scale: f32, filler: &'a mut dyn Fill, ) -> Ui<'a>
frame with something to fill the slots the view declares — the
runner’s extension list ([Box<dyn Extension>] is a Fill), or a
test’s stand-in. Ui::slot calls it in place, and Ui::finish
lets it fill "root" and report unknown slots before layout.
Sourcepub fn session(&self) -> &Session
pub fn session(&self) -> &Session
The session this core draws from. Hand it to Core::new_in to open
another window sharing its fonts, images, sounds and glyph atlas.
Sourcepub fn viewport(&self) -> Size
pub fn viewport(&self) -> Size
The viewport (logical px) the current frame was begun with — the
window, less the devtools’ dock while the panel is docked:
what the host lays out into. Changes to it
arrive as resize events (see take_pending_events), a dock
coming, going or resizing among them.
Sourcepub fn origin(&self) -> OriginId
pub fn origin(&self) -> OriginId
The origin nodes opened right now are tagged with: OriginId::HOST
in the host’s own view, the filling extension’s inside a fill (see
Core::fill).
Sourcepub fn output(&mut self) -> (&DisplayList, &mut GlyphAtlas)
pub fn output(&mut self) -> (&DisplayList, &mut GlyphAtlas)
The finished frame’s draw data: display list plus the glyph atlas the renderer mirrors (mutable so it can clear the dirty flag).
Sourcepub fn begin_frame(&mut self, viewport: Size, scale: f32)
pub fn begin_frame(&mut self, viewport: Size, scale: f32)
Begins a frame without handing out a Ui: what Core::frame
calls first. A binding that drives the builder methods on the core
directly starts here and ends with Ui::wrap(core).finish().
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for Core
impl !RefUnwindSafe for Core
impl !Send for Core
impl !Sync for Core
impl !UnwindSafe for Core
impl Unpin for Core
impl UnsafeUnpin for Core
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.