platform: extension filter on Windows/macOS system pickers

Windows: IFileOpenDialog SetFileTypes with the allowed extensions
(plus a default extension) when the host passes any.
macOS: NSOpenPanel setAllowedFileTypes from the same list (empty = all).
This commit is contained in:
2026-09-02 12:16:11 +08:00
parent a934be5bc6
commit 2426ad3523
2 changed files with 40 additions and 1 deletions
+16 -1
View File
@@ -13,7 +13,8 @@ use cocoa::{
},
base::{BOOL, NO, YES, id, nil, selector},
foundation::{
NSArray, NSAutoreleasePool, NSBundle, NSInteger, NSProcessInfo, NSString, NSUInteger, NSURL,
NSArray, NSAutoreleasePool, NSBundle, NSInteger, NSMutableArray, NSProcessInfo, NSString,
NSUInteger, NSURL,
},
};
use core_foundation::{
@@ -767,6 +768,20 @@ impl Platform for MacPlatform {
let _: () = msg_send![panel, setPrompt: ns_string(&prompt)];
}
// Extension filter (the host's allowed_extensions): the
// open panel's allowedFileTypes. Empty = any.
if !options.allowed_extensions.is_empty() {
let ns_array = {
let arr = NSMutableArray::<NSString>::new();
for ext in &options.allowed_extensions {
let s = ns_string(ext.as_str());
arr.addObject(&*s);
}
arr
};
let _: () = msg_send![panel, setAllowedFileTypes: &*ns_array];
}
let _: () = msg_send![panel, beginWithCompletionHandler: block];
}
})
+24
View File
@@ -1188,6 +1188,30 @@ fn file_open_dialog(
folder_dialog.SetOkButtonLabel(&HSTRING::from(prompt))?;
}
// Extension filter (the host's allowed_extensions, e.g.
// .ove/.otio/.fcpxml for the project import): the common
// ComDlg filter spec.
if !options.allowed_extensions.is_empty() {
let filter = options
.allowed_extensions
.iter()
.map(|ext| format!("*.{ext}"))
.collect::<Vec<_>>()
.join(";");
// The HSTRINGs must outlive the call (the filter spec holds
// raw pointers into them).
let name = windows::core::HSTRING::from("Supported files");
let pattern = windows::core::HSTRING::from(filter);
let spec = Common::COMDLG_FILTERSPEC {
pszName: name.as_ptr(),
pszSpec: pattern.as_ptr(),
};
folder_dialog.SetFileTypes(1, &spec)?;
folder_dialog.SetDefaultExtension(
&HSTRING::from(options.allowed_extensions[0].as_str()),
)?;
}
if folder_dialog.Show(window).is_err() {
// User cancelled
return Ok(None);