Skip to content

Commit ddcc6f2

Browse files
committed
dialog: Add more xdg portal fields for saving
This reduces the likelyhood of the user saving a file without an extension. In the case of flatpaks portals provide the application with a virtual path to the user selected file exclusively. As the name of this file cannot be changed (e.g. to fix the extension) it is important to give the dialog enough hints so that the user will name it something sensible. * `current_filter`: Index of the filter to show on dialog creation * `current_name`: Placeholder for a save file operation * `current_file`: Path to an existing file to save over
1 parent aaa5d70 commit ddcc6f2

File tree

3 files changed

+62
-8
lines changed

3 files changed

+62
-8
lines changed

include/SDL3/SDL_dialog.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,17 @@ typedef enum SDL_FileDialogType
323323
*/
324324
extern SDL_DECLSPEC void SDLCALL SDL_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props);
325325

326-
#define SDL_PROP_FILE_DIALOG_FILTERS_POINTER "SDL.filedialog.filters"
327-
#define SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER "SDL.filedialog.nfilters"
328-
#define SDL_PROP_FILE_DIALOG_WINDOW_POINTER "SDL.filedialog.window"
329-
#define SDL_PROP_FILE_DIALOG_LOCATION_STRING "SDL.filedialog.location"
330-
#define SDL_PROP_FILE_DIALOG_MANY_BOOLEAN "SDL.filedialog.many"
331-
#define SDL_PROP_FILE_DIALOG_TITLE_STRING "SDL.filedialog.title"
332-
#define SDL_PROP_FILE_DIALOG_ACCEPT_STRING "SDL.filedialog.accept"
333-
#define SDL_PROP_FILE_DIALOG_CANCEL_STRING "SDL.filedialog.cancel"
326+
#define SDL_PROP_FILE_DIALOG_FILTERS_POINTER "SDL.filedialog.filters"
327+
#define SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER "SDL.filedialog.nfilters"
328+
#define SDL_PROP_FILE_DIALOG_CURRENT_FILTER_NUMBER "SDL.filedialog.current_filter"
329+
#define SDL_PROP_FILE_DIALOG_WINDOW_POINTER "SDL.filedialog.window"
330+
#define SDL_PROP_FILE_DIALOG_LOCATION_STRING "SDL.filedialog.location"
331+
#define SDL_PROP_FILE_DIALOG_CURRENT_NAME_STRING "SDL.filedialog.current_name"
332+
#define SDL_PROP_FILE_DIALOG_CURRENT_FILE_STRING "SDL.filedialog.current_file"
333+
#define SDL_PROP_FILE_DIALOG_MANY_BOOLEAN "SDL.filedialog.many"
334+
#define SDL_PROP_FILE_DIALOG_TITLE_STRING "SDL.filedialog.title"
335+
#define SDL_PROP_FILE_DIALOG_ACCEPT_STRING "SDL.filedialog.accept"
336+
#define SDL_PROP_FILE_DIALOG_CANCEL_STRING "SDL.filedialog.cancel"
334337

335338
/* Ends C function definitions when using C++ */
336339
#ifdef __cplusplus

src/dialog/unix/SDL_portaldialog.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,20 @@ static void DBus_AppendFilters(SDL_DBusContext *dbus, DBusMessageIter *options,
137137
dbus->message_iter_close_container(options, &options_pair);
138138
}
139139

140+
static void DBus_AppendCurrentFilter(SDL_DBusContext *dbus, DBusMessageIter *options, const SDL_DialogFileFilter filter)
141+
{
142+
DBusMessageIter options_pair, options_value;
143+
static const char *current_filter_name = "current_filter";
144+
145+
dbus->message_iter_open_container(options, DBUS_TYPE_DICT_ENTRY, NULL, &options_pair);
146+
dbus->message_iter_append_basic(&options_pair, DBUS_TYPE_STRING, &current_filter_name);
147+
dbus->message_iter_open_container(&options_pair, DBUS_TYPE_VARIANT, "(sa(us))", &options_value);
148+
DBus_AppendFilter(dbus, &options_value, filter);
149+
dbus->message_iter_close_container(&options_pair, &options_value);
150+
dbus->message_iter_close_container(options, &options_pair);
151+
152+
}
153+
140154
static void DBus_AppendByteArray(SDL_DBusContext *dbus, DBusMessageIter *options, const char *key, const char *value)
141155
{
142156
DBusMessageIter options_pair, options_value, options_array;
@@ -291,8 +305,11 @@ void SDL_Portal_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_Dialog
291305
SDL_Window* window = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, NULL);
292306
SDL_DialogFileFilter *filters = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, NULL);
293307
int nfilters = (int) SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, 0);
308+
int current_filter = (int) SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_CURRENT_FILTER_NUMBER, -1);
294309
bool allow_many = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false);
295310
const char* default_location = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, NULL);
311+
const char* current_name = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_CURRENT_NAME_STRING, NULL);
312+
const char* current_file = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_CURRENT_FILE_STRING, NULL);
296313
const char* accept = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_ACCEPT_STRING, NULL);
297314
bool open_folders = false;
298315

@@ -408,10 +425,19 @@ void SDL_Portal_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_Dialog
408425
}
409426
if (filters) {
410427
DBus_AppendFilters(dbus, &options, filters, nfilters);
428+
if (current_filter >= 0 && current_filter < nfilters) {
429+
DBus_AppendCurrentFilter(dbus, &options, filters[current_filter]);
430+
}
411431
}
412432
if (default_location) {
413433
DBus_AppendByteArray(dbus, &options, "current_folder", default_location);
414434
}
435+
if (current_file) {
436+
DBus_AppendByteArray(dbus, &options, "current_file", current_file);
437+
}
438+
if (current_name) {
439+
DBus_AppendStringOption(dbus, &options, "current_name", current_name);
440+
}
415441
if (accept) {
416442
DBus_AppendStringOption(dbus, &options, "accept_label", accept);
417443
}

test/testdialog.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ const SDL_DialogFileFilter filters[] = {
2323
};
2424

2525
static void SDLCALL callback(void *userdata, const char * const *files, int filter) {
26+
char **save_path = userdata;
27+
2628
if (files) {
2729
const char* filter_name = "(filter fetching unsupported)";
2830

@@ -36,6 +38,11 @@ static void SDLCALL callback(void *userdata, const char * const *files, int filt
3638

3739
SDL_Log("Filter used: '%s'", filter_name);
3840

41+
if (save_path && *files) {
42+
SDL_free(*save_path);
43+
*save_path = SDL_strdup(*files);
44+
}
45+
3946
while (*files) {
4047
SDL_Log("'%s'", *files);
4148
files++;
@@ -52,9 +59,11 @@ int main(int argc, char *argv[])
5259
SDLTest_CommonState *state;
5360
const SDL_FRect open_file_rect = { 50, 50, 220, 140 };
5461
const SDL_FRect save_file_rect = { 50, 290, 220, 140 };
62+
const SDL_FRect save_adv_file_rect = { 370, 290, 220, 140 };
5563
const SDL_FRect open_folder_rect = { 370, 50, 220, 140 };
5664
int i;
5765
const char *initial_path = NULL;
66+
char *save_path = NULL;
5867

5968
/* Initialize test framework */
6069
state = SDLTest_CommonCreateState(argv, 0);
@@ -117,6 +126,18 @@ int main(int argc, char *argv[])
117126
SDL_ShowOpenFolderDialog(callback, NULL, w, initial_path, 1);
118127
} else if (SDL_PointInRectFloat(&p, &save_file_rect)) {
119128
SDL_ShowSaveFileDialog(callback, NULL, w, filters, SDL_arraysize(filters), initial_path);
129+
} else if (SDL_PointInRectFloat(&p, &save_adv_file_rect)) {
130+
SDL_PropertiesID props = SDL_CreateProperties();
131+
SDL_SetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, SDL_arraysize(filters));
132+
SDL_SetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, (void *) filters);
133+
SDL_SetNumberProperty(props, SDL_PROP_FILE_DIALOG_CURRENT_FILTER_NUMBER, 1);
134+
if(save_path) {
135+
SDL_SetStringProperty(props, SDL_PROP_FILE_DIALOG_CURRENT_FILE_STRING, save_path);
136+
} else {
137+
SDL_SetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, initial_path);
138+
SDL_SetStringProperty(props, SDL_PROP_FILE_DIALOG_CURRENT_NAME_STRING, "Untitled.index");
139+
}
140+
SDL_ShowFileDialogWithProperties(SDL_FILEDIALOG_SAVEFILE, callback, &save_path, props);
120141
}
121142
}
122143
}
@@ -134,12 +155,16 @@ int main(int argc, char *argv[])
134155
SDL_SetRenderDrawColor(r, 0, 255, 0, SDL_ALPHA_OPAQUE);
135156
SDL_RenderFillRect(r, &save_file_rect);
136157

158+
SDL_SetRenderDrawColor(r, 0, 255, 0, SDL_ALPHA_OPAQUE);
159+
SDL_RenderFillRect(r, &save_adv_file_rect);
160+
137161
SDL_SetRenderDrawColor(r, 0, 0, 255, SDL_ALPHA_OPAQUE);
138162
SDL_RenderFillRect(r, &open_folder_rect);
139163

140164
SDL_SetRenderDrawColor(r, 0, 0, 0, SDL_ALPHA_OPAQUE);
141165
SDLTest_DrawString(r, open_file_rect.x+5, open_file_rect.y+open_file_rect.h/2, "Open File...");
142166
SDLTest_DrawString(r, save_file_rect.x+5, save_file_rect.y+save_file_rect.h/2, "Save File...");
167+
SDLTest_DrawString(r, save_adv_file_rect.x+5, save_adv_file_rect.y+save_adv_file_rect.h/2, "Save File with props...");
143168
SDLTest_DrawString(r, open_folder_rect.x+5, open_folder_rect.y+open_folder_rect.h/2, "Open Folder...");
144169

145170
SDL_RenderPresent(r);

0 commit comments

Comments
 (0)