oxiui — The COOLJAPAN Pure-Rust GUI facade
oxiui is the top-level façade crate for OxiUI — the COOLJAPAN Pure-Rust UI layer with no GTK (C), no Qt (C++), no SDL (C), no system widgets, and no raw AppKit / Win32 / Cocoa bindings. It wraps the immediate-mode widget API from oxiui-core, selects a render + framework backend through Cargo features, and re-exports everything an application needs behind one builder: App. By default it boots an egui application rendered via wgpu; alternative backends (iced, Dioxus, software) are opt-in. The wasm32 / browser entry point is the separate unpublished oxiui-web copy-template, not a facade feature. (A Slint adapter exists as the standalone oxiui-slint crate — it is a KNOWN-NON-PURE, direct-opt-in dependency, not a facade feature; see 0.2.0 removal notice.)
The facade is the only crate most applications depend on. It owns the application life-cycle: window configuration (AppConfig), the event loop (App::run), headless rendering for CI (App::run_headless_once, App::screenshot), and cross-cutting features — plugins (Plugin), global hotkeys (HotkeyRegistry), a fuzzy-searchable command palette (CommandPalette), and a toast NotificationQueue. GPU drivers (Vulkan/Metal/DX12/WebGPU) are OS-provided at runtime and do not appear in cargo tree --edges normal, keeping the build Pure Rust.
Default-features note (GOVERNANCE §6):
default = ["gpu", "egui"]. A zero-feature facade build must select at least one Pure adapter (ADAPTER_PATTERN §3 rule 4), mirroring precedents such asoxicrypto'sdefault = ["pure"]andoxitls'sdefault = ["pure", "webpki-roots"]. For a strictly minimal / ffi-audit build use--no-default-features --features software.
Installation
[]
# Default: egui + wgpu native app
= "0.2.1"
# Headless / ffi-audit: CPU softbuffer framebuffer, no GPU stack at build time
= { = "0.2.1", = false, = ["software"] }
# iced retained-mode backend
= { = "0.2.1", = ["iced"] }
# Everything: tables, accessibility, plus the iced backend
= { = "0.2.1", = ["iced", "table", "a11y"] }
Quick Start
egui backend (default)
use ;
new
.theme
.content
.run
.expect;
iced backend
use ;
new
.theme
.backend
.content
.run
.expect;
Headless (CI-friendly, no display)
use ;
let exit = new
.content
.run_headless_once?;
assert_eq!;
# Ok::
Backend Selection
The active backend is chosen with App::backend and the Backend enum. The default is Backend::Egui. Each non-default variant is gated behind its own Cargo feature; the variant is only present when its feature is enabled.
Backend variant |
Feature | Framework / mode | Status |
|---|---|---|---|
Egui (default) |
egui |
egui + eframe, immediate-mode, rendered via wgpu | Live native window; drives the real eframe::run_native event loop via EguiRunner. |
Iced |
iced |
iced, retained-mode (Elm-style update/view) | Live native window; drives the real iced::application event loop via IcedRunner, honouring AppConfig's configured window size and waiting for on_close hooks to run before the window actually closes. Button clicks carry one-frame latency (inherent to the retained↔immediate bridge). |
Dioxus |
dioxus |
Dioxus reactive framework (minimal Pure-Rust feature set) |
M5: headless collection mode. Native rendering via dioxus-native deferred to M6. |
There is no Backend::Slint variant — the slint feature was removed from the facade
in 0.2.0 because oxiui-slint is a KNOWN-NON-PURE adapter (pulls in a C fontconfig
binding on Linux via slint → parley/fontique). Use the standalone
oxiui-slint crate directly instead.
The egui-on-wasm32 path is not driven through App::run (which returns UiError::Unsupported on wasm32); instead use oxiui_web::mount from the unpublished oxiui-web copy-template in a browser binary.
API Overview
Application builder
| Item | Kind | Description |
|---|---|---|
App |
struct | The application builder and runner. Lazy: no GPU device, window, or event loop is created until run(). |
AppConfig |
struct | Window configuration (title, size, min/max size, decorations, transparency, always-on-top, icon, position, extra fonts). Builder methods + Default. |
AppExit |
enum | Exit status: Ok, Error(String), RequestedByUser, Programmatic(String). |
Backend |
enum | Backend selector (see table above). |
App builder methods
| Method | Description |
|---|---|
App::new(config) |
Create an app from an AppConfig (theme defaults to cooljapan_default). |
.theme(Box<dyn Theme>) |
Set the UI theme. |
.content(F) |
Set the per-frame content closure (FnMut(&mut dyn UiCtx) + Send). |
.with_state(state, F) |
Set a stateful content closure; state is owned and passed by &mut each frame. |
.backend(Backend) |
Select the GUI backend. |
.min_size / .max_size / .decorations / .transparent / .always_on_top / .icon / .position |
Window-config passthroughs. |
.with_font(family, bytes) |
Register an extra font family (egui path; iced stores bytes, registration deferred). |
.with_frame_skip(bool) |
egui: defer repaint by 1 s when no input events occurred (CPU-saving dirty flag). |
.with_egui_ctx(F) |
egui escape hatch — per-frame callback receiving the raw egui::Context (requires egui). |
.table(source) |
Render an oxiui_table::RowSource as the app content (requires table). |
.with_persistent_state(initial, path, F) |
Stateful content closure (FnMut(&mut dyn UiCtx, &mut State)) whose state is decoded from path via oxicode at startup and re-encoded to path from the on_close hook (requires persist). Decode/encode failures are non-fatal (fall back to initial; warn to stderr). |
.on_init / .on_frame / .on_close / .on_resize / .on_focus |
Register lifecycle hooks (called in registration order). |
.plugin(P) |
Register a Plugin; plugins are sorted by ascending priority(). |
.notify(title, body, urgency) |
Enqueue a toast (urgency 0=low/3 s, 1=normal/5 s, 2=critical/10 s). |
.try_hotkey(mods, key, action) |
Register a global hotkey; Err(HotkeyConflict) on duplicate (mods, key). |
.register_command(name, shortcut) |
Add a command to the palette. |
.command_matches(query) -> Vec<String> |
Fuzzy-search command labels (subsequence match). |
.with_design_tokens(tokens) / .with_typography(scale) / .design_tokens() / .typography() |
Set/read oxiui_theme::DesignTokens / TypographyScale beyond the theme's Palette, for backends and layout engines that need the spacing scale at frame time. |
.open_window(WindowConfig) -> WindowId / .close_window(id) / .secondary_windows() / .window_channel() |
Multi-window registry (oxiui::multiwindow). Descriptors are queued for backends to open as OS windows (egui show_viewport_deferred / iced multi_window dispatch is planned for M7); WindowChannel carries cross-window messages today. |
.menu_bar(F) / .with_menu_bar(MenuBar) / .get_menu_bar() |
Build or attach a cross-platform menu bar (oxiui::menu). Pure data model — backend translation (egui egui-menu / iced widget::menu) is planned for M7. |
.file_dialog(...) / .file_save_dialog(...) / .message_dialog(...) / .confirm_dialog(...) / .prompt_dialog(...) / .poll_dialog(id) / .respond_dialog(id, resp) / .dialog_queue() |
Pure in-process dialog request/response queue (oxiui::dialog::DialogQueue) — headless-testable, no OS dialog. Needs no feature flag. |
.file_dialog_native(...) / .message_dialog_native(...) |
Blocking native OS file-picker / message-box dialogs via rfd (requires dialogs; no-op fallback without it). |
.soft_renderer() -> SoftRenderer |
Construct an off-screen oxiui_render_soft::SoftRenderer for custom rendering/compositing (requires software). |
.notifications() / .hotkeys() / .extra_fonts() |
Read-only accessors for testing. |
.run() -> Result<AppExit, UiError> |
Launch the native window + event loop (dispatches by backend). |
.run_headless_once() -> Result<AppExit, UiError> |
Run one synthetic frame against a no-op UiCtx (no window; fires init/frame hooks + plugins, including on_close — so .with_persistent_state persists deterministically in headless runs too). |
.run_with_return(F) -> Result<T, UiError> |
Run content once headlessly and forward its return value. |
.screenshot() -> Result<Vec<u8>, UiError> |
Render a headless frame to PNG bytes (requires software; else UiError::Unsupported). |
.build_a11y_snapshot(window_id) -> A11yTree |
Record content through RecordingUiCtx into an accessibility tree (requires a11y). |
Cross-cutting feature types
| Item | Kind | Description |
|---|---|---|
Plugin |
trait | Life-cycle plugin: init, update, and priority (lower = earlier). |
HotkeyRegistry |
struct | Registry enforcing unique (Modifiers, Key) bindings; register, conflict_check, len, is_empty. |
HotkeyBinding |
struct | A single registered hotkey (id, modifiers, key, action). |
HotkeyConflict |
struct | Error when two hotkeys share a (Modifiers, Key) pair (Display + Error). |
Command |
struct | A named, searchable command (id, label, shortcut, action). |
CommandPalette |
struct | Fuzzy (subsequence, case-insensitive) command registry; register, register_with_shortcut, search, len, is_empty. |
Notification |
struct | A pending toast (title, body, duration_ms, urgency, created_at). |
NotificationQueue |
struct | FIFO toast queue; push, enqueue, pop_due, len, is_empty. |
Pluggable runner infrastructure (oxiui::runner)
| Item | Kind | Description |
|---|---|---|
BackendRunner |
trait | Object-safe trait decoupling backend selection from App::run; run(self, config, content, lifecycle). |
LifecycleConfig |
struct | on_close / on_resize / on_focus hook vectors passed to a runner. |
ContentFn |
type alias | Box<dyn FnMut(&mut dyn UiCtx) + Send>. |
EguiRunner |
struct | Live egui runner — owns the eframe::run_native loop (requires egui). |
IcedRunner |
struct | Live iced runner — owns the iced::application loop (requires iced). |
EguiRunner/IcedRunnerown the live event loops:App::run()moves its theme, hooks, and plugins into the matching runner and delegates viaBackendRunner::run. Arunner::LifecycleTrackerdeduplicates window size/focus/close snapshots soon_resize/on_focusfire only on real changes andon_closefires at most once.
Re-exported modules
| Module | Gate | Contents |
|---|---|---|
oxiui::prelude |
— | The common set: App, AppConfig, AppExit, Backend, HotkeyConflict, Notification, Plugin; from oxiui-core: ButtonResponse, Color, UiCtx, UiError, Point/Rect/Size, AlignContent/FlexWrap/RichTextSpan, reactive (Signal, Computed, ReactiveRuntime, ReactiveError); from oxiui-theme: CooljapanTheme. |
oxiui::core |
— | Glob re-export of all of oxiui-core. |
oxiui::theme |
— | cooljapan_default, dark, light. |
oxiui::theme_picker |
— | theme_picker, by_name (re-exported as theme_by_name), BUILTIN_THEMES. |
oxiui::text |
— | FontSpec, FontStyle, FontFeature. |
oxiui::solver |
— | Constraint solver: Constraint, Expression, RelOp, Solver, SolverError, Strength, Term, Variable. |
oxiui::reactive |
— | Signal, Computed, ReactiveRuntime, ReactiveError. |
oxiui::render |
software |
Framebuffer, RgbaBuffer, render_headless_once, render_headless_scene. |
oxiui::table |
table |
Glob re-export of oxiui-table. |
oxiui::accessibility |
a11y |
A11yTree, A11yNode, WidgetRole. |
oxiui::recording |
a11y |
RecordingUiCtx, RecordingEntry. |
oxiui::multiwindow |
— | WindowRegistry, SecondaryWindow; backs App::open_window/close_window. |
oxiui::dialog |
— | Pure in-process DialogQueue, DialogKind, DialogResponse, DialogId; backs App::file_dialog and friends. |
oxiui::menu |
— | MenuBar, MenuBarBuilder, Menu, MenuItem — closure-based menu-bar DSL; backs App::menu_bar. |
oxiui::native_dialog |
dialogs |
open_file_dialog, save_file_dialog, message_dialog, confirm_dialog — blocking rfd-backed native dialogs; backs App::*_dialog_native. |
oxiui::logging |
tracing |
init_logging, LogLevel — installs a tracing-subscriber fmt subscriber respecting RUST_LOG. |
Crate-root re-exports
From oxiui-core at the crate root: ButtonResponse, Color, FontSpec, Palette, Theme, UiCtx, UiError. From runner: BackendRunner, LifecycleConfig (always), plus EguiRunner (egui) and IcedRunner (iced). From theme_picker: theme_by_name, theme_picker, BUILTIN_THEMES. From multiwindow: SecondaryWindow. From dialog: DialogId, DialogKind, DialogQueue, DialogResponse. From menu: Menu, MenuBar, MenuBarBuilder, MenuItem. From native_dialog: DialogResult, MessageLevel.
Web (wasm32) entry point
The facade itself does not mount a browser canvas. On wasm32, App::run returns Err(UiError::Unsupported) directing you to oxiui_web::mount(canvas_id). That entry point lives in the unpublished oxiui-web crate (publish = false), which is provided as a copy-template for your own wasm app rather than a crates.io dependency. See its README for the browser API and build steps.
Feature Flags
Features fall into two groups: render backends (how pixels reach the screen) and framework backends (which widget framework drives the frame), plus optional capability modules.
Render backends
| Feature | Pulls in | Description |
|---|---|---|
gpu |
oxiui-render-wgpu |
wgpu GPU rendering (Metal/Vulkan/DX12/WebGPU drivers OS-provided at runtime). Part of default. |
software |
oxiui-render-soft |
Pure-CPU softbuffer framebuffer; enables oxiui::render::* and App::screenshot. No GPU stack at build time. |
Framework backends
| Feature | Pulls in | Description |
|---|---|---|
egui |
oxiui-egui, oxiui-render-wgpu, egui, eframe, png |
egui + eframe immediate-mode backend (default). Enables the with_egui_ctx escape hatch and Backend::Egui. |
iced |
oxiui-iced, iced |
iced retained-mode backend; enables Backend::Iced and IcedRunner. |
dioxus |
oxiui-dioxus (+ its dioxus) |
Dioxus reactive adapter (minimal Pure-Rust set); enables Backend::Dioxus. |
No
slintfeature. The facade'sslintfeature was removed in 0.2.0 —oxiui-slintpulls in a C fontconfig binding (yeslogic-fontconfig-sys) on Linux with no pure opt-out, so it can no longer be aggregated into the facade's Pure Rust closure. Use the standaloneoxiui-slintcrate directly instead.
Capability modules
| Feature | Pulls in | Description |
|---|---|---|
table |
oxiui-table |
Table widget; enables oxiui::table::* and App::table. |
a11y |
oxiui-accessibility, accesskit |
Accessibility tree builder; enables oxiui::accessibility, oxiui::recording, and App::build_a11y_snapshot. |
persist |
oxicode |
Enables App::with_persistent_state, which loads/saves app state to disk via oxicode (see below). |
dialogs |
rfd |
Enables oxiui::native_dialog and the App::*_dialog_native methods — blocking native OS file-picker / message-box dialogs. The built-in in-process oxiui::dialog::DialogQueue (App::file_dialog, App::message_dialog, …) needs no feature and works headlessly. |
tracing |
tracing, tracing-subscriber |
Enables oxiui::logging::init_logging, installing a tracing-subscriber fmt subscriber for OxiUI's frame/layout/paint/event spans. |
default |
gpu + egui |
Boots an egui app rendered via wgpu. |
Note: there is no
webfeature. The wasm32 browser entry point lives in the unpublishedoxiui-webcrate (publish = false), used as a copy-template — see Web (wasm32) entry point above.
Errors
App methods return Result<_, oxiui_core::UiError>. UiError is #[non_exhaustive].
| Variant | Meaning (facade context) |
|---|---|
Backend(String) |
Windowing / GPU / backend-runtime initialisation failure (e.g. eframe or iced run error). |
Render(String) |
Render-pipeline error. |
Window(String) |
Window-management error. |
Unsupported(String) |
Requested feature/backend not available (e.g. screenshot without software; App::run on wasm32). |
Layout(String) |
Layout-engine error (unsatisfiable constraints). |
Focus(String) |
Focus-management error. |
Clipboard(String) |
Clipboard access error. |
DragDrop(String) |
Drag-and-drop protocol error. |
Other(String) |
Any other error. |
A separate HotkeyConflict error (its own std::error::Error type) is returned by App::try_hotkey / HotkeyRegistry::register on a duplicate (Modifiers, Key) binding.
Examples
The crate ships runnable examples (see examples/):
Related Crates
| Crate | Role |
|---|---|
oxiui-core |
Core traits/types: UiCtx, Theme, Palette, Color, UiError, events, reactive primitives, constraint solver. |
oxiui-text |
Text shaping and font handling. |
oxiui-theme |
COOLJAPAN themes (cooljapan_default, dark, light, CooljapanTheme). |
oxiui-table |
Table widget (table feature). |
oxiui-accessibility |
accesskit-based a11y tree (a11y feature). |
oxiui-render-soft |
Pure-CPU software renderer (software feature). |
oxiui-render-wgpu |
wgpu GPU renderer (gpu feature). |
oxiui-egui |
egui + eframe backend (egui feature). |
oxiui-iced |
iced retained-mode backend (iced feature). |
oxiui-slint |
Slint adapter. Not a facade feature (removed in 0.2.0, KNOWN-NON-PURE) — depend on it directly instead. |
oxiui-dioxus |
Dioxus adapter (dioxus feature). |
oxiui-web |
wasm32 browser entry point — unpublished (publish = false) copy-template, not a facade feature/dependency. |
License
Apache-2.0 — COOLJAPAN OU (Team Kitasan)