LavaUI docs

enum LavaApp

Swift

enum LavaApp

Reusable window/input/invalidation/render loop, so a second LavaUI executable is a main.swift of a dozen lines instead of a copy of HelloWorldApp's ~350.

Split into open + run because asset loading a specific app owns (an app icon, a brand image) has to happen once, against an already-open Editor, before the first makeRoot() — folding it into run's hot path would either re-load it every rebuild or force every caller to thread a cache through their own view. Two calls keeps that ordering explicit:

guard let editor = LavaApp.open(title: "My App") else { exit(1) }
let icon = ImageStore.loadAsset(
    named: "icon.png", bundle: .module, into: editor)
LavaApp.run(editor: editor) { MyRootView(icon: icon) }

Sources/LavaUI/LavaApp.swift:20

Properties

static var currentWindow: WindowID { get }

The window whose frame is being built or whose handler is running.

Ambient rather than passed down, for the reason WindowScope gives at length: a view genuinely does not know which window it is in, and every view in a tree would have to thread the answer through to the one place that wants it. Outside a frame this is the first window.

Sources/LavaUI/LavaApp.swift:318

static var mainLayoutHost: LayoutHost? { get }

The layout host of the window the app started with, once run has brought it up. Nil before that, and after teardown.

For the app that has to know how big the tree it just laid out actually isagentFrame(sid:) on a committed layout answers it. A context menu is the case this exists for: it has to tell the compositor its size before the compositor will place it, and the only honest source for that number is the layout pass, not a second pile of font arithmetic that agrees with Yoga until a face changes.

Everything else about a window's geometry is told to the app. This is the one question that runs the other way.

Sources/LavaUI/LavaApp.swift:242

static var windowCount: Int { get }

Not documented.

Sources/LavaUI/LavaApp.swift:228

Methods

static func closeCurrentWindow()

Closes the window this handler is running in. What a "Close" button in a secondary window wants, without the window having to know its own id.

Sources/LavaUI/LavaApp.swift:322

static func closeWindow(_ id: WindowID)

Closes a window this app opened. Closing the window the app started with ends run, the same as its titlebar X.

Takes effect at the end of the current frame, so it is safe from a handler running inside that window's own tree.

Sources/LavaUI/LavaApp.swift:299

static func isWindowOpen(_ id: WindowID) -> Bool

Whether id is still open.

Sources/LavaUI/LavaApp.swift:308

static func open(title: String, assetsRoot: String? = nil, width: Float = 1280, height: Float = 800) -> Editor?

Opens the window and does one-time framework setup: default font bootstrap, clipboard bridge. Logs and returns nil if the window failed to open — the caller should exit(1).

assetsRoot
Engine resource root (directory with shaders/). Default is the SwiftPM CanvasResources bundle. Fonts always load from LavaUI's own resource bundle.

Sources/LavaUI/LavaApp.swift:28

@discardableResult static func openWindow<V>(title: String, width: Float = 800, height: Float = 600, onClose: (() -> Void)? = nil, makeRoot: @escaping () -> V) -> WindowID? where V : View

Opens a second window running its own view tree, sharing this process's GPU, font atlas, texture cache and frame loop.

Safe to call from a button handler: the window is created immediately but brought up at the end of the current frame, so it never draws against a half-updated tree, and the caller's own window still presents the frame the click belongs to.

The new window gets its own focus, invalidation and hover state (see WindowScope) and the app-level onRawKey from run. It does not get the menubar: a second menubar strip is a decision for the app, not a default, and the DBus global menu is registered per process.

Returns nil if the engine could not open it, or if called before run.

Sources/LavaUI/LavaApp.swift:260

static func resolveAssetsRoot(_ override: String? = nil) -> String

Back-compat alias — engine root only. App images should use ImageStore.loadAsset(named:bundle:into:) with the app bundle.

Sources/LavaUI/LavaApp.swift:82

static func resolveEngineAssetsRoot(_ override: String? = nil) -> String

Engine assets root: override, else CANVAS_ASSETS_ROOT, else the CanvasResources SwiftPM bundle (checked-in SPIR-V under shaders/).

Sources/LavaUI/LavaApp.swift:75

static func run<V>(editor: Editor, menu: (() -> MenuBar)? = nil, onRawKey: ((InputEvent) -> Bool)? = nil, makeRoot: @escaping () -> V) where V : View

Runs the full input/invalidation/render/agent-server loop until the window closes.

Drives every open window, not just this one: openWindow adds a second tree to the same loop, and one GLFW wait serves all of them, so N windows cost N draw arenas rather than N event loops. The app ends when the window opened here closes; secondary windows come and go under it. See LavaWindow for the per-window half and WindowScope for what each window owns privately.

  • makeRoot: rebuilds the view tree from scratch. Called on the first frame and on any invalidation that can't be satisfied per-node (see ViewInvalidation.consumeDirtyBodyNodes) — keep it cheap, an app's own one-time setup belongs before this call, against the Editor open already returned.
  • menu: optional application menubar. When a global-menu registrar is available (Vala Panel / Plasma appmenu / …), the tree is exported via DBusMenu and no in-window strip is drawn. Otherwise MenuChromeRoot draws it with Vulkan. Override with LAVA_MENU=vulkan or dbus. Rebuilt on every full body pass so labels/isEnabled stay in sync. Menu shortcuts are matched after onRawKey (both backends).
  • onRawKey: first look at every key event, ahead of focus/overlay/ content-scale handling. Return true to consume it.

Sources/LavaUI/LavaApp.swift:109