| Crates.io | dear-imgui-winit |
| lib.rs | dear-imgui-winit |
| version | 0.8.0 |
| created_at | 2025-09-13 17:28:33.147729+00 |
| updated_at | 2026-01-02 18:00:47.749219+00 |
| description | Winit platform backend for dear-imgui-rs |
| homepage | https://github.com/Latias94/dear-imgui-rs |
| repository | https://github.com/Latias94/dear-imgui-rs |
| max_upload_size | |
| id | 1837944 |
| size | 195,603 |
Winit platform backend for the dear-imgui-rs Rust crate. It wires winit input/events,
cursor handling and DPI awareness into Dear ImGui. Inspired by
imgui-rs/imgui-winit-support.
| Item | Version |
|---|---|
| Crate | 0.8.x |
| dear-imgui-rs | 0.8.x |
| winit | 0.30.12 |
See also: docs/COMPATIBILITY.md for the full workspace matrix.
Minimal flow with winit 0.30 ApplicationHandler-style loops:
use dear_imgui_rs::{Context, Condition};
use dear_imgui_winit::{WinitPlatform, HiDpiMode};
use winit::{event::WindowEvent, event_loop::{ActiveEventLoop, EventLoop}, window::WindowId};
struct App { /* ... */ }
impl winit::application::ApplicationHandler for App {
fn resumed(&mut self, el: &ActiveEventLoop) { /* create window + ImGui + WinitPlatform */ }
fn window_event(&mut self, el: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
let window = /* get your window */;
// 1) forward the window-local event to ImGui
self.imgui
.platform
.handle_window_event(&mut self.imgui.context, &window, &event);
match event {
WindowEvent::RedrawRequested => {
// 2) per-frame prep
self.imgui.platform.prepare_frame(&window, &mut self.imgui.context);
let ui = self.imgui.context.frame();
// 3) build UI
ui.window("Hello").size([400.0, 300.0], Condition::FirstUseEver).build(|| {
ui.text("ImGui + winit");
});
// 4) update OS cursor from UI
self.imgui.platform.prepare_render_with_ui(&ui, &window);
// 5) render via your renderer backend
let draw_data = self.imgui.context.render();
/* renderer.render(&draw_data) */
}
_ => {}
}
}
}
APIs of interest:
WinitPlatform::new(&mut Context)WinitPlatform::attach_window(&Window, HiDpiMode, &mut Context)WinitPlatform::handle_window_event(&mut Context, &Window, &WindowEvent) — for ApplicationHandler::window_eventWinitPlatform::handle_event(&mut Context, &Window, &Event<T>) — for closure-style EventLoop::runWinitPlatform::prepare_frame(&Window, &mut Context)WinitPlatform::prepare_render_with_ui(&Ui, &Window) — updates OS cursor from ImGuiHiDpiMode controls how the backend derives the framebuffer scale:
Default: use winit’s window.scale_factor() directly.Rounded: round the winit factor to the nearest integer to avoid blurry scaling.Locked(f64): force a custom factor (e.g. 1.0).When DPI changes (ScaleFactorChanged), the backend adjusts:
io.display_size, io.display_framebuffer_scaleHelpers are provided if you pass winit logical values around and need the same coordinates ImGui uses:
scale_size_from_winit(&Window, LogicalSize<f64>) -> LogicalSize<f64>scale_pos_from_winit(&Window, LogicalPosition<f64>) -> LogicalPosition<f64>scale_pos_for_winit(&Window, LogicalPosition<f64>) -> LogicalPosition<f64>dear-imgui::Key. When event.text
is present on key press, characters are injected via io.add_input_character.
Coverage includes letters/digits, punctuation (',.-/;=[]\`), function and lock keys,
and numpad (0-9, decimal/divide/multiply/subtract/add/equal/enter).PixelDelta wheel is mapped to ±1.0 steps
(consistent with most ImGui backends); LineDelta uses the provided values.ModifiersChanged and mirrored into left/right variants.Basic touch-to-mouse translation is provided:
prepare_render_with_ui inspects
ui.io().want_text_input() and toggles Window::set_ime_allowed(...)
accordingly. This means IME (and soft keyboards on mobile) are only enabled
while text widgets are active.WinitPlatform::set_ime_allowed(&window, bool). Auto-management may adjust
it again on subsequent frames unless you disable it.WinitPlatform::set_ime_auto_management(false).WinitPlatform::ime_enabled().prepare_render_with_ui(&Ui, &Window) updates the OS cursor from ui.mouse_cursor().
Changes are cached to avoid redundant OS calls. If ConfigFlags::NO_MOUSE_CURSOR_CHANGE
is set, OS cursor updates are skipped. The software-drawn cursor flag is currently not
exposed via our Io wrapper (defaults to OS cursor).
If Dear ImGui requests repositioning (io.want_set_mouse_pos()), prepare_frame
will set the OS cursor position accordingly.
You can force Dear ImGui to draw the cursor by enabling the software cursor:
// Option 1: via Io directly
imgui_ctx.io_mut().set_mouse_draw_cursor(true);
// Option 2: helper on the platform
platform.set_software_cursor_enabled(&mut imgui_ctx, true);
When software cursor is enabled:
This backend sets (when appropriate):
BackendFlags::HAS_MOUSE_CURSORSBackendFlags::HAS_SET_MOUSE_POSFor diagnostics, the backend also sets BackendPlatformName to "dear-imgui-winit {version}".
Multi-viewport support is available behind the multi-viewport feature and is
experimental. It follows the upstream backend split:
dear-imgui-winit/multi-viewport) owns OS windows and
routes events for secondary viewports.dear-imgui-wgpu/multi-viewport-winit)
to create per-viewport render targets and draw them.Current support matrix:
multi_viewport_wgpu example.
cargo run -p dear-imgui-examples --bin multi_viewport_wgpu --features multi-viewportsdl3_opengl_multi_viewport or sdl3_glow_multi_viewport).This crate targets the dear-imgui-rs bindings in this repository and its API
surface. It’s intentionally separate from imgui-rs/imgui-winit-support, though
many behaviors are aligned for familiarity.
Known limitations: