Skip to main content

dear_imgui_sys/
lib.rs

1//! Low-level FFI bindings for Dear ImGui (via cimgui C API) with docking support
2//!
3//! This crate provides raw, unsafe bindings to Dear ImGui using the cimgui C API,
4//! specifically targeting the docking branch (multi-viewport capable).
5//!
6//! ## Features
7//!
8//! - **docking**: Always enabled in this crate
9//! - **freetype**: Enable FreeType font rasterizer support
10//! - **wasm**: Enable WebAssembly compatibility
11//! - **backend-shim-\***: Expose selected repository-owned backend shim modules
12//!   for low-level integrations
13//!
14//! ## WebAssembly Support
15//!
16//! When the `wasm` feature is enabled, this crate provides full WASM compatibility:
17//! - Disables platform-specific functions (file I/O, shell functions, etc.)
18//! - Configures Dear ImGui for WASM environment
19//! - Compatible with wasm-bindgen and web targets
20//!
21//! ## Safety
22//!
23//! This crate provides raw FFI bindings and is inherently unsafe. Users should
24//! prefer the high-level `dear-imgui-rs` crate for safe Rust bindings.
25//!
26//! ## Usage
27//!
28//! This crate is typically not used directly. Instead, use the `dear-imgui-rs` crate
29//! which provides safe, idiomatic Rust bindings built on top of these FFI bindings.
30//!
31//! ## Backend Shim Modules
32//!
33//! For downstream backend crates, engine integrations, and platform-specific
34//! application glue, `dear-imgui-sys` can expose selected official backend
35//! pieces through `backend_shim::*`.
36//!
37//! Important boundary:
38//!
39//! - these modules expose the repository-owned C shim ABI
40//! - they do not expose upstream `imgui_impl_*` C++ symbol names as a stable
41//!   Rust-facing contract
42//! - enabling `backend-shim-*` features does not imply that `dear-imgui-rs`
43//!   already owns a safe wrapper for those backends
44//!
45//! Typical feature gates:
46//!
47//! - `backend-shim-opengl3`
48//! - `backend-shim-android`
49//! - `backend-shim-win32`
50//! - `backend-shim-dx11`
51//!
52//! SDLRenderer3 and SDLGPU3 renderer shims are owned by `dear-imgui-sdl3`.
53//!
54//! ## Android Direction
55//!
56//! The current Android story is intentionally low-level but supported.
57//!
58//! ```toml
59//! [dependencies]
60//! dear-imgui-rs = "0.10"
61//! dear-imgui-sys = { version = "0.10", features = ["backend-shim-android", "backend-shim-opengl3"] }
62//! ```
63//!
64//! Recommended split of responsibilities:
65//!
66//! - `dear-imgui-rs` owns the safe core `Context`, `Io`, frame lifecycle, and
67//!   render snapshots
68//! - `dear-imgui-sys::backend_shim::{android, opengl3}` exposes the low-level
69//!   official backend pieces
70//! - the Android application still owns lifecycle glue, input translation
71//!   strategy, EGL / GLES context creation, and packaging
72//!
73//! The repository's concrete reference for this path is
74//! `examples-android/dear-imgui-android-smoke/`, which now carries a minimal
75//! NativeActivity + EGL / GLES3 render loop proving that downstream users can
76//! build Android support on top of `dear-imgui-rs` + `dear-imgui-sys` even
77//! before a dedicated first-party Android convenience crate exists.
78
79#![allow(non_upper_case_globals)]
80#![allow(non_camel_case_types)]
81#![allow(non_snake_case)]
82#![allow(dead_code)]
83#![allow(unnecessary_transmutes)]
84#![allow(clippy::all)]
85// Bindgen may derive Eq/Hash for structs containing function pointers.
86// New Clippy lint warns these comparisons are unpredictable; suppress for raw FFI types.
87#![allow(unpredictable_function_pointer_comparisons)]
88
89// Bindings are generated into OUT_DIR and included via a submodule so that
90// possible inner attributes in the generated file are accepted at module root.
91mod ffi;
92pub use ffi::*;
93
94/// Optional backend shim entry points for downstream integrations.
95///
96/// These modules expose the repository-owned C shim ABI for selected official
97/// Dear ImGui backends. They do not expose the upstream C++ symbols directly,
98/// and they do not imply that `dear-imgui-sys` or `dear-imgui-rs` owns full
99/// safe integration for those backends.
100pub mod backend_shim;
101
102// This project always builds Dear ImGui with `IMGUI_USE_WCHAR32`, so `ImWchar` must be 32-bit.
103const _: [(); 4] = [(); std::mem::size_of::<ImWchar>()];
104
105// Ensure common ImGui typedefs are available even if bindgen doesn't emit them explicitly
106
107// cimgui exposes typed vectors (e.g., ImVector_ImVec2) instead of a generic ImVector<T>.
108// The sys crate intentionally avoids adding higher-level helpers here.
109
110// cimgui C API avoids C++ ABI pitfalls; no MSVC-specific conversions are required.
111
112/// Whether this build linked the repository-owned PlatformIO out-parameter hook shim.
113pub const HAS_PLATFORM_IO_OUT_PARAM_HOOKS: bool = cfg!(dear_imgui_rs_platform_io_hooks);
114
115unsafe extern "C" {
116    fn dear_imgui_stack_begin_horizontal_str(
117        str_id: *const std::os::raw::c_char,
118        size: ImVec2,
119        align: f32,
120    );
121    fn dear_imgui_stack_begin_horizontal_ptr(
122        ptr_id: *const std::ffi::c_void,
123        size: ImVec2,
124        align: f32,
125    );
126    fn dear_imgui_stack_begin_horizontal_int(id: std::os::raw::c_int, size: ImVec2, align: f32);
127    fn dear_imgui_stack_begin_horizontal_id(id: ImGuiID, size: ImVec2, align: f32);
128    fn dear_imgui_stack_end_horizontal();
129    fn dear_imgui_stack_begin_vertical_str(
130        str_id: *const std::os::raw::c_char,
131        size: ImVec2,
132        align: f32,
133    );
134    fn dear_imgui_stack_begin_vertical_ptr(
135        ptr_id: *const std::ffi::c_void,
136        size: ImVec2,
137        align: f32,
138    );
139    fn dear_imgui_stack_begin_vertical_int(id: std::os::raw::c_int, size: ImVec2, align: f32);
140    fn dear_imgui_stack_begin_vertical_id(id: ImGuiID, size: ImVec2, align: f32);
141    fn dear_imgui_stack_end_vertical();
142    fn dear_imgui_stack_spring(weight: f32, spacing: f32);
143    fn dear_imgui_stack_suspend_layout();
144    fn dear_imgui_stack_resume_layout();
145}
146
147/// Start a stack-layout horizontal group using a string ID.
148///
149/// This is a repository-owned compatibility shim for the stack layout extension
150/// used by `imgui-node-editor` examples; it is not an official Dear ImGui API.
151///
152/// # Safety
153///
154/// Requires an active Dear ImGui context and current window. `str_id` must point
155/// to a valid NUL-terminated string for the duration of the call.
156#[inline]
157pub unsafe fn ImGuiStack_BeginHorizontal_Str(
158    str_id: *const std::os::raw::c_char,
159    size: ImVec2,
160    align: f32,
161) {
162    unsafe { dear_imgui_stack_begin_horizontal_str(str_id, size, align) }
163}
164
165/// Start a stack-layout horizontal group using a pointer ID.
166///
167/// # Safety
168///
169/// Requires an active Dear ImGui context and current window. `ptr_id` is used as
170/// an ID value only and is not dereferenced.
171#[inline]
172pub unsafe fn ImGuiStack_BeginHorizontal_Ptr(
173    ptr_id: *const std::ffi::c_void,
174    size: ImVec2,
175    align: f32,
176) {
177    unsafe { dear_imgui_stack_begin_horizontal_ptr(ptr_id, size, align) }
178}
179
180/// Start a stack-layout horizontal group using an integer ID.
181///
182/// # Safety
183///
184/// Requires an active Dear ImGui context and current window.
185#[inline]
186pub unsafe fn ImGuiStack_BeginHorizontal_Int(id: std::os::raw::c_int, size: ImVec2, align: f32) {
187    unsafe { dear_imgui_stack_begin_horizontal_int(id, size, align) }
188}
189
190/// Start a stack-layout horizontal group using a precomputed ImGui ID.
191///
192/// # Safety
193///
194/// Requires an active Dear ImGui context and current window.
195#[inline]
196pub unsafe fn ImGuiStack_BeginHorizontal_Id(id: ImGuiID, size: ImVec2, align: f32) {
197    unsafe { dear_imgui_stack_begin_horizontal_id(id, size, align) }
198}
199
200/// End the current stack-layout horizontal group.
201///
202/// # Safety
203///
204/// Must match a previous `ImGuiStack_BeginHorizontal_*` call.
205#[inline]
206pub unsafe fn ImGuiStack_EndHorizontal() {
207    unsafe { dear_imgui_stack_end_horizontal() }
208}
209
210/// Start a stack-layout vertical group using a string ID.
211///
212/// # Safety
213///
214/// Requires an active Dear ImGui context and current window. `str_id` must point
215/// to a valid NUL-terminated string for the duration of the call.
216#[inline]
217pub unsafe fn ImGuiStack_BeginVertical_Str(
218    str_id: *const std::os::raw::c_char,
219    size: ImVec2,
220    align: f32,
221) {
222    unsafe { dear_imgui_stack_begin_vertical_str(str_id, size, align) }
223}
224
225/// Start a stack-layout vertical group using a pointer ID.
226///
227/// # Safety
228///
229/// Requires an active Dear ImGui context and current window. `ptr_id` is used as
230/// an ID value only and is not dereferenced.
231#[inline]
232pub unsafe fn ImGuiStack_BeginVertical_Ptr(
233    ptr_id: *const std::ffi::c_void,
234    size: ImVec2,
235    align: f32,
236) {
237    unsafe { dear_imgui_stack_begin_vertical_ptr(ptr_id, size, align) }
238}
239
240/// Start a stack-layout vertical group using an integer ID.
241///
242/// # Safety
243///
244/// Requires an active Dear ImGui context and current window.
245#[inline]
246pub unsafe fn ImGuiStack_BeginVertical_Int(id: std::os::raw::c_int, size: ImVec2, align: f32) {
247    unsafe { dear_imgui_stack_begin_vertical_int(id, size, align) }
248}
249
250/// Start a stack-layout vertical group using a precomputed ImGui ID.
251///
252/// # Safety
253///
254/// Requires an active Dear ImGui context and current window.
255#[inline]
256pub unsafe fn ImGuiStack_BeginVertical_Id(id: ImGuiID, size: ImVec2, align: f32) {
257    unsafe { dear_imgui_stack_begin_vertical_id(id, size, align) }
258}
259
260/// End the current stack-layout vertical group.
261///
262/// # Safety
263///
264/// Must match a previous `ImGuiStack_BeginVertical_*` call.
265#[inline]
266pub unsafe fn ImGuiStack_EndVertical() {
267    unsafe { dear_imgui_stack_end_vertical() }
268}
269
270/// Insert a spring separator into the current stack layout.
271///
272/// # Safety
273///
274/// Requires an active stack layout.
275#[inline]
276pub unsafe fn ImGuiStack_Spring(weight: f32, spacing: f32) {
277    unsafe { dear_imgui_stack_spring(weight, spacing) }
278}
279
280/// Temporarily suspend the current stack layout.
281///
282/// # Safety
283///
284/// Requires an active stack layout and must be matched by resume.
285#[inline]
286pub unsafe fn ImGuiStack_SuspendLayout() {
287    unsafe { dear_imgui_stack_suspend_layout() }
288}
289
290/// Resume a suspended stack layout.
291///
292/// # Safety
293///
294/// Must match a previous suspend call.
295#[inline]
296pub unsafe fn ImGuiStack_ResumeLayout() {
297    unsafe { dear_imgui_stack_resume_layout() }
298}
299
300#[cfg(dear_imgui_rs_platform_io_hooks)]
301unsafe extern "C" {
302    fn dear_imgui_rs_platform_io_set_platform_get_window_pos(
303        platform_io: *mut ImGuiPlatformIO,
304        user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_pos: *mut ImVec2)>,
305    );
306
307    fn dear_imgui_rs_platform_io_set_platform_get_window_size(
308        platform_io: *mut ImGuiPlatformIO,
309        user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_size: *mut ImVec2)>,
310    );
311
312    fn dear_imgui_rs_platform_io_set_platform_get_window_framebuffer_scale(
313        platform_io: *mut ImGuiPlatformIO,
314        user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_scale: *mut ImVec2)>,
315    );
316
317    fn dear_imgui_rs_platform_io_set_platform_get_window_work_area_insets(
318        platform_io: *mut ImGuiPlatformIO,
319        user_callback: Option<
320            unsafe extern "C" fn(vp: *mut ImGuiViewport, out_insets: *mut ImVec4),
321        >,
322    );
323}
324
325/// Install a C-compatible out-parameter callback for `ImGuiPlatformIO::Platform_GetWindowPos`.
326///
327/// This avoids exposing Rust callbacks through the small-aggregate `ImVec2` return ABI used by
328/// Dear ImGui's C++ callback slot. The shim keeps its own per-`ImGuiPlatformIO` storage and does
329/// not occupy `ImGuiIO::BackendLanguageUserData`.
330///
331/// # Safety
332///
333/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
334/// must obey Dear ImGui's platform callback contract and must not unwind.
335#[inline]
336pub unsafe fn ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam(
337    platform_io: *mut ImGuiPlatformIO,
338    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_pos: *mut ImVec2)>,
339) {
340    #[cfg(dear_imgui_rs_platform_io_hooks)]
341    unsafe {
342        dear_imgui_rs_platform_io_set_platform_get_window_pos(platform_io, user_callback)
343    }
344
345    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
346    {
347        let _ = platform_io;
348        if user_callback.is_some() {
349            panic!(
350                "dear-imgui-sys was built without PlatformIO out-parameter hooks; \
351                 rebuild without IMGUI_SYS_SKIP_CC to install Platform_GetWindowPos callbacks"
352            );
353        }
354    }
355}
356
357/// Install a C-compatible out-parameter callback for `ImGuiPlatformIO::Platform_GetWindowSize`.
358///
359/// See [`ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam`] for the ABI rationale.
360///
361/// # Safety
362///
363/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
364/// must obey Dear ImGui's platform callback contract and must not unwind.
365#[inline]
366pub unsafe fn ImGuiPlatformIO_Set_Platform_GetWindowSize_OutParam(
367    platform_io: *mut ImGuiPlatformIO,
368    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_size: *mut ImVec2)>,
369) {
370    #[cfg(dear_imgui_rs_platform_io_hooks)]
371    unsafe {
372        dear_imgui_rs_platform_io_set_platform_get_window_size(platform_io, user_callback)
373    }
374
375    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
376    {
377        let _ = platform_io;
378        if user_callback.is_some() {
379            panic!(
380                "dear-imgui-sys was built without PlatformIO out-parameter hooks; \
381                 rebuild without IMGUI_SYS_SKIP_CC to install Platform_GetWindowSize callbacks"
382            );
383        }
384    }
385}
386
387/// Install a C-compatible out-parameter callback for
388/// `ImGuiPlatformIO::Platform_GetWindowFramebufferScale`.
389///
390/// See [`ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam`] for the ABI rationale.
391///
392/// # Safety
393///
394/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
395/// must obey Dear ImGui's platform callback contract and must not unwind.
396#[inline]
397pub unsafe fn ImGuiPlatformIO_Set_Platform_GetWindowFramebufferScale_OutParam(
398    platform_io: *mut ImGuiPlatformIO,
399    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_scale: *mut ImVec2)>,
400) {
401    #[cfg(dear_imgui_rs_platform_io_hooks)]
402    unsafe {
403        dear_imgui_rs_platform_io_set_platform_get_window_framebuffer_scale(
404            platform_io,
405            user_callback,
406        )
407    }
408
409    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
410    {
411        let _ = platform_io;
412        if user_callback.is_some() {
413            panic!(
414                "dear-imgui-sys was built without PlatformIO out-parameter hooks; \
415                 rebuild without IMGUI_SYS_SKIP_CC to install \
416                 Platform_GetWindowFramebufferScale callbacks"
417            );
418        }
419    }
420}
421
422/// Install a C-compatible out-parameter callback for
423/// `ImGuiPlatformIO::Platform_GetWindowWorkAreaInsets`.
424///
425/// See [`ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam`] for the ABI rationale.
426///
427/// # Safety
428///
429/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
430/// must obey Dear ImGui's platform callback contract and must not unwind.
431#[inline]
432pub unsafe fn ImGuiPlatformIO_Set_Platform_GetWindowWorkAreaInsets_OutParam(
433    platform_io: *mut ImGuiPlatformIO,
434    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_insets: *mut ImVec4)>,
435) {
436    #[cfg(dear_imgui_rs_platform_io_hooks)]
437    unsafe {
438        dear_imgui_rs_platform_io_set_platform_get_window_work_area_insets(
439            platform_io,
440            user_callback,
441        )
442    }
443
444    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
445    {
446        let _ = platform_io;
447        if user_callback.is_some() {
448            panic!(
449                "dear-imgui-sys was built without PlatformIO out-parameter hooks; \
450                 rebuild without IMGUI_SYS_SKIP_CC to install Platform_GetWindowWorkAreaInsets \
451                 callbacks"
452            );
453        }
454    }
455}
456
457// Re-export commonly used types for convenience
458pub use ImColor as Color;
459pub use ImVec2 as Vector2;
460pub use ImVec4 as Vector4;
461
462/// Version information for the Dear ImGui library
463pub const IMGUI_VERSION: &str = env!("CARGO_PKG_VERSION");
464
465/// Docking features are always available in this crate
466pub const HAS_DOCKING: bool = true;
467
468/// Check if FreeType support is available
469#[cfg(feature = "freetype")]
470pub const HAS_FREETYPE: bool = true;
471
472#[cfg(not(feature = "freetype"))]
473pub const HAS_FREETYPE: bool = false;
474
475/// Check if WASM support is available
476#[cfg(feature = "wasm")]
477pub const HAS_WASM: bool = true;
478
479#[cfg(not(feature = "wasm"))]
480pub const HAS_WASM: bool = false;
481
482// (No wasm-specific shims are required when using shared memory import style.)
483
484impl ImVec2 {
485    #[inline]
486    pub const fn new(x: f32, y: f32) -> ImVec2 {
487        ImVec2 { x, y }
488    }
489
490    #[inline]
491    pub const fn zero() -> ImVec2 {
492        ImVec2 { x: 0.0, y: 0.0 }
493    }
494}
495
496impl From<[f32; 2]> for ImVec2 {
497    #[inline]
498    fn from(array: [f32; 2]) -> ImVec2 {
499        ImVec2::new(array[0], array[1])
500    }
501}
502
503impl From<(f32, f32)> for ImVec2 {
504    #[inline]
505    fn from((x, y): (f32, f32)) -> ImVec2 {
506        ImVec2::new(x, y)
507    }
508}
509
510impl From<ImVec2> for [f32; 2] {
511    #[inline]
512    fn from(v: ImVec2) -> [f32; 2] {
513        [v.x, v.y]
514    }
515}
516
517impl From<ImVec2> for (f32, f32) {
518    #[inline]
519    fn from(v: ImVec2) -> (f32, f32) {
520        (v.x, v.y)
521    }
522}
523
524impl From<mint::Vector2<f32>> for ImVec2 {
525    #[inline]
526    fn from(v: mint::Vector2<f32>) -> ImVec2 {
527        ImVec2::new(v.x, v.y)
528    }
529}
530
531#[cfg(feature = "glam")]
532impl From<glam::Vec2> for ImVec2 {
533    #[inline]
534    fn from(v: glam::Vec2) -> ImVec2 {
535        ImVec2::new(v.x, v.y)
536    }
537}
538
539impl ImVec4 {
540    #[inline]
541    pub const fn new(x: f32, y: f32, z: f32, w: f32) -> ImVec4 {
542        ImVec4 { x, y, z, w }
543    }
544
545    #[inline]
546    pub const fn zero() -> ImVec4 {
547        ImVec4 {
548            x: 0.0,
549            y: 0.0,
550            z: 0.0,
551            w: 0.0,
552        }
553    }
554}
555
556impl From<[f32; 4]> for ImVec4 {
557    #[inline]
558    fn from(array: [f32; 4]) -> ImVec4 {
559        ImVec4::new(array[0], array[1], array[2], array[3])
560    }
561}
562
563impl From<(f32, f32, f32, f32)> for ImVec4 {
564    #[inline]
565    fn from((x, y, z, w): (f32, f32, f32, f32)) -> ImVec4 {
566        ImVec4::new(x, y, z, w)
567    }
568}
569
570impl From<ImVec4> for [f32; 4] {
571    #[inline]
572    fn from(v: ImVec4) -> [f32; 4] {
573        [v.x, v.y, v.z, v.w]
574    }
575}
576
577impl From<ImVec4> for (f32, f32, f32, f32) {
578    #[inline]
579    fn from(v: ImVec4) -> (f32, f32, f32, f32) {
580        (v.x, v.y, v.z, v.w)
581    }
582}
583
584impl From<mint::Vector4<f32>> for ImVec4 {
585    #[inline]
586    fn from(v: mint::Vector4<f32>) -> ImVec4 {
587        ImVec4::new(v.x, v.y, v.z, v.w)
588    }
589}
590
591#[cfg(feature = "glam")]
592impl From<glam::Vec4> for ImVec4 {
593    #[inline]
594    fn from(v: glam::Vec4) -> ImVec4 {
595        ImVec4::new(v.x, v.y, v.z, v.w)
596    }
597}