From 4869a85fbb7062627b28195a945ad70db1c1dbe0 Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Wed, 3 Nov 2021 16:49:38 -0500 Subject: [PATCH 1/8] add ability to close window from user code, add HostWindowHandle --- Cargo.toml | 2 +- examples/open_window.rs | 3 +- src/macos/view.rs | 2 +- src/macos/window.rs | 156 ++++++++++++++++++++++++++++++++++++---- src/win/window.rs | 118 ++++++++++++++++++++++++++---- src/window.rs | 10 ++- src/x11/window.rs | 127 +++++++++++++++++++++++++++----- 7 files changed, 366 insertions(+), 52 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e9b1aa02..d781e3c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,4 +33,4 @@ objc = "0.2.7" uuid = { version = "0.8", features = ["v4"] } [dev-dependencies] -rtrb = "0.1.1" +rtrb = "0.2" diff --git a/examples/open_window.rs b/examples/open_window.rs index 5e148a39..78a7d976 100644 --- a/examples/open_window.rs +++ b/examples/open_window.rs @@ -1,7 +1,6 @@ use std::time::Duration; use rtrb::{RingBuffer, Consumer}; - use baseview::{Event, EventStatus, Window, WindowHandler, WindowScalePolicy}; #[derive(Debug, Clone)] @@ -38,7 +37,7 @@ fn main() { scale: WindowScalePolicy::SystemScaleFactor, }; - let (mut tx, rx) = RingBuffer::new(128).split(); + let (mut tx, rx) = RingBuffer::new(128); ::std::thread::spawn(move || { loop { diff --git a/src/macos/view.rs b/src/macos/view.rs index 5d017aeb..2f056dad 100644 --- a/src/macos/view.rs +++ b/src/macos/view.rs @@ -245,7 +245,7 @@ extern "C" fn release(this: &mut Object, _sel: Sel) { .retain_count_after_build; if retain_count <= retain_count_after_build { - WindowState::from_field(this).remove_timer(); + WindowState::from_field(this).stop(); this.set_ivar( BASEVIEW_STATE_IVAR, diff --git a/src/macos/window.rs b/src/macos/window.rs index 09182353..a884679b 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -1,14 +1,17 @@ +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; use std::ffi::c_void; use cocoa::appkit::{ NSApp, NSApplication, NSApplicationActivationPolicyRegular, - NSBackingStoreBuffered, NSWindow, NSWindowStyleMask, + NSBackingStoreBuffered, NSWindow, NSWindowStyleMask, NSView, + NSRunningApplication, NSApplicationActivateIgnoringOtherApps }; use cocoa::base::{id, nil, NO}; use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString}; use core_foundation::runloop::{ CFRunLoop, CFRunLoopTimer, CFRunLoopTimerContext, __CFRunLoopTimer, - kCFRunLoopDefaultMode, + kCFRunLoopDefaultMode, }; use keyboard_types::KeyboardEvent; @@ -18,30 +21,84 @@ use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle} use crate::{ Event, EventStatus, WindowHandler, WindowOpenOptions, WindowScalePolicy, - WindowInfo, + WindowInfo, WindowEvent, }; use super::view::{create_view, BASEVIEW_STATE_IVAR}; use super::keyboard::KeyboardState; +pub struct HostWindowHandle { + handle_dropped: Arc, + window_dropped: Arc, +} + +impl HostWindowHandle { + pub fn window_was_dropped(&self) -> bool { + self.window_dropped.load(Ordering::Relaxed) + } +} + +impl Drop for HostWindowHandle { + fn drop(&mut self) { + self.handle_dropped.store(true, Ordering::Relaxed); + } +} + +pub struct HostHandle { + handle_dropped: Arc, + window_dropped: Arc, +} + +impl HostHandle { + pub fn new() -> (Self, HostWindowHandle) { + let handle_dropped = Arc::new(AtomicBool::new(false)); + let window_dropped = Arc::new(AtomicBool::new(false)); + + let handle = HostWindowHandle { + handle_dropped: Arc::clone(&handle_dropped), + window_dropped: Arc::clone(&window_dropped), + }; + + ( + Self { handle_dropped, window_dropped }, + handle + ) + } + + pub fn handle_was_dropped(&self) -> bool { + self.handle_dropped.load(Ordering::Relaxed) + } +} + +impl Drop for HostHandle { + fn drop(&mut self) { + self.window_dropped.store(true, Ordering::Relaxed); + } +} pub struct Window { + /// Only set if we created the parent window, i.e. we are running in + /// parentless mode + ns_app: Option, /// Only set if we created the parent window, i.e. we are running in /// parentless mode ns_window: Option, + /// Only set if we did not create the parent window + host_handle: Option, /// Our subclassed NSView ns_view: id, + close_requested: bool, } impl Window { - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> HostWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, B: Send + 'static, { - let _pool = unsafe { NSAutoreleasePool::new(nil) }; + let pool = unsafe { NSAutoreleasePool::new(nil) }; let handle = if let RawWindowHandle::MacOS(handle) = parent.raw_window_handle() { handle @@ -51,9 +108,14 @@ impl Window { let ns_view = unsafe { create_view(&options) }; + let (host_handle, host_window_handle) = HostHandle::new(); + let window = Window { + ns_app: None, ns_window: None, + host_handle: Some(host_handle), ns_view, + close_requested: false, }; Self::init(window, build); @@ -61,28 +123,45 @@ impl Window { unsafe { let _: id = msg_send![handle.ns_view as *mut Object, addSubview: ns_view]; } + + // Must drain pool before returning so retain counts are correct + unsafe { + let _: () = msg_send![pool, drain]; + } + + host_window_handle } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> RawWindowHandle + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, HostWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, B: Send + 'static, { - let _pool = unsafe { NSAutoreleasePool::new(nil) }; + let pool = unsafe { NSAutoreleasePool::new(nil) }; let ns_view = unsafe { create_view(&options) }; + let (host_handle, host_window_handle) = HostHandle::new(); + let window = Window { + ns_app: None, ns_window: None, + host_handle: Some(host_handle), ns_view, + close_requested: false, }; let raw_window_handle = window.raw_window_handle(); Self::init(window, build); - raw_window_handle + // Must drain pool before returning so retain counts are correct + unsafe { + let _: () = msg_send![pool, drain]; + } + + (raw_window_handle, host_window_handle) } pub fn open_blocking(options: WindowOpenOptions, build: B) @@ -91,7 +170,7 @@ impl Window { B: FnOnce(&mut crate::Window) -> H, B: Send + 'static, { - let _pool = unsafe { NSAutoreleasePool::new(nil) }; + let pool = unsafe { NSAutoreleasePool::new(nil) }; // It seems prudent to run NSApp() here before doing other // work. It runs [NSApplication sharedApplication], which is @@ -128,13 +207,18 @@ impl Window { let ns_window = NSWindow::alloc(nil) .initWithContentRect_styleMask_backing_defer_( rect, - NSWindowStyleMask::NSTitledWindowMask, + NSWindowStyleMask::NSTitledWindowMask | + NSWindowStyleMask::NSClosableWindowMask | + NSWindowStyleMask::NSMiniaturizableWindowMask, NSBackingStoreBuffered, NO, ) .autorelease(); ns_window.center(); + // We are already releasing the window with our autorelease pool + let _: () = msg_send![ns_window, setReleasedWhenClosed: NO]; + let title = NSString::alloc(nil) .init_str(&options.title) .autorelease(); @@ -148,17 +232,25 @@ impl Window { let ns_view = unsafe { create_view(&options) }; let window = Window { + ns_app: Some(app), ns_window: Some(ns_window), + host_handle: None, ns_view, + close_requested: false, }; Self::init(window, build); unsafe { ns_window.setContentView_(ns_view); - } - unsafe { + // Make sure app gets focus + let current_app = NSRunningApplication::currentApplication(nil); + current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps); + + // Must drain pool before running app so retain counts are correct + let _: () = msg_send![pool, drain]; + app.run(); } } @@ -194,6 +286,10 @@ impl Window { WindowState::setup_timer(window_state_ptr); } } + + pub fn request_close(&mut self) { + self.close_requested = true; + } } @@ -226,6 +322,30 @@ impl WindowState { pub(super) fn trigger_frame(&mut self) { self.window_handler .on_frame(&mut crate::Window::new(&mut self.window)); + + // Check if the host handle was dropped + if let Some(host_handle) = &self.window.host_handle { + if host_handle.handle_was_dropped() { + self.window.close_requested = false; + + unsafe { + self.window.ns_view.removeFromSuperview(); + } + } + } + + // Check if the user requested the window to close + if self.window.close_requested { + self.window.close_requested = false; + + unsafe { + self.window.ns_view.removeFromSuperview(); + + if let Some(ns_window) = self.window.ns_window.take() { + ns_window.close(); + } + } + } } pub(super) fn process_native_key_event( @@ -276,10 +396,16 @@ impl WindowState { } /// Call when freeing view - pub(super) unsafe fn remove_timer(&mut self) { + pub(super) unsafe fn stop(&mut self) { if let Some(frame_timer) = self.frame_timer.take() { - CFRunLoop::get_current() - .remove_timer(&frame_timer, kCFRunLoopDefaultMode); + CFRunLoop::get_current().remove_timer(&frame_timer, kCFRunLoopDefaultMode); + } + + self.trigger_event(Event::Window(WindowEvent::WillClose)); + + // If in non-parented mode, we want to also quit the app altogether + if let Some(app) = self.window.ns_app.take() { + app.stop_(app); } } } diff --git a/src/win/window.rs b/src/win/window.rs index 82cd4630..36ff34c9 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -2,12 +2,13 @@ use winapi::shared::guiddef::GUID; use winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM}; use winapi::shared::windef::{HWND, RECT}; use winapi::um::combaseapi::CoCreateGuid; +use winapi::um::winnt::LPCSTR; use winapi::um::winuser::{ AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DispatchMessageW, GetMessageW, GetWindowLongPtrW, PostMessageW, RegisterClassW, SetTimer, SetWindowLongPtrW, TranslateMessage, UnregisterClassW, LoadCursorW, DestroyWindow, SetProcessDpiAwarenessContext, SetWindowPos, - GetDpiForWindow, + GetDpiForWindow, RegisterWindowMessageA, CS_OWNDC, GWLP_USERDATA, IDC_ARROW, MSG, WM_CLOSE, WM_CREATE, WM_MOUSEMOVE, WM_MOUSEWHEEL, WHEEL_DELTA, WM_SHOWWINDOW, WM_TIMER, WM_NCDESTROY, WNDCLASSW, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, @@ -18,6 +19,8 @@ use winapi::um::winuser::{ SetCapture, GetCapture, ReleaseCapture, IsWindow, SWP_NOZORDER, SWP_NOMOVE }; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; use std::cell::RefCell; use std::ffi::{OsStr, c_void}; use std::os::windows::ffi::OsStrExt; @@ -57,6 +60,55 @@ unsafe fn generate_guid() -> String { const WIN_FRAME_TIMER: usize = 4242; +pub struct HostWindowHandle { + hwnd: Option, + destroy_msg_id: u32, + window_dropped: Arc, +} + +impl HostWindowHandle { + pub fn window_was_dropped(&self) -> bool { + self.window_dropped.load(Ordering::Relaxed) + } +} + +impl Drop for HostWindowHandle { + fn drop(&mut self) { + if let Some(hwnd) = self.hwnd { + unsafe { + PostMessageW(hwnd, self.destroy_msg_id, 0, 0); + } + } + } +} + +pub struct HostHandle { + window_dropped: Arc, +} + +impl HostHandle { + pub fn new() -> (Self, HostWindowHandle) { + let window_dropped = Arc::new(AtomicBool::new(false)); + + let handle = HostWindowHandle { + hwnd: None, + destroy_msg_id: 0, + window_dropped: Arc::clone(&window_dropped), + }; + + ( + Self { window_dropped }, + handle + ) + } +} + +impl Drop for HostHandle { + fn drop(&mut self) { + self.window_dropped.store(true, Ordering::Relaxed); + } +} + unsafe extern "system" fn wnd_proc( hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM, ) -> LRESULT { @@ -67,7 +119,8 @@ unsafe extern "system" fn wnd_proc( let window_state_ptr = GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut RefCell; if !window_state_ptr.is_null() { - let mut window = Window { hwnd }; + let destroy_msg_id = (&*window_state_ptr).borrow().destroy_msg_id; + let mut window = Window { hwnd, destroy_msg_id }; let mut window = crate::Window::new(&mut window); match msg { @@ -254,7 +307,15 @@ unsafe extern "system" fn wnd_proc( unregister_wnd_class(window_state.borrow().window_class); SetWindowLongPtrW(hwnd, GWLP_USERDATA, 0); } - _ => {} + _ => { + if msg == destroy_msg_id { + // FIXME: handler should decide whether window stays open or not + // (except if the message came from the host handle being dropped, + // in which case the window should always be closed) + DestroyWindow(hwnd); + return 0; + } + } } @@ -294,19 +355,22 @@ unsafe fn unregister_wnd_class(wnd_class: ATOM) { struct WindowState { window_class: ATOM, window_info: WindowInfo, + host_handle: Option, keyboard_state: KeyboardState, mouse_button_counter: usize, handler: Box, scale_policy: WindowScalePolicy, dw_style: u32, + destroy_msg_id: u32, } pub struct Window { hwnd: HWND, + destroy_msg_id: u32, } impl Window { - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> HostWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -318,21 +382,30 @@ impl Window { h => panic!("unsupported parent handle {:?}", h), }; - Self::open(true, parent, options, build); + let (host_handle, mut host_window_handle) = HostHandle::new(); + + Self::open(true, parent, options, build, Some(host_handle), Some(&mut host_window_handle)); + + host_window_handle } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> RawWindowHandle + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, HostWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, B: Send + 'static, { - let hwnd = Self::open(true, null_mut(), options, build); + let (host_handle, mut host_window_handle) = HostHandle::new(); - RawWindowHandle::Windows(WindowsHandle { - hwnd: hwnd as *mut std::ffi::c_void, - ..WindowsHandle::empty() - }) + let hwnd = Self::open(true, null_mut(), options, build, Some(host_handle), Some(&mut host_window_handle)); + + ( + RawWindowHandle::Windows(WindowsHandle { + hwnd: hwnd as *mut std::ffi::c_void, + ..WindowsHandle::empty() + }), + host_window_handle + ) } pub fn open_blocking(options: WindowOpenOptions, build: B) @@ -341,7 +414,7 @@ impl Window { B: FnOnce(&mut crate::Window) -> H, B: Send + 'static, { - let hwnd = Self::open(false, null_mut(), options, build); + let hwnd = Self::open(false, null_mut(), options, build, None, None); unsafe { let mut msg: MSG = std::mem::zeroed(); @@ -363,7 +436,9 @@ impl Window { parented: bool, parent: HWND, options: WindowOpenOptions, - build: B + build: B, + host_handle: Option, + host_window_handle: Option<&mut HostWindowHandle>, ) -> HWND where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -424,17 +499,21 @@ impl Window { null_mut(), ); // todo: manage error ^ + + let destroy_msg_id = RegisterWindowMessageA("Baseview::DestroyMsg\0".as_ptr() as LPCSTR); - let handler = Box::new(build(&mut crate::Window::new(&mut Window { hwnd }))); + let handler = Box::new(build(&mut crate::Window::new(&mut Window { hwnd, destroy_msg_id }))); let mut window_state = Box::new(RefCell::new(WindowState { window_class, window_info, + host_handle, keyboard_state: KeyboardState::new(), mouse_button_counter: 0, handler, scale_policy: options.scale, dw_style: flags, + destroy_msg_id, })); // Only works on Windows 10 unfortunately. @@ -490,9 +569,20 @@ impl Window { ); } + if let Some(host_window_handle) = host_window_handle { + host_window_handle.hwnd = Some(hwnd); + host_window_handle.destroy_msg_id = destroy_msg_id; + } + hwnd } } + + pub fn request_close(&mut self) { + unsafe { + PostMessageW(self.hwnd, self.destroy_msg_id, 0, 0); + } + } } unsafe impl HasRawWindowHandle for Window { diff --git a/src/window.rs b/src/window.rs index 199a0df9..849106f9 100644 --- a/src/window.rs +++ b/src/window.rs @@ -12,6 +12,8 @@ use crate::win as platform; #[cfg(target_os = "linux")] use crate::x11 as platform; +pub use platform::HostWindowHandle; + pub trait WindowHandler { fn on_frame(&mut self, window: &mut Window); fn on_event(&mut self, window: &mut Window, event: Event) -> EventStatus; @@ -31,7 +33,7 @@ impl<'a> Window<'a> { } } - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> HostWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -41,7 +43,7 @@ impl<'a> Window<'a> { platform::Window::open_parented::(parent, options, build) } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> RawWindowHandle + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, HostWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut Window) -> H, @@ -58,6 +60,10 @@ impl<'a> Window<'a> { { platform::Window::open_blocking::(options, build) } + + pub fn request_close(&mut self) { + self.window.request_close(); + } } unsafe impl<'a> HasRawWindowHandle for Window<'a> { diff --git a/src/x11/window.rs b/src/x11/window.rs index 3a10a0c8..b530228d 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -1,3 +1,5 @@ +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; use std::os::raw::{c_ulong, c_void}; use std::sync::mpsc; use std::time::*; @@ -26,8 +28,10 @@ pub struct Window { frame_interval: Duration, event_loop_running: bool, + close_requested: bool, new_physical_size: Option, + host_handle: Option, } // Hack to allow sending a RawWindowHandle between threads. Do not make public @@ -37,8 +41,57 @@ unsafe impl Send for SendableRwh {} type WindowOpenResult = Result; +pub struct HostWindowHandle { + handle_dropped: Arc, + window_dropped: Arc, +} + +impl HostWindowHandle { + pub fn window_was_dropped(&self) -> bool { + self.window_dropped.load(Ordering::Relaxed) + } +} + +impl Drop for HostWindowHandle { + fn drop(&mut self) { + self.handle_dropped.store(true, Ordering::Relaxed); + } +} + +pub struct HostHandle { + handle_dropped: Arc, + window_dropped: Arc, +} + +impl HostHandle { + pub fn new() -> (Self, HostWindowHandle) { + let handle_dropped = Arc::new(AtomicBool::new(false)); + let window_dropped = Arc::new(AtomicBool::new(false)); + + let handle = HostWindowHandle { + handle_dropped: Arc::clone(&handle_dropped), + window_dropped: Arc::clone(&window_dropped), + }; + + ( + Self { handle_dropped, window_dropped }, + handle + ) + } + + pub fn handle_was_dropped(&self) -> bool { + self.handle_dropped.load(Ordering::Relaxed) + } +} + +impl Drop for HostHandle { + fn drop(&mut self) { + self.window_dropped.store(true, Ordering::Relaxed); + } +} + impl Window { - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> HostWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -54,14 +107,18 @@ impl Window { let (tx, rx) = mpsc::sync_channel::(1); + let (host_handle, host_window_handle) = HostHandle::new(); + let thread = thread::spawn(move || { - Self::window_thread(Some(parent_id), options, build, tx.clone()); + Self::window_thread(Some(parent_id), options, build, tx.clone(), Some(host_handle)); }); let _ = rx.recv().unwrap().unwrap(); + + host_window_handle } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> RawWindowHandle + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, HostWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -69,11 +126,16 @@ impl Window { { let (tx, rx) = mpsc::sync_channel::(1); + let (host_handle, host_window_handle) = HostHandle::new(); + let thread = thread::spawn(move || { - Self::window_thread(None, options, build, tx.clone()); + Self::window_thread(None, options, build, tx.clone(), Some(host_handle)); }); - rx.recv().unwrap().unwrap().0 + ( + rx.recv().unwrap().unwrap().0, + host_window_handle + ) } pub fn open_blocking(options: WindowOpenOptions, build: B) @@ -85,7 +147,7 @@ impl Window { let (tx, rx) = mpsc::sync_channel::(1); let thread = thread::spawn(move || { - Self::window_thread(None, options, build, tx.clone()); + Self::window_thread(None, options, build, tx.clone(), None); }); let _ = rx.recv().unwrap().unwrap(); @@ -97,6 +159,7 @@ impl Window { parent: Option, options: WindowOpenOptions, build: B, tx: mpsc::SyncSender, + host_handle: Option, ) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -194,8 +257,10 @@ impl Window { frame_interval: Duration::from_millis(15), event_loop_running: false, + close_requested: false, new_physical_size: None, + host_handle, }; let mut handler = build(&mut crate::Window::new(&mut window)); @@ -212,10 +277,6 @@ impl Window { window.run_event_loop(&mut handler); } - pub fn window_info(&self) -> &WindowInfo { - &self.window_info - } - pub fn set_mouse_cursor(&mut self, mouse_cursor: MouseCursor) { if self.mouse_cursor == mouse_cursor { return @@ -236,6 +297,10 @@ impl Window { self.mouse_cursor = mouse_cursor; } + pub fn request_close(&mut self) { + self.close_requested = true; + } + #[inline] fn drain_xcb_events(&mut self, handler: &mut dyn WindowHandler) { // the X server has a tendency to send spurious/extraneous configure notify events when a @@ -306,9 +371,43 @@ impl Window { self.drain_xcb_events(handler); } } + + // Check if the host's handle was dropped (such as when the host + // requested the window to close) + if let Some(host_handle) = &self.host_handle { + if host_handle.handle_was_dropped() { + self.handle_must_close(handler); + self.close_requested = false; + } + } + + // Check if the user has requested the window to close + if self.close_requested { + self.handle_close_requested(handler); + self.close_requested = false; + } } } + fn handle_close_requested(&mut self, handler: &mut dyn WindowHandler) { + handler.on_event( + &mut crate::Window::new(self), + Event::Window(WindowEvent::WillClose) + ); + + // FIXME: handler should decide whether window stays open or not + self.event_loop_running = false; + } + + fn handle_must_close(&mut self, handler: &mut dyn WindowHandler) { + handler.on_event( + &mut crate::Window::new(self), + Event::Window(WindowEvent::WillClose) + ); + + self.event_loop_running = false; + } + fn handle_xcb_event(&mut self, handler: &mut dyn WindowHandler, event: xcb::GenericEvent) { let event_type = event.response_type() & !0x80; @@ -347,13 +446,7 @@ impl Window { .unwrap_or(xcb::NONE); if wm_delete_window == data32[0] { - handler.on_event( - &mut crate::Window::new(self), - Event::Window(WindowEvent::WillClose) - ); - - // FIXME: handler should decide whether window stays open or not - self.event_loop_running = false; + self.handle_close_requested(handler); } } From 5f35f356ca236621117ba51f0331059217a897bd Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Tue, 9 Nov 2021 10:39:30 -0600 Subject: [PATCH 2/8] fix manual close method for Mac, rename HostWindowHandle to ChildWindowHandle --- src/macos/window.rs | 126 +++++++++++++++++++++----------------------- src/win/window.rs | 60 ++++++++++----------- src/window.rs | 6 +-- src/x11/window.rs | 72 ++++++++++++------------- 4 files changed, 129 insertions(+), 135 deletions(-) diff --git a/src/macos/window.rs b/src/macos/window.rs index 7494835d..d2b84c49 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -2,16 +2,12 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::ffi::c_void; -use cocoa::appkit::{ - NSApp, NSApplication, NSApplicationActivationPolicyRegular, - NSBackingStoreBuffered, NSWindow, NSWindowStyleMask, NSView, - NSRunningApplication, NSApplicationActivateIgnoringOtherApps -}; +use cocoa::appkit::{NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSBackingStoreBuffered, NSWindow, NSWindowStyleMask}; use cocoa::base::{id, nil, NO}; use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString}; use core_foundation::runloop::{ CFRunLoop, CFRunLoopTimer, CFRunLoopTimerContext, __CFRunLoopTimer, - kCFRunLoopDefaultMode, + kCFRunLoopDefaultMode, }; use keyboard_types::KeyboardEvent; @@ -27,52 +23,54 @@ use crate::{ use super::view::{create_view, BASEVIEW_STATE_IVAR}; use super::keyboard::KeyboardState; -pub struct HostWindowHandle { - handle_dropped: Arc, - window_dropped: Arc, +pub struct ChildWindowHandle { + parent_dropped: Arc, + child_window_dropped: Arc, } -impl HostWindowHandle { +impl ChildWindowHandle { pub fn window_was_dropped(&self) -> bool { - self.window_dropped.load(Ordering::Relaxed) + self.child_window_dropped.load(Ordering::Relaxed) } } -impl Drop for HostWindowHandle { +impl Drop for ChildWindowHandle { fn drop(&mut self) { - self.handle_dropped.store(true, Ordering::Relaxed); + self.parent_dropped.store(true, Ordering::Relaxed); } } -pub struct HostHandle { - handle_dropped: Arc, - window_dropped: Arc, +struct ParentHandle { + _parent_dropped: Arc, + child_window_dropped: Arc, } -impl HostHandle { - pub fn new() -> (Self, HostWindowHandle) { - let handle_dropped = Arc::new(AtomicBool::new(false)); - let window_dropped = Arc::new(AtomicBool::new(false)); +impl ParentHandle { + pub fn new() -> (Self, ChildWindowHandle) { + let parent_dropped = Arc::new(AtomicBool::new(false)); + let child_window_dropped = Arc::new(AtomicBool::new(false)); - let handle = HostWindowHandle { - handle_dropped: Arc::clone(&handle_dropped), - window_dropped: Arc::clone(&window_dropped), + let handle = ChildWindowHandle { + parent_dropped: Arc::clone(&parent_dropped), + child_window_dropped: Arc::clone(&child_window_dropped), }; ( - Self { handle_dropped, window_dropped }, + Self { _parent_dropped: parent_dropped, child_window_dropped }, handle ) } - pub fn handle_was_dropped(&self) -> bool { - self.handle_dropped.load(Ordering::Relaxed) + /* + pub fn parent_did_drop(&self) -> bool { + self.parent_dropped.load(Ordering::Relaxed) } + */ } -impl Drop for HostHandle { +impl Drop for ParentHandle { fn drop(&mut self) { - self.window_dropped.store(true, Ordering::Relaxed); + self.child_window_dropped.store(true, Ordering::Relaxed); } } @@ -83,15 +81,13 @@ pub struct Window { /// Only set if we created the parent window, i.e. we are running in /// parentless mode ns_window: Option, - /// Only set if we did not create the parent window - host_handle: Option, /// Our subclassed NSView ns_view: id, close_requested: bool, } impl Window { - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> HostWindowHandle + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> ChildWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -108,17 +104,16 @@ impl Window { let ns_view = unsafe { create_view(&options) }; - let (host_handle, host_window_handle) = HostHandle::new(); + let (parent_handle, child_window_handle) = ParentHandle::new(); let window = Window { ns_app: None, ns_window: None, - host_handle: Some(host_handle), ns_view, close_requested: false, }; - Self::init(window, build); + Self::init(window, build, Some(parent_handle)); unsafe { let _: id = msg_send![handle.ns_view as *mut Object, addSubview: ns_view]; @@ -127,14 +122,10 @@ impl Window { let () = msg_send![pool, drain]; } - unsafe { - let _: () = msg_send![pool, drain]; - } - - host_window_handle + child_window_handle } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, HostWindowHandle) + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, ChildWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -144,26 +135,24 @@ impl Window { let ns_view = unsafe { create_view(&options) }; - let (host_handle, host_window_handle) = HostHandle::new(); - let window = Window { ns_app: None, ns_window: None, - host_handle: Some(host_handle), ns_view, close_requested: false, }; let raw_window_handle = window.raw_window_handle(); - Self::init(window, build); + let (parent_handle, child_window_handle) = ParentHandle::new(); + + Self::init(window, build, Some(parent_handle)); - // Must drain pool before returning so retain counts are correct unsafe { - let _: () = msg_send![pool, drain]; + let () = msg_send![pool, drain]; } - (raw_window_handle, host_window_handle) + (raw_window_handle, child_window_handle) } pub fn open_blocking(options: WindowOpenOptions, build: B) @@ -217,9 +206,6 @@ impl Window { ); ns_window.center(); - // We are already releasing the window with our autorelease pool - let _: () = msg_send![ns_window, setReleasedWhenClosed: NO]; - let title = NSString::alloc(nil) .init_str(&options.title) .autorelease(); @@ -235,16 +221,14 @@ impl Window { let window = Window { ns_app: Some(app), ns_window: Some(ns_window), - host_handle: None, ns_view, close_requested: false, }; - Self::init(window, build); + Self::init(window, build, None); unsafe { ns_window.setContentView_(ns_view); - let () = msg_send![ns_view as id, release]; let () = msg_send![pool, drain]; @@ -255,7 +239,8 @@ impl Window { fn init( mut window: Window, - build: B + build: B, + parent_handle: Option, ) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -273,6 +258,7 @@ impl Window { keyboard_state: KeyboardState::new(), frame_timer: None, retain_count_after_build, + _parent_handle: parent_handle, })); unsafe { @@ -296,6 +282,7 @@ pub(super) struct WindowState { window_handler: Box, keyboard_state: KeyboardState, frame_timer: Option, + _parent_handle: Option, pub retain_count_after_build: usize, } @@ -320,27 +307,33 @@ impl WindowState { pub(super) fn trigger_frame(&mut self) { self.window_handler .on_frame(&mut crate::Window::new(&mut self.window)); - - // Check if the host handle was dropped - if let Some(host_handle) = &self.window.host_handle { - if host_handle.handle_was_dropped() { + + let mut do_close = false; + + /* FIXME: Is it even necessary to check if the parent dropped the handle + // in MacOS? + // Check if the parent handle was dropped + if let Some(parent_handle) = &self.parent_handle { + if parent_handle.parent_did_drop() { + do_close = true; self.window.close_requested = false; - - unsafe { - self.window.ns_view.removeFromSuperview(); - } } } + */ // Check if the user requested the window to close if self.window.close_requested { + do_close = true; self.window.close_requested = false; + } + if do_close { unsafe { - self.window.ns_view.removeFromSuperview(); - if let Some(ns_window) = self.window.ns_window.take() { ns_window.close(); + } else { + // FIXME: How do we close a non-parented window? Is this even + // possible in a DAW host usecase? } } } @@ -396,7 +389,8 @@ impl WindowState { /// Call when freeing view pub(super) unsafe fn stop(&mut self) { if let Some(frame_timer) = self.frame_timer.take() { - CFRunLoop::get_current().remove_timer(&frame_timer, kCFRunLoopDefaultMode); + CFRunLoop::get_current() + .remove_timer(&frame_timer, kCFRunLoopDefaultMode); } self.trigger_event(Event::Window(WindowEvent::WillClose)); @@ -421,4 +415,4 @@ unsafe impl HasRawWindowHandle for Window { ..MacOSHandle::empty() }) } -} +} \ No newline at end of file diff --git a/src/win/window.rs b/src/win/window.rs index 36ff34c9..d80ef364 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -60,19 +60,19 @@ unsafe fn generate_guid() -> String { const WIN_FRAME_TIMER: usize = 4242; -pub struct HostWindowHandle { +pub struct ChildWindowHandle { hwnd: Option, destroy_msg_id: u32, - window_dropped: Arc, + child_window_dropped: Arc, } -impl HostWindowHandle { +impl ChildWindowHandle { pub fn window_was_dropped(&self) -> bool { - self.window_dropped.load(Ordering::Relaxed) + self.child_window_dropped.load(Ordering::Relaxed) } } -impl Drop for HostWindowHandle { +impl Drop for ChildWindowHandle { fn drop(&mut self) { if let Some(hwnd) = self.hwnd { unsafe { @@ -82,30 +82,30 @@ impl Drop for HostWindowHandle { } } -pub struct HostHandle { - window_dropped: Arc, +struct ParentHandle { + child_window_dropped: Arc, } -impl HostHandle { - pub fn new() -> (Self, HostWindowHandle) { - let window_dropped = Arc::new(AtomicBool::new(false)); +impl ParentHandle { + pub fn new() -> (Self, ChildWindowHandle) { + let child_window_dropped = Arc::new(AtomicBool::new(false)); - let handle = HostWindowHandle { + let handle = ChildWindowHandle { hwnd: None, destroy_msg_id: 0, - window_dropped: Arc::clone(&window_dropped), + child_window_dropped: Arc::clone(&child_window_dropped), }; ( - Self { window_dropped }, + Self { child_window_dropped }, handle ) } } -impl Drop for HostHandle { +impl Drop for ParentHandle { fn drop(&mut self) { - self.window_dropped.store(true, Ordering::Relaxed); + self.child_window_dropped.store(true, Ordering::Relaxed); } } @@ -355,7 +355,7 @@ unsafe fn unregister_wnd_class(wnd_class: ATOM) { struct WindowState { window_class: ATOM, window_info: WindowInfo, - host_handle: Option, + parent_handle: Option, keyboard_state: KeyboardState, mouse_button_counter: usize, handler: Box, @@ -370,7 +370,7 @@ pub struct Window { } impl Window { - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> HostWindowHandle + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> ChildWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -382,29 +382,29 @@ impl Window { h => panic!("unsupported parent handle {:?}", h), }; - let (host_handle, mut host_window_handle) = HostHandle::new(); + let (parent_handle, mut child_window_handle) = ParentHandle::new(); - Self::open(true, parent, options, build, Some(host_handle), Some(&mut host_window_handle)); + Self::open(true, parent, options, build, Some(parent_handle), Some(&mut child_window_handle)); - host_window_handle + child_window_handle } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, HostWindowHandle) + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, ChildWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, B: Send + 'static, { - let (host_handle, mut host_window_handle) = HostHandle::new(); + let (parent_handle, mut child_window_handle) = ParentHandle::new(); - let hwnd = Self::open(true, null_mut(), options, build, Some(host_handle), Some(&mut host_window_handle)); + let hwnd = Self::open(true, null_mut(), options, build, Some(parent_handle), Some(&mut child_window_handle)); ( RawWindowHandle::Windows(WindowsHandle { hwnd: hwnd as *mut std::ffi::c_void, ..WindowsHandle::empty() }), - host_window_handle + child_window_handle ) } @@ -437,8 +437,8 @@ impl Window { parent: HWND, options: WindowOpenOptions, build: B, - host_handle: Option, - host_window_handle: Option<&mut HostWindowHandle>, + parent_handle: Option, + child_window_handle: Option<&mut ChildWindowHandle>, ) -> HWND where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -507,7 +507,7 @@ impl Window { let mut window_state = Box::new(RefCell::new(WindowState { window_class, window_info, - host_handle, + parent_handle, keyboard_state: KeyboardState::new(), mouse_button_counter: 0, handler, @@ -569,9 +569,9 @@ impl Window { ); } - if let Some(host_window_handle) = host_window_handle { - host_window_handle.hwnd = Some(hwnd); - host_window_handle.destroy_msg_id = destroy_msg_id; + if let Some(child_window_handle) = child_window_handle { + child_window_handle.hwnd = Some(hwnd); + child_window_handle.destroy_msg_id = destroy_msg_id; } hwnd diff --git a/src/window.rs b/src/window.rs index 849106f9..d6dbb00d 100644 --- a/src/window.rs +++ b/src/window.rs @@ -12,7 +12,7 @@ use crate::win as platform; #[cfg(target_os = "linux")] use crate::x11 as platform; -pub use platform::HostWindowHandle; +pub use platform::ChildWindowHandle; pub trait WindowHandler { fn on_frame(&mut self, window: &mut Window); @@ -33,7 +33,7 @@ impl<'a> Window<'a> { } } - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> HostWindowHandle + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> ChildWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -43,7 +43,7 @@ impl<'a> Window<'a> { platform::Window::open_parented::(parent, options, build) } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, HostWindowHandle) + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, ChildWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut Window) -> H, diff --git a/src/x11/window.rs b/src/x11/window.rs index b530228d..70e845b9 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -31,7 +31,7 @@ pub struct Window { close_requested: bool, new_physical_size: Option, - host_handle: Option, + parent_handle: Option, } // Hack to allow sending a RawWindowHandle between threads. Do not make public @@ -41,57 +41,57 @@ unsafe impl Send for SendableRwh {} type WindowOpenResult = Result; -pub struct HostWindowHandle { - handle_dropped: Arc, - window_dropped: Arc, +pub struct ChildWindowHandle { + parent_dropped: Arc, + child_window_dropped: Arc, } -impl HostWindowHandle { +impl ChildWindowHandle { pub fn window_was_dropped(&self) -> bool { - self.window_dropped.load(Ordering::Relaxed) + self.child_window_dropped.load(Ordering::Relaxed) } } -impl Drop for HostWindowHandle { +impl Drop for ChildWindowHandle { fn drop(&mut self) { - self.handle_dropped.store(true, Ordering::Relaxed); + self.parent_dropped.store(true, Ordering::Relaxed); } } -pub struct HostHandle { - handle_dropped: Arc, - window_dropped: Arc, +struct ParentHandle { + parent_dropped: Arc, + child_window_dropped: Arc, } -impl HostHandle { - pub fn new() -> (Self, HostWindowHandle) { - let handle_dropped = Arc::new(AtomicBool::new(false)); - let window_dropped = Arc::new(AtomicBool::new(false)); +impl ParentHandle { + pub fn new() -> (Self, ChildWindowHandle) { + let parent_dropped = Arc::new(AtomicBool::new(false)); + let child_window_dropped = Arc::new(AtomicBool::new(false)); - let handle = HostWindowHandle { - handle_dropped: Arc::clone(&handle_dropped), - window_dropped: Arc::clone(&window_dropped), + let handle = ChildWindowHandle { + parent_dropped: Arc::clone(&parent_dropped), + child_window_dropped: Arc::clone(&child_window_dropped), }; ( - Self { handle_dropped, window_dropped }, + Self { parent_dropped, child_window_dropped }, handle ) } - pub fn handle_was_dropped(&self) -> bool { - self.handle_dropped.load(Ordering::Relaxed) + pub fn parent_did_drop(&self) -> bool { + self.parent_dropped.load(Ordering::Relaxed) } } -impl Drop for HostHandle { +impl Drop for ParentHandle { fn drop(&mut self) { - self.window_dropped.store(true, Ordering::Relaxed); + self.child_window_dropped.store(true, Ordering::Relaxed); } } impl Window { - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> HostWindowHandle + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> ChildWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -107,18 +107,18 @@ impl Window { let (tx, rx) = mpsc::sync_channel::(1); - let (host_handle, host_window_handle) = HostHandle::new(); + let (parent_handle, child_window_handle) = ParentHandle::new(); let thread = thread::spawn(move || { - Self::window_thread(Some(parent_id), options, build, tx.clone(), Some(host_handle)); + Self::window_thread(Some(parent_id), options, build, tx.clone(), Some(parent_handle)); }); let _ = rx.recv().unwrap().unwrap(); - host_window_handle + child_window_handle } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, HostWindowHandle) + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, ChildWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -126,15 +126,15 @@ impl Window { { let (tx, rx) = mpsc::sync_channel::(1); - let (host_handle, host_window_handle) = HostHandle::new(); + let (parent_handle, child_window_handle) = ParentHandle::new(); let thread = thread::spawn(move || { - Self::window_thread(None, options, build, tx.clone(), Some(host_handle)); + Self::window_thread(None, options, build, tx.clone(), Some(parent_handle)); }); ( rx.recv().unwrap().unwrap().0, - host_window_handle + child_window_handle ) } @@ -159,7 +159,7 @@ impl Window { parent: Option, options: WindowOpenOptions, build: B, tx: mpsc::SyncSender, - host_handle: Option, + parent_handle: Option, ) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -260,7 +260,7 @@ impl Window { close_requested: false, new_physical_size: None, - host_handle, + parent_handle, }; let mut handler = build(&mut crate::Window::new(&mut window)); @@ -372,10 +372,10 @@ impl Window { } } - // Check if the host's handle was dropped (such as when the host + // Check if the parents's handle was dropped (such as when the host // requested the window to close) - if let Some(host_handle) = &self.host_handle { - if host_handle.handle_was_dropped() { + if let Some(parent_handle) = &self.parent_handle { + if parent_handle.parent_did_drop() { self.handle_must_close(handler); self.close_requested = false; } From b920f52bc1260eca6abbabb5c15bd8547313393d Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Wed, 10 Nov 2021 11:55:14 -0600 Subject: [PATCH 3/8] fix rustfmt.toml and run cargo format --- .rustfmt.toml => rustfmt.toml | 0 src/macos/window.rs | 68 ++++++++++++++--------------------- src/win/window.rs | 60 +++++++++++++++++++------------ src/window.rs | 8 +++-- src/x11/window.rs | 43 +++++++++------------- 5 files changed, 87 insertions(+), 92 deletions(-) rename .rustfmt.toml => rustfmt.toml (100%) diff --git a/.rustfmt.toml b/rustfmt.toml similarity index 100% rename from .rustfmt.toml rename to rustfmt.toml diff --git a/src/macos/window.rs b/src/macos/window.rs index 026817e7..0987d5ee 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -1,6 +1,6 @@ +use std::ffi::c_void; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use std::ffi::c_void; use cocoa::appkit::{ NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSBackingStoreBuffered, NSWindow, @@ -53,10 +53,7 @@ impl ParentHandle { child_window_dropped: Arc::clone(&child_window_dropped), }; - ( - Self { _parent_dropped: parent_dropped, child_window_dropped }, - handle - ) + (Self { _parent_dropped: parent_dropped, child_window_dropped }, handle) } /* @@ -85,7 +82,9 @@ pub struct Window { } impl Window { - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> ChildWindowHandle + pub fn open_parented( + parent: &P, options: WindowOpenOptions, build: B, + ) -> ChildWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -104,12 +103,7 @@ impl Window { let (parent_handle, child_window_handle) = ParentHandle::new(); - let window = Window { - ns_app: None, - ns_window: None, - ns_view, - close_requested: false, - }; + let window = Window { ns_app: None, ns_window: None, ns_view, close_requested: false }; Self::init(window, build, Some(parent_handle)); @@ -123,7 +117,9 @@ impl Window { child_window_handle } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, ChildWindowHandle) + pub fn open_as_if_parented( + options: WindowOpenOptions, build: B, + ) -> (RawWindowHandle, ChildWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -133,12 +129,7 @@ impl Window { let ns_view = unsafe { create_view(&options) }; - let window = Window { - ns_app: None, - ns_window: None, - ns_view, - close_requested: false, - }; + let window = Window { ns_app: None, ns_window: None, ns_view, close_requested: false }; let raw_window_handle = window.raw_window_handle(); @@ -188,15 +179,14 @@ impl Window { ); let ns_window = unsafe { - let ns_window = NSWindow::alloc(nil) - .initWithContentRect_styleMask_backing_defer_( - rect, - NSWindowStyleMask::NSTitledWindowMask | - NSWindowStyleMask::NSClosableWindowMask | - NSWindowStyleMask::NSMiniaturizableWindowMask, - NSBackingStoreBuffered, - NO, - ); + let ns_window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_( + rect, + NSWindowStyleMask::NSTitledWindowMask + | NSWindowStyleMask::NSClosableWindowMask + | NSWindowStyleMask::NSMiniaturizableWindowMask, + NSBackingStoreBuffered, + NO, + ); ns_window.center(); let title = NSString::alloc(nil).init_str(&options.title).autorelease(); @@ -228,14 +218,11 @@ impl Window { } } - fn init( - mut window: Window, - build: B, - parent_handle: Option, - ) - where H: WindowHandler + 'static, - B: FnOnce(&mut crate::Window) -> H, - B: Send + 'static, + fn init(mut window: Window, build: B, parent_handle: Option) + where + H: WindowHandler + 'static, + B: FnOnce(&mut crate::Window) -> H, + B: Send + 'static, { let window_handler = Box::new(build(&mut crate::Window::new(&mut window))); @@ -289,9 +276,8 @@ impl WindowState { } pub(super) fn trigger_frame(&mut self) { - self.window_handler - .on_frame(&mut crate::Window::new(&mut self.window)); - + self.window_handler.on_frame(&mut crate::Window::new(&mut self.window)); + let mut do_close = false; /* FIXME: Is it even necessary to check if the parent dropped the handle @@ -304,7 +290,7 @@ impl WindowState { } } */ - + // Check if the user requested the window to close if self.window.close_requested { do_close = true; @@ -379,4 +365,4 @@ unsafe impl HasRawWindowHandle for Window { ..MacOSHandle::empty() }) } -} \ No newline at end of file +} diff --git a/src/win/window.rs b/src/win/window.rs index cc75fc89..ec1967cd 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -17,12 +17,12 @@ use winapi::um::winuser::{ XBUTTON1, XBUTTON2, }; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; use std::cell::RefCell; use std::ffi::{c_void, OsStr}; use std::os::windows::ffi::OsStrExt; use std::ptr::null_mut; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; use raw_window_handle::{windows::WindowsHandle, HasRawWindowHandle, RawWindowHandle}; @@ -90,10 +90,7 @@ impl ParentHandle { child_window_dropped: Arc::clone(&child_window_dropped), }; - ( - Self { child_window_dropped }, - handle - ) + (Self { child_window_dropped }, handle) } } @@ -359,7 +356,9 @@ pub struct Window { } impl Window { - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> ChildWindowHandle + pub fn open_parented( + parent: &P, options: WindowOpenOptions, build: B, + ) -> ChildWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -373,12 +372,21 @@ impl Window { let (parent_handle, mut child_window_handle) = ParentHandle::new(); - Self::open(true, parent, options, build, Some(parent_handle), Some(&mut child_window_handle)); + Self::open( + true, + parent, + options, + build, + Some(parent_handle), + Some(&mut child_window_handle), + ); child_window_handle } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, ChildWindowHandle) + pub fn open_as_if_parented( + options: WindowOpenOptions, build: B, + ) -> (RawWindowHandle, ChildWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -386,14 +394,21 @@ impl Window { { let (parent_handle, mut child_window_handle) = ParentHandle::new(); - let hwnd = Self::open(true, null_mut(), options, build, Some(parent_handle), Some(&mut child_window_handle)); + let hwnd = Self::open( + true, + null_mut(), + options, + build, + Some(parent_handle), + Some(&mut child_window_handle), + ); ( RawWindowHandle::Windows(WindowsHandle { hwnd: hwnd as *mut std::ffi::c_void, ..WindowsHandle::empty() }), - child_window_handle + child_window_handle, ) } @@ -422,16 +437,13 @@ impl Window { } fn open( - parented: bool, - parent: HWND, - options: WindowOpenOptions, - build: B, - parent_handle: Option, - child_window_handle: Option<&mut ChildWindowHandle>, + parented: bool, parent: HWND, options: WindowOpenOptions, build: B, + parent_handle: Option, child_window_handle: Option<&mut ChildWindowHandle>, ) -> HWND - where H: WindowHandler + 'static, - B: FnOnce(&mut crate::Window) -> H, - B: Send + 'static, + where + H: WindowHandler + 'static, + B: FnOnce(&mut crate::Window) -> H, + B: Send + 'static, { unsafe { let mut title: Vec = OsStr::new(&options.title[..]).encode_wide().collect(); @@ -486,10 +498,12 @@ impl Window { null_mut(), ); // todo: manage error ^ - - let destroy_msg_id = RegisterWindowMessageA("Baseview::DestroyMsg\0".as_ptr() as LPCSTR); - let handler = Box::new(build(&mut crate::Window::new(&mut Window { hwnd, destroy_msg_id }))); + let destroy_msg_id = + RegisterWindowMessageA("Baseview::DestroyMsg\0".as_ptr() as LPCSTR); + + let handler = + Box::new(build(&mut crate::Window::new(&mut Window { hwnd, destroy_msg_id }))); let mut window_state = Box::new(RefCell::new(WindowState { window_class, diff --git a/src/window.rs b/src/window.rs index aa678056..6e0d186d 100644 --- a/src/window.rs +++ b/src/window.rs @@ -30,7 +30,9 @@ impl<'a> Window<'a> { Window { window, phantom: PhantomData } } - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> ChildWindowHandle + pub fn open_parented( + parent: &P, options: WindowOpenOptions, build: B, + ) -> ChildWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -40,7 +42,9 @@ impl<'a> Window<'a> { platform::Window::open_parented::(parent, options, build) } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, ChildWindowHandle) + pub fn open_as_if_parented( + options: WindowOpenOptions, build: B, + ) -> (RawWindowHandle, ChildWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut Window) -> H, diff --git a/src/x11/window.rs b/src/x11/window.rs index 447b9c00..f5746c7d 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -1,7 +1,7 @@ -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; use std::os::raw::{c_ulong, c_void}; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc; +use std::sync::Arc; use std::thread; use std::time::*; @@ -68,10 +68,7 @@ impl ParentHandle { child_window_dropped: Arc::clone(&child_window_dropped), }; - ( - Self { parent_dropped, child_window_dropped }, - handle - ) + (Self { parent_dropped, child_window_dropped }, handle) } pub fn parent_did_drop(&self) -> bool { @@ -86,7 +83,9 @@ impl Drop for ParentHandle { } impl Window { - pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> ChildWindowHandle + pub fn open_parented( + parent: &P, options: WindowOpenOptions, build: B, + ) -> ChildWindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -113,7 +112,9 @@ impl Window { child_window_handle } - pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> (RawWindowHandle, ChildWindowHandle) + pub fn open_as_if_parented( + options: WindowOpenOptions, build: B, + ) -> (RawWindowHandle, ChildWindowHandle) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -127,10 +128,7 @@ impl Window { Self::window_thread(None, options, build, tx.clone(), Some(parent_handle)); }); - ( - rx.recv().unwrap().unwrap().0, - child_window_handle - ) + (rx.recv().unwrap().unwrap().0, child_window_handle) } pub fn open_blocking(options: WindowOpenOptions, build: B) @@ -152,12 +150,11 @@ impl Window { fn window_thread( parent: Option, options: WindowOpenOptions, build: B, - tx: mpsc::SyncSender, - parent_handle: Option, - ) - where H: WindowHandler + 'static, - B: FnOnce(&mut crate::Window) -> H, - B: Send + 'static, + tx: mpsc::SyncSender, parent_handle: Option, + ) where + H: WindowHandler + 'static, + B: FnOnce(&mut crate::Window) -> H, + B: Send + 'static, { // Connect to the X server // FIXME: baseview error type instead of unwrap() @@ -375,20 +372,14 @@ impl Window { } fn handle_close_requested(&mut self, handler: &mut dyn WindowHandler) { - handler.on_event( - &mut crate::Window::new(self), - Event::Window(WindowEvent::WillClose) - ); + handler.on_event(&mut crate::Window::new(self), Event::Window(WindowEvent::WillClose)); // FIXME: handler should decide whether window stays open or not self.event_loop_running = false; } fn handle_must_close(&mut self, handler: &mut dyn WindowHandler) { - handler.on_event( - &mut crate::Window::new(self), - Event::Window(WindowEvent::WillClose) - ); + handler.on_event(&mut crate::Window::new(self), Event::Window(WindowEvent::WillClose)); self.event_loop_running = false; } From a9dac8349a1174a6aff122c29e1543b6f9ed63d8 Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Wed, 10 Nov 2021 12:01:28 -0600 Subject: [PATCH 4/8] fix merge conflict mistake --- src/win/window.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/win/window.rs b/src/win/window.rs index ec1967cd..b115826a 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -6,15 +6,15 @@ use winapi::um::winnt::LPCSTR; use winapi::um::winuser::{ AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, GetCapture, GetDpiForWindow, GetMessageW, GetWindowLongPtrW, IsWindow, LoadCursorW, - PostMessageW, RegisterClassW, ReleaseCapture, SetCapture, SetProcessDpiAwarenessContext, - SetTimer, SetWindowLongPtrW, SetWindowPos, TranslateMessage, UnregisterClassW, CS_OWNDC, - GET_XBUTTON_WPARAM, GWLP_USERDATA, IDC_ARROW, MSG, SWP_NOMOVE, SWP_NOZORDER, WHEEL_DELTA, - WM_CHAR, WM_CLOSE, WM_CREATE, WM_DPICHANGED, WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, - WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEMOVE, WM_MOUSEWHEEL, - WM_NCDESTROY, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, WM_SYSKEYDOWN, - WM_SYSKEYUP, WM_TIMER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD, - WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, - XBUTTON1, XBUTTON2, + PostMessageW, RegisterClassW, RegisterWindowMessageA, ReleaseCapture, SetCapture, + SetProcessDpiAwarenessContext, SetTimer, SetWindowLongPtrW, SetWindowPos, TranslateMessage, + UnregisterClassW, CS_OWNDC, GET_XBUTTON_WPARAM, GWLP_USERDATA, IDC_ARROW, MSG, SWP_NOMOVE, + SWP_NOZORDER, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE, WM_DPICHANGED, WM_INPUTLANGCHANGE, + WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEMOVE, + WM_MOUSEWHEEL, WM_NCDESTROY, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, + WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TIMER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, + WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, + WS_VISIBLE, XBUTTON1, XBUTTON2, }; use std::cell::RefCell; From 7f721ebff127f7499127c992eea7b2d704449368 Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Wed, 10 Nov 2021 12:06:34 -0600 Subject: [PATCH 5/8] fix more merge conflict mistakes --- rustfmt.toml => .rustfmt.toml | 0 src/macos/window.rs | 6 +++++- 2 files changed, 5 insertions(+), 1 deletion(-) rename rustfmt.toml => .rustfmt.toml (100%) diff --git a/rustfmt.toml b/.rustfmt.toml similarity index 100% rename from rustfmt.toml rename to .rustfmt.toml diff --git a/src/macos/window.rs b/src/macos/window.rs index 0987d5ee..55149f68 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -17,9 +17,13 @@ use objc::{msg_send, runtime::Object, sel, sel_impl}; use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle}; -use crate::{Event, EventStatus, WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy}; +use crate::{ + Event, EventStatus, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, + WindowScalePolicy, +}; use super::keyboard::KeyboardState; +use super::view::{create_view, BASEVIEW_STATE_IVAR}; pub struct ChildWindowHandle { parent_dropped: Arc, From 99ee8782d1a4377b4efe4c8da4e970f111c4a790 Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Fri, 12 Nov 2021 16:06:33 -0600 Subject: [PATCH 6/8] implement requested changes (with a non-broken commit this time) --- src/macos/window.rs | 92 +++++++++++++++----------- src/win/window.rs | 156 ++++++++++++++++++-------------------------- src/window.rs | 14 ++-- src/x11/window.rs | 123 +++++++++++++++++++--------------- 4 files changed, 193 insertions(+), 192 deletions(-) diff --git a/src/macos/window.rs b/src/macos/window.rs index 55149f68..f33f9e76 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -1,4 +1,5 @@ use std::ffi::c_void; +use std::marker::PhantomData; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -25,51 +26,69 @@ use crate::{ use super::keyboard::KeyboardState; use super::view::{create_view, BASEVIEW_STATE_IVAR}; -pub struct ChildWindowHandle { - parent_dropped: Arc, - child_window_dropped: Arc, +pub struct WindowHandle { + raw_window_handle: Option, + close_requested: Arc, + window_dropped: Arc, + + // Ensure handle is !Send + _phantom: PhantomData<*mut ()>, } -impl ChildWindowHandle { +impl WindowHandle { + pub fn close(&mut self) { + if let Some(_) = self.raw_window_handle.take() { + self.close_requested.store(true, Ordering::Relaxed); + } + } + pub fn window_was_dropped(&self) -> bool { - self.child_window_dropped.load(Ordering::Relaxed) + self.window_dropped.load(Ordering::Relaxed) } } -impl Drop for ChildWindowHandle { - fn drop(&mut self) { - self.parent_dropped.store(true, Ordering::Relaxed); +unsafe impl HasRawWindowHandle for WindowHandle { + fn raw_window_handle(&self) -> RawWindowHandle { + if let Some(raw_window_handle) = self.raw_window_handle { + if !self.window_dropped.load(Ordering::Relaxed) { + return raw_window_handle; + } + } + + RawWindowHandle::MacOS(MacOSHandle { ..MacOSHandle::empty() }) } } struct ParentHandle { - _parent_dropped: Arc, - child_window_dropped: Arc, + _close_requested: Arc, + window_dropped: Arc, } impl ParentHandle { - pub fn new() -> (Self, ChildWindowHandle) { - let parent_dropped = Arc::new(AtomicBool::new(false)); - let child_window_dropped = Arc::new(AtomicBool::new(false)); - - let handle = ChildWindowHandle { - parent_dropped: Arc::clone(&parent_dropped), - child_window_dropped: Arc::clone(&child_window_dropped), + pub fn new(raw_window_handle: RawWindowHandle) -> (Self, WindowHandle) { + let close_requested = Arc::new(AtomicBool::new(false)); + let window_dropped = Arc::new(AtomicBool::new(false)); + + let handle = WindowHandle { + raw_window_handle: Some(raw_window_handle), + close_requested: Arc::clone(&close_requested), + window_dropped: Arc::clone(&window_dropped), + _phantom: PhantomData::default(), }; - (Self { _parent_dropped: parent_dropped, child_window_dropped }, handle) + (Self { _close_requested: close_requested, window_dropped }, handle) } /* pub fn parent_did_drop(&self) -> bool { - self.parent_dropped.load(Ordering::Relaxed) + self.close_requested.load(Ordering::Relaxed) } */ } impl Drop for ParentHandle { fn drop(&mut self) { - self.child_window_dropped.store(true, Ordering::Relaxed); + self.window_dropped.store(true, Ordering::Relaxed); } } @@ -86,9 +105,7 @@ pub struct Window { } impl Window { - pub fn open_parented( - parent: &P, options: WindowOpenOptions, build: B, - ) -> ChildWindowHandle + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> WindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -105,11 +122,9 @@ impl Window { let ns_view = unsafe { create_view(&options) }; - let (parent_handle, child_window_handle) = ParentHandle::new(); - let window = Window { ns_app: None, ns_window: None, ns_view, close_requested: false }; - Self::init(window, build, Some(parent_handle)); + let window_handle = Self::init(true, window, build); unsafe { let _: id = msg_send![handle.ns_view as *mut Object, addSubview: ns_view]; @@ -118,12 +133,10 @@ impl Window { let () = msg_send![pool, drain]; } - child_window_handle + window_handle } - pub fn open_as_if_parented( - options: WindowOpenOptions, build: B, - ) -> (RawWindowHandle, ChildWindowHandle) + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> WindowHandle where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -135,17 +148,13 @@ impl Window { let window = Window { ns_app: None, ns_window: None, ns_view, close_requested: false }; - let raw_window_handle = window.raw_window_handle(); - - let (parent_handle, child_window_handle) = ParentHandle::new(); - - Self::init(window, build, Some(parent_handle)); + let window_handle = Self::init(true, window, build); unsafe { let () = msg_send![pool, drain]; } - (raw_window_handle, child_window_handle) + window_handle } pub fn open_blocking(options: WindowOpenOptions, build: B) @@ -210,7 +219,7 @@ impl Window { close_requested: false, }; - Self::init(window, build, None); + let _ = Self::init(false, window, build); unsafe { ns_window.setContentView_(ns_view); @@ -222,7 +231,7 @@ impl Window { } } - fn init(mut window: Window, build: B, parent_handle: Option) + fn init(parented: bool, mut window: Window, build: B) -> WindowHandle where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -230,6 +239,9 @@ impl Window { { let window_handler = Box::new(build(&mut crate::Window::new(&mut window))); + let (parent_handle, window_handle) = ParentHandle::new(window.raw_window_handle()); + let parent_handle = if parented { Some(parent_handle) } else { None }; + let retain_count_after_build: usize = unsafe { msg_send![window.ns_view, retainCount] }; let window_state_ptr = Box::into_raw(Box::new(WindowState { @@ -247,9 +259,11 @@ impl Window { WindowState::setup_timer(window_state_ptr); } + + window_handle } - pub fn request_close(&mut self) { + pub fn close(&mut self) { self.close_requested = true; } } diff --git a/src/win/window.rs b/src/win/window.rs index b115826a..f57df960 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -2,23 +2,22 @@ use winapi::shared::guiddef::GUID; use winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM}; use winapi::shared::windef::{HWND, RECT}; use winapi::um::combaseapi::CoCreateGuid; -use winapi::um::winnt::LPCSTR; use winapi::um::winuser::{ AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, - GetCapture, GetDpiForWindow, GetMessageW, GetWindowLongPtrW, IsWindow, LoadCursorW, - PostMessageW, RegisterClassW, RegisterWindowMessageA, ReleaseCapture, SetCapture, - SetProcessDpiAwarenessContext, SetTimer, SetWindowLongPtrW, SetWindowPos, TranslateMessage, - UnregisterClassW, CS_OWNDC, GET_XBUTTON_WPARAM, GWLP_USERDATA, IDC_ARROW, MSG, SWP_NOMOVE, - SWP_NOZORDER, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE, WM_DPICHANGED, WM_INPUTLANGCHANGE, - WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEMOVE, - WM_MOUSEWHEEL, WM_NCDESTROY, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, - WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TIMER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, - WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, - WS_VISIBLE, XBUTTON1, XBUTTON2, + GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW, + ReleaseCapture, SetCapture, SetProcessDpiAwarenessContext, SetTimer, SetWindowLongPtrW, + SetWindowPos, TranslateMessage, UnregisterClassW, CS_OWNDC, GET_XBUTTON_WPARAM, GWLP_USERDATA, + IDC_ARROW, MSG, SWP_NOMOVE, SWP_NOZORDER, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE, + WM_DPICHANGED, WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, + WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_NCDESTROY, WM_RBUTTONDOWN, + WM_RBUTTONUP, WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TIMER, + WM_USER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, + WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, XBUTTON1, XBUTTON2, }; use std::cell::RefCell; -use std::ffi::{c_void, OsStr}; +use std::ffi::OsStr; +use std::marker::PhantomData; use std::os::windows::ffi::OsStrExt; use std::ptr::null_mut; use std::sync::atomic::{AtomicBool, Ordering}; @@ -26,6 +25,8 @@ use std::sync::Arc; use raw_window_handle::{windows::WindowsHandle, HasRawWindowHandle, RawWindowHandle}; +const BV_WINDOW_MUST_CLOSE: UINT = WM_USER + 1; + use crate::{ Event, MouseButton, MouseEvent, PhyPoint, PhySize, ScrollDelta, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy, @@ -54,49 +55,62 @@ unsafe fn generate_guid() -> String { const WIN_FRAME_TIMER: usize = 4242; -pub struct ChildWindowHandle { +pub struct WindowHandle { hwnd: Option, - destroy_msg_id: u32, - child_window_dropped: Arc, + window_dropped: Arc, + + // Ensure handle is !Send + _phantom: PhantomData<*mut ()>, } -impl ChildWindowHandle { +impl WindowHandle { + pub fn close(&mut self) { + if let Some(hwnd) = self.hwnd.take() { + unsafe { + PostMessageW(hwnd, BV_WINDOW_MUST_CLOSE, 0, 0); + } + } + } + pub fn window_was_dropped(&self) -> bool { - self.child_window_dropped.load(Ordering::Relaxed) + self.window_dropped.load(Ordering::Relaxed) } } -impl Drop for ChildWindowHandle { - fn drop(&mut self) { +unsafe impl HasRawWindowHandle for WindowHandle { + fn raw_window_handle(&self) -> RawWindowHandle { if let Some(hwnd) = self.hwnd { - unsafe { - PostMessageW(hwnd, self.destroy_msg_id, 0, 0); - } + RawWindowHandle::Windows(WindowsHandle { + hwnd: hwnd as *mut std::ffi::c_void, + ..WindowsHandle::empty() + }) + } else { + RawWindowHandle::Windows(WindowsHandle { ..WindowsHandle::empty() }) } } } struct ParentHandle { - child_window_dropped: Arc, + window_dropped: Arc, } impl ParentHandle { - pub fn new() -> (Self, ChildWindowHandle) { - let child_window_dropped = Arc::new(AtomicBool::new(false)); + pub fn new(hwnd: HWND) -> (Self, WindowHandle) { + let window_dropped = Arc::new(AtomicBool::new(false)); - let handle = ChildWindowHandle { - hwnd: None, - destroy_msg_id: 0, - child_window_dropped: Arc::clone(&child_window_dropped), + let handle = WindowHandle { + hwnd: Some(hwnd), + window_dropped: Arc::clone(&window_dropped), + _phantom: PhantomData::default(), }; - (Self { child_window_dropped }, handle) + (Self { window_dropped }, handle) } } impl Drop for ParentHandle { fn drop(&mut self) { - self.child_window_dropped.store(true, Ordering::Relaxed); + self.window_dropped.store(true, Ordering::Relaxed); } } @@ -110,8 +124,7 @@ unsafe extern "system" fn wnd_proc( let window_state_ptr = GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut RefCell; if !window_state_ptr.is_null() { - let destroy_msg_id = (&*window_state_ptr).borrow().destroy_msg_id; - let mut window = Window { hwnd, destroy_msg_id }; + let mut window = Window { hwnd }; let mut window = crate::Window::new(&mut window); match msg { @@ -298,10 +311,7 @@ unsafe extern "system" fn wnd_proc( SetWindowLongPtrW(hwnd, GWLP_USERDATA, 0); } _ => { - if msg == destroy_msg_id { - // FIXME: handler should decide whether window stays open or not - // (except if the message came from the host handle being dropped, - // in which case the window should always be closed) + if msg == BV_WINDOW_MUST_CLOSE { DestroyWindow(hwnd); return 0; } @@ -341,24 +351,20 @@ unsafe fn unregister_wnd_class(wnd_class: ATOM) { struct WindowState { window_class: ATOM, window_info: WindowInfo, - parent_handle: Option, + _parent_handle: Option, keyboard_state: KeyboardState, mouse_button_counter: usize, handler: Box, scale_policy: WindowScalePolicy, dw_style: u32, - destroy_msg_id: u32, } pub struct Window { hwnd: HWND, - destroy_msg_id: u32, } impl Window { - pub fn open_parented( - parent: &P, options: WindowOpenOptions, build: B, - ) -> ChildWindowHandle + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> WindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -370,46 +376,20 @@ impl Window { h => panic!("unsupported parent handle {:?}", h), }; - let (parent_handle, mut child_window_handle) = ParentHandle::new(); + let (window_handle, _) = Self::open(true, parent, options, build); - Self::open( - true, - parent, - options, - build, - Some(parent_handle), - Some(&mut child_window_handle), - ); - - child_window_handle + window_handle } - pub fn open_as_if_parented( - options: WindowOpenOptions, build: B, - ) -> (RawWindowHandle, ChildWindowHandle) + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> WindowHandle where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, B: Send + 'static, { - let (parent_handle, mut child_window_handle) = ParentHandle::new(); - - let hwnd = Self::open( - true, - null_mut(), - options, - build, - Some(parent_handle), - Some(&mut child_window_handle), - ); - - ( - RawWindowHandle::Windows(WindowsHandle { - hwnd: hwnd as *mut std::ffi::c_void, - ..WindowsHandle::empty() - }), - child_window_handle, - ) + let (window_handle, _) = Self::open(true, null_mut(), options, build); + + window_handle } pub fn open_blocking(options: WindowOpenOptions, build: B) @@ -418,7 +398,7 @@ impl Window { B: FnOnce(&mut crate::Window) -> H, B: Send + 'static, { - let hwnd = Self::open(false, null_mut(), options, build, None, None); + let (_, hwnd) = Self::open(false, null_mut(), options, build); unsafe { let mut msg: MSG = std::mem::zeroed(); @@ -438,8 +418,7 @@ impl Window { fn open( parented: bool, parent: HWND, options: WindowOpenOptions, build: B, - parent_handle: Option, child_window_handle: Option<&mut ChildWindowHandle>, - ) -> HWND + ) -> (WindowHandle, HWND) where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -499,22 +478,20 @@ impl Window { ); // todo: manage error ^ - let destroy_msg_id = - RegisterWindowMessageA("Baseview::DestroyMsg\0".as_ptr() as LPCSTR); + let handler = Box::new(build(&mut crate::Window::new(&mut Window { hwnd }))); - let handler = - Box::new(build(&mut crate::Window::new(&mut Window { hwnd, destroy_msg_id }))); + let (parent_handle, window_handle) = ParentHandle::new(hwnd); + let parent_handle = if parented { Some(parent_handle) } else { None }; let mut window_state = Box::new(RefCell::new(WindowState { window_class, window_info, - parent_handle, + _parent_handle: parent_handle, keyboard_state: KeyboardState::new(), mouse_button_counter: 0, handler, scale_policy: options.scale, dw_style: flags, - destroy_msg_id, })); // Only works on Windows 10 unfortunately. @@ -570,18 +547,13 @@ impl Window { ); } - if let Some(child_window_handle) = child_window_handle { - child_window_handle.hwnd = Some(hwnd); - child_window_handle.destroy_msg_id = destroy_msg_id; - } - - hwnd + (window_handle, hwnd) } } - pub fn request_close(&mut self) { + pub fn close(&mut self) { unsafe { - PostMessageW(self.hwnd, self.destroy_msg_id, 0, 0); + PostMessageW(self.hwnd, BV_WINDOW_MUST_CLOSE, 0, 0); } } } diff --git a/src/window.rs b/src/window.rs index 6e0d186d..099f0710 100644 --- a/src/window.rs +++ b/src/window.rs @@ -12,7 +12,7 @@ use crate::win as platform; #[cfg(target_os = "linux")] use crate::x11 as platform; -pub use platform::ChildWindowHandle; +pub use platform::WindowHandle; pub trait WindowHandler { fn on_frame(&mut self, window: &mut Window); @@ -30,9 +30,7 @@ impl<'a> Window<'a> { Window { window, phantom: PhantomData } } - pub fn open_parented( - parent: &P, options: WindowOpenOptions, build: B, - ) -> ChildWindowHandle + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> WindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -42,9 +40,7 @@ impl<'a> Window<'a> { platform::Window::open_parented::(parent, options, build) } - pub fn open_as_if_parented( - options: WindowOpenOptions, build: B, - ) -> (RawWindowHandle, ChildWindowHandle) + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> WindowHandle where H: WindowHandler + 'static, B: FnOnce(&mut Window) -> H, @@ -62,8 +58,8 @@ impl<'a> Window<'a> { platform::Window::open_blocking::(options, build) } - pub fn request_close(&mut self) { - self.window.request_close(); + pub fn close(&mut self) { + self.window.close(); } } diff --git a/src/x11/window.rs b/src/x11/window.rs index f5746c7d..f9787cee 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -1,3 +1,4 @@ +use std::marker::PhantomData; use std::os::raw::{c_ulong, c_void}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc; @@ -15,77 +16,93 @@ use crate::{ use super::keyboard::{convert_key_press_event, convert_key_release_event}; -pub struct Window { - xcb_connection: XcbConnection, - window_id: u32, - window_info: WindowInfo, - mouse_cursor: MouseCursor, +pub struct WindowHandle { + raw_window_handle: Option, + close_requested: Arc, + window_dropped: Arc, - frame_interval: Duration, - event_loop_running: bool, - close_requested: bool, - - new_physical_size: Option, - parent_handle: Option, + // Ensure handle is !Send + _phantom: PhantomData<*mut ()>, } -// Hack to allow sending a RawWindowHandle between threads. Do not make public -struct SendableRwh(RawWindowHandle); - -unsafe impl Send for SendableRwh {} - -type WindowOpenResult = Result; - -pub struct ChildWindowHandle { - parent_dropped: Arc, - child_window_dropped: Arc, -} +impl WindowHandle { + pub fn close(&mut self) { + if let Some(_) = self.raw_window_handle.take() { + self.close_requested.store(true, Ordering::Relaxed); + } + } -impl ChildWindowHandle { pub fn window_was_dropped(&self) -> bool { - self.child_window_dropped.load(Ordering::Relaxed) + self.window_dropped.load(Ordering::Relaxed) } } -impl Drop for ChildWindowHandle { - fn drop(&mut self) { - self.parent_dropped.store(true, Ordering::Relaxed); +unsafe impl HasRawWindowHandle for WindowHandle { + fn raw_window_handle(&self) -> RawWindowHandle { + if let Some(raw_window_handle) = self.raw_window_handle { + if !self.window_dropped.load(Ordering::Relaxed) { + return raw_window_handle; + } + } + + RawWindowHandle::Xlib(XlibHandle { ..raw_window_handle::unix::XlibHandle::empty() }) } } struct ParentHandle { - parent_dropped: Arc, - child_window_dropped: Arc, + close_requested: Arc, + window_dropped: Arc, } impl ParentHandle { - pub fn new() -> (Self, ChildWindowHandle) { - let parent_dropped = Arc::new(AtomicBool::new(false)); - let child_window_dropped = Arc::new(AtomicBool::new(false)); - - let handle = ChildWindowHandle { - parent_dropped: Arc::clone(&parent_dropped), - child_window_dropped: Arc::clone(&child_window_dropped), + pub fn new() -> (Self, WindowHandle) { + let close_requested = Arc::new(AtomicBool::new(false)); + let window_dropped = Arc::new(AtomicBool::new(false)); + + let handle = WindowHandle { + raw_window_handle: None, + close_requested: Arc::clone(&close_requested), + window_dropped: Arc::clone(&window_dropped), + _phantom: PhantomData::default(), }; - (Self { parent_dropped, child_window_dropped }, handle) + (Self { close_requested, window_dropped }, handle) } pub fn parent_did_drop(&self) -> bool { - self.parent_dropped.load(Ordering::Relaxed) + self.close_requested.load(Ordering::Relaxed) } } impl Drop for ParentHandle { fn drop(&mut self) { - self.child_window_dropped.store(true, Ordering::Relaxed); + self.window_dropped.store(true, Ordering::Relaxed); } } +pub struct Window { + xcb_connection: XcbConnection, + window_id: u32, + window_info: WindowInfo, + mouse_cursor: MouseCursor, + + frame_interval: Duration, + event_loop_running: bool, + close_requested: bool, + + new_physical_size: Option, + parent_handle: Option, +} + +// Hack to allow sending a RawWindowHandle between threads. Do not make public +struct SendableRwh(RawWindowHandle); + +unsafe impl Send for SendableRwh {} + +type WindowOpenResult = Result; + impl Window { - pub fn open_parented( - parent: &P, options: WindowOpenOptions, build: B, - ) -> ChildWindowHandle + pub fn open_parented(parent: &P, options: WindowOpenOptions, build: B) -> WindowHandle where P: HasRawWindowHandle, H: WindowHandler + 'static, @@ -101,20 +118,19 @@ impl Window { let (tx, rx) = mpsc::sync_channel::(1); - let (parent_handle, child_window_handle) = ParentHandle::new(); + let (parent_handle, mut window_handle) = ParentHandle::new(); let thread = thread::spawn(move || { Self::window_thread(Some(parent_id), options, build, tx.clone(), Some(parent_handle)); }); - let _ = rx.recv().unwrap().unwrap(); + let raw_window_handle = rx.recv().unwrap().unwrap(); + window_handle.raw_window_handle = Some(raw_window_handle.0); - child_window_handle + window_handle } - pub fn open_as_if_parented( - options: WindowOpenOptions, build: B, - ) -> (RawWindowHandle, ChildWindowHandle) + pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> WindowHandle where H: WindowHandler + 'static, B: FnOnce(&mut crate::Window) -> H, @@ -122,13 +138,16 @@ impl Window { { let (tx, rx) = mpsc::sync_channel::(1); - let (parent_handle, child_window_handle) = ParentHandle::new(); + let (parent_handle, mut window_handle) = ParentHandle::new(); let thread = thread::spawn(move || { Self::window_thread(None, options, build, tx.clone(), Some(parent_handle)); }); - (rx.recv().unwrap().unwrap().0, child_window_handle) + let raw_window_handle = rx.recv().unwrap().unwrap(); + window_handle.raw_window_handle = Some(raw_window_handle.0); + + window_handle } pub fn open_blocking(options: WindowOpenOptions, build: B) @@ -282,7 +301,7 @@ impl Window { self.mouse_cursor = mouse_cursor; } - pub fn request_close(&mut self) { + pub fn close(&mut self) { self.close_requested = true; } @@ -365,7 +384,7 @@ impl Window { // Check if the user has requested the window to close if self.close_requested { - self.handle_close_requested(handler); + self.handle_must_close(handler); self.close_requested = false; } } From d6cdf5d07c7396283513d43b68476df62abd6ef8 Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Mon, 15 Nov 2021 09:46:32 -0600 Subject: [PATCH 7/8] implement requested changes --- src/macos/window.rs | 18 +++++++++--------- src/win/window.rs | 16 ++++++++-------- src/window.rs | 36 +++++++++++++++++++++++++++++++++--- src/x11/window.rs | 26 +++++++++++++++++--------- 4 files changed, 67 insertions(+), 29 deletions(-) diff --git a/src/macos/window.rs b/src/macos/window.rs index f33f9e76..b8ee46ce 100644 --- a/src/macos/window.rs +++ b/src/macos/window.rs @@ -29,7 +29,7 @@ use super::view::{create_view, BASEVIEW_STATE_IVAR}; pub struct WindowHandle { raw_window_handle: Option, close_requested: Arc, - window_dropped: Arc, + is_open: Arc, // Ensure handle is !Send _phantom: PhantomData<*mut ()>, @@ -42,15 +42,15 @@ impl WindowHandle { } } - pub fn window_was_dropped(&self) -> bool { - self.window_dropped.load(Ordering::Relaxed) + pub fn is_open(&self) -> bool { + self.is_open.load(Ordering::Relaxed) } } unsafe impl HasRawWindowHandle for WindowHandle { fn raw_window_handle(&self) -> RawWindowHandle { if let Some(raw_window_handle) = self.raw_window_handle { - if !self.window_dropped.load(Ordering::Relaxed) { + if self.is_open.load(Ordering::Relaxed) { return raw_window_handle; } } @@ -61,22 +61,22 @@ unsafe impl HasRawWindowHandle for WindowHandle { struct ParentHandle { _close_requested: Arc, - window_dropped: Arc, + is_open: Arc, } impl ParentHandle { pub fn new(raw_window_handle: RawWindowHandle) -> (Self, WindowHandle) { let close_requested = Arc::new(AtomicBool::new(false)); - let window_dropped = Arc::new(AtomicBool::new(false)); + let is_open = Arc::new(AtomicBool::new(true)); let handle = WindowHandle { raw_window_handle: Some(raw_window_handle), close_requested: Arc::clone(&close_requested), - window_dropped: Arc::clone(&window_dropped), + is_open: Arc::clone(&is_open), _phantom: PhantomData::default(), }; - (Self { _close_requested: close_requested, window_dropped }, handle) + (Self { _close_requested: close_requested, is_open }, handle) } /* @@ -88,7 +88,7 @@ impl ParentHandle { impl Drop for ParentHandle { fn drop(&mut self) { - self.window_dropped.store(true, Ordering::Relaxed); + self.is_open.store(false, Ordering::Relaxed); } } diff --git a/src/win/window.rs b/src/win/window.rs index f57df960..f91ac17a 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -57,7 +57,7 @@ const WIN_FRAME_TIMER: usize = 4242; pub struct WindowHandle { hwnd: Option, - window_dropped: Arc, + is_open: Arc, // Ensure handle is !Send _phantom: PhantomData<*mut ()>, @@ -72,8 +72,8 @@ impl WindowHandle { } } - pub fn window_was_dropped(&self) -> bool { - self.window_dropped.load(Ordering::Relaxed) + pub fn is_open(&self) -> bool { + self.is_open.load(Ordering::Relaxed) } } @@ -91,26 +91,26 @@ unsafe impl HasRawWindowHandle for WindowHandle { } struct ParentHandle { - window_dropped: Arc, + is_open: Arc, } impl ParentHandle { pub fn new(hwnd: HWND) -> (Self, WindowHandle) { - let window_dropped = Arc::new(AtomicBool::new(false)); + let is_open = Arc::new(AtomicBool::new(true)); let handle = WindowHandle { hwnd: Some(hwnd), - window_dropped: Arc::clone(&window_dropped), + is_open: Arc::clone(&is_open), _phantom: PhantomData::default(), }; - (Self { window_dropped }, handle) + (Self { is_open }, handle) } } impl Drop for ParentHandle { fn drop(&mut self) { - self.window_dropped.store(true, Ordering::Relaxed); + self.is_open.store(false, Ordering::Relaxed); } } diff --git a/src/window.rs b/src/window.rs index 099f0710..5a042e6f 100644 --- a/src/window.rs +++ b/src/window.rs @@ -12,13 +12,40 @@ use crate::win as platform; #[cfg(target_os = "linux")] use crate::x11 as platform; -pub use platform::WindowHandle; +pub struct WindowHandle { + window_handle: platform::WindowHandle, + // so that WindowHandle is !Send on all platforms + phantom: PhantomData<*mut ()>, +} + +impl WindowHandle { + fn new(window_handle: platform::WindowHandle) -> Self { + Self { window_handle, phantom: PhantomData::default() } + } + + /// Close the window + pub fn close(&mut self) { + self.window_handle.close(); + } + + /// Returns `true` if the window is still open, and returns `false` + /// if the window was closed/dropped. + pub fn is_open(&self) -> bool { + self.window_handle.is_open() + } +} pub trait WindowHandler { fn on_frame(&mut self, window: &mut Window); fn on_event(&mut self, window: &mut Window, event: Event) -> EventStatus; } +unsafe impl HasRawWindowHandle for WindowHandle { + fn raw_window_handle(&self) -> RawWindowHandle { + self.window_handle.raw_window_handle() + } +} + pub struct Window<'a> { window: &'a mut platform::Window, // so that Window is !Send on all platforms @@ -37,7 +64,8 @@ impl<'a> Window<'a> { B: FnOnce(&mut Window) -> H, B: Send + 'static, { - platform::Window::open_parented::(parent, options, build) + let window_handle = platform::Window::open_parented::(parent, options, build); + WindowHandle::new(window_handle) } pub fn open_as_if_parented(options: WindowOpenOptions, build: B) -> WindowHandle @@ -46,7 +74,8 @@ impl<'a> Window<'a> { B: FnOnce(&mut Window) -> H, B: Send + 'static, { - platform::Window::open_as_if_parented::(options, build) + let window_handle = platform::Window::open_as_if_parented::(options, build); + WindowHandle::new(window_handle) } pub fn open_blocking(options: WindowOpenOptions, build: B) @@ -58,6 +87,7 @@ impl<'a> Window<'a> { platform::Window::open_blocking::(options, build) } + /// Close the window pub fn close(&mut self) { self.window.close(); } diff --git a/src/x11/window.rs b/src/x11/window.rs index f9787cee..5c3b7c70 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -19,7 +19,7 @@ use super::keyboard::{convert_key_press_event, convert_key_release_event}; pub struct WindowHandle { raw_window_handle: Option, close_requested: Arc, - window_dropped: Arc, + is_open: Arc, // Ensure handle is !Send _phantom: PhantomData<*mut ()>, @@ -28,19 +28,23 @@ pub struct WindowHandle { impl WindowHandle { pub fn close(&mut self) { if let Some(_) = self.raw_window_handle.take() { + // FIXME: This will need to be changed from just setting an atomic to somehow + // synchronizing with the window being closed (using a synchronous channel, or + // by joining on the event loop thread). + self.close_requested.store(true, Ordering::Relaxed); } } - pub fn window_was_dropped(&self) -> bool { - self.window_dropped.load(Ordering::Relaxed) + pub fn is_open(&self) -> bool { + self.is_open.load(Ordering::Relaxed) } } unsafe impl HasRawWindowHandle for WindowHandle { fn raw_window_handle(&self) -> RawWindowHandle { if let Some(raw_window_handle) = self.raw_window_handle { - if !self.window_dropped.load(Ordering::Relaxed) { + if self.is_open.load(Ordering::Relaxed) { return raw_window_handle; } } @@ -51,22 +55,22 @@ unsafe impl HasRawWindowHandle for WindowHandle { struct ParentHandle { close_requested: Arc, - window_dropped: Arc, + is_open: Arc, } impl ParentHandle { pub fn new() -> (Self, WindowHandle) { let close_requested = Arc::new(AtomicBool::new(false)); - let window_dropped = Arc::new(AtomicBool::new(false)); + let is_open = Arc::new(AtomicBool::new(true)); let handle = WindowHandle { raw_window_handle: None, close_requested: Arc::clone(&close_requested), - window_dropped: Arc::clone(&window_dropped), + is_open: Arc::clone(&is_open), _phantom: PhantomData::default(), }; - (Self { close_requested, window_dropped }, handle) + (Self { close_requested, is_open }, handle) } pub fn parent_did_drop(&self) -> bool { @@ -76,7 +80,7 @@ impl ParentHandle { impl Drop for ParentHandle { fn drop(&mut self) { - self.window_dropped.store(true, Ordering::Relaxed); + self.is_open.store(false, Ordering::Relaxed); } } @@ -375,6 +379,10 @@ impl Window { // Check if the parents's handle was dropped (such as when the host // requested the window to close) + // + // FIXME: This will need to be changed from just setting an atomic to somehow + // synchronizing with the window being closed (using a synchronous channel, or + // by joining on the event loop thread). if let Some(parent_handle) = &self.parent_handle { if parent_handle.parent_did_drop() { self.handle_must_close(handler); From 2fab6ecfc9a717e611bf890599f8529c5ddcf837 Mon Sep 17 00:00:00 2001 From: Billy Messenger Date: Mon, 15 Nov 2021 09:48:23 -0600 Subject: [PATCH 8/8] slight reordering of impls --- src/window.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/window.rs b/src/window.rs index 5a042e6f..9b5dfbbf 100644 --- a/src/window.rs +++ b/src/window.rs @@ -35,17 +35,17 @@ impl WindowHandle { } } -pub trait WindowHandler { - fn on_frame(&mut self, window: &mut Window); - fn on_event(&mut self, window: &mut Window, event: Event) -> EventStatus; -} - unsafe impl HasRawWindowHandle for WindowHandle { fn raw_window_handle(&self) -> RawWindowHandle { self.window_handle.raw_window_handle() } } +pub trait WindowHandler { + fn on_frame(&mut self, window: &mut Window); + fn on_event(&mut self, window: &mut Window, event: Event) -> EventStatus; +} + pub struct Window<'a> { window: &'a mut platform::Window, // so that Window is !Send on all platforms