use crate::sys;
use std::cell::UnsafeCell;
#[cfg(feature = "multi-viewport")]
use super::trampolines;
#[repr(transparent)]
pub struct PlatformIo {
pub(super) raw: UnsafeCell<sys::ImGuiPlatformIO>,
}
const _: [(); std::mem::size_of::<sys::ImGuiPlatformIO>()] =
[(); std::mem::size_of::<PlatformIo>()];
const _: [(); std::mem::align_of::<sys::ImGuiPlatformIO>()] =
[(); std::mem::align_of::<PlatformIo>()];
#[cfg(feature = "multi-viewport")]
pub(crate) fn clear_typed_callbacks_for_context(ctx: *mut sys::ImGuiContext) {
trampolines::clear_callbacks_for_context(ctx);
}
#[cfg(not(feature = "multi-viewport"))]
pub(crate) fn clear_typed_callbacks_for_context(_ctx: *mut sys::ImGuiContext) {}
#[cfg(feature = "multi-viewport")]
pub(crate) unsafe fn clear_out_param_callbacks_for_current_context() {
let pio = unsafe { sys::igGetPlatformIO_Nil() };
if pio.is_null() {
return;
}
unsafe {
sys::ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam(pio, None);
sys::ImGuiPlatformIO_Set_Platform_GetWindowSize_OutParam(pio, None);
sys::ImGuiPlatformIO_Set_Platform_GetWindowFramebufferScale_OutParam(pio, None);
sys::ImGuiPlatformIO_Set_Platform_GetWindowWorkAreaInsets_OutParam(pio, None);
}
}
#[cfg(not(feature = "multi-viewport"))]
pub(crate) unsafe fn clear_out_param_callbacks_for_current_context() {}
#[cfg(feature = "multi-viewport")]
pub(super) unsafe fn clear_out_param_callbacks_for_platform_io(pio: *mut sys::ImGuiPlatformIO) {
if pio.is_null() {
return;
}
unsafe {
sys::ImGuiPlatformIO_Set_Platform_GetWindowPos_OutParam(pio, None);
sys::ImGuiPlatformIO_Set_Platform_GetWindowSize_OutParam(pio, None);
sys::ImGuiPlatformIO_Set_Platform_GetWindowFramebufferScale_OutParam(pio, None);
sys::ImGuiPlatformIO_Set_Platform_GetWindowWorkAreaInsets_OutParam(pio, None);
}
}
#[cfg(feature = "multi-viewport")]
pub(super) fn assert_platform_io_out_param_hooks_available(callback_name: &str) {
assert!(
sys::HAS_PLATFORM_IO_OUT_PARAM_HOOKS,
"dear-imgui-sys was built without PlatformIO out-parameter hooks; \
rebuild without IMGUI_SYS_SKIP_CC to install {callback_name} callbacks"
);
}
impl PlatformIo {
#[inline]
pub(super) fn inner(&self) -> &sys::ImGuiPlatformIO {
unsafe { &*self.raw.get() }
}
#[inline]
pub(super) fn inner_mut(&mut self) -> &mut sys::ImGuiPlatformIO {
unsafe { &mut *self.raw.get() }
}
pub unsafe fn from_raw<'a>(raw: *const sys::ImGuiPlatformIO) -> &'a Self {
unsafe { &*(raw as *const Self) }
}
pub unsafe fn from_raw_mut<'a>(raw: *mut sys::ImGuiPlatformIO) -> &'a mut Self {
unsafe { &mut *(raw as *mut Self) }
}
pub fn as_raw(&self) -> *const sys::ImGuiPlatformIO {
self.raw.get().cast_const()
}
pub fn as_raw_mut(&mut self) -> *mut sys::ImGuiPlatformIO {
self.raw.get()
}
#[cfg(feature = "multi-viewport")]
fn is_current_context_platform_io(&self) -> bool {
unsafe {
if sys::igGetCurrentContext().is_null() {
return false;
}
let current = sys::igGetPlatformIO_Nil();
!current.is_null() && std::ptr::addr_eq(current.cast_const(), self.as_raw())
}
}
#[cfg(feature = "multi-viewport")]
pub(super) fn assert_current_context_platform_io_for_callbacks(&self) {
assert!(
self.is_current_context_platform_io(),
"PlatformIo typed/out-parameter callback setters must be called on the active ImGui context's PlatformIo"
);
}
#[cfg(feature = "multi-viewport")]
pub(super) fn store_current_context_cb<T: Copy>(
&self,
slot: &trampolines::CallbackSlot<T>,
callback: Option<T>,
) {
self.assert_current_context_platform_io_for_callbacks();
trampolines::store_cb(slot, callback);
}
#[cfg(feature = "multi-viewport")]
pub(super) fn clear_current_context_cb<T: Copy>(&self, slot: &trampolines::CallbackSlot<T>) {
self.assert_current_context_platform_io_for_callbacks();
trampolines::clear_cb_for_current_context(slot);
}
#[cfg(feature = "multi-viewport")]
pub(super) fn clear_platform_io_cb<T: Copy>(&self, slot: &trampolines::CallbackSlot<T>) {
trampolines::clear_cb_for_platform_io(self.as_raw(), slot);
}
}