Skip to content

Commit

Permalink
Fix macOS memory leaks on dealloc of custom objects
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Mar 9, 2023
1 parent 712c807 commit 881a791
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/platform_impl/macos/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -63,3 +64,30 @@ pub fn window_position(position: LogicalPosition<f64>) -> 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<T: ClassType>
where
T::Super: ClassType,
{
ptr: *const T,
}

impl<T: ClassType> DeallocHelper<T>
where
T::Super: ClassType,
{
pub(crate) unsafe fn new(ptr: *const T) -> Self {
Self { ptr }
}
}

impl<T: ClassType> Drop for DeallocHelper<T>
where
T::Super: ClassType,
{
fn drop(&mut self) {
unsafe { msg_send![super(self.ptr, T::Super::class()), dealloc] }
}
}
3 changes: 3 additions & 0 deletions src/platform_impl/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ declare_class!(
pub(super) state: IvarDrop<Box<ViewState>>,
marked_text: IvarDrop<Id<NSMutableAttributedString, Owned>>,
accepts_first_mouse: bool,
_dealloc_helper: IvarDrop<Box<super::util::DeallocHelper<WinitView>>>,
}

unsafe impl ClassType for WinitView {
Expand Down Expand Up @@ -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);

Expand Down
3 changes: 3 additions & 0 deletions src/platform_impl/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ declare_class!(
// SAFETY: These are initialized in WinitWindow::new, right after it is created.
shared_state: IvarDrop<Box<Mutex<SharedState>>>,
decorations: IvarDrop<Box<AtomicBool>>,
_dealloc_helper: IvarDrop<Box<super::util::DeallocHelper<WinitWindow>>>,
}

unsafe impl ClassType for WinitWindow {
Expand Down Expand Up @@ -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));
Expand Down
4 changes: 4 additions & 0 deletions src/platform_impl/macos/window_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ declare_class!(

// Used to prevent redundant events.
previous_scale_factor: f64,

_dealloc_helper: IvarDrop<Box<super::util::DeallocHelper<WinitWindowDelegate>>>,
}

unsafe impl ClassType for WinitWindowDelegate {
Expand All @@ -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();
Expand Down

0 comments on commit 881a791

Please sign in to comment.