pub struct GpuiApp {
pub editor_actor: EditorActorHandle,
pub render_state: Arc<ArcSwap<RenderState>>,
pub theme: GpuiTheme,
pub pane_render_registry: GpuiPaneRenderRegistry,
pub paint_request: Arc<Notify>,
}Expand description
The GPUI-side renderer composition root. Mirrors
lattice-ui-tui::app::App in shape: renderer-side caches
plus the renderer-neutral Editor. A future lsp_file_watcher
field joins when the LSP runtime adapter for GPUI lands.
Fields§
§editor_actor: EditorActorHandleSlice 3c.final.E.swap: cfg-gated. Production builds hold an
[EditorActorHandle]; test builds keep direct Editor
ownership for fixtures that mutate state without going
through the dispatch path. Same shape as TUI peer’s App.
render_state: Arc<ArcSwap<RenderState>>Phase 5.8.AF.5 / Slice 3c.atomic.K: renderer-side clone of
the editor’s RenderState cell. Parallel of the TUI peer’s
App.render_state field (3c.atomic.A): isolates the
renderer’s read path from self.editor so the eventual
App.editor: Editor → handle swap doesn’t disturb call
sites. Today both Arc handles point at the same underlying
ArcSwap<RenderState> instance — readers observe identical
values byte-for-byte regardless of which they go through.
theme: GpuiTheme§pane_render_registry: GpuiPaneRenderRegistry§paint_request: Arc<Notify>Slice 3c.final.B-extension: paint_request cloned at boot so
EditorView::new can subscribe without a read_editor round-trip.
The Arc<Notify> is shared with the highlights worker; wakes
propagate to GPUI’s foreground executor via cx.notify().
Implementations§
Source§impl GpuiApp
impl GpuiApp
Sourcepub fn new(document: Document) -> Self
pub fn new(document: Document) -> Self
Build the GPUI peer’s composition root from an initial
Document. Mirrors lattice-ui-tui::app::App::new:
delegates the renderer-neutral construction to
Editor::boot (LSP subsystem, command / mode /
completion / picker / config registries, snippet handle,
event bus, syntax, buffer registry) and supplies the
renderer-side caches alongside.
Real dispatch (key events -> Action -> editor.dispatch) +
paint (read editor.document snapshot + cursor) wire in
5.7.B.3 / 5.7.B.4. The renderer-side post-boot helpers
the TUI peer runs after Editor::boot
(activate_major_for_buffer_kind,
publish_document_opened_for_active,
ensure_named_synthetic_document,
ensure_messages_buffer) plug in as the corresponding
GPUI wiring lands – their bodies are host-resident, so
this peer will call the same methods via its own renderer-
signal handler.
Sourcepub fn ad(&self) -> Arc<ActiveDocumentRenderState> ⓘ
pub fn ad(&self) -> Arc<ActiveDocumentRenderState> ⓘ
Phase 5.8.AF.5 / Slice 3c.atomic.K: wait-free snapshot of
the active-buffer hot-path render state. Returns an Arc
clone of RenderState.active_document. Parallel of the
TUI peer’s App::ad() – the GPUI peer reads its
renderer-side state through this method so the eventual
editor → handle swap leaves call sites untouched.
Sourcepub fn messages(&self) -> Arc<MessagesRenderState> ⓘ
pub fn messages(&self) -> Arc<MessagesRenderState> ⓘ
Slice 3c.final.B.7: published echo-area state — parallel
of TUI peer’s App::messages().
Sourcepub fn modeline(&self) -> Arc<ModelineRenderState> ⓘ
pub fn modeline(&self) -> Arc<ModelineRenderState> ⓘ
Slice 3c.final.B.7: published modeline + cmdline + search
state — parallel of TUI peer’s App::modeline().
Sourcepub fn options(&self) -> Arc<OptionsRenderState> ⓘ
pub fn options(&self) -> Arc<OptionsRenderState> ⓘ
Slice 3c.final.B.10: published typed-options registry —
parallel of TUI peer’s App::options().
Sourcepub fn modes(&self) -> Arc<ModesRenderState> ⓘ
pub fn modes(&self) -> Arc<ModesRenderState> ⓘ
Slice 3c.final.B.11: published active-modes map —
parallel of TUI peer’s App::modes().
Sourcepub fn buffer_locals(&self) -> Arc<BufferLocalsRenderState> ⓘ
pub fn buffer_locals(&self) -> Arc<BufferLocalsRenderState> ⓘ
Slice 3c.final.B.9: published buffer-locals map —
parallel of TUI peer’s App::buffer_locals().
Sourcepub fn mutate_editor<F>(&mut self, f: F)
pub fn mutate_editor<F>(&mut self, f: F)
Phase 5.8.AF.5 / Slice 3c.final.E.4: routing helpers for
editor mutations. Same shape as the TUI peer’s
App::mutate_editor / App::mutate_editor_with. Pre-swap
runs the closure against &mut self.editor + publishes RS;
post-swap delegates to the actor handle. Forward-compatible
Send + 'static bounds.
Sourcepub fn mutate_editor_with<F, R>(&mut self, f: F) -> R
pub fn mutate_editor_with<F, R>(&mut self, f: F) -> R
Variant for closures that return a value.
Sourcepub fn read_editor<F, R>(&self, f: F) -> R
pub fn read_editor<F, R>(&self, f: F) -> R
Read-only helper – parallels App::read_editor on the TUI
peer. In production routes through the actor handle’s
with_editor blocking RPC; in tests calls directly.
Sourcepub fn set_viewport_height(&mut self, height: u32)
pub fn set_viewport_height(&mut self, height: u32)
Phase 5.8.AF.5 / Slice 3c.atomic.K: publishing wrapper
around editor.viewport_height writes. Parallel of the
TUI peer’s App::set_viewport_height (3c.atomic.D): the
per-frame viewport recompute happens outside dispatch, so
it must republish render-state for ad().viewport_height
and ad().scroll to observe the new values. Without this
wrapper, a window resize would leave the published
viewport / scroll one frame behind every time.
Sourcepub fn set_pane_viewport(&mut self, idx: usize, rows: u32, cols: u32)
pub fn set_pane_viewport(&mut self, idx: usize, rows: u32, cols: u32)
Issue #25 (2026-05-22): per-pane geometry hand-off. The
renderer’s per-frame layout pass fires one of these per
leaf in the pane tree. Production routes through the
editor actor’s typed SetPaneViewport command;
cfg(test) mutates the in-process editor directly
(parallels the mutate_editor_with pattern). The
host’s handler writes onto PaneState[idx] and mirrors
the active leaf’s height into Editor::viewport_height
for cursor-clamp + highlights worker.
Sourcepub fn set_popup_viewport(&mut self, rows: u32, cols: u32)
pub fn set_popup_viewport(&mut self, rows: u32, cols: u32)
PU.2: floating-popup inner-geometry hand-off — the GPUI peer of
the TUI App::set_popup_viewport. The renderer is the sizing
authority for the popup’s inner rect, so it pushes the resolved
(rows, cols) to the host; build_cells_panes reads
Editor::popup_viewport_{height,width} to size the synthetic
PaneId::POPUP DisplayMatrix the popup interior EditorElement
paints from. Plain field writes (no special host handler), so it
routes through mutate_editor (which republishes RS) rather than a
typed actor command. Diff-then-send in the render loop keeps a
steady-state popup at zero RPCs.
Sourcepub fn set_band_viewport(&mut self, rows: u32, cols: u32)
pub fn set_band_viewport(&mut self, rows: u32, cols: u32)
WK.12: the minibuffer band’s inner-geometry hand-off — the peer of
Self::set_popup_viewport for PaneId::MINIBUFFER_BAND.
build_cells_panes reads Editor::band_viewport_{height,width} to size
the band’s matrix; without this the band paints unstyled fallback text.
Sourcepub fn set_completion_docs_viewport(&mut self, rows: u32, cols: u32)
pub fn set_completion_docs_viewport(&mut self, rows: u32, cols: u32)
PU.5d: completion-docs side-popup inner-geometry hand-off — the peer
of Self::set_popup_viewport for the second synthetic popup
(PaneId::COMPLETION_DOCS). build_cells_panes reads
Editor::completion_docs_viewport_{height,width} to size the docs
DisplayMatrix. Diff-then-send in the render loop keeps churn down.
Sourcepub fn dismiss_popup(&mut self)
pub fn dismiss_popup(&mut self)
Dismiss any active help popup. Phase 5.8.AE: routes
through the host’s dismiss_popup so popup state lands
uniformly across both peers. Slice 3c.final.C: now goes
through Action::DismissPopup instead of a direct host
call.
Sourcepub fn ensure_cursor_in_viewport(&mut self)
pub fn ensure_cursor_in_viewport(&mut self)
Auto-scroll the active pane so the cursor stays in the
visible viewport ([scroll, scroll + viewport_height)).
Mirrors the TUI peer’s per-tick scroll-clamp; both renderer
peers funnel through the host’s editor.scroll so any
host-side cursor jump (a motion, a :N, a search bounce)
is reflected here on the next paint.
Phase 5.8.O: foundational for cursorline / visual selection (5.8.P, 5.8.Q) — those features paint within the viewport and would mis-render if the cursor sat outside it.
Sourcepub fn handle_renderer_signal(&mut self, signal: RendererSignal)
pub fn handle_renderer_signal(&mut self, signal: RendererSignal)
Renderer-side handler for the RendererSignal stream
the host emits from option cascades + mode lifecycle
helpers. Phase 5.7.B.7 wiring – mirrors the TUI peer’s
App::handle_renderer_signal in shape; each arm’s body
reflects the GPUI peer’s current capability surface.
As GPUI-side infrastructure grows (theme cache, popup + pane display, file-tree buffers, window-close bridge), the corresponding arms light up. The signal contract itself is stable – the host doesn’t know which renderer is on the other side; both peers see the same enum.
Sourcepub fn dispatch_keystroke(
&mut self,
key: &str,
control: bool,
alt: bool,
shift: bool,
platform: bool,
) -> Option<DispatchOutcome>
pub fn dispatch_keystroke( &mut self, key: &str, control: bool, alt: bool, shift: bool, platform: bool, ) -> Option<DispatchOutcome>
Convenience entry point for GPUI’s key-down event handler:
dispatch_keystroke(&ev.keystroke.key, mods.control, mods.alt, mods.shift, mods.platform). Walks the same pipeline as the
TUI peer (chord normalisation → renderer-neutral translate
→ editor.dispatch); returns the DispatchOutcome for
callers that want to inspect renderer signals (or
None if the key string didn’t map to a chord).
Phase 5.7.B.3 scope: the outcome’s renderer signals are
returned but not yet fanned out (no GPUI-side equivalent of
App::handle_renderer_signal yet). 5.7.B.4+ adds a signal
handler so theme changes, option-cache rebuilds, and major-
mode activations propagate to the renderer caches.
Sourcepub fn dispatch_chord(&mut self, chord: KeyChord) -> DispatchOutcome
pub fn dispatch_chord(&mut self, chord: KeyChord) -> DispatchOutcome
Translate a canonical KeyChord into an Action (via
the renderer-neutral host pipeline) and dispatch it. Used
by Self::dispatch_keystroke after the GPUI-shaped event
has been normalised, and directly by tests that drive the
editor with synthetic chords.
Builds TranslateContext from current Editor state.
chord_capture reads the published ad().chord_capture flag (the
host computes it via Editor::chord_capture_active each publish), so
the actor-based peer doesn’t need a live &Editor. With it,
:describe-key (and any ArgKind::Chord arg) captures the next
keystroke instead of dispatching it — was hard-wired false.
Sourcepub fn rebuild_gpui_theme(&mut self)
pub fn rebuild_gpui_theme(&mut self)
Rebuild the cached GpuiTheme from
editor.host_theme.
Mirrors the TUI peer’s App::rebuild_tui_theme. Called
at boot (inside finalize_boot) and on every
RendererSignal::ThemeChanged so theme cascades
propagate to the GPUI cache without the binary having
to re-read host_theme per frame.
Phase 5.7.B.12: the body is currently a shape-only
no-op – host_theme doesn’t yet carry direct window-bg
/ fg / status / cursor fields the GPUI peer can map. The
next iteration grows host_theme (or adds a GPUI-typed
theme overlay in lattice-host::ui::theme) and this
method translates each into Rgba. Until then the cache
keeps its Default palette; the wiring is what this
slice unblocks.
Sourcepub fn dispatch_action(&mut self, action: Action) -> DispatchOutcome
pub fn dispatch_action(&mut self, action: Action) -> DispatchOutcome
Dispatch a single Action through editor.dispatch and
drain the deferred-action queue iteratively.
editor.dispatch runs ONE action and returns the outcome;
for many actions (Action::Invoke resolving to an
AppEffect::EnterMode / EnterVisual / etc.) the host
emits a follow-up Action in
outcome.next_actions rather than mutating directly –
see Editor::apply_app_effect in lattice_host::dispatch.
The TUI peer’s App::apply drains the queue with a
recursive call; this method does the same shape with an
explicit FIFO loop so basic state transitions land without
needing the renderer’s full effect / signal fan-out yet
(5.7.B.4+ work).
outcome.effects are aggregated across the chain but NOT
re-applied – the host has already called
editor.handle_effect(effect.clone()) on each one during
the inner dispatch (the renderer-coupled match arms remain
a 5.7.B.4+ follow-up). renderer_signals accumulate the
same way; callers can inspect them once the GPUI peer
gains a signal handler.
Auto Trait Implementations§
impl !RefUnwindSafe for GpuiApp
impl !UnwindSafe for GpuiApp
impl Freeze for GpuiApp
impl Send for GpuiApp
impl Sync for GpuiApp
impl Unpin for GpuiApp
impl UnsafeUnpin for GpuiApp
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
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§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.§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.§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.§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.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more