diff options
| author | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
| commit | 5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch) | |
| tree | 8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/dialog/cocoa | |
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/src/dialog/cocoa')
| -rw-r--r-- | contrib/SDL-3.2.8/src/dialog/cocoa/SDL_cocoadialog.m | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/dialog/cocoa/SDL_cocoadialog.m b/contrib/SDL-3.2.8/src/dialog/cocoa/SDL_cocoadialog.m new file mode 100644 index 0000000..fb9c5ad --- /dev/null +++ b/contrib/SDL-3.2.8/src/dialog/cocoa/SDL_cocoadialog.m | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | #include "SDL_internal.h" | ||
| 22 | #include "../SDL_dialog.h" | ||
| 23 | #include "../SDL_dialog_utils.h" | ||
| 24 | |||
| 25 | #ifdef SDL_PLATFORM_MACOS | ||
| 26 | |||
| 27 | #import <Cocoa/Cocoa.h> | ||
| 28 | #import <UniformTypeIdentifiers/UTType.h> | ||
| 29 | |||
| 30 | void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props) | ||
| 31 | { | ||
| 32 | SDL_Window* window = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, NULL); | ||
| 33 | SDL_DialogFileFilter *filters = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, NULL); | ||
| 34 | int nfilters = (int) SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, 0); | ||
| 35 | bool allow_many = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false); | ||
| 36 | const char* default_location = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, NULL); | ||
| 37 | const char* title = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_TITLE_STRING, NULL); | ||
| 38 | const char* accept = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_ACCEPT_STRING, NULL); | ||
| 39 | |||
| 40 | if (filters) { | ||
| 41 | const char *msg = validate_filters(filters, nfilters); | ||
| 42 | |||
| 43 | if (msg) { | ||
| 44 | SDL_SetError("%s", msg); | ||
| 45 | callback(userdata, NULL, -1); | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | if (SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER) != NULL) { | ||
| 51 | SDL_SetError("File dialog driver unsupported (don't set SDL_HINT_FILE_DIALOG_DRIVER)"); | ||
| 52 | callback(userdata, NULL, -1); | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | // NSOpenPanel inherits from NSSavePanel | ||
| 57 | NSSavePanel *dialog; | ||
| 58 | NSOpenPanel *dialog_as_open; | ||
| 59 | |||
| 60 | switch (type) { | ||
| 61 | case SDL_FILEDIALOG_SAVEFILE: | ||
| 62 | dialog = [NSSavePanel savePanel]; | ||
| 63 | break; | ||
| 64 | |||
| 65 | case SDL_FILEDIALOG_OPENFILE: | ||
| 66 | dialog_as_open = [NSOpenPanel openPanel]; | ||
| 67 | [dialog_as_open setAllowsMultipleSelection:((allow_many == true) ? YES : NO)]; | ||
| 68 | dialog = dialog_as_open; | ||
| 69 | break; | ||
| 70 | |||
| 71 | case SDL_FILEDIALOG_OPENFOLDER: | ||
| 72 | dialog_as_open = [NSOpenPanel openPanel]; | ||
| 73 | [dialog_as_open setCanChooseFiles:NO]; | ||
| 74 | [dialog_as_open setCanChooseDirectories:YES]; | ||
| 75 | [dialog_as_open setAllowsMultipleSelection:((allow_many == true) ? YES : NO)]; | ||
| 76 | dialog = dialog_as_open; | ||
| 77 | break; | ||
| 78 | }; | ||
| 79 | |||
| 80 | if (title) { | ||
| 81 | [dialog setTitle:[NSString stringWithUTF8String:title]]; | ||
| 82 | } | ||
| 83 | |||
| 84 | if (accept) { | ||
| 85 | [dialog setPrompt:[NSString stringWithUTF8String:accept]]; | ||
| 86 | } | ||
| 87 | |||
| 88 | if (filters) { | ||
| 89 | // On macOS 11.0 and up, this is an array of UTType. Prior to that, it's an array of NSString | ||
| 90 | NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:nfilters ]; | ||
| 91 | |||
| 92 | int has_all_files = 0; | ||
| 93 | for (int i = 0; i < nfilters; i++) { | ||
| 94 | char *pattern = SDL_strdup(filters[i].pattern); | ||
| 95 | char *pattern_ptr = pattern; | ||
| 96 | |||
| 97 | if (!pattern_ptr) { | ||
| 98 | callback(userdata, NULL, -1); | ||
| 99 | return; | ||
| 100 | } | ||
| 101 | |||
| 102 | for (char *c = pattern; *c; c++) { | ||
| 103 | if (*c == ';') { | ||
| 104 | *c = '\0'; | ||
| 105 | if(@available(macOS 11.0, *)) { | ||
| 106 | [types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]]; | ||
| 107 | } else { | ||
| 108 | [types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]]; | ||
| 109 | } | ||
| 110 | pattern_ptr = c + 1; | ||
| 111 | } else if (*c == '*') { | ||
| 112 | has_all_files = 1; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | if(@available(macOS 11.0, *)) { | ||
| 116 | [types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]]; | ||
| 117 | } else { | ||
| 118 | [types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]]; | ||
| 119 | } | ||
| 120 | |||
| 121 | SDL_free(pattern); | ||
| 122 | } | ||
| 123 | |||
| 124 | if (!has_all_files) { | ||
| 125 | if (@available(macOS 11.0, *)) { | ||
| 126 | [dialog setAllowedContentTypes:types]; | ||
| 127 | } else { | ||
| 128 | [dialog setAllowedFileTypes:types]; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | // Keep behavior consistent with other platforms | ||
| 134 | [dialog setAllowsOtherFileTypes:YES]; | ||
| 135 | |||
| 136 | if (default_location) { | ||
| 137 | [dialog setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:default_location]]]; | ||
| 138 | } | ||
| 139 | |||
| 140 | NSWindow *w = NULL; | ||
| 141 | |||
| 142 | if (window) { | ||
| 143 | w = (__bridge NSWindow *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL); | ||
| 144 | } | ||
| 145 | |||
| 146 | if (w) { | ||
| 147 | // [dialog beginWithCompletionHandler:^(NSInteger result) { | ||
| 148 | [dialog beginSheetModalForWindow:w completionHandler:^(NSInteger result) { | ||
| 149 | if (result == NSModalResponseOK) { | ||
| 150 | if (dialog_as_open) { | ||
| 151 | NSArray* urls = [dialog_as_open URLs]; | ||
| 152 | const char *files[[urls count] + 1]; | ||
| 153 | for (int i = 0; i < [urls count]; i++) { | ||
| 154 | files[i] = [[[urls objectAtIndex:i] path] UTF8String]; | ||
| 155 | } | ||
| 156 | files[[urls count]] = NULL; | ||
| 157 | callback(userdata, files, -1); | ||
| 158 | } else { | ||
| 159 | const char *files[2] = { [[[dialog URL] path] UTF8String], NULL }; | ||
| 160 | callback(userdata, files, -1); | ||
| 161 | } | ||
| 162 | } else if (result == NSModalResponseCancel) { | ||
| 163 | const char *files[1] = { NULL }; | ||
| 164 | callback(userdata, files, -1); | ||
| 165 | } | ||
| 166 | }]; | ||
| 167 | } else { | ||
| 168 | if ([dialog runModal] == NSModalResponseOK) { | ||
| 169 | if (dialog_as_open) { | ||
| 170 | NSArray* urls = [dialog_as_open URLs]; | ||
| 171 | const char *files[[urls count] + 1]; | ||
| 172 | for (int i = 0; i < [urls count]; i++) { | ||
| 173 | files[i] = [[[urls objectAtIndex:i] path] UTF8String]; | ||
| 174 | } | ||
| 175 | files[[urls count]] = NULL; | ||
| 176 | callback(userdata, files, -1); | ||
| 177 | } else { | ||
| 178 | const char *files[2] = { [[[dialog URL] path] UTF8String], NULL }; | ||
| 179 | callback(userdata, files, -1); | ||
| 180 | } | ||
| 181 | } else { | ||
| 182 | const char *files[1] = { NULL }; | ||
| 183 | callback(userdata, files, -1); | ||
| 184 | } | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | #endif // SDL_PLATFORM_MACOS | ||
