Skip to content

Commit bf89a05

Browse files
authored
fix(core): dialog parent window on macOS, closes #3312 (#3753)
1 parent 4e807a5 commit bf89a05

File tree

3 files changed

+155
-75
lines changed

3 files changed

+155
-75
lines changed

.changes/dialog-parent-macos.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch
3+
---
4+
5+
Use asynchronous file dialog on macOS and Windows to properly set the parent window.

core/tauri/src/api/dialog.rs

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,52 @@ macro_rules! run_dialog {
3333
}};
3434
}
3535

36+
#[cfg(not(target_os = "linux"))]
37+
macro_rules! run_file_dialog {
38+
($e:expr, $h: ident) => {{
39+
std::thread::spawn(move || {
40+
let response = crate::async_runtime::block_on($e);
41+
$h(response);
42+
});
43+
}};
44+
}
45+
46+
#[cfg(target_os = "linux")]
47+
macro_rules! run_file_dialog {
48+
($e:expr, $h: ident) => {{
49+
std::thread::spawn(move || {
50+
let context = glib::MainContext::default();
51+
context.invoke_with_priority(glib::PRIORITY_HIGH, move || {
52+
let response = $e;
53+
$h(response);
54+
});
55+
});
56+
}};
57+
}
58+
3659
macro_rules! run_dialog_sync {
3760
($e:expr) => {{
3861
let (tx, rx) = sync_channel(0);
3962
let cb = move |response| {
4063
tx.send(response).unwrap();
4164
};
42-
run_dialog!($e, cb);
65+
run_file_dialog!($e, cb);
4366
rx.recv().unwrap()
4467
}};
4568
}
4669

4770
macro_rules! file_dialog_builder {
4871
() => {
72+
#[cfg(target_os = "linux")]
73+
type FileDialog = rfd::FileDialog;
74+
#[cfg(not(target_os = "linux"))]
75+
type FileDialog = rfd::AsyncFileDialog;
76+
4977
/// The file dialog builder.
5078
///
5179
/// Constructs file picker dialogs that can select single/multiple files or directories.
5280
#[derive(Debug, Default)]
53-
pub struct FileDialogBuilder(rfd::FileDialog);
81+
pub struct FileDialogBuilder(FileDialog);
5482

5583
impl FileDialogBuilder {
5684
/// Gets the default file dialog builder.
@@ -127,7 +155,11 @@ pub mod blocking {
127155
/// }
128156
/// ```
129157
pub fn pick_file(self) -> Option<PathBuf> {
130-
run_dialog_sync!(self.0.pick_file())
158+
#[allow(clippy::let_and_return)]
159+
let response = run_dialog_sync!(self.0.pick_file());
160+
#[cfg(not(target_os = "linux"))]
161+
let response = response.map(|p| p.path().to_path_buf());
162+
response
131163
}
132164

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

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

171212
/// Shows the dialog to save a file.
@@ -184,7 +225,11 @@ pub mod blocking {
184225
/// }
185226
/// ```
186227
pub fn save_file(self) -> Option<PathBuf> {
187-
run_dialog_sync!(self.0.save_file())
228+
#[allow(clippy::let_and_return)]
229+
let response = run_dialog_sync!(self.0.save_file());
230+
#[cfg(not(target_os = "linux"))]
231+
let response = response.map(|p| p.path().to_path_buf());
232+
response
188233
}
189234
}
190235

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

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

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

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

0 commit comments

Comments
 (0)