Inputs
Config, platform runtime handles, app font caches, surface size, content scale, and the command/env to execute.
Component flow
The app runtime provides the GUI loop. Each surface builds the shared state that connects platform callbacks, renderer state, terminal IO, mailboxes, and worker threads.
Config, platform runtime handles, app font caches, surface size, content scale, and the command/env to execute.
A stable `Surface` containing renderer state, `Termio`, renderer and IO thread managers, runtime mailboxes, and spawned threads.
The surface is called from the main thread, but it creates the objects used by IO and renderer threads.
`main` creates core app state, initializes `apprt.App`, starts the optional quit timer, and runs the GUI event loop. Runtime-specific surface creation happens after this handoff.
const app: *App = try App.create(alloc);
var app_runtime: apprt.App = undefined;
try app_runtime.init(app, .{});
try app_runtime.run();
`Surface.init` first converts user config into derived config, initializes the runtime surface, computes DPI-aware font sizing, references the shared font grid, calculates renderer sizing, and initializes the renderer implementation with a surface mailbox.
const font_grid_key, const font_grid = try app.font_grid_set.ref(
&derived_config.font,
font_size,
);
var renderer_impl = try Renderer.init(alloc, .{
.font_grid = font_grid,
.size = size,
.surface_mailbox = .{ .surface = self, .app = app_mailbox },
});
After renderer thread and IO thread managers exist, the surface creates the exec backend, SPSC IO mailbox, and `Termio`. The renderer state stores a pointer to `self.io.terminal`; thread startup happens only after Termio has been initialized and the first resize/finalization work has completed.
.renderer_state = .{
.mutex = mutex,
.terminal = &self.io.terminal,
},
.io = undefined,
.io_thread = io_thread,
self.renderer_thr = try std.Thread.spawn(.{}, rendererpkg.Thread.threadMain, .{&self.renderer_thread});
self.io_thr = try std.Thread.spawn(.{}, termio.Thread.threadMain, .{ &self.io_thread, &self.io });
Read next: Input and Mailbox follows how the surface sends user input into the `Termio` thread.