1#ifndef WEBVIEW_CALLBACKS_H
2#define WEBVIEW_CALLBACKS_H
3
4#include <gtk/gtk.h>
5#include <webkit/webkit.h>
6#include <glib-object.h>
7
8// Forward declarations for Go callbacks
9extern void goOnTitleChanged(unsigned long id, char* title);
10extern void goOnURIChanged(unsigned long id, char* uri);
11extern void goOnThemeChanged(unsigned long id, int prefer_dark);
12extern void goOnFaviconURIChanged(unsigned long id, char* page_uri, char* favicon_uri);
13extern void* goResolveURIScheme(char* uri, size_t* out_len, char** out_mime);
14extern void goQuitMainLoop();
15
16// Static inline functions to avoid multiple definition errors
17static inline void on_title_notify(GObject* obj, GParamSpec* pspec, gpointer user_data) {
18 (void)pspec;
19 WebKitWebView* view = WEBKIT_WEB_VIEW(obj);
20 const gchar* title = webkit_web_view_get_title(view);
21 GtkWindow* win = GTK_WINDOW(user_data);
22 if (title && win) {
23 gtk_window_set_title(win, title);
24 }
25}
26
27static inline void on_title_notify_id(GObject* obj, GParamSpec* pspec, gpointer user_data) {
28 (void)pspec; (void)obj;
29 const gchar* title = webkit_web_view_get_title(WEBKIT_WEB_VIEW(obj));
30 if (title) { goOnTitleChanged((unsigned long)user_data, (char*)title); }
31}
32
33static inline void on_uri_notify(GObject* obj, GParamSpec* pspec, gpointer user_data) {
34 (void)pspec; (void)obj;
35 const gchar* uri = webkit_web_view_get_uri(WEBKIT_WEB_VIEW(obj));
36 if (uri) { goOnURIChanged((unsigned long)user_data, (char*)uri); }
37}
38
39static inline void on_theme_changed(GObject* obj, GParamSpec* pspec, gpointer user_data) {
40 (void)pspec;
41 GtkSettings* settings = GTK_SETTINGS(obj);
42 if (!settings) return;
43 gboolean prefer = FALSE;
44 g_object_get(settings, "gtk-application-prefer-dark-theme", &prefer, NULL);
45 goOnThemeChanged((unsigned long)user_data, prefer ? 1 : 0);
46}
47
48static inline void on_uri_scheme(WebKitURISchemeRequest* request, gpointer user_data) {
49 (void)user_data;
50 const gchar* uri = webkit_uri_scheme_request_get_uri(request);
51 size_t n = 0;
52 char* mime = NULL;
53 void* buf = goResolveURIScheme((char*)uri, &n, &mime);
54 if (buf && n > 0 && mime) {
55 GInputStream* stream = g_memory_input_stream_new_from_data(buf, (gssize)n, g_free);
56 webkit_uri_scheme_request_finish(request, stream, (gint64)n, mime);
57 g_object_unref(stream);
58 g_free(mime);
59 } else {
60 GError* err = g_error_new_literal(g_quark_from_string("dumber"), 404, "Not found");
61 webkit_uri_scheme_request_finish_error(request, err);
62 g_error_free(err);
63 }
64}
65
66static inline char* mask_uri_for_log(const char* uri) {
67 if (!uri) return g_strdup("NULL");
68 const char* p = strstr(uri, "://");
69 const char* start = p ? p + 3 : uri;
70 const char* slash = strchr(start, '/');
71 size_t host_len = slash ? (size_t)(slash - start) : strlen(start);
72 const size_t max_len = 64;
73 if (host_len <= max_len) {
74 return g_strndup(start, host_len);
75 } else {
76 char* prefix = g_strndup(start, max_len);
77 char* res = g_strdup_printf("%s...", prefix);
78 g_free(prefix);
79 return res;
80 }
81}
82
83static inline void on_favicon_changed(WebKitFaviconDatabase* database, gchar* page_uri, gchar* favicon_uri, gpointer user_data) {
84 (void)database;
85
86 if (!favicon_uri || !page_uri) {
87 printf("[favicon-c] Invalid favicon or page URI for WebView ID %lu\n", (unsigned long)user_data);
88 return;
89 }
90
91 // Log only a masked/shortened form of the URIs (no full URIs)
92 char* masked_page = mask_uri_for_log(page_uri);
93 char* masked_favicon = mask_uri_for_log(favicon_uri);
94 printf("[favicon-c] Favicon changed - page: %s, favicon: %s, WebView ID: %lu\n",
95 masked_page, masked_favicon, (unsigned long)user_data);
96 g_free(masked_page);
97 g_free(masked_favicon);
98
99 // Pass the full page URI and favicon URI to Go
100 goOnFaviconURIChanged((unsigned long)user_data, page_uri, favicon_uri);
101}
102
103// GTK4 close-request signal handler
104static inline gboolean on_close_request(GtkWindow* window, gpointer user_data) {
105 (void)window; (void)user_data;
106 goQuitMainLoop();
107 return FALSE; // Allow the window to close
108}
109
110#endif // WEBVIEW_CALLBACKS_H