iu_ui
While cross-platform GUI libraries in Rust are fantastic, michiu takes the opposite direction...
iu_ui is the last 5 letters of michiu_ui, and it looks like a face
Example
A simple counter example showcasing both reactive UI declaration and explicit event loop control:
[dependencies] michiu = "0.2.2" pollster = "1.0.1" use michiu::{accessibility::a11y, prelude::*}; fn main() -> Result<(), Box<dyn std::error::Error>> { let _ = MichiuWindow::init_dpi_awareness(); let com = MichiuComContext::new_ro_single()?; let builder = MichiuWindowBuilder::new() .with_title("Sample App") .with_visible(false) .with_com_context(&com) .with_no_redirection_bitmap(true) .with_inner_size(LogicalSize::new(600.0, 500.0)) .into_unvalidated(); let window = MichiuWindow::build(builder.try_into()?)?; let scale_factor = window.scale_factor() as f32; let handle = window.handle().assume_valid(); let rect = handle.client_rect(); let renderer = pollster::block_on(MichiuRenderer::new( handle.hwnd(), rect.cast(), scale_factor, ))?; let (mut app, mut pump) = MichiuAppBuilder::new(window) .with_accessibility_support(true) .with_auto_resolve_cursor(true) .build_with_ui(renderer, move || { let (count, set_count) = create_signal(0u32); flex( ii().size_full() .justify_center() .items_center() .bg_color(oklch(0.209, 0.0, 0.0)), ) .tag::<a11y::AMain>() .child( flex( ii().r(4.0) .size((200.0, 40.0)) .justify_center() .bg_color(oklch(0.3132, 0.0, 0.0)) .cursor_pointer() .pressed(ii().transform_scale(0.98, 0.98)) .hovered(ii().bg_color(oklch(0.4017, 0.0, 0.0))) .focusable_self_both() .focused_visible( ii().outline_solid(2.0) .outline_offset(2.0) .outline_color(oklch(0.5433, 0.1913, 266.76)), ), ) .tag::<a11y::AButton>() .on_click(move || set_count.set(count.get() + 1)) .label( move || format!("Count: {}", count.get()), ii().font_size(18.0).text_color(oklch(0.9491, 0.0, 0.0)), ), ) })?; app.set_visible(true); while pump.wait_event(|event, _, raw| { let resp = app.standard_handle_window_event(&event, &raw); if resp.needs_redraw { app.redraw_requested(); } if resp.needs_update_window { app.update_window(); } if resp.consumed { return; } if let MichiuAnyEvent::Window { event, .. } = event { match event { MichiuEvent::CloseRequested => { app.destroy(); } MichiuEvent::Destroyed => { app.quit(); } MichiuEvent::RedrawRequested => { app.standard_redraw(); } _ => {} } } })? {} Ok(()) } Architectures
Composition
- Foreground Layer (wgpu / DX12): Renders UI elements. Areas designated for external visuals are physically punched out using SDF masks and subtractive blending.
- Background Layer (DirectComposition): Hosts raw
IDCompositionVisual2(ExternalVisual) alongside opaque backgrounds.
This setup allows for zero-copy visual "sandwiches" (e.g., WebView2 ⇄ Native UI ⇄ WebView2) composed at the OS level.
(Note: The WebView2 integration is currently an experimental proof-of-concept for the composition pipeline).
Widget-less
There are no fixed widget structs like Button or TextInput. Every node is just an Entity(KeyData).
- Nodes gain capabilities (
.text(),.modify(),.on_click(), etc.) dynamically by registering their IDs into Structure of Arrays (SoA) tables. A "component" is merely an intersection of multiple SoA tables on an Entity. - Styles are defined as standalone
Modifiers (ii()) and shared via CoW (Arc::make_mut). - Internal layout and rendering rely on flat 1D arrays:
FlatDfsSequence: Linear DFS traversal for 2-pass Taffy layout calculations.SortedEntitiesVec: Shared between forward-pass GPU batching and reverse-pass (rev()) hit-testing.
Because of this DOD foundation, borrow-checker conflicts are virtually non-existent, allowing developers to mix paradigms depending on the context:
- Reactive: Automatic dependency tracking with
create_signaland.provide(). - Direct imperative mutation: Moving
Entitydirectly into closures. - Contextual: Using
cx.current()via_withhandlers. - Tag queries: Attaching marker types (
.tag::<MyTag>()). Marker tags likea11y::AButton(A11yInferenceTag) handle both semantic queries and Windows UI Automation (AccessKit) mapping at once.
Win32 API
- No Inversion of Control: You explicitly drive
pump.wait_event(...)and can directly hook into raw Win32 messages (HWND,UINT,WPARAM,LPARAM). - Style Guards (
michiu_guard): Prevents common Win32 UB and invalid states at type/validation levels (e.g., mutually exclusive flags likeWS_CHILDvsWS_POPUP, OLE STA requirements, DirectComposition synchronization rules). - Raw external inputs are wrapped in
Unvalidated<T>(with escape hatches likeassume_validfor prototyping).
External
Instead of bundling heavy media decoders:
ExternalVisual: OS-level zero-copy composition viaIDCompositionVisual2.ExternalTexture: Supplies external buffers (video frames, decoders) directly to wgpu viaresolve_view.ExternalData: Reactive, file-watched asset loading (e.g., custom style sheets).
Workspace
Published Crates:
michiu: The facade crate (you only need this for most use cases)michiu_ui: Core DOD UI engine and wgpu / DirectComposition renderermichiu_window: Win32 windowing, event pump, and message handlingmichiu_guard: Compile-time and runtime validation layer for Win32/COM invariants
Workspace Examples & Catalogs:
- sample_collection/: Interactive testbed showcasing composition pipelines, transforms, and events.
- a11y_catalog/: Catalog of copy-paste accessible UI patterns and high-contrast theme tests.
What started as a simple IME indicator tool somehow escalated into building an entire DirectComposition-based GUI framework from scratch.
Since this is still very much an experimental project, please feel free to poke around and share your thoughts! Impressions on the API ergonomics, simple questions, or bug reports are all super welcome—you don't have to be a graphics guru.
(If you happen to spot any obvious Win32/COM blunders, do let me know—just please be gentle...
)
1 post - 1 participant

