From 92cdf5e3af168b15de56ca8a39c4041fd083b4e6 Mon Sep 17 00:00:00 2001 From: dtzxporter Date: Thu, 8 Feb 2024 00:09:53 -0500 Subject: [PATCH 1/3] Properly support setting the parent window for the sync macOS backend. This will properly show the sheets as children of the parent window. Update panel_ffi.rs --- src/backend/macos/file_dialog/panel_ffi.rs | 30 +++++++++++++--------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/backend/macos/file_dialog/panel_ffi.rs b/src/backend/macos/file_dialog/panel_ffi.rs index 805f623..c3fdea8 100644 --- a/src/backend/macos/file_dialog/panel_ffi.rs +++ b/src/backend/macos/file_dialog/panel_ffi.rs @@ -1,11 +1,10 @@ use crate::FileDialog; -use std::ops::Deref; 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}; @@ -32,6 +31,7 @@ pub struct Panel { pub(crate) panel: Id, _focus_manager: FocusManager, _policy_manager: PolicyManager, + parent: Option>, } impl AsModal for Panel { @@ -51,6 +51,7 @@ impl Panel { panel: unsafe { Id::from_ptr(panel) }, _focus_manager, _policy_manager, + parent: None, } } @@ -63,6 +64,14 @@ impl Panel { } pub fn run_modal(&self) -> i32 { + if let Some(parent) = self.parent.clone() { + let completion: *const () = std::ptr::null(); + + unsafe { + msg_send![self.panel, beginSheetModalForWindow: parent completionHandler: &completion] + } + } + unsafe { msg_send![self.panel, runModal] } } @@ -130,11 +139,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 +168,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 +197,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 +223,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 +245,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 +268,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); From 29fe1df2fdf7f915543749ef7aa0e64d9a63af04 Mon Sep 17 00:00:00 2001 From: dtzxporter Date: Thu, 8 Feb 2024 00:11:34 -0500 Subject: [PATCH 2/3] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) 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` From bd70d6d55d89f79a653f1dab4e0dfff90f8a7ec3 Mon Sep 17 00:00:00 2001 From: dtzxporter Date: Thu, 8 Feb 2024 00:19:48 -0500 Subject: [PATCH 3/3] Fix message dialog sync on macOS as well. Re-order parent in panel_ffi. Update panel_ffi.rs Attempt to fix issue with modal windows. --- src/backend/macos/file_dialog/panel_ffi.rs | 7 +++++-- src/backend/macos/message_dialog.rs | 23 ++++++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/backend/macos/file_dialog/panel_ffi.rs b/src/backend/macos/file_dialog/panel_ffi.rs index c3fdea8..83bb3f3 100644 --- a/src/backend/macos/file_dialog/panel_ffi.rs +++ b/src/backend/macos/file_dialog/panel_ffi.rs @@ -1,5 +1,6 @@ use crate::FileDialog; +use std::mem; use std::path::Path; use std::{ops::DerefMut, path::PathBuf}; @@ -29,9 +30,9 @@ fn make_nsstring(s: &str) -> Id { pub struct Panel { pub(crate) panel: Id, + parent: Option>, _focus_manager: FocusManager, _policy_manager: PolicyManager, - parent: Option>, } impl AsModal for Panel { @@ -65,11 +66,13 @@ impl Panel { pub fn run_modal(&self) -> i32 { if let Some(parent) = self.parent.clone() { - let completion: *const () = std::ptr::null(); + let completion = { block::ConcreteBlock::new(|_: isize| {}) }; unsafe { msg_send![self.panel, beginSheetModalForWindow: parent completionHandler: &completion] } + + mem::forget(completion); } unsafe { msg_send![self.panel, runModal] } 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) }