COOLJAPAN
← All posts

OxiUI 0.2.2 Released — Multi-Window and the Menu Bar Actually Draw Now, and Two Backends Stop Lying About Success

OxiUI 0.2.2 wires the facade's multi-window registry and menu bar into a real rendering path for the first time (egui opens real OS viewports, iced/headless render the bar too), makes oxiui-slint and oxiui-dioxus return an honest error instead of a fabricated Ok(()), fixes GPU device-loss/OOM panics in oxiui-compute-wgpu, and restores wasm32 compilation for oxiui-web. 2,024 tests passing, the sovereign Pure Rust GUI layer for the COOLJAPAN ecosystem.

release oxiui pure-rust cooljapan noffi ui gui security cross-platform

App::open_window and App::menu_bar have been callable since OxiUI shipped. Until this release, calling them stored a value that nothing ever read.

Today we released OxiUI 0.2.2 — a release that finishes wiring two APIs that previously compiled, chained, and silently did nothing: the multi-window registry and the menu bar now reach a real rendering path in every backend that can support them. Alongside that, two backends (oxiui-slint, oxiui-dioxus) stop returning a fabricated Ok(()) for a window that never opened, oxiui-compute-wgpu stops panicking on GPU device loss, and oxiui-web compiles for wasm32-unknown-unknown again.

No GTK. No Qt. No SDL. The dependency shape hasn’t changed — OxiUI still builds in a clean rust:slim container on the same egui/iced/slint/dioxus facades and the same wgpu/softbuffer rendering paths. What changed in 0.2.2 is how honestly each backend reports what it actually did.

Why OxiUI 0.2.2 is a game changer

The previous release (0.2.1) fixed lifecycle hooks that compiled but never fired. This release closes the same category of bug in three more places, plus two real crashes:

OxiUI 0.2.2 ends all of that.

Technical Deep Dive: shell, widget IDs, and honest failure

  1. The shell pipeline (oxiui::shell, oxiui::menu). ShellConfig is the single value that carries everything a backend needs to actually show windows and menus — secondary windows plus their content closures, the menu bar, and a WindowHandle. BackendRunner::set_shell is the seam every backend implements against; a backend that can’t support part of the shell (iced can’t do multi-window — its 0.14 application runtime is single-window, iced::daemon would be required) rejects it explicitly with UiError::Unsupported rather than accepting and ignoring it.
  2. Disjoint widget-id ranges (EguiUiCtx::with_id_base, IcedUiCtx::with_id_base/next_widget_id). Rendering the menu bar and the content into the same frame means two UiCtxs drawing widgets that need stable, non-colliding IDs. The menu bar’s widget count changes as its dropdown opens and closes; without a reserved high ID range, every content widget’s ID would shift underneath it, silently rerouting iced clicks and invalidating egui’s persistent widget state (dropdown selection, popup position, grid column widths).
  3. New WindowHandle and headless frame driving. App::open_window_with(config, F) attaches a per-window content closure; App::window_handle() returns a cloneable, thread-safe handle with open/close/focus, drained each frame into a WindowSession state machine. App::run_headless_frame(&mut dyn UiCtx) -> usize drives one complete frame — menu bar, init, content, per-frame hooks — and reports how many menu actions fired, the display-free way to exercise the whole shell path in tests.
  4. A new fuzz harness (fuzz/) for oxiui-render-soft. fuzz_fill_polygon/fuzz_composite_into generalize the 0.2.1 security fixes to arbitrary finite input, and a new fuzz_bezier_flatten target found two real, still-open crashes on its first run: a subtract-overflow panic in scanline.rs’s fast-forward loop and a stack-overflow in path.rs’s adaptive bezier flattening from finite-input float overflow. Both repro inputs are checked into fuzz/regressions/ (not gitignored, unlike the corpus/artifact dirs) with decoded parameters in fuzz/regressions/README.md — tracked in TODO.md’s backlog, not yet fixed.

Getting Started

cargo add oxiui
use oxiui::{App, theme};
use oxiui::menu::{MenuBar, MenuItem};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    App::new("My App")
        .theme(theme::cooljapan_default())
        .menu_bar(MenuBar::new().item(MenuItem::action("Quit", |_| std::process::exit(0))))
        .content(|ui| {
            ui.heading("Hello from OxiUI — the menu bar above this actually renders now");
        })
        .run()?;
    Ok(())
}

Open a second window and hold onto a handle for it:

use oxiui::{App, WindowConfig};

let app = App::new("Main")
    .open_window_with(WindowConfig::new("settings"), |ui| {
        ui.label("Settings window content");
    });
let handle = app.window_handle();
handle.open("settings")?;

What’s New in 0.2.2

Tips

This is the foundation

OxiUI is part of NoFFI — the COOLJAPAN initiative to replace every C/C++/Fortran/-sys FFI dependency in the Rust ecosystem with a clean, memory-safe, 100% Pure Rust implementation. It’s built directly on its NoFFI siblings OxiText (text shaping) and OxiFont (font loading + raster), and OxiAero depends on oxiui-compute-wgpu for its GPU compute path — exactly the crate this release made fail gracefully instead of panicking on device loss.

Repository: https://github.com/cool-japan/oxiui

Star the repo if you’d rather get UiError::Unsupported than a window that silently never opens.

Pure Rust UI — sovereign, safe, and honest about what it can’t do yet.

KitaSan at COOLJAPAN OÜ August 6, 2026

↑ Back to all posts