Skip to content

Commit 1709ac8

Browse files
authored
Merge pull request #648 from hdijkema/gtkwebkit-navigation
Fix problems with navigation events that aren't generated by GtkWebKit.
2 parents 80f8976 + 9d3833e commit 1709ac8

File tree

2 files changed

+123
-2
lines changed

2 files changed

+123
-2
lines changed

include/webui.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,19 @@ WEBUI_EXPORT void webui_set_browser_folder(const char* path);
523523
*/
524524
WEBUI_EXPORT bool webui_set_default_root_folder(const char* path);
525525

526+
/**
527+
* @brief Set a callback to catch the navigation event of the WebView window.
528+
* Must return `false` to prevent the navigation event, `true` otherwise.
529+
*
530+
* @example
531+
* bool myNavigationEvent(size_t window) {
532+
* // Prevent WebView window navigation event
533+
* return false;
534+
* }
535+
* webui_set_navigation_handler_wv(myWindow, myNavigationEvent);
536+
*/
537+
WEBUI_EXPORT void webui_set_navigation_handler_wv(size_t window, bool (*navigate_handler)(size_t window));
538+
526539
/**
527540
* @brief Set a callback to catch the close event of the WebView window.
528541
* Must return `false` to prevent the close event, `true` otherwise.

src/webui.c

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,18 @@ typedef struct webui_event_inf_t {
247247
typedef void *(*webkit_web_view_new_func)(void);
248248
typedef void (*webkit_web_view_load_uri_func)(void *, const char *);
249249
typedef const char *(*webkit_web_view_get_title_func)(void *);
250+
typedef void (*webkit_1ptr_arg_func)(void *);
251+
typedef int (*webkit_1ptr_arg_2int_func)(void *);
252+
typedef void *(*webkit_1ptr_arg_2ptr_func)(void *);
253+
typedef const char *(*webkit_1ptr_arg_2str_func)(void *);
250254
static webkit_web_view_new_func webkit_web_view_new = NULL;
251255
static webkit_web_view_load_uri_func webkit_web_view_load_uri = NULL;
252256
static webkit_web_view_get_title_func webkit_web_view_get_title = NULL;
253-
257+
static webkit_1ptr_arg_func webkit_policy_decision_ignore = NULL;
258+
static webkit_1ptr_arg_2int_func webkit_navigation_policy_decision_get_navigation_type = NULL;
259+
static webkit_1ptr_arg_2ptr_func webkit_navigation_policy_decision_get_request = NULL;
260+
static webkit_1ptr_arg_2str_func webkit_uri_request_get_uri = NULL;
261+
254262
typedef struct _webui_wv_linux_t {
255263
// Linux WebView
256264
void* gtk_win;
@@ -355,6 +363,7 @@ typedef struct _webui_window_t {
355363
int x;
356364
int y;
357365
bool position_set;
366+
bool (*navigation_handler_wv)(size_t window);
358367
bool (*close_handler_wv)(size_t window);
359368
const void*(*files_handler)(const char* filename, int* length);
360369
const void*(*files_handler_window)(size_t window, const char* filename, int* length);
@@ -759,6 +768,21 @@ void webui_run(size_t window, const char* script) {
759768
_webui_send_all(win, 0, WEBUI_CMD_JS_QUICK, script, js_len);
760769
}
761770

771+
void webui_set_navigation_handler_wv(size_t window, bool (*navigate_handler)(size_t window)) {
772+
#ifdef WEBUI_LOG
773+
webui_log_debug("[User]webui_set_navigation_handler_wv(%zu, %p)", window, navigate_handler);
774+
#endif
775+
776+
// Dereference
777+
if (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS) || _webui.wins[window] == NULL)
778+
return;
779+
780+
_webui_window_t* win = _webui.wins[window];
781+
782+
// Set the navigation handler
783+
win->navigation_handler_wv = navigate_handler;
784+
}
785+
762786
void webui_set_close_handler_wv(size_t window, bool(*close_handler)(size_t window)) {
763787

764788
// Initialization
@@ -11763,6 +11787,79 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
1176311787
}
1176411788
}
1176511789

11790+
// Decision Event
11791+
#define WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION 0
11792+
#define WEBKIT_NAVIGATION_TYPE_LINK_CLICKED 0
11793+
#define WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED 1
11794+
#define WEBKIT_NAVIGATION_TYPE_BACK_FORWARD 2
11795+
#define WEBKIT_NAVIGATION_TYPE_RELOAD 3
11796+
#define WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED 4
11797+
#define WEBKIT_NAVIGATION_TYPE_OTHER 5
11798+
11799+
static bool _webui_wv_event_decision(void *widget, void *decision, int decision_type, void *user_data) {
11800+
switch(decision_type) {
11801+
case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: {
11802+
11803+
int navigation_type = webkit_navigation_policy_decision_get_navigation_type(decision);
11804+
bool intercept_navigation = false;
11805+
11806+
_webui_window_t* win = _webui_dereference_win_ptr(user_data);
11807+
if (win->navigate_handler) {
11808+
intercept_navigation = !(win->navigate_handler(win->num));
11809+
}
11810+
11811+
if (intercept_navigation) {
11812+
webkit_policy_decision_ignore(decision);
11813+
11814+
void *uri_request = webkit_navigation_policy_decision_get_request(decision);
11815+
const char *webkit_uri = webkit_uri_request_get_uri(uri_request);
11816+
11817+
size_t s = strlen(webkit_uri) + 1;
11818+
char *uri = (char *) _webui_malloc(s);
11819+
strncpy(uri, webkit_uri, s - 1);
11820+
uri[s] = '\0';
11821+
11822+
char buf[20];
11823+
snprintf(buf, 20, "%d", navigation_type);
11824+
size_t nt_s = strlen(buf) + 1;
11825+
char *type = (char *) _webui_malloc(nt_s);
11826+
strncpy(uri, buf, nt_s - 1);
11827+
uri[nt_s] = '\0';
11828+
11829+
// Event Info
11830+
webui_event_inf_t* event_inf = NULL;
11831+
size_t event_num = _webui_new_event_inf(win, &event_inf);
11832+
event_inf->client = NULL; // This is a WebKitGTK Event, so we don't have any WebSocket client
11833+
event_inf->connection_id = 0; // This is a WebKitGTK Event, so we don't have any WebSocket connection ID
11834+
11835+
// Event Info Extras
11836+
event_inf->event_data[0] = uri;
11837+
event_inf->event_size[0] = strlen(uri);
11838+
event_inf->event_data[1] = type;
11839+
event_inf->event_size[1] = strlen(type);
11840+
11841+
_webui_window_event(
11842+
win, // Event -> Window
11843+
0, // Event -> Client Unique ID | This is a WebKitGTK Event, so we don't have any WebSocket client unique ID
11844+
WEBUI_EVENT_NAVIGATION, // Event -> Type of this event
11845+
"", // Event -> HTML Element
11846+
event_num, // Event -> Event Number
11847+
0, // Event -> Client ID | This is a WebKitGTK Event, so we don't have any WebSocket client ID
11848+
NULL // Event -> Full cookies | TODO: Get cookies using WebKKitGTK APIs
11849+
);
11850+
11851+
// Free event
11852+
_webui_free_event_inf(win, event_num);
11853+
11854+
// Return that this event is handled.
11855+
return true;
11856+
}
11857+
}
11858+
break;
11859+
}
11860+
return false;
11861+
}
11862+
1176611863
// Close Event
1176711864
static void _webui_wv_event_closed(void *widget, void *arg) {
1176811865
#ifdef WEBUI_LOG
@@ -12095,6 +12192,14 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
1209512192
libwebkit, "webkit_web_view_load_uri");
1209612193
webkit_web_view_get_title = (webkit_web_view_get_title_func)dlsym(
1209712194
libwebkit, "webkit_web_view_get_title");
12195+
webkit_policy_decision_ignore = (webkit_1ptr_arg_func)dlsym(
12196+
libwebkit, "webkit_policy_decision_ignore");
12197+
webkit_navigation_policy_decision_get_navigation_type = (webkit_1ptr_arg_2int_func)dlsym(
12198+
libwebkit, "webkit_navigation_policy_decision_get_navigation_type");
12199+
webkit_navigation_policy_decision_get_request = (webkit_1ptr_arg_2ptr_func)dlsym(
12200+
libwebkit, "webkit_navigation_policy_decision_get_request");
12201+
webkit_uri_request_get_uri = (webkit_1ptr_arg_2str_func)dlsym(
12202+
libwebkit, "webkit_uri_request_get_uri");
1209812203

1209912204
// Check GTK
1210012205
if (
@@ -12119,7 +12224,10 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
1211912224
}
1212012225

1212112226
// Check WebView
12122-
if (!webkit_web_view_new || !webkit_web_view_load_uri || !webkit_web_view_get_title) {
12227+
if (!webkit_web_view_new || !webkit_web_view_load_uri || !webkit_web_view_get_title ||
12228+
!webkit_policy_decision_ignore || !webkit_navigation_policy_decision_get_navigation_type ||
12229+
!webkit_navigation_policy_decision_get_request || !webkit_uri_request_get_uri
12230+
) {
1212312231
#ifdef WEBUI_LOG
1212412232
printf("[Core]\t\t_webui_load_gtk_and_webkit() -> WebKit symbol addresses failed\n");
1212512233
#endif

0 commit comments

Comments
 (0)