diff --git a/imgui-examples/examples/support/mod.rs b/imgui-examples/examples/support/mod.rs index 546c4dc..bbbe347 100644 --- a/imgui-examples/examples/support/mod.rs +++ b/imgui-examples/examples/support/mod.rs @@ -158,13 +158,19 @@ impl System { renderer .render(&mut target, draw_data) .expect("Rendering failed"); - imgui.update_platform_windows(); target.finish().expect("Failed to swap buffers"); + + imgui.update_platform_windows(); + imgui.render_platform_windows_default(); } Event::WindowEvent { event: WindowEvent::CloseRequested, + window_id, .. - } => *control_flow = ControlFlow::Exit, + } if window_id == display.gl_window().window().id() => *control_flow = ControlFlow::Exit, + Event::WindowEvent { event, window_id, .. } if window_id != display.gl_window().window().id() => { + platform.handle_viewport_event(&mut imgui, window_id, &event); + }, event => { let gl_window = display.gl_window(); platform.handle_event(imgui.io_mut(), gl_window.window(), &event); diff --git a/imgui-winit-support/src/lib.rs b/imgui-winit-support/src/lib.rs index 83dd78c..3a009c5 100644 --- a/imgui-winit-support/src/lib.rs +++ b/imgui-winit-support/src/lib.rs @@ -188,8 +188,10 @@ use winit_20 as winit; ))] use winit_19 as winit; -use imgui::{self, BackendFlags, ConfigFlags, Context, Io, Key, Ui, PlatformViewportBackend, ViewportFlags, PlatformMonitor, Viewport}; -use std::cell::Cell; +use imgui::{self, BackendFlags, ConfigFlags, Context, Io, Key, Ui, PlatformViewportBackend, ViewportFlags, PlatformMonitor}; +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; +use std::{cell::Cell, ptr::null_mut}; use std::cmp::Ordering; use winit::dpi::{LogicalPosition, LogicalSize}; @@ -466,51 +468,56 @@ impl PlatformViewportBackend for ViewportBackend { fn create_window(&mut self, viewport: &mut imgui::Viewport) { let window = winit::window::WindowBuilder::new() .with_always_on_top(viewport.flags.contains(ViewportFlags::TOP_MOST)) - .with_decorations(!viewport.flags.contains(ViewportFlags::NO_DECORATION)) + // .with_decorations(!viewport.flags.contains(ViewportFlags::NO_DECORATION)) .with_resizable(true) .with_visible(false) .build(unsafe{&*self.event_loop}) .unwrap(); - viewport.platform_handle = Box::into_raw(Box::new(PlatformHandle::SecondaryWindow(window))) as *mut _; + let mut hasher = DefaultHasher::new(); + viewport.platform_handle = window.id().hash(&hasher); + viewport.platform_handle = hasher.finish() as *mut c_void; + + viewport.platform_user_data = Box::into_raw(Box::new(PlatformHandle::SecondaryWindow(window))) as *mut _; } fn destroy_window(&mut self, viewport: &mut imgui::Viewport) { unsafe { // drop window - Box::from_raw(viewport.platform_handle as *mut PlatformHandle); + Box::from_raw(viewport.platform_user_data as *mut PlatformHandle); + viewport.platform_user_data = null_mut(); // satisfy ImGui check } } fn show_window(&mut self, viewport: &mut imgui::Viewport) { - let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() }; + let window = unsafe { (*(viewport.platform_user_data as *const PlatformHandle)).get() }; window.set_visible(true); } fn set_window_pos(&mut self, viewport: &mut imgui::Viewport, pos: [f32; 2]) { - let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() }; + let window = unsafe { (*(viewport.platform_user_data as *const PlatformHandle)).get() }; window.set_outer_position(winit::dpi::LogicalPosition::new(pos[0], pos[1])); } fn get_window_pos(&mut self, viewport: &mut imgui::Viewport) -> [f32; 2] { - let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() }; + let window = unsafe { (*(viewport.platform_user_data as *const PlatformHandle)).get() }; let pos = window.outer_position().unwrap(); [pos.x as f32, pos.y as f32] } fn set_window_size(&mut self, viewport: &mut imgui::Viewport, size: [f32; 2]) { - let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() }; + let window = unsafe { (*(viewport.platform_user_data as *const PlatformHandle)).get() }; window.set_inner_size(winit::dpi::LogicalSize::new(size[0], size[1])); } fn get_window_size(&mut self, viewport: &mut imgui::Viewport) -> [f32; 2] { - let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() }; + let window = unsafe { (*(viewport.platform_user_data as *const PlatformHandle)).get() }; let size = window.inner_size(); [size.width as f32, size.width as f32] } fn set_window_focus(&mut self, viewport: &mut imgui::Viewport) { - let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() }; + let window = unsafe { (*(viewport.platform_user_data as *const PlatformHandle)).get() }; window.focus_window(); } @@ -523,7 +530,7 @@ impl PlatformViewportBackend for ViewportBackend { } fn set_window_title(&mut self, viewport: &mut imgui::Viewport, title: &str) { - let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() }; + let window = unsafe { (*(viewport.platform_user_data as *const PlatformHandle)).get() }; window.set_title(title); } @@ -618,9 +625,10 @@ impl WinitPlatform { pio.monitors.replace_from_slice(&monitors); let main_viewport = imgui.main_viewport_mut(); - main_viewport.platform_handle = Box::into_raw(Box::new(PlatformHandle::MainWindow(main_window as *const _))) as *mut _; - println!("MAIN VIEWPORT: {:016X}", main_viewport as *mut Viewport as u64); - println!("PLATFORM HANDLE: {:016X}", main_viewport.platform_handle as u64); + let mut hasher = DefaultHasher::new(); + main_window.id().hash(&mut hasher); + main_viewport.platform_handle = hasher.finish() as *mut c_void; + main_viewport.platform_user_data = Box::into_raw(Box::new(PlatformHandle::MainWindow(main_window as *const _))) as *mut _; } /// Attaches the platform instance to a winit window. @@ -979,6 +987,37 @@ impl WinitPlatform { _ => (), } } + pub fn handle_viewport_event(&mut self, imgui: &mut imgui::Context, window_id: winit::window::WindowId, window_event: &winit::event::WindowEvent) { + let hasher = DefaultHasher::new(); + window_id.hash(&mut hasher); + let viewport_id = hasher.finish(); + + match *window_event { + WindowEvent::Resized(new_size) => { + + }, + WindowEvent::Moved(_) => todo!(), + WindowEvent::CloseRequested => todo!(), + WindowEvent::Destroyed => todo!(), + WindowEvent::DroppedFile(_) => todo!(), + WindowEvent::HoveredFile(_) => todo!(), + WindowEvent::HoveredFileCancelled => todo!(), + WindowEvent::ReceivedCharacter(_) => todo!(), + WindowEvent::Focused(_) => todo!(), + WindowEvent::KeyboardInput { device_id, input, is_synthetic } => todo!(), + WindowEvent::ModifiersChanged(_) => todo!(), + WindowEvent::CursorMoved { device_id, position, modifiers } => todo!(), + WindowEvent::CursorEntered { device_id } => todo!(), + WindowEvent::CursorLeft { device_id } => todo!(), + WindowEvent::MouseWheel { device_id, delta, phase, modifiers } => todo!(), + WindowEvent::MouseInput { device_id, state, button, modifiers } => todo!(), + WindowEvent::TouchpadPressure { device_id, pressure, stage } => todo!(), + WindowEvent::AxisMotion { device_id, axis, value } => todo!(), + WindowEvent::Touch(_) => todo!(), + WindowEvent::ScaleFactorChanged { scale_factor, new_inner_size } => todo!(), + WindowEvent::ThemeChanged(_) => todo!(), + } + } #[cfg(all( not(any( feature = "winit-26", diff --git a/imgui/src/context.rs b/imgui/src/context.rs index a233795..e822b83 100644 --- a/imgui/src/context.rs +++ b/imgui/src/context.rs @@ -1,9 +1,9 @@ use parking_lot::ReentrantMutex; use std::cell::UnsafeCell; -use std::ffi::{CStr, CString}; +use std::ffi::{CStr, CString, c_void}; use std::ops::Drop; use std::path::PathBuf; -use std::ptr; +use std::ptr::{self, null_mut}; use crate::clipboard::{ClipboardBackend, ClipboardContext}; use crate::fonts::atlas::{FontAtlas, FontId, SharedFontAtlas}; @@ -275,6 +275,11 @@ impl Context { sys::igUpdatePlatformWindows(); } } + pub fn render_platform_windows_default(&mut self) { + unsafe { + sys::igRenderPlatformWindowsDefault(null_mut(), null_mut()); + } + } fn create_internal(mut shared_font_atlas: Option) -> Self { let _guard = CTX_MUTEX.lock(); assert!( @@ -564,6 +569,18 @@ impl Context { &mut *(sys::igGetMainViewport() as *mut Viewport) } } + pub fn viewport_by_id(&self, id: *mut c_void) -> Option<&Viewport> { + unsafe { + let ptr = sys::igFindViewportByPlatformHandle(id) as *const Viewport; + ptr.as_ref() + } + } + pub fn viewport_by_id_mut(&mut self, id: *mut c_void) -> Option<&mut Viewport> { + unsafe { + let ptr = sys::igFindViewportByPlatformHandle(id) as *mut Viewport; + ptr.as_mut() + } + } /// Returns an immutable reference to the user interface style #[doc(alias = "GetStyle")] pub fn style(&self) -> &Style { diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index b80a2ca..e3d0a31 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -283,6 +283,7 @@ impl Ui { /// Previously, this was erroneously constructed with `From` implementations. /// Now, however, it is made from the `Ui` object directly, with a few /// deprecated helper methods here. +#[repr(transparent)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] pub struct Id(pub(crate) u32);