std::window
std::window is the opt-in standard-library windowing facade. Importing and
reaching this module's runtime calls is the signal that an executable wants
platform window support; unrelated std:: users do not link window provider
shims or provider frameworks.
Application code that wants portable provider-owned windows should stay on
this public facade. Stdlib-owned window examples do not declare ext, import
std::runtime::*, reference silk_rt_* symbols, or pass native
header/source inputs to reach a provider. Explicit native interop examples may
instead ship their own .m provider and call it through Silk ext.
The implementation provides target detection, opt-in Apple SDK
framework linkage, a high-level run(...) application entrypoint, real AppKit
window handles, nonblocking AppKit event polling on macOS, a UIKit application
lifecycle path for iOS device and simulator targets, a runtime-loaded GTK
provider for Linux, and a portable native window-control API. On macOS,
Options maps to AppKit creation settings and control calls route to the
underlying NSWindow. On iOS, run(...) enters UIApplicationMain; direct
window controls report ApplicationLifecycleRequired when UIKit owns the
lifecycle. On Linux, the runtime selects GTK only when GTK can be loaded and a
display connection can be initialized. The CLI automatically materializes an
adjacent <output>.app bundle for iOS executable builds whose module graph
reaches std::window.
Exported API#
module std::window;
import std::result;
export enum Backend { Unsupported, MacOS, IOS, GTK }
export enum WindowErrorKind {
UnsupportedPlatform,
InvalidDimensions,
InvalidColor,
RuntimeFailed,
ApplicationLifecycleRequired,
}
export enum EventKind { NoEvent, CloseRequested, Provider }
export error WindowFailed { code: int }
impl WindowFailed {
public fn kind (self: &WindowFailed) -> WindowErrorKind;
}
export struct Size { width: int = 0, height: int = 0 }
export struct Position { x: int = 0, y: int = 0 }
export struct Color {
red: f64 = 0.0,
green: f64 = 0.0,
blue: f64 = 0.0,
alpha: f64 = 1.0,
}
export struct Options {
title: string,
size: Size,
position: Position = Position{ x: 0, y: 0 },
positioned: bool = false,
min_size: Size = Size{ width: 0, height: 0 },
max_size: Size = Size{ width: 0, height: 0 },
resizable: bool = true,
minimizable: bool = true,
maximizable: bool = true,
closable: bool = true,
frameless: bool = false,
utility: bool = false,
visible: bool = true,
always_on_top: bool = false,
background: Color = Color{ red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 },
has_background: bool = false,
}
export struct Window {
handle: u64,
size: Size,
title: string = "",
position: Position = Position{ x: 0, y: 0 },
}
export struct Event { kind: EventKind }
impl Window {
public fn is_valid (self: Window) -> bool;
public fn show (self: Window) -> ActionResult;
public fn hide (self: Window) -> ActionResult;
public fn focus (self: Window) -> ActionResult;
public fn blur (self: Window) -> ActionResult;
public fn minimize (self: Window) -> ActionResult;
public fn maximize (self: Window) -> ActionResult;
public fn restore (self: Window) -> ActionResult;
public fn is_visible (self: Window) -> BoolResult;
public fn set_title (self: Window, title: string) -> ActionResult;
public fn set_size (self: Window, value: Size) -> ActionResult;
public fn size (self: Window) -> SizeResult;
public fn set_position (self: Window, value: Position) -> ActionResult;
public fn position (self: Window) -> PositionResult;
public fn set_always_on_top (self: Window, enabled: bool) -> ActionResult;
public fn is_always_on_top (self: Window) -> BoolResult;
public fn set_background (self: Window, color: Color) -> ActionResult;
public fn next_event (self: Window) -> EventResult;
public fn poll (self: Window) -> PollResult;
public fn close (self: Window) -> CloseResult;
}
export type WindowResult = std::result::Result(Window, WindowFailed);
export type EventResult = std::result::Result(Event, WindowFailed);
export type PollResult = std::result::Result(bool, WindowFailed);
export type CloseResult = std::result::Result(bool, WindowFailed);
export type ActionResult = std::result::Result(bool, WindowFailed);
export type BoolResult = std::result::Result(bool, WindowFailed);
export type SizeResult = std::result::Result(Size, WindowFailed);
export type PositionResult = std::result::Result(Position, WindowFailed);
export type RunResult = std::result::Result(bool, WindowFailed);
export type FrameCallback = fn (Window) -> int;
export fn options (title: string, width: int, height: int) -> Options;
export fn failed (kind: WindowErrorKind) -> WindowFailed;
export fn backend () -> Backend;
export fn is_supported () -> bool;
export fn open (options: Options) -> WindowResult;
export fn screen_size () -> SizeResult;
export fn show (window: Window) -> ActionResult;
export fn hide (window: Window) -> ActionResult;
export fn focus (window: Window) -> ActionResult;
export fn blur (window: Window) -> ActionResult;
export fn minimize (window: Window) -> ActionResult;
export fn maximize (window: Window) -> ActionResult;
export fn restore (window: Window) -> ActionResult;
export fn is_visible (window: Window) -> BoolResult;
export fn set_title (window: Window, title: string) -> ActionResult;
export fn set_size (window: Window, value: Size) -> ActionResult;
export fn size (window: Window) -> SizeResult;
export fn set_position (window: Window, value: Position) -> ActionResult;
export fn position (window: Window) -> PositionResult;
export fn set_always_on_top (window: Window, enabled: bool) -> ActionResult;
export fn is_always_on_top (window: Window) -> BoolResult;
export fn set_background (window: Window, color: Color) -> ActionResult;
export fn next_event (window: Window) -> EventResult;
export fn poll (window: Window) -> PollResult;
export fn close (window: Window) -> CloseResult;
export fn run (options: Options) -> RunResult;
export fn run_loop (options: Options, frame: FrameCallback) -> RunResult;
Provider Model#
Windowing support is intentionally not part of default hosted runtime behavior.
The compiler links provider support only when reachable code imports and calls
std::window / std::window::*.
The std::runtime::window module is the stdlib-owned implementation boundary,
not the application API. It may use target-gated runtime symbols internally,
but callers should use std::window types and functions.
Current providers:
Backend::MacOSfor macOS targets.Backend::IOSforios-aarch64,ios-simulator-aarch64, andios-simulator-x86_64.Backend::GTKfor Linux targets when the bundled runtime can load GTK and initialize the process display connection.
Unsupported targets return Backend::Unsupported and open(...) returns
Err(UnsupportedPlatform). Those targets use local runtime stubs and do not
declare or import silk_rt_window_* provider symbols.
Errors#
WindowFailed.kind() returns a stable WindowErrorKind:
UnsupportedPlatformmeans the current target has no selected provider.InvalidDimensionsmeans a requested size or size constraint is zero, negative, incomplete, or internally inconsistent.InvalidColormeans a normalized RGBA channel is outside0.0 ... 1.0.RuntimeFailedmeans the selected provider rejected or could not complete the operation.ApplicationLifecycleRequiredmeans the selected provider owns the requested operation under its application lifecycle, such as direct UIKit window controls outsideUIApplicationMain.
High-Level Application API#
run(options) is the ergonomic entrypoint for application code. A minimal
window application imports only std::window:
import std::window;
fn main () -> int {
let options = std::window::Options{
title: "Silk Window App",
size: std::window::Size{ width: 640, height: 480 },
min_size: std::window::Size{ width: 360, height: 240 },
background: std::window::Color{ red: 0.08, green: 0.10, blue: 0.12, alpha: 1.0 },
has_background: true,
};
return match (std::window::run(options)) {
Ok(_) => 0,
Err(failed) => failed.code,
};
}
The same program is shipped as examples/std_window_app.slk.
Window Options And Controls#
Options keeps the simple { title, size } shape as the minimum useful
window configuration. Additional fields have compile-time defaults, so callers
can opt into native behavior without helper-specific APIs:
positionedpluspositionplaces the window at a provider screen coordinate.min_sizeandmax_sizeapply native size constraints when both width and height are non-zero.resizable,minimizable,maximizable,closable,frameless, andutilitymap to native window chrome on providers that support those concepts.visiblecan create a hidden window for applications that want to configure it before showing it.always_on_toprequests a floating window level.has_backgroundplusbackgroundapplies a normalized RGBA native background color.
After opening a window, applications can use show, hide, focus, blur,
minimize, maximize, restore, set_title, set_size, size,
set_position, position, set_always_on_top, is_always_on_top,
set_background, and is_visible. These functions are part of the public
facade and are also exposed as Window methods, so normal application code can
write window.set_title(...), window.size(), and window.close(). For
interactive applications, prefer run_loop(...) so the stdlib owns open,
event-poll, and close sequencing while application code receives a Window
inside the frame callback. Examples and applications should not call
std::runtime::window directly.
import std::task;
import std::window;
fn frame (window: std::window::Window) -> int {
let title_code = match (window.set_title("Ready - close the window to exit")) {
Ok(_) => 0,
Err(failed) => failed.code,
};
if title_code != 0 {
return title_code;
}
let resize_code = match (window.set_size(std::window::Size{ width: 560, height: 340 })) {
Ok(_) => 0,
Err(failed) => failed.code,
};
if resize_code != 0 {
return resize_code;
}
match (window.size()) {
Ok(current) => {
if current.width <= 0 || current.height <= 0 {
return 40;
}
},
Err(failed) => {
return failed.code;
},
};
std::task::sleep_ms(16);
return 0;
}
fn main () -> int {
let options = std::window::Options{
title: "Silk Window Controls",
size: std::window::Size{ width: 520, height: 320 },
min_size: std::window::Size{ width: 360, height: 240 },
positioned: true,
position: std::window::Position{ x: 80, y: 360 },
background: std::window::Color{ red: 0.04, green: 0.14, blue: 0.22, alpha: 1.0 },
has_background: true,
};
return match (std::window::run_loop(options, frame)) {
Ok(_) => 0,
Err(failed) => failed.code,
};
}
The fuller interactive control example is shipped as
examples/std_window_controls.slk; it remains open until the user closes the
window.
For frame-rendering demos, use run_loop(options, frame). The stdlib owns the
provider lifecycle and the application provides only per-frame behavior:
import std::graphics::window;
import std::window;
fn draw_frame (window: std::window::Window) -> int {
let color = std::graphics::window::ClearColor{
red: 0.05,
green: 0.20,
blue: 0.85,
alpha: 1.0,
};
return match (std::graphics::window::clear(window, color)) {
Ok(_) => 0,
Err(failed) => failed.code,
};
}
fn main () -> int {
let options = std::window::Options{
title: "Silk Metal Window",
size: std::window::Size{ width: 800, height: 520 },
};
return match (std::window::run_loop(options, draw_frame)) {
Ok(_) => 0,
Err(failed) => failed.code,
};
}
The same pattern is shipped as examples/std_macos_metal_window.slk.
On macOS, run(...) opens an AppKit window, activates the application, and
blocks in the platform event loop until the user closes the last window.
run_loop(...) opens a provider window, polls events through
next_event(...), calls the supplied frame callback while the window remains
open, and always routes cleanup through close(...). On iOS device and
simulator targets, run(...) enters UIApplicationMain with a
runtime-registered application delegate that creates a UIWindow and root
view controller from the supplied Options. UIKit launch applies the requested
title, frame size, visibility, and background color fields; desktop chrome and
positioning fields have no UIKit equivalent and remain no-ops on iOS.
On Linux, run(...) opens a GTK window and blocks in gtk_main() until that
window is destroyed. run_loop(...) uses the same open(...) and
next_event(...) surface as macOS: GTK events are drained without blocking,
provider-only events report EventKind::Provider, and destroying or hiding
the window reports EventKind::CloseRequested. GTK applies title, size,
minimum/maximum size hints, visibility, positioning, always-on-top, background
color, resizable/decorated state, and closable state where the active window
manager honors those GTK hints. blur(...) is a successful no-op on GTK
because focus transfer is controlled by the window manager.
When the CLI builds an iOS executable whose reachable module graph includes
std::window, it keeps the requested executable at -o <output> and also
creates <output>.app next to it. The app bundle contains the executable,
Info.plist, and PkgInfo; on macOS hosts it is ad-hoc signed after
materialization. No extra CLI flag is required.
Manual Event Loop API#
run_loop(...) should be the default stdlib API for applications that need a
per-frame callback. open(...), next_event(...), and close(...) remain the
portable nonblocking event surface for applications that need custom lifecycle
control.
It returns:
EventKind::NoEventwhen no provider event is immediately available,EventKind::Providerwhen the provider consumed an event that does not yet have a portable payload,EventKind::CloseRequestedwhen the provider-owned window is no longer visible and the portable loop should stop.
On macOS, next_event(...) pumps at most one AppKit event, updates AppKit
windows, and checks the underlying NSWindow visibility. On Linux, it drains
one pending GTK event when available, checks the provider record for destroy
notifications, and reports close when the window is no longer visible. On iOS,
nonblocking event delivery is owned by UIApplicationMain, so direct
next_event(...) returns Err(ApplicationLifecycleRequired) for a valid
bootstrap handle. On unsupported targets, next_event(...) returns
Err(UnsupportedPlatform).
poll(...) and close(...) perform the same provider-availability check
before calling the runtime, so unsupported targets report
Err(UnsupportedPlatform) instead of a generic runtime failure.
Current Runtime Behavior#
open(...) validates dimensions, optional size constraints, and color ranges,
checks provider availability, and returns a window value containing the provider
handle plus the requested logical size, title, and position. On macOS the
handle is a provider-owned AppKit NSWindow. Creation options are applied
before the window is shown when possible, next_event(...) pumps one AppKit
event, poll(...) updates AppKit windows for compatibility, control functions
route to NSWindow, and close(...) closes that window. On Linux, the handle
is a bundled runtime record around a GTK top-level window; GTK libraries are
loaded with dlopen, so builds do not need GTK headers and unrelated programs
do not link GTK. On iOS, run(...) is the owned lifecycle entrypoint; direct
open(...) remains a bootstrap capability handle because UIKit windows and
events must be created and delivered under application lifecycle ownership.
Direct control calls on that handle report ApplicationLifecycleRequired. The
lifecycle-owned run(...) path carries title, requested size, visibility, and
background color into the UIKit launch delegate.
When reachable code calls the std::window runtime on host-backed Mach-O
targets, the compiler links the matching provider framework:
AppKitformacos-aarch64,UIKitforios-aarch64,ios-simulator-aarch64, andios-simulator-x86_64.
When reachable code calls the std::window runtime on Linux/x86_64, the
compiler statically links the bundled runtime archive and adds the dynamic
loader API provider needed by the GTK shim (libdl.so.2 on glibc targets,
libc.so on musl targets). GTK itself remains a runtime-loaded provider:
missing GTK libraries or a missing display connection make
backend() == Backend::Unsupported.
The next implementation steps are:
- richer portable input-event payloads plus surface and rendering integration on top of the current visible-window providers.
- explicit UIKit lifecycle callbacks for application-authored post-launch
window mutations after
UIApplicationMainhas created the provider-owned window.
Relationship To std::graphics#
std::graphics exposes low-level rendering API bindings such as OpenGL,
OpenGL ES, and Vulkan. It intentionally does not own windows, surfaces, or
event loops. std::window is the higher layer responsible for platform window
bootstrap and eventual surface/context integration.
Source repository · Edit this page · View Markdown