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//! - **stack-layout**: Enable the native patched core artifact used by blueprint-style layouts
12//! - **prebuilt**: Allow downloading a compatible native prebuilt artifact
13//! - **build-from-source**: Force compilation of the native artifact from vendored sources
14//! - **test-engine**: Enable native test engine hooks and force a source build
15//! - **backend-shim-\***: Expose selected repository-owned backend shim modules
16//!   for low-level integrations
17//!
18//! ## WebAssembly Support
19//!
20//! When the `wasm` feature is enabled, this crate provides full WASM compatibility:
21//! - Disables platform-specific functions (file I/O, shell functions, etc.)
22//! - Configures Dear ImGui for WASM environment
23//! - Compatible with wasm-bindgen and web targets
24//!
25//! ## Safety
26//!
27//! This crate provides raw FFI bindings and is inherently unsafe. Users should
28//! prefer the high-level `dear-imgui-rs` crate for safe Rust bindings.
29//!
30//! ## Usage
31//!
32//! This crate is typically not used directly. Instead, use the `dear-imgui-rs` crate
33//! which provides safe, idiomatic Rust bindings built on top of these FFI bindings.
34//!
35//! ## Backend Shim Modules
36//!
37//! For downstream backend crates, engine integrations, and platform-specific
38//! application glue, `dear-imgui-sys` can expose selected official backend
39//! pieces through `backend_shim::*`.
40//!
41//! Important boundary:
42//!
43//! - these modules expose the repository-owned C shim ABI
44//! - they do not expose upstream `imgui_impl_*` C++ symbol names as a stable
45//!   Rust-facing contract
46//! - enabling `backend-shim-*` features does not imply that `dear-imgui-rs`
47//!   already owns a safe wrapper for those backends
48//!
49//! Typical feature gates:
50//!
51//! - `backend-shim-opengl3`
52//! - `backend-shim-android`
53//! - `backend-shim-win32`
54//! - `backend-shim-dx11`
55//!
56//! SDLRenderer3 and SDLGPU3 renderer shims are owned by `dear-imgui-sdl3`.
57//!
58//! ## Android Direction
59//!
60//! The current Android story is intentionally low-level but supported.
61//!
62//! ```toml
63//! [dependencies]
64//! dear-imgui-rs = "0.10"
65//! dear-imgui-sys = { version = "0.10", features = ["backend-shim-android", "backend-shim-opengl3"] }
66//! ```
67//!
68//! Recommended split of responsibilities:
69//!
70//! - `dear-imgui-rs` owns the safe core `Context`, `Io`, frame lifecycle, and
71//!   render snapshots
72//! - `dear-imgui-sys::backend_shim::{android, opengl3}` exposes the low-level
73//!   official backend pieces
74//! - the Android application still owns lifecycle glue, input translation
75//!   strategy, EGL / GLES context creation, and packaging
76//!
77//! The repository's concrete reference for this path is
78//! `examples-android/dear-imgui-android-smoke/`, which now carries a minimal
79//! NativeActivity + EGL / GLES3 render loop proving that downstream users can
80//! build Android support on top of `dear-imgui-rs` + `dear-imgui-sys` even
81//! before a dedicated first-party Android convenience crate exists.
82
83#![allow(non_upper_case_globals)]
84#![allow(non_camel_case_types)]
85#![allow(non_snake_case)]
86#![allow(dead_code)]
87#![allow(unnecessary_transmutes)]
88#![allow(clippy::all)]
89// Bindgen may derive Eq/Hash for structs containing function pointers.
90// New Clippy lint warns these comparisons are unpredictable; suppress for raw FFI types.
91#![allow(unpredictable_function_pointer_comparisons)]
92
93#[cfg(all(feature = "stack-layout", dear_imgui_rs_wasm_import_target))]
94compile_error!("feature `stack-layout` is native-only and cannot be combined with WASM");
95
96#[cfg(all(feature = "test-engine", dear_imgui_rs_wasm_import_target))]
97compile_error!("feature `test-engine` is native source-only and cannot be combined with WASM");
98
99#[cfg(all(feature = "prebuilt", dear_imgui_rs_wasm_import_target))]
100compile_error!("feature `prebuilt` is native-only and cannot be combined with WASM");
101
102// Bindings are generated into OUT_DIR and included via a submodule so that
103// possible inner attributes in the generated file are accepted at module root.
104mod ffi;
105pub use ffi::*;
106
107#[cfg_attr(
108    dear_imgui_rs_wasm_import_target,
109    link(wasm_import_module = "imgui-sys-v1")
110)]
111unsafe extern "C" {
112    pub fn dear_imgui_rs_show_demo_window_without_font_atlas(p_open: *mut bool);
113    pub fn dear_imgui_rs_show_metrics_window_without_font_atlas(p_open: *mut bool);
114    pub fn dear_imgui_rs_show_style_editor_without_font_atlas(ref_: *mut ImGuiStyle);
115    pub fn dear_imgui_rs_show_font_atlas_debug_panel();
116    pub fn dear_imgui_rs_dock_builder_keep_root_alive(root_id: ImGuiID) -> ::std::os::raw::c_int;
117    pub fn dear_imgui_rs_dock_builder_root_has_active_content_window(
118        root_id: ImGuiID,
119    ) -> ::std::os::raw::c_int;
120    pub fn dear_imgui_rs_dock_builder_copy_node(
121        source_root_id: ImGuiID,
122        destination_root_id: ImGuiID,
123        remap_data: *mut ImGuiID,
124        remap_capacity: ::std::os::raw::c_int,
125    ) -> ::std::os::raw::c_int;
126}
127
128/// Optional backend shim entry points for downstream integrations.
129///
130/// These modules expose the repository-owned C shim ABI for selected official
131/// Dear ImGui backends. They do not expose the upstream C++ symbols directly,
132/// and they do not imply that `dear-imgui-sys` or `dear-imgui-rs` owns full
133/// safe integration for those backends.
134pub mod backend_shim;
135
136// This project always builds Dear ImGui with `IMGUI_DISABLE_OBSOLETE_FUNCTIONS` so the native
137// layouts match cimgui's generated struct definitions, and with `IMGUI_USE_WCHAR32` so `ImWchar`
138// must be 32-bit.
139const _: [(); 4] = [(); std::mem::size_of::<ImWchar>()];
140
141// Ensure common ImGui typedefs are available even if bindgen doesn't emit them explicitly
142
143// cimgui exposes typed vectors (e.g., ImVector_ImVec2) instead of a generic ImVector<T>.
144// The sys crate intentionally avoids adding higher-level helpers here.
145
146// Core cimgui calls use the C ABI. PlatformIO aggregate callbacks retain C++ ABI-sensitive
147// signatures, so repository-owned shims translate them to pointer/out-parameter callbacks.
148
149/// Whether this build linked the repository-owned PlatformIO aggregate ABI hook shim.
150pub const HAS_PLATFORM_IO_AGGREGATE_HOOKS: bool = cfg!(dear_imgui_rs_platform_io_hooks);
151
152#[cfg(feature = "stack-layout")]
153mod stack_layout {
154    use super::*;
155
156    unsafe extern "C" {
157        fn dear_imgui_stack_begin_horizontal_str(
158            str_id: *const std::os::raw::c_char,
159            size: ImVec2,
160            align: f32,
161        );
162        fn dear_imgui_stack_begin_horizontal_ptr(
163            ptr_id: *const std::ffi::c_void,
164            size: ImVec2,
165            align: f32,
166        );
167        fn dear_imgui_stack_begin_horizontal_int(id: std::os::raw::c_int, size: ImVec2, align: f32);
168        fn dear_imgui_stack_begin_horizontal_id(id: ImGuiID, size: ImVec2, align: f32);
169        fn dear_imgui_stack_end_horizontal();
170        fn dear_imgui_stack_begin_vertical_str(
171            str_id: *const std::os::raw::c_char,
172            size: ImVec2,
173            align: f32,
174        );
175        fn dear_imgui_stack_begin_vertical_ptr(
176            ptr_id: *const std::ffi::c_void,
177            size: ImVec2,
178            align: f32,
179        );
180        fn dear_imgui_stack_begin_vertical_int(id: std::os::raw::c_int, size: ImVec2, align: f32);
181        fn dear_imgui_stack_begin_vertical_id(id: ImGuiID, size: ImVec2, align: f32);
182        fn dear_imgui_stack_end_vertical();
183        fn dear_imgui_stack_spring(weight: f32, spacing: f32);
184        fn dear_imgui_stack_suspend_layout();
185        fn dear_imgui_stack_resume_layout();
186        fn dear_imgui_stack_destroy_context_state(context: *mut ImGuiContext);
187        fn dear_imgui_stack_state_count() -> usize;
188    }
189
190    /// Start a stack-layout horizontal group using a string ID.
191    ///
192    /// This is a repository-owned compatibility shim for the stack layout extension
193    /// used by `imgui-node-editor` examples; it is not an official Dear ImGui API.
194    ///
195    /// # Safety
196    ///
197    /// Requires an active Dear ImGui context and current window. `str_id` must point
198    /// to a valid NUL-terminated string for the duration of the call.
199    #[inline]
200    pub unsafe fn ImGuiStack_BeginHorizontal_Str(
201        str_id: *const std::os::raw::c_char,
202        size: ImVec2,
203        align: f32,
204    ) {
205        unsafe { dear_imgui_stack_begin_horizontal_str(str_id, size, align) }
206    }
207
208    /// Start a stack-layout horizontal group using a pointer ID.
209    ///
210    /// # Safety
211    ///
212    /// Requires an active Dear ImGui context and current window. `ptr_id` is used as
213    /// an ID value only and is not dereferenced.
214    #[inline]
215    pub unsafe fn ImGuiStack_BeginHorizontal_Ptr(
216        ptr_id: *const std::ffi::c_void,
217        size: ImVec2,
218        align: f32,
219    ) {
220        unsafe { dear_imgui_stack_begin_horizontal_ptr(ptr_id, size, align) }
221    }
222
223    /// Start a stack-layout horizontal group using an integer ID.
224    ///
225    /// # Safety
226    ///
227    /// Requires an active Dear ImGui context and current window.
228    #[inline]
229    pub unsafe fn ImGuiStack_BeginHorizontal_Int(
230        id: std::os::raw::c_int,
231        size: ImVec2,
232        align: f32,
233    ) {
234        unsafe { dear_imgui_stack_begin_horizontal_int(id, size, align) }
235    }
236
237    /// Start a stack-layout horizontal group using a precomputed ImGui ID.
238    ///
239    /// # Safety
240    ///
241    /// Requires an active Dear ImGui context and current window.
242    #[inline]
243    pub unsafe fn ImGuiStack_BeginHorizontal_Id(id: ImGuiID, size: ImVec2, align: f32) {
244        unsafe { dear_imgui_stack_begin_horizontal_id(id, size, align) }
245    }
246
247    /// End the current stack-layout horizontal group.
248    ///
249    /// # Safety
250    ///
251    /// Must match a previous `ImGuiStack_BeginHorizontal_*` call.
252    #[inline]
253    pub unsafe fn ImGuiStack_EndHorizontal() {
254        unsafe { dear_imgui_stack_end_horizontal() }
255    }
256
257    /// Start a stack-layout vertical group using a string ID.
258    ///
259    /// # Safety
260    ///
261    /// Requires an active Dear ImGui context and current window. `str_id` must point
262    /// to a valid NUL-terminated string for the duration of the call.
263    #[inline]
264    pub unsafe fn ImGuiStack_BeginVertical_Str(
265        str_id: *const std::os::raw::c_char,
266        size: ImVec2,
267        align: f32,
268    ) {
269        unsafe { dear_imgui_stack_begin_vertical_str(str_id, size, align) }
270    }
271
272    /// Start a stack-layout vertical group using a pointer ID.
273    ///
274    /// # Safety
275    ///
276    /// Requires an active Dear ImGui context and current window. `ptr_id` is used as
277    /// an ID value only and is not dereferenced.
278    #[inline]
279    pub unsafe fn ImGuiStack_BeginVertical_Ptr(
280        ptr_id: *const std::ffi::c_void,
281        size: ImVec2,
282        align: f32,
283    ) {
284        unsafe { dear_imgui_stack_begin_vertical_ptr(ptr_id, size, align) }
285    }
286
287    /// Start a stack-layout vertical group using an integer ID.
288    ///
289    /// # Safety
290    ///
291    /// Requires an active Dear ImGui context and current window.
292    #[inline]
293    pub unsafe fn ImGuiStack_BeginVertical_Int(id: std::os::raw::c_int, size: ImVec2, align: f32) {
294        unsafe { dear_imgui_stack_begin_vertical_int(id, size, align) }
295    }
296
297    /// Start a stack-layout vertical group using a precomputed ImGui ID.
298    ///
299    /// # Safety
300    ///
301    /// Requires an active Dear ImGui context and current window.
302    #[inline]
303    pub unsafe fn ImGuiStack_BeginVertical_Id(id: ImGuiID, size: ImVec2, align: f32) {
304        unsafe { dear_imgui_stack_begin_vertical_id(id, size, align) }
305    }
306
307    /// End the current stack-layout vertical group.
308    ///
309    /// # Safety
310    ///
311    /// Must match a previous `ImGuiStack_BeginVertical_*` call.
312    #[inline]
313    pub unsafe fn ImGuiStack_EndVertical() {
314        unsafe { dear_imgui_stack_end_vertical() }
315    }
316
317    /// Insert a spring separator into the current stack layout.
318    ///
319    /// # Safety
320    ///
321    /// Requires an active stack layout.
322    #[inline]
323    pub unsafe fn ImGuiStack_Spring(weight: f32, spacing: f32) {
324        unsafe { dear_imgui_stack_spring(weight, spacing) }
325    }
326
327    /// Temporarily suspend the current stack layout.
328    ///
329    /// # Safety
330    ///
331    /// Requires an active stack layout and must be matched by resume.
332    #[inline]
333    pub unsafe fn ImGuiStack_SuspendLayout() {
334        unsafe { dear_imgui_stack_suspend_layout() }
335    }
336
337    /// Resume a suspended stack layout.
338    ///
339    /// # Safety
340    ///
341    /// Must match a previous suspend call.
342    #[inline]
343    pub unsafe fn ImGuiStack_ResumeLayout() {
344        unsafe { dear_imgui_stack_resume_layout() }
345    }
346
347    /// Remove all stack-layout state owned by an ImGui context.
348    ///
349    /// # Safety
350    ///
351    /// `context` must be null or point to a live ImGui context. Call this before destroying that
352    /// context and while no stack-layout operation is active concurrently.
353    #[inline]
354    pub unsafe fn ImGuiStack_DestroyContextState(context: *mut ImGuiContext) {
355        unsafe { dear_imgui_stack_destroy_context_state(context) }
356    }
357
358    /// Return the number of ImGui contexts with retained stack-layout state.
359    ///
360    /// # Safety
361    ///
362    /// No stack-layout operation may mutate the native state concurrently.
363    #[doc(hidden)]
364    #[inline]
365    pub unsafe fn ImGuiStack_StateCount() -> usize {
366        unsafe { dear_imgui_stack_state_count() }
367    }
368}
369
370#[cfg(feature = "stack-layout")]
371pub use stack_layout::*;
372
373#[cfg(dear_imgui_rs_platform_io_hooks)]
374unsafe extern "C" {
375    fn dear_imgui_rs_platform_io_set_platform_set_window_pos(
376        platform_io: *mut ImGuiPlatformIO,
377        user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, pos: *const ImVec2)>,
378    );
379
380    fn dear_imgui_rs_platform_io_set_platform_get_window_pos(
381        platform_io: *mut ImGuiPlatformIO,
382        user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_pos: *mut ImVec2)>,
383    );
384
385    fn dear_imgui_rs_platform_io_set_platform_set_window_size(
386        platform_io: *mut ImGuiPlatformIO,
387        user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2)>,
388    );
389
390    fn dear_imgui_rs_platform_io_set_platform_get_window_size(
391        platform_io: *mut ImGuiPlatformIO,
392        user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_size: *mut ImVec2)>,
393    );
394
395    fn dear_imgui_rs_platform_io_set_platform_get_window_framebuffer_scale(
396        platform_io: *mut ImGuiPlatformIO,
397        user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_scale: *mut ImVec2)>,
398    );
399
400    fn dear_imgui_rs_platform_io_set_platform_get_window_work_area_insets(
401        platform_io: *mut ImGuiPlatformIO,
402        user_callback: Option<
403            unsafe extern "C" fn(vp: *mut ImGuiViewport, out_insets: *mut ImVec4),
404        >,
405    );
406
407    fn dear_imgui_rs_platform_io_clear_platform_set_window_pos_if_pointer_param(
408        platform_io: *mut ImGuiPlatformIO,
409        user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, pos: *const ImVec2),
410    ) -> std::os::raw::c_int;
411
412    fn dear_imgui_rs_platform_io_clear_platform_set_window_size_if_pointer_param(
413        platform_io: *mut ImGuiPlatformIO,
414        user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2),
415    ) -> std::os::raw::c_int;
416
417    fn dear_imgui_rs_platform_io_clear_platform_get_window_pos_if_out_param(
418        platform_io: *mut ImGuiPlatformIO,
419        user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, out_pos: *mut ImVec2),
420    ) -> std::os::raw::c_int;
421
422    fn dear_imgui_rs_platform_io_clear_platform_get_window_size_if_out_param(
423        platform_io: *mut ImGuiPlatformIO,
424        user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, out_size: *mut ImVec2),
425    ) -> std::os::raw::c_int;
426
427    fn dear_imgui_rs_platform_io_clear_platform_get_window_framebuffer_scale_if_out_param(
428        platform_io: *mut ImGuiPlatformIO,
429        user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, out_scale: *mut ImVec2),
430    ) -> std::os::raw::c_int;
431
432    fn dear_imgui_rs_platform_io_clear_platform_get_window_work_area_insets_if_out_param(
433        platform_io: *mut ImGuiPlatformIO,
434        user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, out_insets: *mut ImVec4),
435    ) -> std::os::raw::c_int;
436
437    fn dear_imgui_rs_platform_io_set_renderer_set_window_size(
438        platform_io: *mut ImGuiPlatformIO,
439        user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2)>,
440    );
441
442    fn dear_imgui_rs_platform_io_renderer_set_window_size_matches_pointer_param(
443        platform_io: *mut ImGuiPlatformIO,
444        user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2),
445    ) -> std::os::raw::c_int;
446
447    fn dear_imgui_rs_platform_io_get_renderer_set_window_size_pointer_param(
448        platform_io: *mut ImGuiPlatformIO,
449        out_callback: *mut Option<
450            unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2),
451        >,
452    ) -> std::os::raw::c_int;
453
454    fn dear_imgui_rs_platform_io_clear_renderer_set_window_size_if_pointer_param(
455        platform_io: *mut ImGuiPlatformIO,
456        user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2),
457    ) -> std::os::raw::c_int;
458
459    fn dear_imgui_rs_platform_io_probe_aggregate_callbacks(
460        platform_io: *mut ImGuiPlatformIO,
461        out_result: *mut DearImguiRsPlatformIoAggregateProbeResult,
462    ) -> std::os::raw::c_int;
463
464    fn dear_imgui_rs_platform_io_invoke_platform_set_window_pos(
465        callbacks: *const ImGuiPlatformIO,
466        viewport: *mut ImGuiViewport,
467        pos: *const ImVec2,
468    ) -> std::os::raw::c_int;
469
470    fn dear_imgui_rs_platform_io_invoke_renderer_set_window_size(
471        callbacks: *const ImGuiPlatformIO,
472        viewport: *mut ImGuiViewport,
473        size: *const ImVec2,
474    ) -> std::os::raw::c_int;
475
476    fn dear_imgui_rs_platform_io_aggregate_callback_storage_count() -> std::os::raw::c_int;
477
478    fn dear_imgui_rs_find_live_viewport_by_address(
479        context: *mut ImGuiContext,
480        address: usize,
481    ) -> *mut ImGuiViewport;
482}
483
484/// Resolve a retained viewport address through the current Context's internal live registry.
485///
486/// Dear ImGui may change a viewport's numeric ID in place while docking transfers ownership.
487/// This repository-owned helper therefore compares the address against `ImGuiContext::Viewports`
488/// without dereferencing the retained address.
489///
490/// # Safety
491///
492/// `context` must be the current live Context. The returned pointer remains valid only while that
493/// Context stays current and no Dear ImGui operation removes the viewport.
494#[doc(hidden)]
495#[inline]
496pub unsafe fn ImGuiContext_FindLiveViewportByAddress(
497    context: *mut ImGuiContext,
498    address: usize,
499) -> *mut ImGuiViewport {
500    #[cfg(dear_imgui_rs_platform_io_hooks)]
501    {
502        unsafe { dear_imgui_rs_find_live_viewport_by_address(context, address) }
503    }
504    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
505    {
506        let _ = (context, address);
507        std::ptr::null_mut()
508    }
509}
510
511/// Results returned by [`ImGuiPlatformIO_ProbeAggregateCallbacks`].
512///
513/// This test-support ABI is intentionally defined by the repository-owned C++ shim. It lets Rust
514/// tests exercise Dear ImGui's real C++ callback slots without calling Rust trampolines directly.
515#[repr(C)]
516#[derive(Clone, Copy, Debug, Default, PartialEq)]
517pub struct DearImguiRsPlatformIoAggregateProbeResult {
518    pub PlatformGetWindowPos: ImVec2,
519    pub PlatformGetWindowSize: ImVec2,
520    pub PlatformGetWindowFramebufferScale: ImVec2,
521    pub PlatformGetWindowWorkAreaInsets: ImVec4,
522}
523
524/// C++ measurements for selected public Dear ImGui aggregate layouts.
525///
526/// This is an internal CI-only ABI probe enabled by the `abi-probe` feature.
527#[cfg(feature = "abi-probe")]
528#[doc(hidden)]
529#[repr(C)]
530#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
531pub struct DearImguiRsPublicAggregateLayoutProbe {
532    pub ImDrawDataSize: usize,
533    pub ImDrawDataAlign: usize,
534    pub ImDrawDataFrameCountOffset: usize,
535    pub ImDrawDataCmdListsOffset: usize,
536    pub ImDrawDataTexturesOffset: usize,
537    pub ImTextureDataSize: usize,
538    pub ImTextureDataAlign: usize,
539    pub ImTextureDataUniqueIDOffset: usize,
540    pub ImTextureDataQueueUserDataOffset: usize,
541    pub ImTextureDataTexIDOffset: usize,
542    pub ImTextureDataUpdatesOffset: usize,
543    pub ImTextureDataWantDestroyNextFrameOffset: usize,
544    pub ImGuiPlatformIOSize: usize,
545    pub ImGuiPlatformIOAlign: usize,
546    pub ImGuiPlatformIOSessionDateOffset: usize,
547    pub ImGuiPlatformIORenderStateOffset: usize,
548    pub ImGuiPlatformIOPlatformCreateWindowOffset: usize,
549    pub ImGuiPlatformIORendererCreateWindowOffset: usize,
550    pub ImGuiPlatformIOMonitorsOffset: usize,
551    pub ImGuiPlatformIOTexturesOffset: usize,
552    pub ImGuiPlatformIOViewportsOffset: usize,
553}
554
555#[cfg(feature = "abi-probe")]
556unsafe extern "C" {
557    fn dear_imgui_rs_probe_public_aggregate_layouts(
558        out_probe: *mut DearImguiRsPublicAggregateLayoutProbe,
559    ) -> std::os::raw::c_int;
560}
561
562/// Ask the native C++ translation unit to measure selected aggregate layouts.
563///
564/// This is test support, not a stable downstream API.
565#[cfg(feature = "abi-probe")]
566#[doc(hidden)]
567#[inline]
568pub fn ImGui_ProbePublicAggregateLayouts(
569    out_probe: &mut DearImguiRsPublicAggregateLayoutProbe,
570) -> bool {
571    unsafe { dear_imgui_rs_probe_public_aggregate_layouts(out_probe) != 0 }
572}
573
574/// Install a C-compatible pointer-parameter callback for
575/// `ImGuiPlatformIO::Platform_SetWindowPos`.
576///
577/// # Safety
578///
579/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
580/// must obey Dear ImGui's platform callback contract and must not unwind.
581#[inline]
582pub unsafe fn ImGuiPlatformIO_Set_Platform_SetWindowPos_PointerParam(
583    platform_io: *mut ImGuiPlatformIO,
584    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, pos: *const ImVec2)>,
585) {
586    #[cfg(dear_imgui_rs_platform_io_hooks)]
587    unsafe {
588        dear_imgui_rs_platform_io_set_platform_set_window_pos(platform_io, user_callback)
589    }
590
591    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
592    {
593        if user_callback.is_some() {
594            panic!(
595                "dear-imgui-sys was built without PlatformIO aggregate ABI hooks; \
596                 rebuild without IMGUI_SYS_SKIP_CC to install Platform_SetWindowPos callbacks"
597            );
598        } else if let Some(platform_io) = unsafe { platform_io.as_mut() } {
599            platform_io.Platform_SetWindowPos = None;
600        }
601    }
602}
603
604/// Install a C-compatible out-parameter callback for `ImGuiPlatformIO::Platform_GetWindowPos`.
605///
606/// This avoids exposing Rust callbacks through the small-aggregate `ImVec2` return ABI used by
607/// Dear ImGui's C++ callback slot. The shim keeps its own per-`ImGuiPlatformIO` storage and does
608/// not occupy `ImGuiIO::BackendLanguageUserData`.
609///
610/// # Safety
611///
612/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
613/// must obey Dear ImGui's platform callback contract and must not unwind.
614#[inline]
615pub unsafe fn ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam(
616    platform_io: *mut ImGuiPlatformIO,
617    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_pos: *mut ImVec2)>,
618) {
619    #[cfg(dear_imgui_rs_platform_io_hooks)]
620    unsafe {
621        dear_imgui_rs_platform_io_set_platform_get_window_pos(platform_io, user_callback)
622    }
623
624    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
625    {
626        if user_callback.is_some() {
627            panic!(
628                "dear-imgui-sys was built without PlatformIO aggregate ABI hooks; \
629                 rebuild without IMGUI_SYS_SKIP_CC to install Platform_GetWindowPos callbacks"
630            );
631        } else if let Some(platform_io) = unsafe { platform_io.as_mut() } {
632            platform_io.Platform_GetWindowPos = None;
633        }
634    }
635}
636
637/// Install a C-compatible pointer-parameter callback for
638/// `ImGuiPlatformIO::Platform_SetWindowSize`.
639///
640/// # Safety
641///
642/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
643/// must obey Dear ImGui's platform callback contract and must not unwind.
644#[inline]
645pub unsafe fn ImGuiPlatformIO_Set_Platform_SetWindowSize_PointerParam(
646    platform_io: *mut ImGuiPlatformIO,
647    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2)>,
648) {
649    #[cfg(dear_imgui_rs_platform_io_hooks)]
650    unsafe {
651        dear_imgui_rs_platform_io_set_platform_set_window_size(platform_io, user_callback)
652    }
653
654    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
655    {
656        if user_callback.is_some() {
657            panic!(
658                "dear-imgui-sys was built without PlatformIO aggregate ABI hooks; \
659                 rebuild without IMGUI_SYS_SKIP_CC to install Platform_SetWindowSize callbacks"
660            );
661        } else if let Some(platform_io) = unsafe { platform_io.as_mut() } {
662            platform_io.Platform_SetWindowSize = None;
663        }
664    }
665}
666
667/// Install a C-compatible out-parameter callback for `ImGuiPlatformIO::Platform_GetWindowSize`.
668///
669/// See [`ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam`] for the ABI rationale.
670///
671/// # Safety
672///
673/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
674/// must obey Dear ImGui's platform callback contract and must not unwind.
675#[inline]
676pub unsafe fn ImGuiPlatformIO_Set_Platform_GetWindowSize_OutParam(
677    platform_io: *mut ImGuiPlatformIO,
678    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_size: *mut ImVec2)>,
679) {
680    #[cfg(dear_imgui_rs_platform_io_hooks)]
681    unsafe {
682        dear_imgui_rs_platform_io_set_platform_get_window_size(platform_io, user_callback)
683    }
684
685    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
686    {
687        if user_callback.is_some() {
688            panic!(
689                "dear-imgui-sys was built without PlatformIO aggregate ABI hooks; \
690                 rebuild without IMGUI_SYS_SKIP_CC to install Platform_GetWindowSize callbacks"
691            );
692        } else if let Some(platform_io) = unsafe { platform_io.as_mut() } {
693            platform_io.Platform_GetWindowSize = None;
694        }
695    }
696}
697
698/// Install a C-compatible out-parameter callback for
699/// `ImGuiPlatformIO::Platform_GetWindowFramebufferScale`.
700///
701/// See [`ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam`] for the ABI rationale.
702///
703/// # Safety
704///
705/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
706/// must obey Dear ImGui's platform callback contract and must not unwind.
707#[inline]
708pub unsafe fn ImGuiPlatformIO_Set_Platform_GetWindowFramebufferScale_OutParam(
709    platform_io: *mut ImGuiPlatformIO,
710    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_scale: *mut ImVec2)>,
711) {
712    #[cfg(dear_imgui_rs_platform_io_hooks)]
713    unsafe {
714        dear_imgui_rs_platform_io_set_platform_get_window_framebuffer_scale(
715            platform_io,
716            user_callback,
717        )
718    }
719
720    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
721    {
722        if user_callback.is_some() {
723            panic!(
724                "dear-imgui-sys was built without PlatformIO aggregate ABI hooks; \
725                 rebuild without IMGUI_SYS_SKIP_CC to install \
726                 Platform_GetWindowFramebufferScale callbacks"
727            );
728        } else if let Some(platform_io) = unsafe { platform_io.as_mut() } {
729            platform_io.Platform_GetWindowFramebufferScale = None;
730        }
731    }
732}
733
734/// Install a C-compatible out-parameter callback for
735/// `ImGuiPlatformIO::Platform_GetWindowWorkAreaInsets`.
736///
737/// See [`ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam`] for the ABI rationale.
738///
739/// # Safety
740///
741/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
742/// must obey Dear ImGui's platform callback contract and must not unwind.
743#[inline]
744pub unsafe fn ImGuiPlatformIO_Set_Platform_GetWindowWorkAreaInsets_OutParam(
745    platform_io: *mut ImGuiPlatformIO,
746    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, out_insets: *mut ImVec4)>,
747) {
748    #[cfg(dear_imgui_rs_platform_io_hooks)]
749    unsafe {
750        dear_imgui_rs_platform_io_set_platform_get_window_work_area_insets(
751            platform_io,
752            user_callback,
753        )
754    }
755
756    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
757    {
758        if user_callback.is_some() {
759            panic!(
760                "dear-imgui-sys was built without PlatformIO aggregate ABI hooks; \
761                 rebuild without IMGUI_SYS_SKIP_CC to install Platform_GetWindowWorkAreaInsets \
762                 callbacks"
763            );
764        } else if let Some(platform_io) = unsafe { platform_io.as_mut() } {
765            platform_io.Platform_GetWindowWorkAreaInsets = None;
766        }
767    }
768}
769
770/// Clear `Platform_SetWindowPos` only when it is still owned by the given pointer callback.
771#[doc(hidden)]
772#[inline]
773pub unsafe fn ImGuiPlatformIO_ClearPlatformSetWindowPosIfPointerParam(
774    platform_io: *mut ImGuiPlatformIO,
775    user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, pos: *const ImVec2),
776) -> bool {
777    #[cfg(dear_imgui_rs_platform_io_hooks)]
778    unsafe {
779        return dear_imgui_rs_platform_io_clear_platform_set_window_pos_if_pointer_param(
780            platform_io,
781            user_callback,
782        ) != 0;
783    }
784
785    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
786    {
787        let _ = platform_io;
788        let _ = user_callback;
789        false
790    }
791}
792
793/// Clear `Platform_SetWindowSize` only when it is still owned by the given pointer callback.
794#[doc(hidden)]
795#[inline]
796pub unsafe fn ImGuiPlatformIO_ClearPlatformSetWindowSizeIfPointerParam(
797    platform_io: *mut ImGuiPlatformIO,
798    user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2),
799) -> bool {
800    #[cfg(dear_imgui_rs_platform_io_hooks)]
801    unsafe {
802        return dear_imgui_rs_platform_io_clear_platform_set_window_size_if_pointer_param(
803            platform_io,
804            user_callback,
805        ) != 0;
806    }
807
808    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
809    {
810        let _ = platform_io;
811        let _ = user_callback;
812        false
813    }
814}
815
816/// Clear `Platform_GetWindowPos` only when it is still owned by the given out-parameter callback.
817#[doc(hidden)]
818#[inline]
819pub unsafe fn ImGuiPlatformIO_ClearPlatformGetWindowPosIfOutParam(
820    platform_io: *mut ImGuiPlatformIO,
821    user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, out_pos: *mut ImVec2),
822) -> bool {
823    #[cfg(dear_imgui_rs_platform_io_hooks)]
824    unsafe {
825        return dear_imgui_rs_platform_io_clear_platform_get_window_pos_if_out_param(
826            platform_io,
827            user_callback,
828        ) != 0;
829    }
830
831    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
832    {
833        let _ = platform_io;
834        let _ = user_callback;
835        false
836    }
837}
838
839/// Clear `Platform_GetWindowSize` only when it is still owned by the given out-parameter callback.
840#[doc(hidden)]
841#[inline]
842pub unsafe fn ImGuiPlatformIO_ClearPlatformGetWindowSizeIfOutParam(
843    platform_io: *mut ImGuiPlatformIO,
844    user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, out_size: *mut ImVec2),
845) -> bool {
846    #[cfg(dear_imgui_rs_platform_io_hooks)]
847    unsafe {
848        return dear_imgui_rs_platform_io_clear_platform_get_window_size_if_out_param(
849            platform_io,
850            user_callback,
851        ) != 0;
852    }
853
854    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
855    {
856        let _ = platform_io;
857        let _ = user_callback;
858        false
859    }
860}
861
862/// Clear `Platform_GetWindowFramebufferScale` only when it is still owned by the given callback.
863#[doc(hidden)]
864#[inline]
865pub unsafe fn ImGuiPlatformIO_ClearPlatformGetWindowFramebufferScaleIfOutParam(
866    platform_io: *mut ImGuiPlatformIO,
867    user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, out_scale: *mut ImVec2),
868) -> bool {
869    #[cfg(dear_imgui_rs_platform_io_hooks)]
870    unsafe {
871        return dear_imgui_rs_platform_io_clear_platform_get_window_framebuffer_scale_if_out_param(
872            platform_io,
873            user_callback,
874        ) != 0;
875    }
876
877    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
878    {
879        let _ = platform_io;
880        let _ = user_callback;
881        false
882    }
883}
884
885/// Clear `Platform_GetWindowWorkAreaInsets` only when it is still owned by the given callback.
886#[doc(hidden)]
887#[inline]
888pub unsafe fn ImGuiPlatformIO_ClearPlatformGetWindowWorkAreaInsetsIfOutParam(
889    platform_io: *mut ImGuiPlatformIO,
890    user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, out_insets: *mut ImVec4),
891) -> bool {
892    #[cfg(dear_imgui_rs_platform_io_hooks)]
893    unsafe {
894        return dear_imgui_rs_platform_io_clear_platform_get_window_work_area_insets_if_out_param(
895            platform_io,
896            user_callback,
897        ) != 0;
898    }
899
900    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
901    {
902        let _ = platform_io;
903        let _ = user_callback;
904        false
905    }
906}
907
908/// Install a C-compatible pointer-parameter callback for
909/// `ImGuiPlatformIO::Renderer_SetWindowSize`.
910///
911/// # Safety
912///
913/// `platform_io` must be null or point to a live `ImGuiPlatformIO`. `user_callback`, when present,
914/// must obey Dear ImGui's renderer callback contract and must not unwind.
915#[inline]
916pub unsafe fn ImGuiPlatformIO_Set_Renderer_SetWindowSize_PointerParam(
917    platform_io: *mut ImGuiPlatformIO,
918    user_callback: Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2)>,
919) {
920    #[cfg(dear_imgui_rs_platform_io_hooks)]
921    unsafe {
922        dear_imgui_rs_platform_io_set_renderer_set_window_size(platform_io, user_callback)
923    }
924
925    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
926    {
927        if user_callback.is_some() {
928            panic!(
929                "dear-imgui-sys was built without PlatformIO aggregate ABI hooks; \
930                 rebuild without IMGUI_SYS_SKIP_CC to install Renderer_SetWindowSize callbacks"
931            );
932        } else if let Some(platform_io) = unsafe { platform_io.as_mut() } {
933            platform_io.Renderer_SetWindowSize = None;
934        }
935    }
936}
937
938/// Whether `Renderer_SetWindowSize` is currently owned by the given pointer callback.
939///
940/// This is an internal ownership primitive for renderer backends. It recognizes only callbacks
941/// installed through [`ImGuiPlatformIO_Set_Renderer_SetWindowSize_PointerParam`].
942#[doc(hidden)]
943#[inline]
944pub unsafe fn ImGuiPlatformIO_RendererSetWindowSizeMatchesPointerParam(
945    platform_io: *mut ImGuiPlatformIO,
946    user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2),
947) -> bool {
948    #[cfg(dear_imgui_rs_platform_io_hooks)]
949    unsafe {
950        return dear_imgui_rs_platform_io_renderer_set_window_size_matches_pointer_param(
951            platform_io,
952            user_callback,
953        ) != 0;
954    }
955
956    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
957    {
958        let _ = platform_io;
959        let _ = user_callback;
960        false
961    }
962}
963
964/// Return the pointer-parameter callback currently stored for `Renderer_SetWindowSize`.
965///
966/// This is an internal ownership primitive for backends that must preserve a foreign aggregate
967/// callback replacement even though all pointer-parameter callbacks share one C++ hook address.
968#[doc(hidden)]
969#[inline]
970pub unsafe fn ImGuiPlatformIO_RendererSetWindowSizePointerParam(
971    platform_io: *mut ImGuiPlatformIO,
972) -> Option<unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2)> {
973    #[cfg(dear_imgui_rs_platform_io_hooks)]
974    unsafe {
975        let mut callback = None;
976        if dear_imgui_rs_platform_io_get_renderer_set_window_size_pointer_param(
977            platform_io,
978            &mut callback,
979        ) != 0
980        {
981            return callback;
982        }
983        None
984    }
985
986    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
987    {
988        let _ = platform_io;
989        None
990    }
991}
992
993/// Clear `Renderer_SetWindowSize` only when it is still owned by the given pointer callback.
994///
995/// This is an internal ownership primitive for renderer backends.
996#[doc(hidden)]
997#[inline]
998pub unsafe fn ImGuiPlatformIO_ClearRendererSetWindowSizeIfPointerParam(
999    platform_io: *mut ImGuiPlatformIO,
1000    user_callback: unsafe extern "C" fn(vp: *mut ImGuiViewport, size: *const ImVec2),
1001) -> bool {
1002    #[cfg(dear_imgui_rs_platform_io_hooks)]
1003    unsafe {
1004        return dear_imgui_rs_platform_io_clear_renderer_set_window_size_if_pointer_param(
1005            platform_io,
1006            user_callback,
1007        ) != 0;
1008    }
1009
1010    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
1011    {
1012        let _ = platform_io;
1013        let _ = user_callback;
1014        false
1015    }
1016}
1017
1018/// Invoke all aggregate PlatformIO callback slots through C++.
1019///
1020/// This is a test-support ABI for validating that callbacks installed by the safe layer cross the
1021/// C++/Rust seam through pointers or out parameters rather than small aggregates by value.
1022///
1023/// # Safety
1024///
1025/// `platform_io` and `out_result` must point to valid live values. The current ImGui context must
1026/// own `platform_io`.
1027#[inline]
1028pub unsafe fn ImGuiPlatformIO_ProbeAggregateCallbacks(
1029    platform_io: *mut ImGuiPlatformIO,
1030    out_result: *mut DearImguiRsPlatformIoAggregateProbeResult,
1031) -> bool {
1032    #[cfg(dear_imgui_rs_platform_io_hooks)]
1033    unsafe {
1034        return dear_imgui_rs_platform_io_probe_aggregate_callbacks(platform_io, out_result) != 0;
1035    }
1036
1037    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
1038    {
1039        let _ = platform_io;
1040        let _ = out_result;
1041        false
1042    }
1043}
1044
1045/// Invoke a saved `Platform_SetWindowPos` callback through C++.
1046///
1047/// This prevents Rust from directly calling a C++ callback slot whose signature contains an
1048/// aggregate by value.
1049///
1050/// # Safety
1051///
1052/// All pointers must be valid live values, and `platform_io` must belong to the current context.
1053#[doc(hidden)]
1054#[inline]
1055pub unsafe fn ImGuiPlatformIO_InvokePlatformSetWindowPos(
1056    callbacks: *const ImGuiPlatformIO,
1057    viewport: *mut ImGuiViewport,
1058    pos: *const ImVec2,
1059) -> bool {
1060    #[cfg(dear_imgui_rs_platform_io_hooks)]
1061    unsafe {
1062        return dear_imgui_rs_platform_io_invoke_platform_set_window_pos(callbacks, viewport, pos)
1063            != 0;
1064    }
1065
1066    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
1067    {
1068        let _ = callbacks;
1069        let _ = viewport;
1070        let _ = pos;
1071        false
1072    }
1073}
1074
1075/// Invoke a saved `Renderer_SetWindowSize` callback through C++ using a pointer parameter.
1076///
1077/// # Safety
1078///
1079/// All pointers must be valid live values. `callbacks` may point to a snapshot of a live callback
1080/// table, and the callback must remain callable for the duration of this call.
1081#[doc(hidden)]
1082#[inline]
1083pub unsafe fn ImGuiPlatformIO_InvokeRendererSetWindowSize(
1084    callbacks: *const ImGuiPlatformIO,
1085    viewport: *mut ImGuiViewport,
1086    size: *const ImVec2,
1087) -> bool {
1088    #[cfg(dear_imgui_rs_platform_io_hooks)]
1089    unsafe {
1090        return dear_imgui_rs_platform_io_invoke_renderer_set_window_size(
1091            callbacks, viewport, size,
1092        ) != 0;
1093    }
1094
1095    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
1096    {
1097        let _ = callbacks;
1098        let _ = viewport;
1099        let _ = size;
1100        false
1101    }
1102}
1103
1104/// Return the number of live aggregate callback storage entries.
1105///
1106/// This is an internal test-support API. It is not a stable public ABI.
1107///
1108/// # Safety
1109///
1110/// The C++ hook storage follows Dear ImGui's single-threaded context model. Serialize this read
1111/// with every aggregate callback install, clear, and context destruction.
1112#[doc(hidden)]
1113#[inline]
1114pub unsafe fn ImGuiPlatformIO_AggregateCallbackStorageCount() -> usize {
1115    #[cfg(dear_imgui_rs_platform_io_hooks)]
1116    unsafe {
1117        return dear_imgui_rs_platform_io_aggregate_callback_storage_count() as usize;
1118    }
1119
1120    #[cfg(not(dear_imgui_rs_platform_io_hooks))]
1121    {
1122        0
1123    }
1124}
1125
1126// Re-export commonly used types for convenience
1127pub use ImColor as Color;
1128pub use ImVec2 as Vector2;
1129pub use ImVec4 as Vector4;
1130
1131/// Version of this Rust binding release.
1132///
1133/// Use [`igGetVersion`] when the linked Dear ImGui runtime version is required.
1134pub const BINDING_VERSION: &str = env!("CARGO_PKG_VERSION");
1135
1136/// Docking features are always available in this crate
1137pub const HAS_DOCKING: bool = true;
1138
1139/// Check if FreeType support is available
1140#[cfg(feature = "freetype")]
1141pub const HAS_FREETYPE: bool = true;
1142
1143#[cfg(not(feature = "freetype"))]
1144pub const HAS_FREETYPE: bool = false;
1145
1146/// Check if WASM support is available
1147#[cfg(all(dear_imgui_rs_wasm_import_target, feature = "wasm"))]
1148pub const HAS_WASM: bool = true;
1149
1150#[cfg(not(all(dear_imgui_rs_wasm_import_target, feature = "wasm")))]
1151pub const HAS_WASM: bool = false;
1152
1153#[cfg(test)]
1154mod target_contract_tests {
1155    #[test]
1156    fn wasm_availability_requires_the_build_selected_import_target() {
1157        assert_eq!(
1158            super::HAS_WASM,
1159            cfg!(all(dear_imgui_rs_wasm_import_target, feature = "wasm"))
1160        );
1161    }
1162}
1163
1164#[cfg(all(test, not(dear_imgui_rs_platform_io_hooks)))]
1165mod aggregate_setter_fallback_tests {
1166    use std::panic::{AssertUnwindSafe, catch_unwind};
1167    use std::ptr;
1168
1169    use super::*;
1170
1171    unsafe extern "C" fn set_vec2_pointer(_viewport: *mut ImGuiViewport, _value: *const ImVec2) {}
1172
1173    unsafe extern "C" fn get_vec2_out(_viewport: *mut ImGuiViewport, _value: *mut ImVec2) {}
1174
1175    unsafe extern "C" fn get_vec4_out(_viewport: *mut ImGuiViewport, _value: *mut ImVec4) {}
1176
1177    unsafe extern "C" fn raw_set_vec2(_viewport: *mut ImGuiViewport, _value: ImVec2) {}
1178
1179    unsafe extern "C" fn raw_get_vec2(_viewport: *mut ImGuiViewport) -> ImVec2 {
1180        ImVec2::zero()
1181    }
1182
1183    unsafe extern "C" fn raw_get_vec4(_viewport: *mut ImGuiViewport) -> ImVec4 {
1184        ImVec4::zero()
1185    }
1186
1187    fn assert_panics(action: impl FnOnce()) {
1188        assert!(catch_unwind(AssertUnwindSafe(action)).is_err());
1189    }
1190
1191    #[test]
1192    fn aggregate_setters_without_cpp_hooks_reject_some_callbacks() {
1193        assert_panics(|| unsafe {
1194            ImGuiPlatformIO_Set_Platform_SetWindowPos_PointerParam(
1195                ptr::null_mut(),
1196                Some(set_vec2_pointer),
1197            );
1198        });
1199        assert_panics(|| unsafe {
1200            ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam(ptr::null_mut(), Some(get_vec2_out));
1201        });
1202        assert_panics(|| unsafe {
1203            ImGuiPlatformIO_Set_Platform_SetWindowSize_PointerParam(
1204                ptr::null_mut(),
1205                Some(set_vec2_pointer),
1206            );
1207        });
1208        assert_panics(|| unsafe {
1209            ImGuiPlatformIO_Set_Platform_GetWindowSize_OutParam(
1210                ptr::null_mut(),
1211                Some(get_vec2_out),
1212            );
1213        });
1214        assert_panics(|| unsafe {
1215            ImGuiPlatformIO_Set_Platform_GetWindowFramebufferScale_OutParam(
1216                ptr::null_mut(),
1217                Some(get_vec2_out),
1218            );
1219        });
1220        assert_panics(|| unsafe {
1221            ImGuiPlatformIO_Set_Platform_GetWindowWorkAreaInsets_OutParam(
1222                ptr::null_mut(),
1223                Some(get_vec4_out),
1224            );
1225        });
1226        assert_panics(|| unsafe {
1227            ImGuiPlatformIO_Set_Renderer_SetWindowSize_PointerParam(
1228                ptr::null_mut(),
1229                Some(set_vec2_pointer),
1230            );
1231        });
1232    }
1233
1234    #[test]
1235    fn aggregate_setters_without_cpp_hooks_clear_matching_raw_slots() {
1236        let mut platform_io = ImGuiPlatformIO {
1237            Platform_SetWindowPos: Some(raw_set_vec2),
1238            Platform_GetWindowPos: Some(raw_get_vec2),
1239            Platform_SetWindowSize: Some(raw_set_vec2),
1240            Platform_GetWindowSize: Some(raw_get_vec2),
1241            Platform_GetWindowFramebufferScale: Some(raw_get_vec2),
1242            Platform_GetWindowWorkAreaInsets: Some(raw_get_vec4),
1243            Renderer_SetWindowSize: Some(raw_set_vec2),
1244            ..ImGuiPlatformIO::default()
1245        };
1246
1247        unsafe {
1248            ImGuiPlatformIO_Set_Platform_SetWindowPos_PointerParam(&mut platform_io, None);
1249        }
1250        assert!(platform_io.Platform_SetWindowPos.is_none());
1251        assert!(platform_io.Platform_GetWindowPos.is_some());
1252
1253        unsafe {
1254            ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam(&mut platform_io, None);
1255        }
1256        assert!(platform_io.Platform_GetWindowPos.is_none());
1257        assert!(platform_io.Platform_SetWindowSize.is_some());
1258
1259        unsafe {
1260            ImGuiPlatformIO_Set_Platform_SetWindowSize_PointerParam(&mut platform_io, None);
1261        }
1262        assert!(platform_io.Platform_SetWindowSize.is_none());
1263        assert!(platform_io.Platform_GetWindowSize.is_some());
1264
1265        unsafe {
1266            ImGuiPlatformIO_Set_Platform_GetWindowSize_OutParam(&mut platform_io, None);
1267        }
1268        assert!(platform_io.Platform_GetWindowSize.is_none());
1269        assert!(platform_io.Platform_GetWindowFramebufferScale.is_some());
1270
1271        unsafe {
1272            ImGuiPlatformIO_Set_Platform_GetWindowFramebufferScale_OutParam(&mut platform_io, None);
1273        }
1274        assert!(platform_io.Platform_GetWindowFramebufferScale.is_none());
1275        assert!(platform_io.Platform_GetWindowWorkAreaInsets.is_some());
1276
1277        unsafe {
1278            ImGuiPlatformIO_Set_Platform_GetWindowWorkAreaInsets_OutParam(&mut platform_io, None);
1279        }
1280        assert!(platform_io.Platform_GetWindowWorkAreaInsets.is_none());
1281        assert!(platform_io.Renderer_SetWindowSize.is_some());
1282
1283        unsafe {
1284            ImGuiPlatformIO_Set_Renderer_SetWindowSize_PointerParam(&mut platform_io, None);
1285        }
1286        assert!(platform_io.Renderer_SetWindowSize.is_none());
1287    }
1288}
1289
1290// (No wasm-specific shims are required when using shared memory import style.)
1291
1292impl ImVec2 {
1293    #[inline]
1294    pub const fn new(x: f32, y: f32) -> ImVec2 {
1295        ImVec2 { x, y }
1296    }
1297
1298    #[inline]
1299    pub const fn zero() -> ImVec2 {
1300        ImVec2 { x: 0.0, y: 0.0 }
1301    }
1302}
1303
1304impl From<[f32; 2]> for ImVec2 {
1305    #[inline]
1306    fn from(array: [f32; 2]) -> ImVec2 {
1307        ImVec2::new(array[0], array[1])
1308    }
1309}
1310
1311impl From<(f32, f32)> for ImVec2 {
1312    #[inline]
1313    fn from((x, y): (f32, f32)) -> ImVec2 {
1314        ImVec2::new(x, y)
1315    }
1316}
1317
1318impl From<ImVec2> for [f32; 2] {
1319    #[inline]
1320    fn from(v: ImVec2) -> [f32; 2] {
1321        [v.x, v.y]
1322    }
1323}
1324
1325impl From<ImVec2> for (f32, f32) {
1326    #[inline]
1327    fn from(v: ImVec2) -> (f32, f32) {
1328        (v.x, v.y)
1329    }
1330}
1331
1332impl From<mint::Vector2<f32>> for ImVec2 {
1333    #[inline]
1334    fn from(v: mint::Vector2<f32>) -> ImVec2 {
1335        ImVec2::new(v.x, v.y)
1336    }
1337}
1338
1339#[cfg(feature = "glam")]
1340impl From<glam::Vec2> for ImVec2 {
1341    #[inline]
1342    fn from(v: glam::Vec2) -> ImVec2 {
1343        ImVec2::new(v.x, v.y)
1344    }
1345}
1346
1347impl ImVec4 {
1348    #[inline]
1349    pub const fn new(x: f32, y: f32, z: f32, w: f32) -> ImVec4 {
1350        ImVec4 { x, y, z, w }
1351    }
1352
1353    #[inline]
1354    pub const fn zero() -> ImVec4 {
1355        ImVec4 {
1356            x: 0.0,
1357            y: 0.0,
1358            z: 0.0,
1359            w: 0.0,
1360        }
1361    }
1362}
1363
1364impl From<[f32; 4]> for ImVec4 {
1365    #[inline]
1366    fn from(array: [f32; 4]) -> ImVec4 {
1367        ImVec4::new(array[0], array[1], array[2], array[3])
1368    }
1369}
1370
1371impl From<(f32, f32, f32, f32)> for ImVec4 {
1372    #[inline]
1373    fn from((x, y, z, w): (f32, f32, f32, f32)) -> ImVec4 {
1374        ImVec4::new(x, y, z, w)
1375    }
1376}
1377
1378impl From<ImVec4> for [f32; 4] {
1379    #[inline]
1380    fn from(v: ImVec4) -> [f32; 4] {
1381        [v.x, v.y, v.z, v.w]
1382    }
1383}
1384
1385impl From<ImVec4> for (f32, f32, f32, f32) {
1386    #[inline]
1387    fn from(v: ImVec4) -> (f32, f32, f32, f32) {
1388        (v.x, v.y, v.z, v.w)
1389    }
1390}
1391
1392impl From<mint::Vector4<f32>> for ImVec4 {
1393    #[inline]
1394    fn from(v: mint::Vector4<f32>) -> ImVec4 {
1395        ImVec4::new(v.x, v.y, v.z, v.w)
1396    }
1397}
1398
1399#[cfg(feature = "glam")]
1400impl From<glam::Vec4> for ImVec4 {
1401    #[inline]
1402    fn from(v: glam::Vec4) -> ImVec4 {
1403        ImVec4::new(v.x, v.y, v.z, v.w)
1404    }
1405}