diff --git a/CHANGELOG.md b/CHANGELOG.md index 874a482..81a89cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Update `raw-window-handle` to 0.6. - Update `winit` in example to 0.29. - Update wasm CSS to respect the color scheme (including dark mode) +- Fix macOS sync backend incorrectly setting the parent window ## 0.13.0 - **[Breaking]** Users of the `xdg-portal` feature must now also select the `tokio` diff --git a/src/backend/macos/file_dialog/panel_ffi.rs b/src/backend/macos/file_dialog/panel_ffi.rs index 805f623..83bb3f3 100644 --- a/src/backend/macos/file_dialog/panel_ffi.rs +++ b/src/backend/macos/file_dialog/panel_ffi.rs @@ -1,11 +1,11 @@ use crate::FileDialog; -use std::ops::Deref; +use std::mem; use std::path::Path; use std::{ops::DerefMut, path::PathBuf}; use objc::{class, msg_send, sel, sel_impl}; -use objc_id::Id; +use objc_id::{Id, Shared}; use super::super::utils::{INSURL, NSURL}; @@ -30,6 +30,7 @@ fn make_nsstring(s: &str) -> Id { pub struct Panel { pub(crate) panel: Id, + parent: Option>, _focus_manager: FocusManager, _policy_manager: PolicyManager, } @@ -51,6 +52,7 @@ impl Panel { panel: unsafe { Id::from_ptr(panel) }, _focus_manager, _policy_manager, + parent: None, } } @@ -63,6 +65,16 @@ impl Panel { } pub fn run_modal(&self) -> i32 { + if let Some(parent) = self.parent.clone() { + let completion = { block::ConcreteBlock::new(|_: isize| {}) }; + + unsafe { + msg_send![self.panel, beginSheetModalForWindow: parent completionHandler: &completion] + } + + mem::forget(completion); + } + unsafe { msg_send![self.panel, runModal] } } @@ -130,11 +142,8 @@ impl Panel { } } - pub fn set_parent(&self, parent: &RawWindowHandle) { - let id = NSWindow::from_raw_window_handle(parent); - unsafe { - let () = msg_send![id, addChildWindow: self.panel.deref() ordered: 1]; - } + pub fn set_parent(&mut self, parent: &RawWindowHandle) { + self.parent = Some(NSWindow::from_raw_window_handle(parent).share()); } pub fn get_result(&self) -> PathBuf { @@ -162,7 +171,7 @@ impl Panel { impl Panel { pub fn build_pick_file(opt: &FileDialog) -> Self { - let panel = Panel::open_panel(); + let mut panel = Panel::open_panel(); if !opt.filters.is_empty() { panel.add_filters(&opt); @@ -191,7 +200,7 @@ impl Panel { } pub fn build_save_file(opt: &FileDialog) -> Self { - let panel = Panel::save_panel(); + let mut panel = Panel::save_panel(); if !opt.filters.is_empty() { panel.add_filters(&opt); @@ -217,7 +226,7 @@ impl Panel { } pub fn build_pick_folder(opt: &FileDialog) -> Self { - let panel = Panel::open_panel(); + let mut panel = Panel::open_panel(); if let Some(path) = &opt.starting_directory { panel.set_path(path, opt.file_name.as_deref()); @@ -239,7 +248,7 @@ impl Panel { } pub fn build_pick_folders(opt: &FileDialog) -> Self { - let panel = Panel::open_panel(); + let mut panel = Panel::open_panel(); if let Some(path) = &opt.starting_directory { panel.set_path(path, opt.file_name.as_deref()); @@ -262,7 +271,7 @@ impl Panel { } pub fn build_pick_files(opt: &FileDialog) -> Self { - let panel = Panel::open_panel(); + let mut panel = Panel::open_panel(); if !opt.filters.is_empty() { panel.add_filters(&opt); diff --git a/src/backend/macos/message_dialog.rs b/src/backend/macos/message_dialog.rs index f7bdc39..b75dd63 100644 --- a/src/backend/macos/message_dialog.rs +++ b/src/backend/macos/message_dialog.rs @@ -1,3 +1,4 @@ +use std::mem; use std::ops::DerefMut; use crate::backend::DialogFutureType; @@ -9,7 +10,7 @@ use super::{ AsModal, }; -use super::utils::{INSWindow, NSWindow}; +use super::utils::{INSApplication, INSWindow, NSApplication, NSWindow}; use objc::runtime::Object; use objc::{class, msg_send, sel, sel_impl}; use objc_foundation::{INSString, NSString}; @@ -35,6 +36,7 @@ enum NSAlertReturn { pub struct NSAlert { buttons: MessageButtons, alert: Id, + parent: Option>, _focus_manager: FocusManager, _policy_manager: PolicyManager, } @@ -93,13 +95,30 @@ impl NSAlert { Self { alert: unsafe { Id::from_retained_ptr(alert) }, + parent: opt.parent.map(|x| NSWindow::from_raw_window_handle(&x)), buttons: opt.buttons, _focus_manager, _policy_manager, } } - pub fn run(self) -> MessageDialogResult { + pub fn run(mut self) -> MessageDialogResult { + if let Some(parent) = self.parent.take() { + let completion = { + block::ConcreteBlock::new(|result: isize| { + let _: () = unsafe { + msg_send![NSApplication::shared_application(), stopModalWithCode: result] + }; + }) + }; + + unsafe { + msg_send![self.alert, beginSheetModalForWindow: parent completionHandler: &completion] + } + + mem::forget(completion); + } + let ret: i64 = unsafe { msg_send![self.alert, runModal] }; dialog_result(&self.buttons, ret) }