diff --git a/programs/include/gui/dialogs.hpp b/programs/include/gui/dialogs.hpp index d518259..edcaa4f 100644 --- a/programs/include/gui/dialogs.hpp +++ b/programs/include/gui/dialogs.hpp @@ -101,18 +101,20 @@ struct Runtime { inline Runtime g_runtime = {}; +inline bool ensure_handle(char* out_message, int out_message_len) { + if (g_runtime.handle) return true; + g_runtime.handle = libloader::dlopen(LIBRARY_PATH); + if (!g_runtime.handle) { + if (out_message && out_message_len > 0) + safe_copy(out_message, out_message_len, "failed to load dialog library"); + return false; + } + return true; +} + inline RunRequestFn resolve_run_request(char* out_message, int out_message_len) { if (g_runtime.run_request) return g_runtime.run_request; - - if (!g_runtime.handle) { - g_runtime.handle = libloader::dlopen(LIBRARY_PATH); - if (!g_runtime.handle) { - if (out_message && out_message_len > 0) - safe_copy(out_message, out_message_len, "failed to load dialog library"); - return nullptr; - } - } - + if (!ensure_handle(out_message, out_message_len)) return nullptr; g_runtime.run_request = (RunRequestFn)libloader::dlsym(g_runtime.handle, RUN_REQUEST_SYMBOL); if (!g_runtime.run_request && out_message && out_message_len > 0) safe_copy(out_message, out_message_len, "failed to resolve dialog entry point"); @@ -121,23 +123,14 @@ inline RunRequestFn resolve_run_request(char* out_message, int out_message_len) inline MessageBoxFn resolve_message_box(char* out_message, int out_message_len) { if (g_runtime.message_box) return g_runtime.message_box; - - if (!g_runtime.handle) { - g_runtime.handle = libloader::dlopen(LIBRARY_PATH); - if (!g_runtime.handle) { - if (out_message && out_message_len > 0) - safe_copy(out_message, out_message_len, "failed to load dialog library"); - return nullptr; - } - } - + if (!ensure_handle(out_message, out_message_len)) return nullptr; g_runtime.message_box = (MessageBoxFn)libloader::dlsym(g_runtime.handle, MESSAGE_BOX_SYMBOL); if (!g_runtime.message_box && out_message && out_message_len > 0) safe_copy(out_message, out_message_len, "failed to resolve message box entry point"); return g_runtime.message_box; } -inline bool run_request(const Request* req, Result* out_res, char* out_message, int out_message_len) { +inline bool run_request(const Request* req, Result& res, char* out_message, int out_message_len) { if (out_message && out_message_len > 0) out_message[0] = '\0'; if (!req) { if (out_message && out_message_len > 0) @@ -145,21 +138,17 @@ inline bool run_request(const Request* req, Result* out_res, char* out_message, return false; } - Result local_res = {}; - reset_result(&local_res); - RunRequestFn run_fn = resolve_run_request(out_message, out_message_len); if (!run_fn) return false; - if (!run_fn(req, &local_res)) { + if (!run_fn(req, &res)) { if (out_message && out_message_len > 0 && !out_message[0]) safe_copy(out_message, out_message_len, "dialog library invocation failed"); return false; } - if (out_res) *out_res = local_res; if (out_message && out_message_len > 0) - safe_copy(out_message, out_message_len, local_res.message); - return montauk::streq(local_res.status, "ok"); + safe_copy(out_message, out_message_len, res.message); + return montauk::streq(res.status, "ok"); } inline bool open_file(const char* title, @@ -173,7 +162,7 @@ inline bool open_file(const char* title, safe_copy(req.initial_path, sizeof(req.initial_path), initial_path); Result res = {}; - bool ok = run_request(&req, &res, out_message, out_message_len); + bool ok = run_request(&req, res, out_message, out_message_len); if (ok && out_path && out_path_len > 0) safe_copy(out_path, out_path_len, res.path); return ok; } @@ -191,7 +180,7 @@ inline bool save_file(const char* title, safe_copy(req.suggested_name, sizeof(req.suggested_name), suggested_name); Result res = {}; - bool ok = run_request(&req, &res, out_message, out_message_len); + bool ok = run_request(&req, res, out_message, out_message_len); if (ok && out_path && out_path_len > 0) safe_copy(out_path, out_path_len, res.path); return ok; } @@ -210,7 +199,7 @@ inline bool print_file(const char* title, safe_copy(req.job_name, sizeof(req.job_name), job_name); Result res = {}; - bool ok = run_request(&req, &res, out_message, out_message_len); + bool ok = run_request(&req, res, out_message, out_message_len); if (ok && out_job_id && out_job_id_len > 0) safe_copy(out_job_id, out_job_id_len, res.job_id); return ok; } @@ -231,7 +220,7 @@ inline bool configure_print(const char* title, safe_copy(req.printer_uri, sizeof(req.printer_uri), initial_printer_uri); Result res = {}; - bool ok = run_request(&req, &res, out_message, out_message_len); + bool ok = run_request(&req, res, out_message, out_message_len); if (ok && out_printer_uri && out_printer_uri_len > 0) safe_copy(out_printer_uri, out_printer_uri_len, res.printer_uri); if (ok && out_printer_name && out_printer_name_len > 0) safe_copy(out_printer_name, out_printer_name_len, res.printer_name); if (ok && out_copies) *out_copies = res.copies > 0 ? res.copies : 1; diff --git a/programs/src/dialogs/Makefile b/programs/src/dialogs/Makefile index 93ce364..3c1599e 100644 --- a/programs/src/dialogs/Makefile +++ b/programs/src/dialogs/Makefile @@ -36,6 +36,7 @@ CXXFLAGS := \ -fno-stack-protector \ -fno-stack-check \ -fPIC \ + -fvisibility=hidden \ -fno-rtti \ -fno-exceptions \ -ffunction-sections \ @@ -74,6 +75,7 @@ LIBC_CFLAGS := \ -fno-stack-protector \ -fno-stack-check \ -fPIC \ + -fvisibility=hidden \ -ffunction-sections \ -fdata-sections \ -m64 \ diff --git a/programs/src/dialogs/main.cpp b/programs/src/dialogs/main.cpp index b322621..c7b34aa 100644 --- a/programs/src/dialogs/main.cpp +++ b/programs/src/dialogs/main.cpp @@ -20,9 +20,44 @@ using namespace gui; namespace dlg = gui::dialogs; +#define DIALOGS_EXPORT extern "C" __attribute__((visibility("default"))) + AppState g_app = {}; static bool g_fonts_ready = false; +// WinEvent::type values (from Api/Syscall.hpp) +static constexpr uint8_t WIN_KEY = 0; +static constexpr uint8_t WIN_MOUSE = 1; +static constexpr uint8_t WIN_RESIZE = 2; +static constexpr uint8_t WIN_CLOSE = 3; +static constexpr uint8_t WIN_SCALE = 4; + +struct DialogCallbacks { + void (*draw)(); + void (*on_close)(); + void (*handle_mouse)(const Montauk::WinEvent& ev); + void (*handle_key)(const Montauk::KeyEvent& key); +}; + +static void run_dialog_loop(const DialogCallbacks& cb) { + while (g_app.running) { + cb.draw(); + g_app.win.present(); + + Montauk::WinEvent ev; + int rc = g_app.win.poll(&ev); + if (rc < 0) { cb.on_close(); break; } + if (rc == 0) { montauk::sleep_ms(16); continue; } + + if (ev.type == WIN_CLOSE) { cb.on_close(); break; } + if (ev.type == WIN_MOUSE) { cb.handle_mouse(ev); continue; } + if (ev.type == WIN_KEY) { cb.handle_key(ev.key); } + // WIN_RESIZE and WIN_SCALE are handled inside WsWindow::poll + } +} + +static void cancel_and_stop() { dialog_cancel(""); } + void dialog_finish(const char* status, const char* path, const char* job_id, const char* message, const char* printer_uri, const char* printer_name, uint32_t copies) { gui::dialogs::safe_copy(g_app.result.status, sizeof(g_app.result.status), status); @@ -68,7 +103,7 @@ static bool ensure_fonts(dlg::Result* result) { return true; } -extern "C" bool dialogs_run_request(const dlg::Request* request, dlg::Result* out_result) { +DIALOGS_EXPORT bool dialogs_run_request(const dlg::Request* request, dlg::Result* out_result) { if (!request || !out_result) return false; set_error_result(out_result, "dialog failed"); @@ -107,53 +142,21 @@ extern "C" bool dialogs_run_request(const dlg::Request* request, dlg::Result* ou return true; } - if (g_app.is_print) printdialog::draw(); - else filedialog::draw(); + void (*draw_fn)() = g_app.is_print ? printdialog::draw : filedialog::draw; + void (*mouse_fn)(const Montauk::WinEvent&) = g_app.is_print ? printdialog::handle_mouse : filedialog::handle_mouse; + void (*key_fn)(const Montauk::KeyEvent&) = g_app.is_print ? printdialog::handle_key : filedialog::handle_key; + + draw_fn(); g_app.win.present(); - while (g_app.running) { - if (g_app.is_print) printdialog::draw(); - else filedialog::draw(); - g_app.win.present(); - - Montauk::WinEvent ev; - int rc = g_app.win.poll(&ev); - if (rc < 0) { - dialog_cancel(""); - break; - } - if (rc == 0) { - montauk::sleep_ms(16); - continue; - } - - if (ev.type == 3) { - dialog_cancel(""); - break; - } - - if (ev.type == 2 || ev.type == 4) { - continue; - } - - if (ev.type == 1) { - if (g_app.is_print) printdialog::handle_mouse(ev); - else filedialog::handle_mouse(ev); - continue; - } - - if (ev.type == 0) { - if (g_app.is_print) printdialog::handle_key(ev.key); - else filedialog::handle_key(ev.key); - } - } + run_dialog_loop({ draw_fn, cancel_and_stop, mouse_fn, key_fn }); cleanup(); *out_result = g_app.result; return true; } -extern "C" uint8_t dialogs_message_box(const char* title, +DIALOGS_EXPORT uint8_t dialogs_message_box(const char* title, const char* message, uint8_t buttons) { if (!ensure_fonts(nullptr)) @@ -178,36 +181,7 @@ extern "C" uint8_t dialogs_message_box(const char* title, messagebox::draw(); g_app.win.present(); - while (g_app.running) { - messagebox::draw(); - g_app.win.present(); - - Montauk::WinEvent ev; - int rc = g_app.win.poll(&ev); - if (rc < 0) { - messagebox::dismiss(); - break; - } - if (rc == 0) { - montauk::sleep_ms(16); - continue; - } - - if (ev.type == 3) { - messagebox::dismiss(); - break; - } - if (ev.type == 2 || ev.type == 4) { - continue; - } - if (ev.type == 1) { - messagebox::handle_mouse(ev); - continue; - } - if (ev.type == 0) { - messagebox::handle_key(ev.key); - } - } + run_dialog_loop({ messagebox::draw, messagebox::dismiss, messagebox::handle_mouse, messagebox::handle_key }); uint8_t choice = messagebox::selected_choice(); cleanup();