From: Andrew Udvare <audvare@gmail.com>
Subject: [PATCH] Show the dialogs through portable-file-dialogs

SDL implements message boxes itself only under X11; everywhere else it shells
out to zenity, so on a Wayland session without zenity installed every box
fails. SDL_ShowMessageBox() then returns -1 without touching the int handed to
it, and ShowYesNoBox() declared that int uninitialised and compared whatever
was in it against IDYES. The first-run box asking for the ROM therefore never
appeared and the game exited with nothing on stdout.

The ROM picker already goes through portable-file-dialogs, which also knows
about kdialog, matedialog and qarma, so route the message boxes through it as
well. When it finds no helper at all, say so and answer no, rather than
whatever the stack happened to hold.

--- a/src/port/Engine.cpp
+++ b/src/port/Engine.cpp
@@ -2,6 +2,7 @@
 
 #include "ship/utils/StringHelper.h"
 #include "GameExtractor.h"
+#include "portable-file-dialogs.h"
 #include "mods/ModManager.h"
 #include "ui/ImguiUI.h"
 #include "ship/Context.h"
@@ -311,36 +312,44 @@
 #if defined(__SWITCH__)
     SPDLOG_ERROR(message);
 #else
-    SDL_ShowSimpleMessageBox(type, title, message, nullptr);
+    // SDL has no message box of its own outside of X11 and shells out to
+    // zenity, which is not the only thing a desktop might have. The ROM picker
+    // already goes through portable-file-dialogs, which knows about kdialog
+    // and qarma as well, so these do too.
+    if (pfd::settings::available()) {
+        pfd::icon icon = pfd::icon::error;
+        if (type == SDL_MESSAGEBOX_WARNING) {
+            icon = pfd::icon::warning;
+        } else if (type == SDL_MESSAGEBOX_INFORMATION) {
+            icon = pfd::icon::info;
+        }
+        pfd::message(title, message, pfd::choice::ok, icon).result();
+    }
     SPDLOG_ERROR(message);
 #endif
 }
 
 int GameEngine::ShowYesNoBox(const char* title, const char* box) {
-    int ret;
 #ifdef _WIN32
-    ret = MessageBoxA(nullptr, box, title, MB_YESNO | MB_ICONQUESTION);
+    return MessageBoxA(nullptr, box, title, MB_YESNO | MB_ICONQUESTION);
 #elif defined(__SWITCH__)
     SPDLOG_ERROR(box);
     return IDYES;
 #else
-    SDL_MessageBoxData boxData = { 0 };
-    SDL_MessageBoxButtonData buttons[2] = { { 0 } };
+    // Answering IDNO when there is nothing to ask with is a decision; the
+    // uninitialised int this used to return when SDL_ShowMessageBox() failed
+    // was not. That is what made a missing zenity look like the game silently
+    // refusing to start.
+    if (!pfd::settings::available()) {
+        SPDLOG_ERROR("No dialog helper available (zenity, kdialog, matedialog or qarma); assuming no");
+        SPDLOG_ERROR(box);
+        return IDNO;
+    }
 
-    buttons[0].buttonid = IDYES;
-    buttons[0].text = "Yes";
-    buttons[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
-    buttons[1].buttonid = IDNO;
-    buttons[1].text = "No";
-    buttons[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
-    boxData.numbuttons = 2;
-    boxData.flags = SDL_MESSAGEBOX_INFORMATION;
-    boxData.message = box;
-    boxData.title = title;
-    boxData.buttons = buttons;
-    SDL_ShowMessageBox(&boxData, &ret);
+    return pfd::message(title, box, pfd::choice::yes_no, pfd::icon::question).result() == pfd::button::yes
+               ? IDYES
+               : IDNO;
 #endif
-    return ret;
 }
 
 void GameEngine::Create() {
