dear-app
dear-app is the Winit + WGPU runtime for dear-imgui-rs. It keeps the main window, Dear ImGui context, add-ons, and user application alive while replacing only GPU-owned state after device loss.
Quick Start
Create a binary crate and add the stable release:
[]
= "0.16"
Then use dear_app::run_ui for applications that only need persistent UI state:
use ;
Run it with cargo run. dear-app re-exports the matching core crate as dear_app::imgui, so this starter cannot accidentally combine incompatible versions.
Fallible Frame Closure
Move the same captured state to run_frame when a small application needs fallible work, explicit
exit, compiled add-ons, or the active GPU generation but does not need lifecycle hooks:
use io;
use ;
The closure value remains alive across frames and GPU recovery. FrameContext::addons() exposes
the add-ons compiled and enabled by AppConfig::addons, while FrameContext::gpu() exposes the
current generation-aware WGPU API. request_exit() is normal control flow: the runtime performs
shutdown exactly once and returns Ok(()). A returned error wins even if the same callback also
requested exit; RunError::Application records ApplicationStage::Frame and retains the original
error through std::error::Error::source.
The complete runnable example is:
cargo run -p dear-imgui-examples --bin fallible_frame
Application Lifecycle
Move from run_frame to Application only when the program needs context initialization, raw
window events, GPU resources, device-loss recovery, or deterministic teardown. The frame body can
move unchanged into Application::frame:
use ;
Application is the single owner of application state:
configure_imguiruns once before renderer initialization.initializedruns once after the first GPU generation is ready.eventreceives events only for the live main window.prepare_framemutates Context-owned resources before the next frame opens.frameis the only per-frame UI callback.gpu_lostruns before old GPU resources are invalidated.gpu_recreatedruns after a replacement generation is committed.shutdownruns once before add-ons and the Dear ImGui context are destroyed.
InitContext exposes the complete Dear ImGui Context only from configure_imgui, before platform
and renderer attachment, for extension APIs that require it. initialized receives
InitializedContext; runtime event, pre-frame, and shutdown hooks likewise expose only narrow IO,
style, font-atlas, and managed-texture capabilities. The runtime compares the Context identity,
native frame sequence, and lifecycle state at every callback boundary, so opening and closing a
frame inside a callback is still reported as RunError::ImGuiFrameOwnership.
Every failing hook is wrapped with its typed ApplicationStage, while the hook's original
RunError remains in the source chain. The first actual failure remains primary. Shutdown still
runs exactly once, and a shutdown or backend-release failure is returned only when no earlier
runtime or event-loop failure exists.
The feature-free lifecycle example implements every hook and displays real hook activity, persistent state, and the active GPU generation:
cargo run -p dear-imgui-examples --bin application_lifecycle
Surface loss and resize do not recreate the application or Dear ImGui context. dear-app acquires and, when necessary, recovers the main surface before calling any per-frame application hook. Timeout and occlusion skip the frame without advancing application or test state. Only WGPU device loss starts GPU recovery, and that callback communicates with the UI thread through the Winit event loop.
Test Engine
Enable the optional test-engine feature when the application owns an interactive Dear ImGui Test Engine. The matching crate is available as dear_app::test_engine; return its TestEngine from Application::test_engine. The runtime then owns the complete render -> pre-swap -> present -> post-swap transaction for every admitted frame. Applications must not call presentation hooks themselves.
Standalone test programs that own their whole frame loop should use TestRunner::run_graphical instead. Headless runs use the explicitly virtual presentation path and do not claim graphical swap coverage.
Configuration
Configuration is a value, not a builder. Docking is opt-in:
use ;
let config = AppConfig ;
DockingConfig configures docking in the main window; it does not enable Dear ImGui platform multi-viewport. dear-app rejects ConfigFlags::VIEWPORTS_ENABLE in 0.16 because its single-window recovery model does not own secondary platform windows. Use the Winit or SDL3 owning runtime examples when an application needs native secondary windows.
GPU Resources
External WGPU textures return an ExternalTextureHandle instead of a raw TextureId. Resolve the handle through the current frame's GpuApi before submitting it to Dear ImGui. Resolution fails after GPU recovery, so an old identifier cannot alias a resource from a newer generation.
Rebuild application-owned GPU resources from gpu_recreated. Managed Dear ImGui textures retain their CPU data and are reset to WantCreate before the old renderer is torn down.
Add-ons
The implot, imnodes, and implot3d features create extension contexts owned by the stable UI
state. Access them through FrameContext::addons() from run_frame or Application::frame.