#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_WAYLAND
#include "SDL.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#include "SDL_waylandmessagebox.h"
#define MAX_BUTTONS 8
int
Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{
int fd_pipe[2];
pid_t pid1;
if (messageboxdata->numbuttons > MAX_BUTTONS) {
return SDL_SetError("Too many buttons (%d max allowed)", MAX_BUTTONS);
}
if (pipe(fd_pipe) != 0) {
return SDL_SetError("pipe() failed: %s", strerror(errno));
}
pid1 = fork();
if (pid1 == 0) {
int argc = 5, i;
const char* argv[5 + 2 + 2 + 2 + 2*MAX_BUTTONS + 1] = {
"zenity", "--question", "--switch", "--no-wrap", "--no-markup"
};
close(fd_pipe[0]);
if (dup2(fd_pipe[1], STDOUT_FILENO) == -1) {
_exit(128);
}
argv[argc++] = "--icon-name";
switch (messageboxdata->flags) {
case SDL_MESSAGEBOX_ERROR:
argv[argc++] = "dialog-error";
break;
case SDL_MESSAGEBOX_WARNING:
argv[argc++] = "dialog-warning";
break;
case SDL_MESSAGEBOX_INFORMATION:
default:
argv[argc++] = "dialog-information";
break;
}
if (messageboxdata->title && messageboxdata->title[0]) {
argv[argc++] = "--title";
argv[argc++] = messageboxdata->title;
} else {
argv[argc++] = "--title=\"\"";
}
if (messageboxdata->message && messageboxdata->message[0]) {
argv[argc++] = "--text";
argv[argc++] = messageboxdata->message;
} else {
argv[argc++] = "--text=\"\"";
}
for (i = 0; i < messageboxdata->numbuttons; ++i) {
if (messageboxdata->buttons[i].text && messageboxdata->buttons[i].text[0]) {
argv[argc++] = "--extra-button";
argv[argc++] = messageboxdata->buttons[i].text;
} else {
argv[argc++] = "--extra-button=\"\"";
}
}
argv[argc] = NULL;
execvp("zenity", (char **)argv);
_exit(129);
} else if (pid1 < 0) {
close(fd_pipe[0]);
close(fd_pipe[1]);
return SDL_SetError("fork() failed: %s", strerror(errno));
} else {
int status;
if (waitpid(pid1, &status, 0) == pid1) {
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) < 128) {
int i;
size_t output_len = 1;
char* output = NULL;
char* tmp = NULL;
FILE* outputfp = NULL;
close(fd_pipe[1]);
if (buttonid == NULL) {
close(fd_pipe[0]);
return 0;
}
*buttonid = -1;
for (i = 0; i < messageboxdata->numbuttons; ++i) {
if (messageboxdata->buttons[i].text != NULL) {
const size_t button_len = SDL_strlen(messageboxdata->buttons[i].text);
if (button_len > output_len) {
output_len = button_len;
}
}
}
output = SDL_malloc(output_len + 1);
if (!output) {
close(fd_pipe[0]);
return SDL_OutOfMemory();
}
output[0] = '\0';
outputfp = fdopen(fd_pipe[0], "r");
if (!outputfp) {
SDL_free(output);
close(fd_pipe[0]);
return SDL_SetError("Couldn't open pipe for reading: %s", strerror(errno));
}
tmp = fgets(output, output_len + 1, outputfp);
fclose(outputfp);
if ((tmp == NULL) || (*tmp == '\0') || (*tmp == '\n')) {
SDL_free(output);
return 0;
}
tmp = SDL_strrchr(output, '\n');
if (tmp != NULL) {
*tmp = '\0';
}
for (i = 0; i < messageboxdata->numbuttons; i += 1) {
if (messageboxdata->buttons[i].text != NULL) {
if (SDL_strcmp(output, messageboxdata->buttons[i].text) == 0) {
*buttonid = messageboxdata->buttons[i].buttonid;
break;
}
}
}
SDL_free(output);
return 0;
} else {
return SDL_SetError("zenity reported error or failed to launch: %d", WEXITSTATUS(status));
}
} else {
return SDL_SetError("zenity failed for some reason");
}
} else {
return SDL_SetError("Waiting on zenity failed: %s", strerror(errno));
}
}
}
#endif