Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions include/webui.h
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,19 @@ 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 to catch the navigation event of the WebView window.
* Must return `false` to prevent the navigation event, `true` otherwise.
*
* @example
* bool myNavigationEvent(size_t window) {
* // Prevent WebView window navigation event
* return false;
* }
* webui_set_navigation_handler_wv(myWindow, myNavigationEvent);
*/
WEBUI_EXPORT void webui_set_navigation_handler_wv(size_t window, bool (*navigate_handler)(size_t window));

/**
* @brief Set a callback to catch the close event of the WebView window.
* Must return `false` to prevent the close event, `true` otherwise.
Expand Down
112 changes: 110 additions & 2 deletions src/webui.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,18 @@ typedef struct webui_event_inf_t {
typedef void *(*webkit_web_view_new_func)(void);
typedef void (*webkit_web_view_load_uri_func)(void *, const char *);
typedef const char *(*webkit_web_view_get_title_func)(void *);
typedef void (*webkit_1ptr_arg_func)(void *);
typedef int (*webkit_1ptr_arg_2int_func)(void *);
typedef void *(*webkit_1ptr_arg_2ptr_func)(void *);
typedef const char *(*webkit_1ptr_arg_2str_func)(void *);
static webkit_web_view_new_func webkit_web_view_new = NULL;
static webkit_web_view_load_uri_func webkit_web_view_load_uri = NULL;
static webkit_web_view_get_title_func webkit_web_view_get_title = NULL;

static webkit_1ptr_arg_func webkit_policy_decision_ignore = NULL;
static webkit_1ptr_arg_2int_func webkit_navigation_policy_decision_get_navigation_type = NULL;
static webkit_1ptr_arg_2ptr_func webkit_navigation_policy_decision_get_request = NULL;
static webkit_1ptr_arg_2str_func webkit_uri_request_get_uri = NULL;

typedef struct _webui_wv_linux_t {
// Linux WebView
void* gtk_win;
Expand Down Expand Up @@ -355,6 +363,7 @@ typedef struct _webui_window_t {
int x;
int y;
bool position_set;
bool (*navigation_handler_wv)(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);
Expand Down Expand Up @@ -759,6 +768,21 @@ void webui_run(size_t window, const char* script) {
_webui_send_all(win, 0, WEBUI_CMD_JS_QUICK, script, js_len);
}

void webui_set_navigation_handler_wv(size_t window, bool (*navigate_handler)(size_t window)) {
#ifdef WEBUI_LOG
webui_log_debug("[User]webui_set_navigation_handler_wv(%zu, %p)", window, navigate_handler);
#endif

// Dereference
if (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS) || _webui.wins[window] == NULL)
return;

_webui_window_t* win = _webui.wins[window];

// Set the navigation handler
win->navigation_handler_wv = navigate_handler;
}

void webui_set_close_handler_wv(size_t window, bool(*close_handler)(size_t window)) {

// Initialization
Expand Down Expand Up @@ -11763,6 +11787,79 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
}
}

// Decision Event
#define WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION 0
#define WEBKIT_NAVIGATION_TYPE_LINK_CLICKED 0
#define WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED 1
#define WEBKIT_NAVIGATION_TYPE_BACK_FORWARD 2
#define WEBKIT_NAVIGATION_TYPE_RELOAD 3
#define WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED 4
#define WEBKIT_NAVIGATION_TYPE_OTHER 5

static bool _webui_wv_event_decision(void *widget, void *decision, int decision_type, void *user_data) {
switch(decision_type) {
case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: {

int navigation_type = webkit_navigation_policy_decision_get_navigation_type(decision);
bool intercept_navigation = false;

_webui_window_t* win = _webui_dereference_win_ptr(user_data);
if (win->navigate_handler) {
intercept_navigation = !(win->navigate_handler(win->num));
}

if (intercept_navigation) {
webkit_policy_decision_ignore(decision);

void *uri_request = webkit_navigation_policy_decision_get_request(decision);
const char *webkit_uri = webkit_uri_request_get_uri(uri_request);

size_t s = strlen(webkit_uri) + 1;
char *uri = (char *) _webui_malloc(s);
strncpy(uri, webkit_uri, s - 1);
uri[s] = '\0';

char buf[20];
snprintf(buf, 20, "%d", navigation_type);
size_t nt_s = strlen(buf) + 1;
char *type = (char *) _webui_malloc(nt_s);
strncpy(uri, buf, nt_s - 1);
uri[nt_s] = '\0';

// Event Info
webui_event_inf_t* event_inf = NULL;
size_t event_num = _webui_new_event_inf(win, &event_inf);
event_inf->client = NULL; // This is a WebKitGTK Event, so we don't have any WebSocket client
event_inf->connection_id = 0; // This is a WebKitGTK Event, so we don't have any WebSocket connection ID

// Event Info Extras
event_inf->event_data[0] = uri;
event_inf->event_size[0] = strlen(uri);
event_inf->event_data[1] = type;
event_inf->event_size[1] = strlen(type);

_webui_window_event(
win, // Event -> Window
0, // Event -> Client Unique ID | This is a WebKitGTK Event, so we don't have any WebSocket client unique ID
WEBUI_EVENT_NAVIGATION, // Event -> Type of this event
"", // Event -> HTML Element
event_num, // Event -> Event Number
0, // Event -> Client ID | This is a WebKitGTK Event, so we don't have any WebSocket client ID
NULL // Event -> Full cookies | TODO: Get cookies using WebKKitGTK APIs
);

// Free event
_webui_free_event_inf(win, event_num);

// Return that this event is handled.
return true;
}
}
break;
}
return false;
}

// Close Event
static void _webui_wv_event_closed(void *widget, void *arg) {
#ifdef WEBUI_LOG
Expand Down Expand Up @@ -12095,6 +12192,14 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
libwebkit, "webkit_web_view_load_uri");
webkit_web_view_get_title = (webkit_web_view_get_title_func)dlsym(
libwebkit, "webkit_web_view_get_title");
webkit_policy_decision_ignore = (webkit_1ptr_arg_func)dlsym(
libwebkit, "webkit_policy_decision_ignore");
webkit_navigation_policy_decision_get_navigation_type = (webkit_1ptr_arg_2int_func)dlsym(
libwebkit, "webkit_navigation_policy_decision_get_navigation_type");
webkit_navigation_policy_decision_get_request = (webkit_1ptr_arg_2ptr_func)dlsym(
libwebkit, "webkit_navigation_policy_decision_get_request");
webkit_uri_request_get_uri = (webkit_1ptr_arg_2str_func)dlsym(
libwebkit, "webkit_uri_request_get_uri");

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

// Check WebView
if (!webkit_web_view_new || !webkit_web_view_load_uri || !webkit_web_view_get_title) {
if (!webkit_web_view_new || !webkit_web_view_load_uri || !webkit_web_view_get_title ||
!webkit_policy_decision_ignore || !webkit_navigation_policy_decision_get_navigation_type ||
!webkit_navigation_policy_decision_get_request || !webkit_uri_request_get_uri
) {
#ifdef WEBUI_LOG
printf("[Core]\t\t_webui_load_gtk_and_webkit() -> WebKit symbol addresses failed\n");
#endif
Expand Down
Loading