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 void on_favicon_changed(WebKitFaviconDatabase* database, gchar* page_uri, gchar* favicon_uri, gpointer user_data) {
67 (void)database;
68 printf("[favicon-c] Favicon changed - page: %s, favicon: %s, WebView ID: %lu\n",
69 page_uri ? page_uri : "NULL", favicon_uri ? favicon_uri : "NULL", (unsigned long)user_data);
70
71 if (!favicon_uri || !page_uri) {
72 printf("[favicon-c] Invalid favicon or page URI for WebView ID %lu\n", (unsigned long)user_data);
73 return;
74 }
75
76 // Pass the page URI and favicon URI to Go
77 // WebKit manages the actual favicon data - we just need to store the URI mapping
78 goOnFaviconURIChanged((unsigned long)user_data, page_uri, favicon_uri);
79}
80
81// GTK4 close-request signal handler
82static inline gboolean on_close_request(GtkWindow* window, gpointer user_data) {
83 (void)window; (void)user_data;
84 goQuitMainLoop();
85 return FALSE; // Allow the window to close
86}
87
88#endif // WEBVIEW_CALLBACKS_H