Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): dialog parent window on macOS, closes #3312 #3753

Merged
merged 4 commits into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/dialog-parent-macos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri": patch
---

Use asynchronous file dialog on macOS and Windows to properly set the parent window.
75 changes: 65 additions & 10 deletions core/tauri/src/api/dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,52 @@ macro_rules! run_dialog {
}};
}

#[cfg(not(target_os = "linux"))]
macro_rules! run_file_dialog {
($e:expr, $h: ident) => {{
std::thread::spawn(move || {
let response = crate::async_runtime::block_on($e);
$h(response);
});
}};
}

#[cfg(target_os = "linux")]
macro_rules! run_file_dialog {
($e:expr, $h: ident) => {{
std::thread::spawn(move || {
let context = glib::MainContext::default();
context.invoke_with_priority(glib::PRIORITY_HIGH, move || {
let response = $e;
$h(response);
});
});
}};
}

macro_rules! run_dialog_sync {
($e:expr) => {{
let (tx, rx) = sync_channel(0);
let cb = move |response| {
tx.send(response).unwrap();
};
run_dialog!($e, cb);
run_file_dialog!($e, cb);
rx.recv().unwrap()
}};
}

macro_rules! file_dialog_builder {
() => {
#[cfg(target_os = "linux")]
type FileDialog = rfd::FileDialog;
#[cfg(not(target_os = "linux"))]
type FileDialog = rfd::AsyncFileDialog;

/// The file dialog builder.
///
/// Constructs file picker dialogs that can select single/multiple files or directories.
#[derive(Debug, Default)]
pub struct FileDialogBuilder(rfd::FileDialog);
pub struct FileDialogBuilder(FileDialog);

impl FileDialogBuilder {
/// Gets the default file dialog builder.
Expand Down Expand Up @@ -127,7 +155,11 @@ pub mod blocking {
/// }
/// ```
pub fn pick_file(self) -> Option<PathBuf> {
run_dialog_sync!(self.0.pick_file())
#[allow(clippy::let_and_return)]
let response = run_dialog_sync!(self.0.pick_file());
#[cfg(not(target_os = "linux"))]
let response = response.map(|p| p.path().to_path_buf());
response
}

/// Shows the dialog to select multiple files.
Expand All @@ -146,7 +178,12 @@ pub mod blocking {
/// }
/// ```
pub fn pick_files(self) -> Option<Vec<PathBuf>> {
run_dialog_sync!(self.0.pick_files())
#[allow(clippy::let_and_return)]
let response = run_dialog_sync!(self.0.pick_files());
#[cfg(not(target_os = "linux"))]
let response =
response.map(|paths| paths.into_iter().map(|p| p.path().to_path_buf()).collect());
response
}

/// Shows the dialog to select a single folder.
Expand All @@ -165,7 +202,11 @@ pub mod blocking {
/// }
/// ```
pub fn pick_folder(self) -> Option<PathBuf> {
run_dialog_sync!(self.0.pick_folder())
#[allow(clippy::let_and_return)]
let response = run_dialog_sync!(self.0.pick_folder());
#[cfg(not(target_os = "linux"))]
let response = response.map(|p| p.path().to_path_buf());
response
}

/// Shows the dialog to save a file.
Expand All @@ -184,7 +225,11 @@ pub mod blocking {
/// }
/// ```
pub fn save_file(self) -> Option<PathBuf> {
run_dialog_sync!(self.0.save_file())
#[allow(clippy::let_and_return)]
let response = run_dialog_sync!(self.0.save_file());
#[cfg(not(target_os = "linux"))]
let response = response.map(|p| p.path().to_path_buf());
response
}
}

Expand Down Expand Up @@ -305,7 +350,9 @@ mod nonblocking {
/// })
/// ```
pub fn pick_file<F: FnOnce(Option<PathBuf>) + Send + 'static>(self, f: F) {
run_dialog!(self.0.pick_file(), f)
#[cfg(not(target_os = "linux"))]
let f = |path: Option<rfd::FileHandle>| f(path.map(|p| p.path().to_path_buf()));
run_file_dialog!(self.0.pick_file(), f)
}

/// Shows the dialog to select multiple files.
Expand All @@ -327,7 +374,11 @@ mod nonblocking {
/// })
/// ```
pub fn pick_files<F: FnOnce(Option<Vec<PathBuf>>) + Send + 'static>(self, f: F) {
run_dialog!(self.0.pick_files(), f)
#[cfg(not(target_os = "linux"))]
let f = |paths: Option<Vec<rfd::FileHandle>>| {
f(paths.map(|list| list.into_iter().map(|p| p.path().to_path_buf()).collect()))
};
run_file_dialog!(self.0.pick_files(), f)
}

/// Shows the dialog to select a single folder.
Expand All @@ -349,7 +400,9 @@ mod nonblocking {
/// })
/// ```
pub fn pick_folder<F: FnOnce(Option<PathBuf>) + Send + 'static>(self, f: F) {
run_dialog!(self.0.pick_folder(), f)
#[cfg(not(target_os = "linux"))]
let f = |path: Option<rfd::FileHandle>| f(path.map(|p| p.path().to_path_buf()));
run_file_dialog!(self.0.pick_folder(), f)
}

/// Shows the dialog to save a file.
Expand All @@ -372,7 +425,9 @@ mod nonblocking {
/// })
/// ```
pub fn save_file<F: FnOnce(Option<PathBuf>) + Send + 'static>(self, f: F) {
run_dialog!(self.0.save_file(), f)
#[cfg(not(target_os = "linux"))]
let f = |path: Option<rfd::FileHandle>| f(path.map(|p| p.path().to_path_buf()));
run_file_dialog!(self.0.save_file(), f)
}
}

Expand Down
Loading