Skip to content

Commit 07d22c9

Browse files
committed
dialog: Fix save file chooser with xdg portal
This correctly sets the xdg portal fields for targeting a specific new filename or existing file. "current_name" sets the dialogs placeholder name. "current_file" targets an existing file. "current_folder" for when the target is a folder.
1 parent f625723 commit 07d22c9

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

src/dialog/unix/SDL_portaldialog.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525

2626
#ifdef SDL_USE_LIBDBUS
2727

28+
#include <libgen.h>
2829
#include <errno.h>
2930
#include <sys/types.h>
3031
#include <sys/wait.h>
32+
#include <sys/stat.h>
3133
#include <unistd.h>
3234

3335
#define PORTAL_DESTINATION "org.freedesktop.portal.Desktop"
@@ -294,7 +296,12 @@ void SDL_Portal_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_Dialog
294296
bool allow_many = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false);
295297
const char* default_location = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, NULL);
296298
const char* accept = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_ACCEPT_STRING, NULL);
299+
char* location_name = NULL;
300+
char* location_folder = NULL;
301+
struct stat statbuf;
297302
bool open_folders = false;
303+
bool save_file_existing = false;
304+
bool save_file_new_named = false;
298305

299306
switch (type) {
300307
case SDL_FILEDIALOG_OPENFILE:
@@ -305,6 +312,22 @@ void SDL_Portal_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_Dialog
305312
case SDL_FILEDIALOG_SAVEFILE:
306313
method = "SaveFile";
307314
method_title = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_TITLE_STRING, "Save File");
315+
if (default_location) {
316+
if (stat(default_location, &statbuf) == 0) {
317+
save_file_existing = S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode);
318+
} else if (errno == ENOENT) {
319+
char *dirc = SDL_strdup(default_location);
320+
location_folder = SDL_strdup(dirname(dirc));
321+
SDL_free(dirc);
322+
save_file_new_named = (stat(location_folder, &statbuf) == 0) && S_ISDIR(statbuf.st_mode);
323+
}
324+
325+
if (save_file_existing || save_file_new_named) {
326+
char *basec = SDL_strdup(default_location);
327+
location_name = SDL_strdup(basename(basec));
328+
SDL_free(basec);
329+
}
330+
}
308331
break;
309332

310333
case SDL_FILEDIALOG_OPENFOLDER:
@@ -410,8 +433,26 @@ void SDL_Portal_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_Dialog
410433
DBus_AppendFilters(dbus, &options, filters, nfilters);
411434
}
412435
if (default_location) {
413-
DBus_AppendByteArray(dbus, &options, "current_folder", default_location);
436+
if (save_file_existing) {
437+
SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Create save dialog for existing file");
438+
DBus_AppendByteArray(dbus, &options, "current_file", default_location);
439+
/* Setting "current_name" should not be necessary however the kde-desktop-portal sets the filename without an extension.
440+
* An alternative would be to match the extension to a filter and set "current_filter".
441+
*/
442+
DBus_AppendStringOption(dbus, &options, "current_name", location_name);
443+
} else if (save_file_new_named) {
444+
SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Create save dialog for new file");
445+
DBus_AppendByteArray(dbus, &options, "current_folder", location_folder);
446+
DBus_AppendStringOption(dbus, &options, "current_name", location_name);
447+
} else {
448+
SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Create dialog at folder");
449+
DBus_AppendByteArray(dbus, &options, "current_folder", default_location);
450+
}
451+
452+
SDL_free(location_name);
453+
SDL_free(location_folder);
414454
}
455+
415456
if (accept) {
416457
DBus_AppendStringOption(dbus, &options, "accept_label", accept);
417458
}

test/testdialog.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#include <SDL3/SDL.h>
1515
#include <SDL3/SDL_main.h>
1616
#include <SDL3/SDL_test.h>
17+
#include <fcntl.h>
18+
#include <sys/stat.h>
19+
#include <unistd.h>
1720

1821
const SDL_DialogFileFilter filters[] = {
1922
{ "All files", "*" },
@@ -23,6 +26,8 @@ const SDL_DialogFileFilter filters[] = {
2326
};
2427

2528
static void SDLCALL callback(void *userdata, const char * const *files, int filter) {
29+
char **saved_path = userdata;
30+
2631
if (files) {
2732
const char* filter_name = "(filter fetching unsupported)";
2833

@@ -36,6 +41,12 @@ static void SDLCALL callback(void *userdata, const char * const *files, int filt
3641

3742
SDL_Log("Filter used: '%s'", filter_name);
3843

44+
if (*files && saved_path) {
45+
*saved_path = SDL_strdup(*files);
46+
int32_t fd = open(*saved_path, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO );
47+
close(fd);
48+
}
49+
3950
while (*files) {
4051
SDL_Log("'%s'", *files);
4152
files++;
@@ -55,6 +66,7 @@ int main(int argc, char *argv[])
5566
const SDL_FRect open_folder_rect = { 370, 50, 220, 140 };
5667
int i;
5768
const char *initial_path = NULL;
69+
char *saved_path = NULL;
5870

5971
/* Initialize test framework */
6072
state = SDLTest_CommonCreateState(argv, 0);
@@ -116,7 +128,19 @@ int main(int argc, char *argv[])
116128
} else if (SDL_PointInRectFloat(&p, &open_folder_rect)) {
117129
SDL_ShowOpenFolderDialog(callback, NULL, w, initial_path, 1);
118130
} else if (SDL_PointInRectFloat(&p, &save_file_rect)) {
119-
SDL_ShowSaveFileDialog(callback, NULL, w, filters, SDL_arraysize(filters), initial_path);
131+
const char *default_filename = "Untitled.index";
132+
const size_t save_path_total_length = SDL_strlen(initial_path) + SDL_strlen(default_filename) + 1;
133+
char *save_path;
134+
if (saved_path) {
135+
save_path = SDL_strdup(saved_path);
136+
} else {
137+
save_path = (char *)SDL_malloc(save_path_total_length);
138+
*save_path = '\0';
139+
SDL_strlcat(save_path, initial_path, save_path_total_length);
140+
SDL_strlcat(save_path, default_filename, save_path_total_length);
141+
}
142+
SDL_ShowSaveFileDialog(callback, &saved_path, w, filters, SDL_arraysize(filters), save_path);
143+
SDL_free(save_path);
120144
}
121145
}
122146
}

0 commit comments

Comments
 (0)