From c457c3237e8c020c59ea437e57e0bd6b5d8c4621 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Fri, 17 Oct 2025 11:36:11 +0200 Subject: [PATCH 1/4] Functionality to callback to the software that integrates webui, on the event of clicking a 'close' button. When the user tries to close the window, using WebView on Windows/Linux, webui will issue a callback (if installed) to the integrating software asking if the window may be closed. Signed-off-by: Hans Dijkema --- include/webui.h | 28 ++++++++++++++++++++ src/webui.c | 70 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 91 insertions(+), 7 deletions(-) diff --git a/include/webui.h b/include/webui.h index 8d239ac74..a2ab0901c 100644 --- a/include/webui.h +++ b/include/webui.h @@ -519,6 +519,34 @@ WEBUI_EXPORT void webui_set_browser_folder(const char* path); */ WEBUI_EXPORT bool webui_set_default_root_folder(const char* path); +/** + * @brief Set a callback function on the given window to catch the + * close button of this window. + * Must return false, if the window cannot close, true, otherwis. + * + * This gives the possibility to check e.g. for non saved files in the + * backend. + * + * A 'NULL' close_handler function pointer will remove the + * current close_handler. + * + * NB. This works only for webview implementations, not for + * browsers. + * + * @example + * bool canClose(size_t window) + * { + * my_internal_window_data *data = getMyInternalWindowData(window); + * bool cc = AskUserForClosePermission(data); + * return cc; + * } + * (...) + * webui_set_close_handler(myWindow, canClose); + */ +WEBUI_EXPORT void webui_set_close_handler(size_t window, bool (*close_handler)(size_t window)); + + + /** * @brief Set a custom handler to serve files. This custom handler should * return full HTTP header and body. diff --git a/src/webui.c b/src/webui.c index d656c31b6..333a326b0 100644 --- a/src/webui.c +++ b/src/webui.c @@ -8,6 +8,8 @@ Canada. */ +#define webui_log_debug printf + // 64Mb max dynamic memory allocation #define WEBUI_MAX_BUF (64000000) @@ -373,6 +375,7 @@ typedef struct _webui_window_t { int x; int y; bool position_set; + bool (*close_handler)(size_t window); const void*(*files_handler)(const char* filename, int* length); const void*(*files_handler_window)(size_t window, const char* filename, int* length); const void* file_handler_async_response; @@ -641,6 +644,7 @@ static bool _webui_wv_set_position(_webui_wv_linux_t* webView, int x, int y); static bool _webui_wv_set_size(_webui_wv_linux_t* webView, int windowWidth, int windowHeight); static bool _webui_wv_show(_webui_window_t* win, char* url); static void _webui_wv_event_closed(void *widget, void *arg); +static bool _webui_wv_event_on_close(void *widget, void *event, void *arg); static int _webui_wv_exit_schedule(void* arg); static bool _webui_wv_maximize(_webui_wv_linux_t* webView); static bool _webui_wv_minimize(_webui_wv_linux_t* webView); @@ -775,6 +779,25 @@ void webui_run(size_t window, const char* script) { _webui_send_all(win, 0, WEBUI_CMD_JS_QUICK, script, js_len); } +void webui_set_close_handler(size_t window, bool(*close_handler)(size_t window)) { + + // Initialization + _webui_init(); + + // Dereference + if (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS) || _webui.wins[window] == NULL) + return; + + _webui_window_t* win = _webui.wins[window]; + +#ifdef WEBUI_LOG + webui_log_debug("[User]webui_set_close_handler(%zu, %p)", window, close_handler); +#endif + + // Set the close handler + win->close_handler = close_handler; +} + void webui_set_file_handler(size_t window, const void*(*handler)(const char* filename, int* length)) { if (handler == NULL) @@ -11531,13 +11554,26 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { } case WM_CLOSE: { if (win) { - // Stop the WebView thread, close the window - // and free resources. - if (win->webView) { - win->webView->stop = true; - _webui_webview_update(win); - } - _webui_wv_event_closed(win); + bool can_close = true; + if (win->close_handler != NULL) { + can_close = win->close_handler(win->num); + #ifdef WEBUI_LOG + webui_log_debug("[Core]\t\tClose Handler installed for %zu, result = %d\n", win->num, can_close); + #endif + } + + if (can_close) { + // Stop the WebView thread, close the window + // and free resources. + if (win->webView) { + win->webView->stop = true; + _webui_webview_update(win); + } + _webui_wv_event_closed(win); + } else { + // Do not close the window, no default processing + return 0; + } } break; } @@ -11972,6 +12008,24 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { } } +#if __linux__ + // Delete Event (implement on close handling) + static bool _webui_wv_event_on_close(void *widget, void *evt, void *arg) { + #ifdef WEBUI_LOG + webui_log_debug("[Core]\t\t_webui_wv_event_on_close()\n"); + #endif + _webui_window_t* win = _webui_dereference_win_ptr(arg); + if (win) { + if (win->close_handler) { + bool can_close = win->close_handler(win->num); + webui_log_debug("can_close = %d", can_close); + return !can_close; + } + } + return false; + } +#endif + static bool _webui_wv_set_size(_webui_wv_linux_t* webView, int windowWidth, int windowHeight) { #ifdef WEBUI_LOG printf("[Core]\t\t_webui_wv_set_size(%d. %d)\n", windowWidth, windowHeight); @@ -12110,6 +12164,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { // Events g_signal_connect_data(win->webView->gtk_wv, "notify::title", G_CALLBACK( _webui_wv_event_title), (void *)win, NULL, 0); + g_signal_connect_data(win->webView->gtk_win, "delete-event", G_CALLBACK( + _webui_wv_event_on_close), (void *)win, NULL, 0); g_signal_connect_data(win->webView->gtk_win, "destroy", G_CALLBACK( _webui_wv_event_closed), (void *)win, NULL, 0); From 0ca0b9c389fdfc452e88eec998749f910b672478 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Fri, 17 Oct 2025 11:40:58 +0200 Subject: [PATCH 2/4] #if __linux__ is not necessary Signed-off-by: Hans Dijkema --- src/webui.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/webui.c b/src/webui.c index 333a326b0..7777e5ccd 100644 --- a/src/webui.c +++ b/src/webui.c @@ -12008,7 +12008,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { } } -#if __linux__ // Delete Event (implement on close handling) static bool _webui_wv_event_on_close(void *widget, void *evt, void *arg) { #ifdef WEBUI_LOG @@ -12024,7 +12023,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { } return false; } -#endif static bool _webui_wv_set_size(_webui_wv_linux_t* webView, int windowWidth, int windowHeight) { #ifdef WEBUI_LOG From b00ecf063f9ae17d97db85c0dd3acb5dfd1a0b10 Mon Sep 17 00:00:00 2001 From: Showns <116365846+AlbertShown@users.noreply.github.com> Date: Fri, 17 Oct 2025 12:50:07 -0400 Subject: [PATCH 3/4] Update text --- include/webui.h | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/include/webui.h b/include/webui.h index a2ab0901c..40755dac6 100644 --- a/include/webui.h +++ b/include/webui.h @@ -520,32 +520,17 @@ WEBUI_EXPORT void webui_set_browser_folder(const char* path); WEBUI_EXPORT bool webui_set_default_root_folder(const char* path); /** - * @brief Set a callback function on the given window to catch the - * close button of this window. - * Must return false, if the window cannot close, true, otherwis. - * - * This gives the possibility to check e.g. for non saved files in the - * backend. - * - * A 'NULL' close_handler function pointer will remove the - * current close_handler. - * - * NB. This works only for webview implementations, not for - * browsers. + * @brief Set a callback to catch the close event of the WebView window. + * Must return `false` to prevent the close event, `true` otherwise. * * @example - * bool canClose(size_t window) - * { - * my_internal_window_data *data = getMyInternalWindowData(window); - * bool cc = AskUserForClosePermission(data); - * return cc; + * bool myCloseEvent(size_t window) { + * // Prevent WebView window close event + * return false; * } - * (...) - * webui_set_close_handler(myWindow, canClose); + * webui_set_close_handler(myWindow, myCloseEvent); */ -WEBUI_EXPORT void webui_set_close_handler(size_t window, bool (*close_handler)(size_t window)); - - +WEBUI_EXPORT void webui_set_close_handler_wv(size_t window, bool (*close_handler)(size_t window)); /** * @brief Set a custom handler to serve files. This custom handler should From 1efae098ca0e72848208c8b8d6bb2d91bf37479b Mon Sep 17 00:00:00 2001 From: Showns <116365846+AlbertShown@users.noreply.github.com> Date: Fri, 17 Oct 2025 13:03:06 -0400 Subject: [PATCH 4/4] Updating code to follow current coding style --- src/webui.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/webui.c b/src/webui.c index 7777e5ccd..e35e80877 100644 --- a/src/webui.c +++ b/src/webui.c @@ -8,8 +8,6 @@ Canada. */ -#define webui_log_debug printf - // 64Mb max dynamic memory allocation #define WEBUI_MAX_BUF (64000000) @@ -375,7 +373,7 @@ typedef struct _webui_window_t { int x; int y; bool position_set; - bool (*close_handler)(size_t window); + bool (*close_handler_wv)(size_t window); const void*(*files_handler)(const char* filename, int* length); const void*(*files_handler_window)(size_t window, const char* filename, int* length); const void* file_handler_async_response; @@ -779,7 +777,7 @@ void webui_run(size_t window, const char* script) { _webui_send_all(win, 0, WEBUI_CMD_JS_QUICK, script, js_len); } -void webui_set_close_handler(size_t window, bool(*close_handler)(size_t window)) { +void webui_set_close_handler_wv(size_t window, bool(*close_handler)(size_t window)) { // Initialization _webui_init(); @@ -790,12 +788,12 @@ void webui_set_close_handler(size_t window, bool(*close_handler)(size_t window)) _webui_window_t* win = _webui.wins[window]; -#ifdef WEBUI_LOG - webui_log_debug("[User]webui_set_close_handler(%zu, %p)", window, close_handler); -#endif + #ifdef WEBUI_LOG + printf("[User]webui_set_close_handler(%zu, %p)", window, close_handler); + #endif // Set the close handler - win->close_handler = close_handler; + win->close_handler_wv = close_handler; } void webui_set_file_handler(size_t window, const void*(*handler)(const char* filename, int* length)) { @@ -11555,13 +11553,12 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { case WM_CLOSE: { if (win) { bool can_close = true; - if (win->close_handler != NULL) { - can_close = win->close_handler(win->num); + if (win->close_handler_wv != NULL) { + can_close = win->close_handler_wv(win->num); #ifdef WEBUI_LOG - webui_log_debug("[Core]\t\tClose Handler installed for %zu, result = %d\n", win->num, can_close); + webui_log_debug("[Core]\t\tClose handler installed for %zu, result = %d\n", win->num, can_close); #endif } - if (can_close) { // Stop the WebView thread, close the window // and free resources. @@ -12011,13 +12008,15 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { // Delete Event (implement on close handling) static bool _webui_wv_event_on_close(void *widget, void *evt, void *arg) { #ifdef WEBUI_LOG - webui_log_debug("[Core]\t\t_webui_wv_event_on_close()\n"); + printf("[Core]\t\t_webui_wv_event_on_close()\n"); #endif _webui_window_t* win = _webui_dereference_win_ptr(arg); if (win) { - if (win->close_handler) { - bool can_close = win->close_handler(win->num); - webui_log_debug("can_close = %d", can_close); + if (win->close_handler_wv) { + bool can_close = win->close_handler_wv(win->num); + #ifdef WEBUI_LOG + printf("[Core]\t\t_webui_wv_event_on_close() -> can_close = %d\n", can_close); + #endif return !can_close; } }