Stipple
A cross-platform UI library and toolkit in Rust.
Stipple draws beautiful, fully themeable interfaces on Linux, macOS, Windows,
Android, iOS, and the web — pixel-identical across platforms under its own
themes, or native under Theme::native() — while depending on as little
third-party code as possible.
It builds on the pure-Rust oxideav media stack
for all 2D content rendering (scene graph, CPU rasterizer, font shaping, image
decode, SVG) and adds everything around it: native windowing and input per OS,
presenting the rendered buffer, and a declarative, reactive UI toolkit.
use *;
Status: pre-alpha. The architecture and phased plan live in
ROADMAP.md. APIs are unstable.
The same app, rendered by Stipple's native backends and screenshotted in CI
(the Visual workflow) — Linux X11 (under Xvfb) and Wayland (under headless
sway), Win32, and Cocoa, each from-scratch with no windowing crates:
| Linux / X11 | Linux / Wayland | Windows / Win32 | macOS / Cocoa |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| Web / wasm + canvas | GPU / GLES (offscreen) |
|---|---|
![]() |
![]() |
Input is verified too: CI synthesizes real events and screenshots the result —
X11 via xdotool (clicking a counter; caret-aware editing — type "Stipple",
arrow-left twice, insert "XY" → "StippXYle" with a mid-string caret), macOS via
cliclick, and Wayland via wtype (whose virtual keyboard exercises the
wl_seat keyboard + xkb-keymap decode path — Tab to focus, then type "stipple
wl"):
| X11 click | X11 edit (mid-string caret) | macOS click | Wayland type |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
Native look
Theme::native() follows the system's light/dark mode and accent color, and on
Windows, macOS and iOS has the OS's own UI framework draw the controls: uxtheme,
AppKit and UIKit, each rendering a control's chrome into a bitmap. Stipple keeps
layout, input, the caret and the labels. Linux has no native framework and Android's
needs the JVM, so controls stay self-drawn there, in the system's colors.
| Windows | macOS | iOS | Linux |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
Windows has no switch and iOS has no checkbox or radio button, so those stay
self-drawn. The GPU backends can't draw these bitmaps yet, so App::render_with
skips the controls' chrome under this theme.
These screenshots, and the others on this page, are committed by CI after each
green push to master.
Themeable by design
Every widget reads its colors and metrics from a [Theme] — a semantic
Palette (roles, interaction states, status colors, overlays), a Typography
scale, a Spacing scale, and a corner radius. Customizing is a one-liner:
Theme::dark().with_accent(color).with_radius(14.0) recolors the accent,
derives its hover/active tints, and picks a readable on-color automatically;
high_contrast() maximizes text/border contrast. Material 3 is built in
too: Theme::material3_light() / material3_dark(), or
Theme::material3_from_seed(color, dark) for Material You dynamic color from
any seed. The same card below is rendered under four themes (light, dark, a
violet-accent dark, high-contrast), montaged in CI:

Design at a glance
- Software-first rendering, with a GPU path: raw, hand-written GLES2
(SDF boxes + glyph atlas, usable for live windows via
App::render_with), Vulkan, Metal, Direct3D 11, and WebGPU backends. No wgpu. - Reactive / declarative API: UI is a function of state. Frames are damage-diffed and only changed regions are re-rasterized and presented.
- Self-drawn widgets: one theme engine, identical on every platform, unless
Theme::native()asks the OS to draw them. - High-DPI: renders at the display's scale on every desktop backend and iOS.
- Accessible: the semantic tree is exposed to AT-SPI (Linux),
NSAccessibility (macOS) and UI Automation (Windows), each over a hand-written
bridge (D-Bus wire protocol,
objc_msgSend, COM vtables). - No
winit/wgpu/taffy/lyon/ GTK / Qt /zbus/windows/objc. OS interfaces are hand-written per platform instipple::platform.
Modules
Stipple is one crate, stipple, with these modules:
| Module | Role |
|---|---|
stipple::geometry |
Logical-pixel math (Point, Size, Rect, Insets, Affine) |
stipple::render |
Scene → oxideav VectorFrame → raster → Surface; fonts |
stipple::platform |
Per-OS windowing, input, clipboard, file dialogs, accessibility bridges, shared memory + sandbox |
stipple::layout |
Flex/box layout solver |
stipple::core |
Reactive runtime: View, Element IR, reconcile, events, a11y tree |
stipple::anim |
Easing, tweens, springs |
stipple::style |
Design tokens and themes (incl. Material 3) |
stipple::widgets |
Standard widget library |
stipple::gpu |
Raw GPU backends, behind the gpu feature; dma-buf / shared-texture export. gl, vk, d3d and mtl enable GLES2, Vulkan, Direct3D 11 and Metal |
App and the prelude live at the crate root. The repository root is the
stipple crate; examples/ holds the demo apps, and docs/ the guides.
Widgets available in the prelude: panel, row, column, spacer,
divider, label, heading, paragraph, button, button_labeled,
button_variant, text_field, text_editor, text_area, checkbox,
radio, switch, slider, progress_bar, spinner, swatch,
setting_row, tabs, scroll, menu / menu_item / open_menu,
open_dialog, tooltip, image / svg (PNG, JPEG, GIF, WebP, BMP and SVG,
decoded by the oxideav stack; see docs/images.md), and
viewport (embedded external content).
Examples
Each opens a real native window via App::run (Wayland, then X11, on Linux;
Win32; Cocoa), or falls back to a one-shot headless render where no display is
available. Platform and subsystem probes live alongside them:
gpuwindow / gpudemo (GLES, --features stipple/gl), d3ddemo,
metaldemo, dmabuftest, dri3probe, viewportdemo, contentproc
(sandboxed content process composited over shared memory), a11ydemo and
uiademo (accessibility bridges), androiddemo (an Android app as a NativeActivity cdylib),
and webdemo (a wasm32 module for a <canvas>). See docs/
for how to build and package each platform.
Status & MSRV
Pre-alpha. The whole workspace builds on Rust 1.88 (edition 2024).
Working today, each verified in CI on its platform:
- The reactive toolkit: layout, state, tap / keyboard / focus / drag / hover / scroll / context menus, caret-aware multi-line text editing with selection, word wrapping, clipboard, overlays, multi-window, and the widgets above.
- Native backends: X11 (with MIT-SHM present), Wayland, Win32,
Cocoa, plus web (wasm + canvas), an iOS UIKit backend (run on the
simulator), and an Android
NativeActivitybackend with touch, keys, timers and display-paced frames (driven on the emulator). - GPU: GLES2 scene rendering in a live window, and off-screen Vulkan, Metal, D3D11 and WebGPU pipelines.
- Accessibility: the full element tree on all three desktops.
- Compositor seams for embedding a sandboxed content process (e.g. a browser engine): viewports, shared-memory and dma-buf / IOSurface / D3D shared-handle buffer transport, input forwarding, seccomp sandboxing, and DRI3 + Present on-window GPU present.
Next up (see ROADMAP.md): mobile touch input and full lifecycle, zero-copy
GPU swapchain present, accessibility change events, and broader toolkit depth.
License
MIT













