Skip to content

Commit c74e22a

Browse files
author
Semphris
committed
Add simple input dialog function
1 parent de1b52f commit c74e22a

File tree

10 files changed

+182
-5
lines changed

10 files changed

+182
-5
lines changed

include/SDL3/SDL_dialog.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,52 @@ extern SDL_DECLSPEC void SDLCALL SDL_ShowFileDialogWithProperties(SDL_FileDialog
334334
#define SDL_PROP_FILE_DIALOG_ACCEPT_STRING "SDL.filedialog.accept"
335335
#define SDL_PROP_FILE_DIALOG_CANCEL_STRING "SDL.filedialog.cancel"
336336

337+
/**
338+
* Callback used by input dialog functions.
339+
*
340+
* If `value` is NULL, an error occured. Details can be obtained with
341+
* SDL_GetError().
342+
*
343+
* If the user cancels the dialog, the callback will be invoked with an empty
344+
* string. It is not possible to differentiate cancelling and inputting an empty
345+
* string.
346+
*
347+
* The value argument should not be freed; it will automatically be freed
348+
* when the callback returns. If you need to keep the string after the callback
349+
* returns, you must duplicate it with SDL_strdup() or some other means.
350+
*
351+
* \param userdata an app-provided pointer, for the callback's use.
352+
* \param value the value provided by the user, or NULL if an error occured.
353+
*
354+
* \since This datatype is available since SDL 3.4.0.
355+
*
356+
* \sa SDL_ShowSimpleInputDialog
357+
*/
358+
typedef void (SDLCALL *SDL_DialogInputCallback)(void *userdata, const char *value);
359+
360+
/**
361+
* Show a simple dialog prompting the user to input a string.
362+
*
363+
* \param callback a function pointer to be invoked when the user inputs a
364+
* string and confirms, or cancels the dialog, or an error
365+
* occurs.
366+
* \param userdata an optional pointer to pass extra data to the callback when
367+
* it will be invoked.
368+
* \param title the title of the dialog. May be NULL.
369+
* \param message the message of the dialog. May be NULL.
370+
* \param value the default value of the dialog. May be NULL.
371+
* \param window the window the dialog should be modal for. May be NULL.
372+
*
373+
* \threadsafety This function should be called only from the main thread. The
374+
* callback may be invoked from the same thread or from a
375+
* different one, depending on the OS's constraints.
376+
*
377+
* \since This function is available since SDL 3.4.0.
378+
*
379+
* \sa SDL_DialogInputCallback
380+
*/
381+
extern SDL_DECLSPEC void SDLCALL SDL_ShowSimpleInputDialog(SDL_DialogInputCallback callback, void *userdata, const char *title, const char *message, const char *value, SDL_Window *window);
382+
337383
/* Ends C function definitions when using C++ */
338384
#ifdef __cplusplus
339385
}

src/dialog/unix/SDL_portaldialog.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,12 @@ void SDL_Portal_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_Dialog
534534
SDL_free(location_folder);
535535
}
536536

537+
void SDL_Portal_ShowSimpleInputDialog(SDL_DialogInputCallback callback, void *userdata, const char *title, const char *message, const char *value, SDL_Window *window)
538+
{
539+
SDL_Unsupported();
540+
callback(userdata, NULL);
541+
}
542+
537543
bool SDL_Portal_detect(void)
538544
{
539545
SDL_DBusContext *dbus = SDL_DBus_GetContext();
@@ -600,6 +606,12 @@ void SDL_Portal_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_Dialog
600606
callback(userdata, NULL, -1);
601607
}
602608

609+
void SDL_Portal_ShowSimpleInputDialog(SDL_DialogInputCallback callback, void *userdata, const char *title, const char *message, const char *value, SDL_Window *window)
610+
{
611+
SDL_Unsupported();
612+
callback(userdata, NULL);
613+
}
614+
603615
bool SDL_Portal_detect(void)
604616
{
605617
return false;

src/dialog/unix/SDL_portaldialog.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,7 @@
2323

2424
void SDL_Portal_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props);
2525

26+
void SDL_Portal_ShowSimpleInputDialog(SDL_DialogInputCallback callback, void *userdata, const char *title, const char *message, const char *value, SDL_Window *window);
27+
2628
/** @returns non-zero if available, zero if unavailable */
2729
bool SDL_Portal_detect(void);

src/dialog/unix/SDL_unixdialog.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
#include "./SDL_portaldialog.h"
2525
#include "./SDL_zenitydialog.h"
2626

27-
static void (*detected_function)(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props) = NULL;
27+
static void (*detected_dialog)(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props) = NULL;
28+
static void (*detected_input)(SDL_DialogInputCallback callback, void *userdata, const char *title, const char *message, const char *value, SDL_Window *window) = NULL;
2829

2930
void SDLCALL hint_callback(void *userdata, const char *name, const char *oldValue, const char *newValue);
3031

@@ -47,14 +48,16 @@ static int detect_available_methods(const char *value)
4748

4849
if (driver == NULL || SDL_strcmp(driver, "portal") == 0) {
4950
if (SDL_Portal_detect()) {
50-
detected_function = SDL_Portal_ShowFileDialogWithProperties;
51+
detected_dialog = SDL_Portal_ShowFileDialogWithProperties;
52+
detected_input = SDL_Zenity_ShowSimpleInputDialog;
5153
return 1;
5254
}
5355
}
5456

5557
if (driver == NULL || SDL_strcmp(driver, "zenity") == 0) {
5658
if (SDL_Zenity_detect()) {
57-
detected_function = SDL_Zenity_ShowFileDialogWithProperties;
59+
detected_dialog = SDL_Zenity_ShowFileDialogWithProperties;
60+
detected_input = SDL_Zenity_ShowSimpleInputDialog;
5861
return 2;
5962
}
6063
}
@@ -71,11 +74,23 @@ void SDLCALL hint_callback(void *userdata, const char *name, const char *oldValu
7174
void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props)
7275
{
7376
// Call detect_available_methods() again each time in case the situation changed
74-
if (!detected_function && !detect_available_methods(NULL)) {
77+
if (!detected_dialog && !detect_available_methods(NULL)) {
7578
// SetError() done by detect_available_methods()
7679
callback(userdata, NULL, -1);
7780
return;
7881
}
7982

80-
detected_function(type, callback, userdata, props);
83+
detected_dialog(type, callback, userdata, props);
84+
}
85+
86+
void SDL_ShowSimpleInputDialog(SDL_DialogInputCallback callback, void *userdata, const char *title, const char *message, const char *value, SDL_Window *window)
87+
{
88+
// Call detect_available_methods() again each time in case the situation changed
89+
if (!detected_input && !detect_available_methods(NULL)) {
90+
// SetError() done by detect_available_methods()
91+
callback(userdata, NULL);
92+
return;
93+
}
94+
95+
detected_input(callback, userdata, title, message, value, window);
8196
}

src/dialog/unix/SDL_zenitydialog.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,92 @@ void SDL_Zenity_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_Dialog
344344
SDL_DetachThread(thread);
345345
}
346346

347+
void SDL_Zenity_ShowSimpleInputDialog(SDL_DialogInputCallback callback, void *userdata, const char *title, const char *message, const char *value, SDL_Window *window)
348+
{
349+
SDL_Process *process = NULL;
350+
SDL_Environment *env = NULL;
351+
int status = -1;
352+
size_t bytes_read = 0;
353+
char *container = NULL;
354+
bool result = false;
355+
const char *argv[9];
356+
int argc = 0;
357+
358+
argv[argc++] = "zenity";
359+
argv[argc++] = "--entry";
360+
361+
if (title) {
362+
argv[argc++] = "--title";
363+
argv[argc++] = title;
364+
}
365+
366+
if (message) {
367+
argv[argc++] = "--text";
368+
argv[argc++] = message;
369+
}
370+
371+
if (value) {
372+
argv[argc++] = "--entry-text";
373+
argv[argc++] = value;
374+
}
375+
376+
argv[argc] = NULL;
377+
378+
env = SDL_CreateEnvironment(true);
379+
if (!env) {
380+
goto done;
381+
}
382+
383+
/* Recent versions of Zenity have different exit codes, but picks up
384+
different codes from the environment */
385+
SDL_SetEnvironmentVariable(env, "ZENITY_OK", "0", true);
386+
SDL_SetEnvironmentVariable(env, "ZENITY_CANCEL", "1", true);
387+
SDL_SetEnvironmentVariable(env, "ZENITY_ESC", "1", true);
388+
SDL_SetEnvironmentVariable(env, "ZENITY_EXTRA", "2", true);
389+
SDL_SetEnvironmentVariable(env, "ZENITY_ERROR", "2", true);
390+
SDL_SetEnvironmentVariable(env, "ZENITY_TIMEOUT", "2", true);
391+
392+
SDL_PropertiesID props = SDL_CreateProperties();
393+
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, argv);
394+
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, env);
395+
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL);
396+
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
397+
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_NULL);
398+
process = SDL_CreateProcessWithProperties(props);
399+
SDL_DestroyProperties(props);
400+
if (!process) {
401+
goto done;
402+
}
403+
404+
container = SDL_ReadProcess(process, &bytes_read, &status);
405+
if (!container) {
406+
goto done;
407+
}
408+
409+
// Strings returned by Zenity finish with '\n'; swap that with a '\0'
410+
container[bytes_read - 1] = '\0';
411+
412+
if (status == 0) {
413+
callback(userdata, container);
414+
} else if (status == 1) {
415+
callback(userdata, "");
416+
} else {
417+
SDL_SetError("Could not run zenity: exit code %d", status);
418+
callback(userdata, NULL);
419+
}
420+
421+
result = true;
422+
423+
done:
424+
SDL_free(container);
425+
SDL_DestroyEnvironment(env);
426+
SDL_DestroyProcess(process);
427+
428+
if (!result) {
429+
callback(userdata, NULL);
430+
}
431+
}
432+
347433
bool SDL_Zenity_detect(void)
348434
{
349435
const char *args[] = {

src/dialog/unix/SDL_zenitydialog.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,7 @@
2323

2424
extern void SDL_Zenity_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props);
2525

26+
extern void SDL_Zenity_ShowSimpleInputDialog(SDL_DialogInputCallback callback, void *userdata, const char *title, const char *message, const char *value, SDL_Window *window);
27+
2628
/** @returns non-zero if available, zero if unavailable */
2729
extern bool SDL_Zenity_detect(void);

src/dynapi/SDL_dynapi.sym

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,7 @@ SDL3_0.0.0 {
12571257
SDL_hid_get_properties;
12581258
SDL_GetPixelFormatFromGPUTextureFormat;
12591259
SDL_GetGPUTextureFormatFromPixelFormat;
1260+
SDL_ShowSimpleInputDialog;
12601261
# extra symbols go here (don't modify this line)
12611262
local: *;
12621263
};

src/dynapi/SDL_dynapi_overrides.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,3 +1282,4 @@
12821282
#define SDL_hid_get_properties SDL_hid_get_properties_REAL
12831283
#define SDL_GetPixelFormatFromGPUTextureFormat SDL_GetPixelFormatFromGPUTextureFormat_REAL
12841284
#define SDL_GetGPUTextureFormatFromPixelFormat SDL_GetGPUTextureFormatFromPixelFormat_REAL
1285+
#define SDL_ShowSimpleInputDialog SDL_ShowSimpleInputDialog_REAL

src/dynapi/SDL_dynapi_procs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,3 +1290,4 @@ SDL_DYNAPI_PROC(Uint32,SDL_AddAtomicU32,(SDL_AtomicU32 *a,int b),(a,b),return)
12901290
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_hid_get_properties,(SDL_hid_device *a),(a),return)
12911291
SDL_DYNAPI_PROC(SDL_PixelFormat,SDL_GetPixelFormatFromGPUTextureFormat,(SDL_GPUTextureFormat a),(a),return)
12921292
SDL_DYNAPI_PROC(SDL_GPUTextureFormat,SDL_GetGPUTextureFormatFromPixelFormat,(SDL_PixelFormat a),(a),return)
1293+
SDL_DYNAPI_PROC(void,SDL_ShowSimpleInputDialog,(SDL_DialogInputCallback a,void *b,const char *c,const char *d,const char *e,SDL_Window *f),(a,b,c,d,e,f),)

test/testdialog.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ static void SDLCALL callback(void *userdata, const char * const *files, int filt
5555
}
5656
}
5757

58+
static void SDLCALL input_callback(void *userdata, const char *input) {
59+
SDL_Log("Input: %s\n", input);
60+
}
61+
5862
char *concat_strings(const char *a, const char *b)
5963
{
6064
char *out = NULL;
@@ -80,6 +84,7 @@ int main(int argc, char *argv[])
8084
const SDL_FRect open_file_rect = { 50, 50, 220, 140 };
8185
const SDL_FRect save_file_rect = { 50, 290, 220, 140 };
8286
const SDL_FRect open_folder_rect = { 370, 50, 220, 140 };
87+
const SDL_FRect input_rect = { 370, 290, 220, 140 };
8388
int i;
8489
const char *default_filename = "Untitled.index";
8590
const char *initial_path = NULL;
@@ -153,6 +158,8 @@ int main(int argc, char *argv[])
153158
}
154159
SDL_ShowSaveFileDialog(callback, &last_saved_path, w, filters, SDL_arraysize(filters), save_path ? save_path : default_filename);
155160
SDL_free(save_path);
161+
} else if (SDL_PointInRectFloat(&p, &input_rect)) {
162+
SDL_ShowSimpleInputDialog(input_callback, NULL, NULL, NULL, NULL, w);
156163
}
157164
}
158165
}
@@ -173,10 +180,14 @@ int main(int argc, char *argv[])
173180
SDL_SetRenderDrawColor(r, 0, 0, 255, SDL_ALPHA_OPAQUE);
174181
SDL_RenderFillRect(r, &open_folder_rect);
175182

183+
SDL_SetRenderDrawColor(r, 255, 255, 0, SDL_ALPHA_OPAQUE);
184+
SDL_RenderFillRect(r, &input_rect);
185+
176186
SDL_SetRenderDrawColor(r, 0, 0, 0, SDL_ALPHA_OPAQUE);
177187
SDLTest_DrawString(r, open_file_rect.x+5, open_file_rect.y+open_file_rect.h/2, "Open File...");
178188
SDLTest_DrawString(r, save_file_rect.x+5, save_file_rect.y+save_file_rect.h/2, "Save File...");
179189
SDLTest_DrawString(r, open_folder_rect.x+5, open_folder_rect.y+open_folder_rect.h/2, "Open Folder...");
190+
SDLTest_DrawString(r, input_rect.x+5, input_rect.y+input_rect.h/2, "Input text...");
180191

181192
SDL_RenderPresent(r);
182193
}

0 commit comments

Comments
 (0)