From a4852f3a108531219abd289028d8417f66b39ddb Mon Sep 17 00:00:00 2001
From: Semphris <[EMAIL REDACTED]>
Date: Sat, 12 Oct 2024 00:30:23 -0400
Subject: [PATCH] SDL_ShowFileDialogWithProperties with more options
---
Android.mk | 1 +
CMakeLists.txt | 1 +
VisualC-GDK/SDL/SDL.vcxproj | 1 +
VisualC-GDK/SDL/SDL.vcxproj.filters | 3 +
VisualC/SDL/SDL.vcxproj | 1 +
VisualC/SDL/SDL.vcxproj.filters | 3 +
include/SDL3/SDL_dialog.h | 94 ++++++++++--
src/dialog/SDL_dialog.c | 103 ++++++++++++++
src/dialog/SDL_dialog.h | 22 +++
src/dialog/android/SDL_androiddialog.c | 39 +++--
src/dialog/cocoa/SDL_cocoadialog.m | 49 +++----
src/dialog/dummy/SDL_dummydialog.c | 16 +--
src/dialog/haiku/SDL_haikudialog.cc | 66 ++++++---
src/dialog/unix/SDL_portaldialog.c | 79 +++++-----
src/dialog/unix/SDL_portaldialog.h | 4 +-
src/dialog/unix/SDL_unixdialog.c | 51 ++-----
src/dialog/unix/SDL_zenitydialog.c | 190 ++++++++++++++-----------
src/dialog/unix/SDL_zenitydialog.h | 4 +-
src/dialog/windows/SDL_windowsdialog.c | 158 +++++++++++++-------
19 files changed, 598 insertions(+), 287 deletions(-)
create mode 100644 src/dialog/SDL_dialog.c
create mode 100644 src/dialog/SDL_dialog.h
diff --git a/Android.mk b/Android.mk
index 6735c877a98f9..56c817a2b62bf 100644
--- a/Android.mk
+++ b/Android.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
$(wildcard $(LOCAL_PATH)/src/core/*.c) \
$(wildcard $(LOCAL_PATH)/src/core/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/cpuinfo/*.c) \
+ $(LOCAL_PATH)/src/dialog/SDL_dialog.c \
$(LOCAL_PATH)/src/dialog/SDL_dialog_utils.c \
$(LOCAL_PATH)/src/dialog/android/SDL_androiddialog.c \
$(wildcard $(LOCAL_PATH)/src/dynapi/*.c) \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d7bcfea28fd58..d60fca5ef2454 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2874,6 +2874,7 @@ endif()
if (SDL_DIALOG)
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/SDL_dialog_utils.c)
+ sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/SDL_dialog.c)
if(ANDROID)
sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/android/SDL_androiddialog.c)
set(HAVE_SDL_DIALOG TRUE)
diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj
index 34a9ae48817d4..f6a119e178e8c 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj
+++ b/VisualC-GDK/SDL/SDL.vcxproj
@@ -517,6 +517,7 @@
</ClCompile>
<ClCompile Include="..\..\src\camera\dummy\SDL_camera_dummy.c" />
<ClCompile Include="..\..\src\camera\SDL_camera.c" />
+ <ClCompile Include="..\..\src\dialog\SDL_dialog.c" />
<ClCompile Include="..\..\src\dialog\SDL_dialog_utils.c" />
<ClCompile Include="..\..\src\filesystem\SDL_filesystem.c" />
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfsops.c" />
diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters
index 64cacdc1f8f0b..8bd8a220acb7e 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj.filters
+++ b/VisualC-GDK/SDL/SDL.vcxproj.filters
@@ -7,6 +7,9 @@
<ClCompile Include="..\..\src\dialog\SDL_dialog_utils.c">
<Filter>dialog</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\dialog\SDL_dialog.c">
+ <Filter>dialog</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\filesystem\SDL_filesystem.c">
<Filter>filesystem</Filter>
</ClCompile>
diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj
index 19da967fd3579..a22ac35d97d99 100644
--- a/VisualC/SDL/SDL.vcxproj
+++ b/VisualC/SDL/SDL.vcxproj
@@ -412,6 +412,7 @@
<ClCompile Include="..\..\src\camera\dummy\SDL_camera_dummy.c" />
<ClCompile Include="..\..\src\camera\mediafoundation\SDL_camera_mediafoundation.c" />
<ClCompile Include="..\..\src\camera\SDL_camera.c" />
+ <ClCompile Include="..\..\src\dialog\SDL_dialog.c" />
<ClCompile Include="..\..\src\dialog\SDL_dialog_utils.c" />
<ClCompile Include="..\..\src\filesystem\SDL_filesystem.c" />
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfsops.c" />
diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters
index 5e6bd30ff12ab..5dc12b0eaef99 100644
--- a/VisualC/SDL/SDL.vcxproj.filters
+++ b/VisualC/SDL/SDL.vcxproj.filters
@@ -950,6 +950,9 @@
<ClCompile Include="..\..\src\camera\SDL_camera.c">
<Filter>camera</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\dialog\SDL_dialog.c">
+ <Filter>dialog</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\dialog\SDL_dialog_utils.c">
<Filter>dialog</Filter>
</ClCompile>
diff --git a/include/SDL3/SDL_dialog.h b/include/SDL3/SDL_dialog.h
index 21b022c5843d2..f59fcabd80f4e 100644
--- a/include/SDL3/SDL_dialog.h
+++ b/include/SDL3/SDL_dialog.h
@@ -30,6 +30,7 @@
#include <SDL3/SDL_stdinc.h>
#include <SDL3/SDL_error.h>
+#include <SDL3/SDL_properties.h>
#include <SDL3/SDL_video.h>
#include <SDL3/SDL_begin_code.h>
@@ -55,6 +56,7 @@ extern "C" {
* \sa SDL_ShowOpenFileDialog
* \sa SDL_ShowSaveFileDialog
* \sa SDL_ShowOpenFolderDialog
+ * \sa SDL_ShowFileDialogWithProperties
*/
typedef struct SDL_DialogFileFilter
{
@@ -93,14 +95,13 @@ typedef struct SDL_DialogFileFilter
* \sa SDL_ShowOpenFileDialog
* \sa SDL_ShowSaveFileDialog
* \sa SDL_ShowOpenFolderDialog
+ * \sa SDL_ShowFileDialogWithProperties
*/
typedef void (SDLCALL *SDL_DialogFileCallback)(void *userdata, const char * const *filelist, int filter);
/**
* Displays a dialog that lets the user select a file on their filesystem.
*
- * This function should only be invoked from the main thread.
- *
* This is an asynchronous function; it will return immediately, and the
* result will be passed to the callback.
*
@@ -127,19 +128,25 @@ typedef void (SDLCALL *SDL_DialogFileCallback)(void *userdata, const char * cons
* Not all platforms support this option.
* \param filters a list of filters, may be NULL. Not all platforms support
* this option, and platforms that do support it may allow the
- * user to ignore the filters.
+ * user to ignore the filters. If non-NULL, it must remain valid
+ * at least until the callback is invoked.
* \param nfilters the number of filters. Ignored if filters is NULL.
* \param default_location the default folder or file to start the dialog at,
* may be NULL. Not all platforms support this option.
* \param allow_many if non-zero, the user will be allowed to select multiple
* entries. Not all platforms support this option.
*
+ * \threadsafety This function should be called only from the main thread. The
+ * callback may be invoked from the same thread or from a
+ * different one, depending on the OS's constraints.
+ *
* \since This function is available since SDL 3.1.3.
*
* \sa SDL_DialogFileCallback
* \sa SDL_DialogFileFilter
* \sa SDL_ShowSaveFileDialog
* \sa SDL_ShowOpenFolderDialog
+ * \sa SDL_ShowFileDialogWithProperties
*/
extern SDL_DECLSPEC void SDLCALL SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location, bool allow_many);
@@ -147,8 +154,6 @@ extern SDL_DECLSPEC void SDLCALL SDL_ShowOpenFileDialog(SDL_DialogFileCallback c
* Displays a dialog that lets the user choose a new or existing file on their
* filesystem.
*
- * This function should only be invoked from the main thread.
- *
* This is an asynchronous function; it will return immediately, and the
* result will be passed to the callback.
*
@@ -174,25 +179,29 @@ extern SDL_DECLSPEC void SDLCALL SDL_ShowOpenFileDialog(SDL_DialogFileCallback c
* Not all platforms support this option.
* \param filters a list of filters, may be NULL. Not all platforms support
* this option, and platforms that do support it may allow the
- * user to ignore the filters.
+ * user to ignore the filters. If non-NULL, it must remain valid
+ * at least until the callback is invoked.
* \param nfilters the number of filters. Ignored if filters is NULL.
* \param default_location the default folder or file to start the dialog at,
* may be NULL. Not all platforms support this option.
*
+ * \threadsafety This function should be called only from the main thread. The
+ * callback may be invoked from the same thread or from a
+ * different one, depending on the OS's constraints.
+ *
* \since This function is available since SDL 3.1.3.
*
* \sa SDL_DialogFileCallback
* \sa SDL_DialogFileFilter
* \sa SDL_ShowOpenFileDialog
* \sa SDL_ShowOpenFolderDialog
+ * \sa SDL_ShowFileDialogWithProperties
*/
extern SDL_DECLSPEC void SDLCALL SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location);
/**
* Displays a dialog that lets the user select a folder on their filesystem.
*
- * This function should only be invoked from the main thread.
- *
* This is an asynchronous function; it will return immediately, and the
* result will be passed to the callback.
*
@@ -222,14 +231,83 @@ extern SDL_DECLSPEC void SDLCALL SDL_ShowSaveFileDialog(SDL_DialogFileCallback c
* \param allow_many if non-zero, the user will be allowed to select multiple
* entries. Not all platforms support this option.
*
+ * \threadsafety This function should be called only from the main thread. The
+ * callback may be invoked from the same thread or from a
+ * different one, depending on the OS's constraints.
+ *
* \since This function is available since SDL 3.1.3.
*
* \sa SDL_DialogFileCallback
* \sa SDL_ShowOpenFileDialog
* \sa SDL_ShowSaveFileDialog
+ * \sa SDL_ShowFileDialogWithProperties
*/
extern SDL_DECLSPEC void SDLCALL SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char *default_location, bool allow_many);
+typedef enum SDL_FileDialogType {
+ SDL_FILEDIALOG_OPENFILE,
+ SDL_FILEDIALOG_SAVEFILE,
+ SDL_FILEDIALOG_OPENFOLDER
+} SDL_FileDialogType;
+
+#define SDL_PROP_FILE_DIALOG_FILTERS_POINTER "SDL.filedialog.filters"
+#define SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER "SDL.filedialog.nfilters"
+#define SDL_PROP_FILE_DIALOG_WINDOW_POINTER "SDL.filedialog.window"
+#define SDL_PROP_FILE_DIALOG_LOCATION_STRING "SDL.filedialog.location"
+#define SDL_PROP_FILE_DIALOG_MANY_BOOLEAN "SDL.filedialog.many"
+#define SDL_PROP_FILE_DIALOG_TITLE_STRING "SDL.filedialog.title"
+#define SDL_PROP_FILE_DIALOG_ACCEPT_STRING "SDL.filedialog.accept"
+#define SDL_PROP_FILE_DIALOG_CANCEL_STRING "SDL.filedialog.cancel"
+
+/**
+ * Create and launch a file dialog with the specified properties.
+ *
+ * These are the supported properties:
+ *
+ * - `SDL_PROP_FILE_DIALOG_FILTERS_POINTER`: a pointer to a list of
+ * SDL_DialogFileFilter's, which will be used as filters for file-based
+ * selections. Ignored if the dialog is an "Open Folder" dialog. If non-NULL,
+ * the array of filters must remain valid at least until the callback is
+ * invoked.
+ * - `SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER`: the number of filters in the array
+ * of filters, if it exists.
+ * - `SDL_PROP_FILE_DIALOG_WINDOW_POINTER`: the window that the dialog should
+ * be modal for.
+ * - `SDL_PROP_FILE_DIALOG_LOCATION_STRING`: the default folder or file to
+ * start the dialog at.
+ * - `SDL_PROP_FILE_DIALOG_MANY_BOOLEAN`: true to allow the user to select more
+ * than one entry.
+ * - `SDL_PROP_FILE_DIALOG_TITLE_STRING`: the title for the dialog.
+ * - `SDL_PROP_FILE_DIALOG_ACCEPT_STRING`: the label that the accept button
+ * should have.
+ * - `SDL_PROP_FILE_DIALOG_CANCEL_STRING`: the label that the cancel button
+ * should have.
+ *
+ * Note that each platform may or may not support any of the properties.
+ *
+ * \param type the type of file dialog.
+ * \param callback a function pointer to be invoked when the user selects a
+ * file and accepts, or cancels the dialog, or an error
+ * occurs.
+ * \param userdata an optional pointer to pass extra data to the callback when
+ * it will be invoked.
+ * \param props the properties to use.
+ *
+ * \threadsafety This function should be called only from the main thread. The
+ * callback may be invoked from the same thread or from a
+ * different one, depending on the OS's constraints.
+ *
+ * \since This function is available since SDL 3.2.0.
+ *
+ * \sa SDL_FileDialogType
+ * \sa SDL_DialogFileCallback
+ * \sa SDL_DialogFileFilter
+ * \sa SDL_ShowOpenFileDialog
+ * \sa SDL_ShowSaveFileDialog
+ * \sa SDL_ShowOpenFolderDialog
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props);
+
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
diff --git a/src/dialog/SDL_dialog.c b/src/dialog/SDL_dialog.c
new file mode 100644
index 0000000000000..938666b210f9c
--- /dev/null
+++ b/src/dialog/SDL_dialog.c
@@ -0,0 +1,103 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_internal.h"
+
+#include "SDL_dialog.h"
+#include "SDL_dialog_utils.h"
+
+void SDL_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props)
+{
+ if (!callback) {
+ return;
+ }
+
+ SDL_DialogFileFilter *filters = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, NULL);
+ int nfilters = (int) SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, -1);
+
+ if (filters && nfilters == -1) {
+ SDL_SetError("Set filter pointers, but didn't set number of filters (SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER)");
+ callback(userdata, NULL, -1);
+ return;
+ }
+
+ const char *msg = validate_filters(filters, nfilters);
+
+ if (msg) {
+ SDL_SetError("Invalid dialog file filters: %s", msg);
+ callback(userdata, NULL, -1);
+ return;
+ }
+
+ switch (type) {
+ case SDL_FILEDIALOG_OPENFILE:
+ case SDL_FILEDIALOG_SAVEFILE:
+ case SDL_FILEDIALOG_OPENFOLDER:
+ SDL_SYS_ShowFileDialogWithProperties(type, callback, userdata, props);
+ break;
+
+ default:
+ SDL_SetError("Unsupported file dialog type: %d", (int) type);
+ callback(userdata, NULL, -1);
+ break;
+ };
+}
+
+void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location, bool allow_many)
+{
+ SDL_PropertiesID props = SDL_CreateProperties();
+
+ SDL_SetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, (void *) filters);
+ SDL_SetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, nfilters);
+ SDL_SetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, window);
+ SDL_SetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, default_location);
+ SDL_SetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, allow_many);
+
+ SDL_ShowFileDialogWithProperties(SDL_FILEDIALOG_OPENFILE, callback, userdata, props);
+
+ SDL_DestroyProperties(props);
+}
+
+void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location)
+{
+ SDL_PropertiesID props = SDL_CreateProperties();
+
+ SDL_SetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, (void *) filters);
+ SDL_SetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, nfilters);
+ SDL_SetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, window);
+ SDL_SetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, default_location);
+
+ SDL_ShowFileDialogWithProperties(SDL_FILEDIALOG_SAVEFILE, callback, userdata, props);
+
+ SDL_DestroyProperties(props);
+}
+
+void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char *default_location, bool allow_many)
+{
+ SDL_PropertiesID props = SDL_CreateProperties();
+
+ SDL_SetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, window);
+ SDL_SetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, default_location);
+ SDL_SetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, allow_many);
+
+ SDL_ShowFileDialogWithProperties(SDL_FILEDIALOG_OPENFOLDER, callback, userdata, props);
+
+ SDL_DestroyProperties(props);
+}
diff --git a/src/dialog/SDL_dialog.h b/src/dialog/SDL_dialog.h
new file mode 100644
index 0000000000000..b3d3318f33ce4
--- /dev/null
+++ b/src/dialog/SDL_dialog.h
@@ -0,0 +1,22 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props);
diff --git a/src/dialog/android/SDL_androiddialog.c b/src/dialog/android/SDL_androiddialog.c
index fd9e102ef64f5..d4723f843b070 100644
--- a/src/dialog/android/SDL_androiddialog.c
+++ b/src/dialog/android/SDL_androiddialog.c
@@ -20,26 +20,39 @@
*/
#include "SDL_internal.h"
+#include "../SDL_dialog.h"
#include "../../core/android/SDL_android.h"
-void SDLCALL SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location, bool allow_many)
+void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props)
{
- if (!Android_JNI_OpenFileDialog(callback, userdata, filters, nfilters, false, allow_many)) {
- // SDL_SetError is already called when it fails
+ SDL_DialogFileFilter *filters = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, NULL);
+ int nfilters = (int) SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, 0);
+ bool allow_many = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false);
+ bool is_save;
+
+ if (SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER) != NULL) {
+ SDL_SetError("File dialog driver unsupported (don't set SDL_HINT_FILE_DIALOG_DRIVER)");
callback(userdata, NULL, -1);
+ return;
}
-}
-void SDLCALL SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location)
-{
- if (!Android_JNI_OpenFileDialog(callback, userdata, filters, nfilters, true, false)) {
+ switch (type) {
+ case SDL_FILEDIALOG_OPENFILE:
+ is_save = false;
+ break;
+
+ case SDL_FILEDIALOG_SAVEFILE:
+ is_save = true;
+ break;
+
+ case SDL_FILEDIALOG_OPENFOLDER:
+ SDL_Unsupported();
+ callback(userdata, NULL, -1);
+ return;
+ };
+
+ if (!Android_JNI_OpenFileDialog(callback, userdata, filters, nfilters, is_save, allow_many)) {
// SDL_SetError is already called when it fails
callback(userdata, NULL, -1);
}
}
-
-void SDLCALL SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char *default_location, bool allow_many)
-{
- SDL_Unsupported();
- callback(userdata, NULL, -1);
-}
diff --git a/src/dialog/cocoa/SDL_cocoadialog.m b/src/dialog/cocoa/SDL_cocoadialog.m
index 2500663735341..22f67b6c54f00 100644
--- a/src/dialog/cocoa/SDL_cocoadialog.m
+++ b/src/dialog/cocoa/SDL_cocoadialog.m
@@ -19,6 +19,7 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
+#include "../SDL_dialog.h"
#include "../SDL_dialog_utils.h"
#ifdef SDL_PLATFORM_MACOS
@@ -26,15 +27,16 @@
#import <Cocoa/Cocoa.h>
#import <UniformTypeIdentifiers/UTType.h>
-typedef enum
+void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props)
{
- FDT_SAVE,
- FDT_OPEN,
- FDT_OPENFOLDER
-} cocoa_FileDialogType;
+ SDL_Window* window = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, NULL);
+ SDL_DialogFileFilter *filters = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, NULL);
+ int nfilters = (int) SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, 0);
+ bool allow_many = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false);
+ const char* default_location = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, NULL);
+ const char* title = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_TITLE_STRING, NULL);
+ const char* accept = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_ACCEPT_STRING, NULL);
-void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many)
-{
if (filters) {
const char *msg = validate_filters(filters, nfilters);
@@ -46,7 +48,7 @@ void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback
}
if (SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER) != NULL) {
- SDL_SetError("File dialog driver unsupported");
+ SDL_SetError("File dialog driver unsupported (don't set SDL_HINT_FILE_DIALOG_DRIVER)");
callback(userdata, NULL, -1);
return;
}
@@ -56,15 +58,17 @@ void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback
NSOpenPanel *dialog_as_open;
switch (type) {
- case FDT_SAVE:
+ case SDL_FILEDIALOG_SAVEFILE:
dialog = [NSSavePanel savePanel];
break;
- case FDT_OPEN:
+
+ case SDL_FILEDIALOG_OPENFILE:
dialog_as_open = [NSOpenPanel openPanel];
[dialog_as_open setAllowsMultipleSelection:((allow_many == true) ? YES : NO)];
dialog = dialog_as_open;
break;
- case FDT_OPENFOLDER:
+
+ case SDL_FILEDIALOG_OPENFOLDER:
dialog_as_open = [NSOpenPanel openPanel];
[dialog_as_open setCanChooseFiles:NO];
[dialog_as_open setCanChooseDirectories:YES];
@@ -73,6 +77,14 @@ void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback
break;
};
+ if (title) {
+ [dialog setTitle:[NSString stringWithUTF8String:title]];
+ }
+
+ if (accept) {
+ [dialog setPrompt:[NSString stringWithUTF8String:accept]];
+ }
+
if (filters) {
// On macOS 11.0 and up, this is an array of UTType. Prior to that, it's an array of NSString
NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:nfilters ];
@@ -175,19 +187,4 @@ void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback
}
}
-void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many)
-{
- show_file_dialog(FDT_OPEN, callback, userdata, window, filters, nfilters, default_location, allow_many);
-}
-
-void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location)
-{
- show_file_dialog(FDT_SAVE, callback, userdata, window, filters, nfilters, default_location, 0);
-}
-
-void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many)
-{
- show_file_dialog(FDT_OPENFOLDER, callback, userdata, window, NULL, 0, default_location, allow_many);
-}
-
#endif // SDL_PLATFORM_MACOS
diff --git a/src/dialog/dummy/SDL_dummydialog.c b/src/dialog/dummy/SDL_dummydialog.c
index 81ba1f59d98ed..16cf1802d33ea 100644
--- a/src/dialog/dummy/SDL_dummydialog.c
+++ b/src/dialog/dummy/SDL_dummydialog.c
@@ -20,21 +20,11 @@
*/
#include "SDL_internal.h"
-#ifdef SDL_DIALOG_DUMMY
-
-void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many)
-{
- SDL_Unsupported();
- callback(userdata, NULL, -1);
-}
+#include "../SDL_dialog.h"
-void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location)
-{
- SDL_Unsupported();
- callback(userdata, NULL, -1);
-}
+#ifdef SDL_DIALOG_DUMMY
-void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many)
+void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props)
{
SDL_Unsupported();
callback(userdata, NULL, -1);
diff --git a/src/dialog/haiku/SDL_haikudialog.cc b/src/dialog/haiku/SDL_haikudialog.cc
index 9d6e37303e4e2..1ebf000a17288 100644
--- a/src/dialog/haiku/SDL_haikudialog.cc
+++ b/src/dialog/haiku/SDL_haikudialog.cc
@@ -20,9 +20,11 @@
*/
#include "SDL_internal.h"
extern "C" {
+#include "../SDL_dialog.h"
#include "../SDL_dialog_utils.h"
}
#include "../../core/haiku/SDL_BeApp.h"
+#include "../../video/haiku/SDL_BWin.h"
#include <string>
#include <vector>
@@ -190,8 +192,35 @@ class CallbackLooper : public BLooper
SDLBRefFilter *m_filter;
};
-void ShowDialog(bool save, SDL_DialogFileCallback callback, void *userdata, bool many, bool modal, const SDL_DialogFileFilter *filters, int nfilters, bool folder, const char *location)
+void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props)
{
+ SDL_Window* window = (SDL_Window*) SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, NULL);
+ SDL_DialogFileFilter* filters = (SDL_DialogFileFilter*) SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, NULL);
+ int nfilters = (int) SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, 0);
+ bool many = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false);
+ const char* location = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, NULL);
+ const char* title = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_TITLE_STRING, NULL);
+ const char* accept = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_ACCEPT_STRING, NULL);
+ const char* cancel = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_CANCEL_STRING, NULL);
+
+ bool modal = !!window;
+
+ bool save = false;
+ bool folder = false;
+
+ switch (type) {
+ case SDL_FILEDIALOG_SAVEFILE:
+ save = true;
+ break;
+
+ case SDL_FILEDIALOG_OPENFILE:
+ break;
+
+ case SDL_FILEDIALOG_OPENFOLDER:
+ folder = true;
+ break;
+ };
+
if (!SDL_InitBeApp()) {
char* err = SDL_strdup(SDL_GetError());
SDL_SetError("Couldn't init Be app: %s", err);
@@ -238,22 +267,27 @@ void ShowDialog(bool save, SDL_DialogFileCallback callback, void *userdata, bool
}
BFilePanel *panel = new BFilePanel(save ? B_SAVE_PANEL : B_OPEN_PANEL, messenger, location ? &entryref : NULL, folder ? B_DIRECTORY_NODE : B_FILE_NODE, many, NULL, filter, modal);
- looper->SetToBeFreed(messenger, panel, filter);
- looper->Run();
- panel->Show();
-}
-void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location, bool allow_many)
-{
- ShowDialog(false, callback, userdata, allow_many == true, !!window, filters, nfilters, false, default_location);
-}
+ if (title) {
+ panel->Window()->SetTitle(title);
+ }
-void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location)
-{
- ShowDialog(true, callback, userdata, false, !!window, filters, nfilters, false, default_location);
-}
+ if (accept) {
+ panel->SetButtonLabel(B_DEFAULT_BUTTON, accept);
+ }
-void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char* default_location, bool allow_many)
-{
- ShowDialog(false, callback, userdata, allow_many == true, !!window, NULL, 0, true, default_location);
+ if (cancel) {
+ panel->SetButtonLabel(B_CANCEL_BUTTON, cancel);
+ }
+
+ if (window) {
+ SDL_BWin *bwin = (SDL_BWin *)(window->internal);
+ panel->Window()->SetLook(B_MODAL_WINDOW_LOOK);
+ panel->Window()->SetFeel(B_MODAL_SUBSET_WINDOW_FEEL);
+ panel->Window()->AddToSubset(bwin);
+ }
+
+ looper->SetToBeFreed(messenger, panel, filter);
+ looper->Run();
+ panel->Show();
}
diff --git a/src/dialog/unix/SDL_portaldialog.c b/src/dialog/unix/SDL_portaldialog.c
index ac6b575c49fe2..2d0567dd558eb 100644
--- a/src/dialog/unix/SDL_portaldialog.c
+++ b/src/dialog/unix/SDL_portaldialog.c
@@ -275,8 +275,43 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-static void DBus_OpenDialog(const char *method, const char *method_title, SDL_DialogFileCallback callback, void* userdat
(Patch may be truncated, please check the link at the top of this post.)