v0.8.0
This release focuses on FFI soundness and correctness improvements for Dear ImGui v1.92+ (texture system, font atlas, callbacks),
plus backend hardening for multi-viewport and renderer integrations.
Highlights
- Major UB/FFI hardening pass across core + backends (callbacks, drag/drop payloads, font atlas memory ownership, texture system).
- Managed textures: correctness fixes for
ImTextureDataconstruction/ownership and the status/TexID contract (fewer asserts and safer iteration). - Font atlas: safer glyph range handling + runtime font merge behavior; align renderer usage with the new
RENDERER_HAS_TEXTURESflow. - Multi-viewport: safer teardown and reentrancy guards for WGPU/Glow/Winit callback paths.
- Extensions: pointer-lifetime fixes and reduced const-casts/
transmutein ImPlot/ImPlot3D/ImNodes/ImGuizmo/Reflect.
Breaking Changes
- Core (
dear-imgui-rs)- Remove
Viewport::main()(returned&'static Viewport); useUi::main_viewport()orContext::main_viewport()to get a viewport reference tied to the caller's lifetime.
- Remove
dear-imgui-wgpu- Bump
wgputo v28 (requires Rust 1.92+).
- Bump
Changed
- Sys bindings: always enable
IMGUI_USE_WCHAR32(ImWchar = 32-bit) across all targets, including import-style WASM bindings. - SDL3 backend: bump SDL3 dependencies (
sdl30.17,sdl3-sys0.6 / SDL 3.4.0).
Added
-
Core (
dear-imgui-rs)Color::to_hsv01/Color::from_hsv01: helpers that match Dear ImGui's HSV semantics (h in[0, 1]).- ImGui-style
i32index variants for optional selection (-1as no selection):
Ui::combo_i32,Ui::combo_simple_string_i32,ListBox::build_simple_i32. - Menu items: shortcut-free and shortcut variants to avoid
None::<&str>turbofish:
Ui::menu_item_toggle_no_shortcut,Ui::menu_item_toggle_with_shortcut,
Ui::menu_item_enabled_selected_no_shortcut,Ui::menu_item_enabled_selected_with_shortcut. Io::mouse_down_button/Io::set_mouse_down_button: typedMouseButtonhelpers forIo::MouseDown.- Legacy columns:
Ui::begin_columns_token(RAIIColumnsTokenends columns on drop). Ui::list_box_config: convenience constructor forListBox.- Scratch C string helpers (no allocation):
with_scratch_txt,with_scratch_txt_two,with_scratch_txt_three,
with_scratch_txt_slice,with_scratch_txt_slice_with_opt.
-
Extensions
dear-implot: add non-variadic text helpers for annotations/tags (avoids calling C..., useful for import-style WASM).dear-imguizmo: expose safe alternative-window helpers and byte-slice ID helpers (str_begin/str_endform).dear-imnodes: expose accessors for the current/raw context pointer.dear-imgui-reflect: derive now supports tuple/unit structs and enums with payload variants (payload types must implementDefaultto allow switching); vector editor adds per-item context menus (insert/remove/move/clear), nested container edits now include index/key segments in response paths (e.g.items[0],map["k"]), andReflectEventis now#[non_exhaustive](includes newReflectEvent::VecCleared).
Fixed
-
FFI: harden
ImString/InputTextbuffer handling to avoid unbounded scans and ensure NUL-terminated, zero-initialized backing storage before calling into C. -
Prebuilt: reject ABI-incompatible prebuilts by requiring
features=wchar32inmanifest.txt(andfreetypewhen enabled). -
Fonts: fix
ImWcharhandling for wchar32 and add non-BMP glyph range/exclude-range test coverage. -
Cross-target FFI: fix remaining
c_charsignedness assumptions (i8 vs u8) and add an armv7 CI type-check sentinel to catch regressions. -
FFI: fix incorrect
c_charsignedness assumptions in a few call sites (thanks @EtherealPsyche, #10). -
Core (
dear-imgui-rs)- Windows: expose ImGui
p_openviaWindow::opened(&mut bool)so the title-bar close button (X) can toggle window state. - Popups/headers: expose the corresponding
bool*variants via
Ui::begin_modal_popup_with_opened,Ui::modal_popup_with_opened,Ui::collapsing_header_with_visible. - Selectables:
Selectable::build_with_refnow uses ImGui'sSelectable(..., bool*)variant for closer upstream behavior parity. - Text helpers: avoid passing user text as a C variadic format string (prevents potential UB when strings contain
%) and prefer non-variadic tooltip/text paths where available. - Tree nodes: avoid calling C variadic tree-node APIs with user-provided labels by routing
TreeNodethrough non-variadicTreeNodeEx+PushID/PopID, preventing potential UB when labels contain%. TextFilter: fix a leak by callingImGuiTextFilter_destroyon drop; avoid per-call allocations; addpass_filter_rangewith correcttext_endsemantics.- Clipboard: handle non-UTF8 clipboard payloads without panicking (lossy conversion), sanitize interior NUL bytes, and guard against missing clipboard user data.
- Draw callbacks: avoid creating
&mutreferences from*constFFI pointers when clearing callback user data; ensureadd_callback_safestores a direct userdata pointer (userdata_size = 0) so Dear ImGui doesn't copy closure bytes into its internal callback buffer (fixes UB when executing callbacks). - Drag and drop typed payloads: avoid passing uninitialized padding bytes across the C++ boundary and read payload bytes using
read_unalignedinstead of creating references into Dear ImGui's unaligned payload storage (fixes UB). - Scratch C strings: avoid scratch-buffer pointer invalidation in multi-string widget calls by using the paired scratch helpers (
scratch_txt_two/scratch_txt_with_opt) when passing multiple C string pointers in one FFI call. - Scratch C strings: sanitize interior NUL bytes (
'\0'→?) instead of panicking when building temporary C string pointers. - Rendering draw lists: handle null vertex/index buffers defensively when constructing slices at the FFI boundary.
- InputText (String-backed): avoid undefined behavior when trimming at NUL by zero-initializing spare capacity, including during ImGui resize callbacks.
- Font atlas: make
FontAtlas::add_font_from_memory_ttfalways copy the TTF bytes into Dear ImGui-owned memory (viaigMemAlloc) and setFontDataOwnedByAtlas=trueso the atlas can safely rebuild and free the buffer (fixes potential use-after-free/double-free when passing Rust-owned buffers). - Font atlas: add safe wrappers for
AddFontFromMemoryCompressedTTF/AddFontFromMemoryCompressedBase85TTFand extendFontSourceaccordingly (Base85 input is now explicitly NUL-terminated viaCString). - Deprecated glyph ranges: fix
GlyphRangesBuilder::add_rangesto pass the correctImWcharlayout, and free internalImVector_ImWcharbuffers; ensureadd_rangesalways passes a NUL-terminated list; addDropfor the underlying C++ builder. - Dynamic fonts: fix
FontConfig::glyph_exclude_rangesto pass the correctImWcharlayout (and now owns the converted ranges buffer, ensuring it is NUL-terminated). - Dynamic fonts: discard baked glyph caches when adding merge-mode fonts, so runtime font merging can override previously-missing glyphs (e.g.
style_and_fontsCJK merge). - Texture iteration/access: make
DrawData::textures()/PlatformIo::textures()yield a guarded mutable view instead of&mut TextureDatafrom&self, and avoid creating&mut TextureDatainternally when returning&TextureDatafromDrawData::texture()/PlatformIo::texture()(prevents Rust aliasing UB while keeping the renderer API ergonomic). - Texture refs: avoid constructing
ImTextureReffrom&TextureDatavia a mutable FFI pointer;&TextureDatanow forwards only the currentTexID(legacy path), use&mut TextureDatafor managed textures. - Texture IDs: make
RawTextureIdmatch Dear ImGui'sImTextureID(ImU64) and add debug assertions to catch pointer-width truncation when converting aTextureIdintousize/*const c_void. - Managed textures: avoid null pointer arithmetic when iterating
DrawData::textures()/PlatformIo::textures()on empty lists; makeDrawData::texture{,_mut}robust to negative vector sizes. - Managed textures: fix
ImTextureDataownership by introducingOwnedTextureData(C++ constructed/destroyed) and makingTextureData::new()return it; useImTextureData_SetStatus/ImTextureData_SetTexIDto preserve ImGui's internal state machine. - Managed textures:
TextureData::set_status(Destroyed)now clearsTexID/BackendUserDatato match Dear ImGui's texture contract and avoid asserts. - Font atlases:
FontAtlas::get_glyph_ranges_defaultincludes the terminating0sentinel. PlatformIo: typed callback setters no longer panic if the internal callback mutex is poisoned.- Clipboard callbacks: handle null
PlatformIOdefensively and guardClipboardContextaccess against reentrant mutable borrows (avoids potential aliasing UB in callbacks). OwnedDrawData: avoid double-free by lettingImDrawDataown and free itsCmdListsstorage (we still destroy the clonedImDrawListpayloads).Context::save_ini_settings: read the returned settings blob usingout_ini_sizeinstead of relying on NUL termination.Ui::get_key_name/Ui::style_color_name: handle null pointers defensively at the FFI boundary.- Draw data types: add compile-time layout assertions to keep
DrawVert/DrawIdxcompatible with sysImDrawVert/ImDrawIdx. - FFI wrappers: add compile-time layout assertions for transparent wrappers (
Io,Style,Font,PlatformIo,Viewport,TextureRef,TextureData) to keep pointer casts sound when updating sys bindings. - Draw data: make internal
DrawData::cmd_listsrepresentation match sys (ImDrawList*pointers) and add compile-time layout assertions forDrawData/DrawList(reduces pointer casts and prevents silent layout drift). Ui::io: panic on null IO pointer instead of dereferencing it (avoid UB when called without an active context).Io/Style/Font/PlatformIo/Viewport/TextureData: store ImGui-owned sys values behindUnsafeCellto make Dear ImGui-driven interior mutability explicit (reduces risk of Rust aliasing UB when the C++ side mutates these structs).- Tests: avoid
mem::zeroed()forImGuiPlatformIOby constructing it via the C++ constructor instead. - Additional FFI hardening: treat negative
ImVectorsizes as empty, guardTextureData::pixels*against invalid dimensions/overflow, clampTextureData::set_width/set_heightto avoidu32 → i32wrap-around, validateInputTextCallbackData::str_as_bytes_mutbuffer bounds before creating slices, and prevent unwinding across FFI (panic → abort).
- Windows: expose ImGui
-
Backends
dear-imgui-wgpu- Font atlas: stop calling
FontAtlas::build()in renderer code when usingBackendFlags::RENDERER_HAS_TEXTURES; skip legacy TexID fallback in the new texture system. - SDL3 multi-viewport: drop unnecessary
unsafe impl Send/Syncfrom the SDL window surface target adapter. - Render callbacks: require
&mut WgpuRenderStateto access the render pass encoder (avoid&mutderived from&self/clippy::mut_from_reffootgun). - Multi-viewport: add
disable()/shutdown_multi_viewport_support()helpers and clear stored globals to avoid stale callback pointers when tearing down a renderer. - Multi-viewport: clear the global renderer pointer on drop so callbacks become a no-op if the renderer is dropped without an explicit disable.
- Multi-viewport: guard access to the global renderer pointer to avoid creating multiple
&mut WgpuRendererreferences across callbacks (skip on reentrancy). - SDL3 multi-viewport: avoid nested mutable borrows of per-viewport
RendererUserDataby caching framebuffer sizes before encoding draw commands (prevents aliasing UB). - Frame resources: pack vertex/index data into byte buffers explicitly instead of casting typed slices to bytes (avoids reading uninitialized padding bytes).
- Multi-viewport: avoid
transmuteforwgpu::Surfacelifetimes in multi-viewport backends, harden draw offsets against integer overflow, and avoid panicking when retrieving cached bind groups. - Managed textures: keep existing GPU texture and mark status
OKwhen aWantUpdatesupload fails (avoids invalidTexIDduring the same frame).
- Font atlas: stop calling
dear-imgui-sdl3- Manual gamepad mode: avoid casting away constness in Rust by taking a
*constpointer array and copying pointers into stable storage on the C++ side. - OpenGL3 renderer: make
RenderDrawDatawrapper const-correct to avoid casting&DrawDatato*mutacross FFI; useTextureData::as_raw_mut()forUpdateTexturehelper to avoid relying on wrapper pointer casts.
- Manual gamepad mode: avoid casting away constness in Rust by taking a
dear-imgui-glow- GL state restore: treat negative
glGetIntegervresults defensively when restoring bindings (avoid castingi32→u32blindly). - Draw callbacks: abort on panic when executing
ImDrawCmdraw callbacks (avoid unwinding acrossextern "C"ABI). - Multi-viewport: clear the global renderer pointer on drop so callbacks become a no-op if the renderer is dropped without an explicit disable.
- Texture map: avoid aliasing
&mut selfwith&self.texture_mapduring rendering by temporarily moving the texture map out (removes raw-pointer borrow workaround, prevents potential aliasing UB). - Multi-viewport: guard access to the global renderer pointer to avoid creating multiple
&mut GlowRendererreferences across callbacks (skip on reentrancy). - Vertex/index uploads: restrict slice-to-bytes conversion to
DrawVert/DrawIdxto avoid accidentally reading padding bytes from arbitrary Rust types. - Textures: validate
TextureIdrange when updating existing OpenGL textures (avoid truncation/panic).
- GL state restore: treat negative
dear-imgui-winit- Multi-viewport: avoid freeing
ViewportDatawhile an&mut ViewportDatareference is still live (raw-pointer cleanup instead). - Multi-viewport: avoid creating
&mut Windowreferences from stored raw window pointers in platform callbacks. - IME bridge: treat
Platform_ImeUserDataas*const Windowin callbacks to avoid suggesting mutability across the FFI boundary. - Keyboard modifiers: submit
ImGuiMod_*key events onModifiersChangedsoio.KeyMods/io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuperare updated correctly (thanks @npc97, #11).
- Multi-viewport: avoid freeing
-
Extensions
dear-implot: fixSubplotToken/MultiAxisToken/LegendTokendouble-end by lettingDropperform the actualEnd*call; make subplot ratio buffers owned to avoid casting away constness.dear-implot: keep axis formatter/transform closures alive for the full plot scope (avoid danglinguser_datapointers if tokens are dropped early).dear-implot: fixMultiAxisPlotaxis setup (Y1 is now configurable) and remove a potential panic when keeping axis labels alive.dear-implot: avoidtransmutewhen passingdear-imgui-rs::TextureIdtoImTextureID.dear-implot3d: fixPlotMeshvertex layout (convert[[f32; 3]]intoImPlot3DPointwithf64fields before the FFI call).dear-implot3d: keep tick label pointers alive forsetup_axis_ticks_*calls (avoids passing dangling pointers to C).dear-implot3d: destroy the correct context pointer on drop (no reliance on "current context").dear-imnodes: trim trailing NUL terminators from INI state strings returned by ImNodes save APIs.dear-imguizmo-quat: avoid casting*constmatrices to*mutin quaternion helpers by using a local mutable copy.dear-implot-sys: build-from-source compiles a patchedcimplot.cppcopy fromOUT_DIRto avoid a known out-of-boundsFormatSpec[16]access in the upstream-generated wrapper code (submodule remains unchanged; when the bug is detected we also skip the CMake build path and fall back to the patchedccbuild).dear-imgui-reflect: harden response/settings scopes against panics, fixVecbutton ID collisions, reduceBTreeMapeditor overhead, and clean up map-add popup temporary state.
Changed
- Core (
dear-imgui-rs)ui.window(...).build(...)only shows a close button whenopened(...)is provided (matches upstream Dear ImGui behavior).Ui::get_iduses the internal scratch buffer instead of allocating aCString.Ui::windownow acceptsInto<Cow<'_, str>>and avoids per-frame string allocation for borrowed names.InputText::hintnow acceptsInto<Cow<'_, str>>, matching label ergonomics and avoiding type changes when passing ownedStrings.- Avoid per-frame allocations for common builder labels/IDs by storing
Cow<'_, str>:
Button,InputText*,InputInt/Float/Double,PlotLines/Histogram,ColorEdit/Picker/Button,
ImageButton,ProgressBar,TableBuilder/ColumnBuilder. - Non-
Uistring entrypoints also use the shared scratch strategy where applicable:
DockBuilder::dock_window,DockBuilder::copy_window_settings, andTextCallbackData::insert_chars. ImStringnow rejects interior NUL bytes in safe constructors/mutators (new,push_str).
dear-imgui-wgpu- Allow enabling both
multi-viewport-winitandmulti-viewport-sdl3simultaneously (exports both helper modules).
- Allow enabling both
- Extensions (
dear-implot,dear-implot3d,dear-imnodes,dear-imguizmo,dear-imguizmo-quat)- Avoid per-call
CStringallocations in most label/text/title APIs by using the shared scratch string helpers.
- Avoid per-call