#![allow(clippy::unnecessary_cast)] use icrate::AppKit::{NSResponder, NSWindow}; use icrate::Foundation::{MainThreadBound, MainThreadMarker, NSObject}; use objc2::rc::{autoreleasepool, Id}; use objc2::{declare_class, mutability, ClassType, DeclaredClass}; use super::event_loop::EventLoopWindowTarget; use super::window_delegate::WindowDelegate; use crate::error::OsError as RootOsError; use crate::window::WindowAttributes; pub(crate) struct Window { window: MainThreadBound>, /// The window only keeps a weak reference to this, so we must keep it around here. delegate: MainThreadBound>, } impl Drop for Window { fn drop(&mut self) { self.window .get_on_main(|window| autoreleasepool(|_| window.close())) } } impl Window { pub(crate) fn new( window_target: &EventLoopWindowTarget, attributes: WindowAttributes, ) -> Result { let mtm = window_target.mtm; let delegate = autoreleasepool(|_| WindowDelegate::new(attributes, mtm))?; Ok(Window { window: MainThreadBound::new(delegate.window().retain(), mtm), delegate: MainThreadBound::new(delegate, mtm), }) } pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&WindowDelegate) + Send + 'static) { // For now, don't actually do queuing, since it may be less predictable self.maybe_wait_on_main(f) } pub(crate) fn maybe_wait_on_main( &self, f: impl FnOnce(&WindowDelegate) -> R + Send, ) -> R { self.delegate.get_on_main(|delegate| f(delegate)) } #[cfg(feature = "rwh_06")] #[inline] pub(crate) fn raw_window_handle_rwh_06( &self, ) -> Result { if let Some(mtm) = MainThreadMarker::new() { Ok(self.delegate.get(mtm).raw_window_handle_rwh_06()) } else { Err(rwh_06::HandleError::Unavailable) } } #[cfg(feature = "rwh_06")] #[inline] pub(crate) fn raw_display_handle_rwh_06( &self, ) -> Result { Ok(rwh_06::RawDisplayHandle::AppKit( rwh_06::AppKitDisplayHandle::new(), )) } } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct WindowId(pub usize); impl WindowId { pub const unsafe fn dummy() -> Self { Self(0) } } impl From for u64 { fn from(window_id: WindowId) -> Self { window_id.0 as u64 } } impl From for WindowId { fn from(raw_id: u64) -> Self { Self(raw_id as usize) } } declare_class!( #[derive(Debug)] pub struct WinitWindow; unsafe impl ClassType for WinitWindow { #[inherits(NSResponder, NSObject)] type Super = NSWindow; type Mutability = mutability::MainThreadOnly; const NAME: &'static str = "WinitWindow"; } impl DeclaredClass for WinitWindow {} unsafe impl WinitWindow { #[method(canBecomeMainWindow)] fn can_become_main_window(&self) -> bool { trace_scope!("canBecomeMainWindow"); true } #[method(canBecomeKeyWindow)] fn can_become_key_window(&self) -> bool { trace_scope!("canBecomeKeyWindow"); true } } ); impl WinitWindow { pub(super) fn id(&self) -> WindowId { WindowId(self as *const Self as usize) } }