1
0
Fork 0

Merge pull request #113757 from bruvzg/mac_nfd_ext

[macOS] Prefer user specified file extensions over OS preferred one.
This commit is contained in:
Thaddeus Crews 2025-12-11 12:12:44 -06:00
commit 1cf3180537
No known key found for this signature in database
GPG Key ID: 8C6E5FEB5FC03CCC
3 changed files with 32 additions and 5 deletions

View File

@ -1060,7 +1060,7 @@ Error DisplayServerMacOS::_file_dialog_with_options_show(const String &p_title,
Vector<String> files;
String url;
url.append_utf8([[[panel URL] path] UTF8String]);
files.push_back(url);
files.push_back([panel_delegate validateFilename:url]);
if (callback.is_valid()) {
if (p_options_in_cb) {
Variant v_result = true;
@ -1179,7 +1179,7 @@ Error DisplayServerMacOS::_file_dialog_with_options_show(const String &p_title,
for (NSUInteger i = 0; i != [urls count]; ++i) {
String url;
url.append_utf8([[[urls objectAtIndex:i] path] UTF8String]);
files.push_back(url);
files.push_back([panel_delegate validateFilename:url]);
}
if (callback.is_valid()) {
if (p_options_in_cb) {

View File

@ -41,6 +41,7 @@
@interface GodotOpenSaveDelegate : NSObject <NSOpenSavePanelDelegate> {
NSSavePanel *dialog;
NSMutableArray *allowed_types;
Vector<Vector<String>> preferred_types;
HashMap<int, String> ctr_ids;
Dictionary options;
@ -51,7 +52,7 @@
}
- (void)makeAccessoryView:(NSSavePanel *)p_panel filters:(const Vector<String> &)p_filters options:(const TypedArray<Dictionary> &)p_options;
- (void)setFileTypes:(NSMutableArray *)p_allowed_types;
- (void)setFileTypes:(NSMutableArray *)p_allowed_types pref:(const Vector<Vector<String>> &)p_preftypes;
- (void)popupOptionAction:(id)p_sender;
- (void)popupCheckAction:(id)p_sender;
- (void)popupFileAction:(id)p_sender;
@ -60,5 +61,6 @@
- (int)setDefaultInt:(const String &)p_name value:(int)p_value;
- (int)setDefaultBool:(const String &)p_name value:(bool)p_value;
- (void)setRootPath:(const String &)p_root_path;
- (String)validateFilename:(const String &)p_path;
@end

View File

@ -103,6 +103,7 @@
}
NSMutableArray *new_allowed_types = [[NSMutableArray alloc] init];
Vector<Vector<String>> pref_types;
bool has_type_popup = false;
{
NSTextField *label = [NSTextField labelWithString:[NSString stringWithUTF8String:RTR("Format").utf8().get_data()]];
@ -117,6 +118,7 @@
NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:NO];
for (int i = 0; i < p_filters.size(); i++) {
Vector<String> tokens = p_filters[i].split(";");
Vector<String> pref_type;
if (tokens.size() >= 1) {
String flt = tokens[0].strip_edges();
String mime = (tokens.size() >= 3) ? tokens[2].strip_edges() : String();
@ -135,9 +137,11 @@
}
if (ut) {
[type_filters addObject:ut];
pref_type.push_back(str.replace("*.", "").strip_edges());
}
} else {
[type_filters addObject:[NSString stringWithUTF8String:str.replace("*.", "").strip_edges().utf8().get_data()]];
pref_type.push_back(str.replace("*.", "").strip_edges());
}
}
}
@ -158,6 +162,7 @@
if ([type_filters count] > 0) {
NSString *name_str = [NSString stringWithUTF8String:((tokens.size() == 1) ? tokens[0] : tokens[1].strip_edges()).utf8().get_data()];
[new_allowed_types addObject:type_filters];
pref_types.push_back(pref_type);
[popup addItemWithTitle:name_str];
}
}
@ -171,6 +176,7 @@
}
} else if (p_filters.size() == 1) {
Vector<String> tokens = p_filters[0].split(";");
Vector<String> pref_type;
if (tokens.size() >= 1) {
String flt = tokens[0].strip_edges();
String mime = (tokens.size() >= 3) ? tokens[2] : String();
@ -189,9 +195,11 @@
}
if (ut) {
[type_filters addObject:ut];
pref_type.push_back(str.replace("*.", "").strip_edges());
}
} else {
[type_filters addObject:[NSString stringWithUTF8String:str.replace("*.", "").strip_edges().utf8().get_data()]];
pref_type.push_back(str.replace("*.", "").strip_edges());
}
}
}
@ -210,10 +218,11 @@
if ([type_filters count] > 0) {
[new_allowed_types addObject:type_filters];
pref_types.push_back(pref_type);
}
}
}
[self setFileTypes:new_allowed_types];
[self setFileTypes:new_allowed_types pref:pref_types];
}
[base_view addSubview:view];
@ -278,8 +287,9 @@
return cid;
}
- (void)setFileTypes:(NSMutableArray *)p_allowed_types {
- (void)setFileTypes:(NSMutableArray *)p_allowed_types pref:(const Vector<Vector<String>> &)p_preftypes {
allowed_types = p_allowed_types;
preferred_types = p_preftypes;
}
- (instancetype)initWithDialog:(NSSavePanel *)p_dialog {
@ -346,6 +356,21 @@
root = p_root_path;
}
- (String)validateFilename:(const String &)p_path {
if (@available(macOS 11, *)) {
if (allowed_types) {
NSMutableArray *type_filters = [allowed_types objectAtIndex:cur_index];
UTType *ut = [type_filters objectAtIndex:0];
String ext = String::utf8([[ut preferredFilenameExtension] UTF8String]);
Vector<String> pref_ext = preferred_types[cur_index];
if (!pref_ext.is_empty() && !pref_ext.has(ext) && p_path.has_extension(ext)) {
return p_path.get_basename() + "." + pref_ext[0];
}
}
}
return p_path;
}
- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError *_Nullable *)outError {
if (root.is_empty()) {
return YES;