diff --git a/src/platform_impl/macos/util/mod.rs b/src/platform_impl/macos/util/mod.rs index 2cfdc47e84..fb30e1b707 100644 --- a/src/platform_impl/macos/util/mod.rs +++ b/src/platform_impl/macos/util/mod.rs @@ -6,6 +6,7 @@ pub(crate) use self::r#async::*; use core_graphics::display::CGDisplay; use objc2::foundation::{CGFloat, NSNotFound, NSPoint, NSRange, NSRect, NSUInteger}; +use objc2::{msg_send, ClassType}; use crate::dpi::LogicalPosition; @@ -63,3 +64,30 @@ pub fn window_position(position: LogicalPosition) -> NSPoint { CGDisplay::main().pixels_high() as CGFloat - position.y as CGFloat, ) } + +/// Helper for the broken `dealloc` impl of `declare_class!` +#[derive(Debug)] +pub(crate) struct DeallocHelper +where + T::Super: ClassType, +{ + ptr: *const T, +} + +impl DeallocHelper +where + T::Super: ClassType, +{ + pub(crate) unsafe fn new(ptr: *const T) -> Self { + Self { ptr } + } +} + +impl Drop for DeallocHelper +where + T::Super: ClassType, +{ + fn drop(&mut self) { + unsafe { msg_send![super(self.ptr, T::Super::class()), dealloc] } + } +} diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index 9bd4c5ef3e..4e18c98095 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -140,6 +140,7 @@ declare_class!( pub(super) state: IvarDrop>, marked_text: IvarDrop>, accepts_first_mouse: bool, + _dealloc_helper: IvarDrop>>, } unsafe impl ClassType for WinitView { @@ -174,6 +175,8 @@ declare_class!( Ivar::write(&mut this.state, Box::new(state)); Ivar::write(&mut this.marked_text, NSMutableAttributedString::new()); Ivar::write(&mut this.accepts_first_mouse, accepts_first_mouse); + let helper = unsafe { super::util::DeallocHelper::new(&*this) }; + Ivar::write(&mut this._dealloc_helper, Box::new(helper)); this.setPostsFrameChangedNotifications(true); diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 6d3e79af96..2faf78291a 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -113,6 +113,7 @@ declare_class!( // SAFETY: These are initialized in WinitWindow::new, right after it is created. shared_state: IvarDrop>>, decorations: IvarDrop>, + _dealloc_helper: IvarDrop>>, } unsafe impl ClassType for WinitWindow { @@ -329,6 +330,8 @@ impl WinitWindow { &mut this.decorations, Box::new(AtomicBool::new(attrs.decorations)), ); + let helper = unsafe { super::util::DeallocHelper::new(&*this) }; + Ivar::write(&mut this._dealloc_helper, Box::new(helper)); this.setReleasedWhenClosed(false); this.setTitle(&NSString::from_str(&attrs.title)); diff --git a/src/platform_impl/macos/window_delegate.rs b/src/platform_impl/macos/window_delegate.rs index baa0fe80ae..405360a325 100644 --- a/src/platform_impl/macos/window_delegate.rs +++ b/src/platform_impl/macos/window_delegate.rs @@ -42,6 +42,8 @@ declare_class!( // Used to prevent redundant events. previous_scale_factor: f64, + + _dealloc_helper: IvarDrop>>, } unsafe impl ClassType for WinitWindowDelegate { @@ -63,6 +65,8 @@ declare_class!( Ivar::write(&mut this.initial_fullscreen, initial_fullscreen); Ivar::write(&mut this.previous_position, None); Ivar::write(&mut this.previous_scale_factor, scale_factor); + let helper = unsafe { super::util::DeallocHelper::new(&*this) }; + Ivar::write(&mut this._dealloc_helper, Box::new(helper)); if scale_factor != 1.0 { this.queue_static_scale_factor_changed_event();