From 7c82d75896da97eef4255f2394818b27d47ec37f Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Mon, 10 Aug 2026 00:30:37 +0200 Subject: [PATCH 1/2] Make ParentWindowHandle Send+Sync on all platforms --- src/platform/macos/mod.rs | 28 ++++++++++++++++++++++++---- src/platform/macos/window.rs | 4 ++-- src/settings.rs | 6 ++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index 156e7cfa..18d3b3e3 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -12,7 +12,7 @@ use dispatch2::MainThreadBound; pub use error::Error; use objc2::__framework_prelude::Retained; use objc2::rc::Weak; -use objc2::MainThreadMarker; +use objc2::{MainThreadMarker, MainThreadOnly}; use objc2_app_kit::NSView; use raw_window_handle::{DisplayHandle, HasWindowHandle}; use std::fmt; @@ -69,9 +69,9 @@ impl fmt::Debug for PlatformHandle { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug)] pub struct ParentWindowHandle { - view: Retained, + view: MainThreadBound>, } impl ParentWindowHandle { @@ -80,6 +80,26 @@ impl ParentWindowHandle { ) -> core::result::Result { let view = extract_raw_window_handle(window.window_handle()?)?; - Ok(Self { view }) + let mtm = view.mtm(); + Ok(Self { view: MainThreadBound::new(view, mtm) }) } } + +impl Clone for ParentWindowHandle { + fn clone(&self) -> Self { + // SAFETY: We only use Retained::clone, which is thread-safe + let mtm = unsafe { MainThreadMarker::new_unchecked() }; + let view = self.view.get(mtm); + Self { view: MainThreadBound::new(view.clone(), mtm) } + } +} + +impl PartialEq for ParentWindowHandle { + fn eq(&self, other: &Self) -> bool { + // SAFETY: We only use Retained::eq, which is thread-safe + let mtm = unsafe { MainThreadMarker::new_unchecked() }; + Retained::eq(self.view.get(mtm), other.view.get(mtm)) + } +} + +impl Eq for ParentWindowHandle {} diff --git a/src/platform/macos/window.rs b/src/platform/macos/window.rs index 895352bc..808c8b43 100644 --- a/src/platform/macos/window.rs +++ b/src/platform/macos/window.rs @@ -39,7 +39,7 @@ impl WindowHandle { let _ = NSApplication::sharedApplication(mtm); if let Some(parent) = init.settings.parent.take() { - return Self::create_window_parented(init, parent.inner.view, mtm); + return Self::create_window_parented(init, parent.inner.view.into_inner(mtm), mtm); } Self::create_window_standalone(init, mtm) @@ -126,7 +126,7 @@ impl WindowHandle { let Some(view) = self.view.load() else { return Ok(()) }; let Some(view) = view.inner_ref() else { return Ok(()) }; - BaseviewView::set_parent(view, new_parent.view); + BaseviewView::set_parent(view, new_parent.view.into_inner(view.mtm)); Ok(()) } diff --git a/src/settings.rs b/src/settings.rs index dd5fb2f4..22d51f3f 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -145,6 +145,12 @@ pub struct ParentWindowHandle { pub(crate) inner: platform::ParentWindowHandle, } +// Assert this is Send+Sync +const _: () = { + const fn foo() {} + foo::(); +}; + impl ParentWindowHandle { /// Grabs a handle to the given `parent_window`, to later create a child window in it. pub fn from_window(parent_window: &impl HasWindowHandle) -> Self { From bfe6723fac3237ff2dbab99b156f4de32d774eb3 Mon Sep 17 00:00:00 2001 From: Adrien Prokopowicz <6529475+prokopyl@users.noreply.github.com> Date: Mon, 10 Aug 2026 00:41:43 +0200 Subject: [PATCH 2/2] Fix win build --- src/platform/win/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/platform/win/mod.rs b/src/platform/win/mod.rs index a295679e..9f650ef8 100644 --- a/src/platform/win/mod.rs +++ b/src/platform/win/mod.rs @@ -54,6 +54,11 @@ pub struct ParentWindowHandle { handle: HWnd, } +// SAFETY: ParentWindowHandle does not actually expose any thread-unsafe operation +unsafe impl Send for ParentWindowHandle {} +// SAFETY: ParentWindowHandle does not actually expose any thread-unsafe operation +unsafe impl Sync for ParentWindowHandle {} + impl ParentWindowHandle { pub fn extract( parent: &impl HasWindowHandle,