commit: 41835171d3e1928248a5c41bfd8fee516ce81227
parent: ab23be019c4193254ca28365693a33c6604f42fa
author: Chris Noxz <chris@noxz.tech>
date: Sat, 28 Dec 2024 15:35:12 +0100
new year commit
5 files changed, 989 insertions(+), 1281 deletions(-)
diff --git a/browser.c b/browser.c
@@ -21,8 +21,9 @@
void
-about_scheme_request(WebKitURISchemeRequest *request,
- gpointer data)
+about_scheme_request(
+ WebKitURISchemeRequest *request,
+ gpointer data)
{
(void) data;
@@ -32,26 +33,33 @@ about_scheme_request(WebKitURISchemeRequest *request,
const gchar *p; /* path holder eg. 'config' */
gchar **w; /* temporary word holder */
gsize sl; /* size of stream */
- int st[4] = {0}; /* memory stats */
- p = webkit_uri_scheme_request_get_path(request);
+ p = request_path(request);
/* about:config */
if (!strcmp(p, "config")) {
g_string_append_printf((m = g_string_new(NULL)), "<html><body>"
"<table style=\"width:100%%;\">"
"<tr>"
- "<th align=\"left\">Configurable Name</th>"
+ "<th align=\"left\">Nonconfigurable Name</th>"
"<th align=\"left\">Value</th>"
"</tr>"
"<tr><td>"__NAME__" version</td><td>%s</td></tr>"
- "<tr><td>WebKit version</td><td>%u.%u.%u</td></tr>",
+ "<tr><td>Gtk version</td><td>%u.%u.%u</td></tr>"
+ "<tr><td>WebKit version</td><td>%u.%u.%u</td></tr>"
+ "<tr>"
+ "<th align=\"left\">Configurable Name</th>"
+ "<th align=\"left\">Value</th>"
+ "</tr>",
VERSION,
+ gtk_get_major_version(),
+ gtk_get_minor_version(),
+ gtk_get_micro_version(),
webkit_get_major_version(),
webkit_get_minor_version(),
webkit_get_micro_version());
- for (int i = 0; i < LastConfig; i++) {
- if (cfg[i].e == NULL)
+ for (int i = 0; i < CFN_LAST; i++) {
+ if (!cfg[i].e)
continue;
g_string_append_printf(m, "<tr><td>%s</td><td>", cfg[i].e);
switch (cfg[i].t) {
@@ -77,23 +85,10 @@ about_scheme_request(WebKitURISchemeRequest *request,
}
g_string_append_printf(m, "</table>");
g_string_append_printf(m, "</body></html>");
- /* about:memory (only exists if memory can be read) */
- } else if (!strcmp(p, "memory")
- && get_memory(&(st[0]), &(st[1]), &(st[2]), &(st[3]))) {
- g_string_append_printf((m = g_string_new(NULL)), "<html><body>"
- "<table style=\"width:100%%;\">"
- "<tr><td>current real memory</td><td>%'d kB</tr>"
- "<tr><td>peak real memory</td><td>%'d kB</tr>"
- "<tr><td>current virt memory</td><td>%'d kB</tr>"
- "<tr><td>peak virt memory</td><td>%'d kB</tr>"
- "</table>"
- "</body></html>",
- st[0], st[1], st[2], st[3]
- );
} else {
webkit_uri_scheme_request_finish_error(request, (e = g_error_new(
BROWSER_ERROR,
- BROWSER_ERROR_INVALID_ABOUT_PATH,
+ BER_INVALID_ABOUT_PATH,
"Invalid 'about:%s' page", p)));
g_error_free(e);
return;
@@ -106,196 +101,222 @@ about_scheme_request(WebKitURISchemeRequest *request,
g_string_free(m, TRUE);
}
-struct Client*
-client_create(const gchar *uri,
- WebKitWebView *related_wv,
- gboolean show,
- gboolean focus_tab)
+void
+attach_to_host(
+ GtkWidget *self)
+{
+ guchar *d = NULL; /* data holder */
+ gint l, /* data length */
+ f; /* data format */
+ GdkAtom t; /* data atom type */
+ GtkWidget *w; /* top widget (window?) */
+
+ if (GTK_IS_PLUG(w = gtk_widget_get_toplevel(self)) || !GTK_IS_WINDOW(w))
+ return;
+
+ if (gdk_property_get(get_widget_win(GTK_WIDGET(w)),
+ gdk_atom_intern(CFG_S(CFN_TAB_HOST), FALSE), GDK_NONE,
+ 0, G_MAXLONG, FALSE, &t, &f, &l, &d)
+ && t == gdk_atom_intern("WINDOW", FALSE)
+ && f == 32
+ && l == sizeof(Window))
+ gl.embed = (long)*((Window*)d);
+ else
+ gl.embed = 0;
+ g_free(d);
+}
+
+void
+attach_to_window(
+ GtkWidget *self)
+{
+ GtkWidget *vbx;
+ GtkWidget *wv;
+
+ gl.embed = 0;
+
+ if (!gl.initialized)
+ return;
+
+ gl.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ if (!(vbx = gtk_bin_get_child(GTK_BIN(self))))
+ return;
+
+ if (!(wv = gtk_container_get_children(GTK_CONTAINER(vbx))->data))
+ return;
+
+ /* window settings */
+ gtk_window_set_default_size(GTK_WINDOW(gl.win), 800, 600);
+ gtk_window_set_title(GTK_WINDOW(gl.win), __NAME__);
+
+ /* connect signal callbacks */
+ CB(gl.win, "destroy", cb_quit);
+ CB(gl.win, "map-event", cb_map);
+
+ g_signal_handlers_disconnect_by_data(G_OBJECT(self), NULL);
+
+ g_object_ref(vbx);
+ gtk_container_remove(GTK_CONTAINER(self), vbx);
+ gtk_container_add(GTK_CONTAINER(gl.win), vbx);
+ g_object_unref(vbx);
+
+ gtk_widget_destroy(self);
+ gtk_widget_show_all(gl.win);
+ gtk_window_set_focus(GTK_WINDOW(gl.win), wv);
+}
+
+void
+fork_url(
+ const gchar *uri)
+{
+ char e[64];
+
+ if (gl.embed > 0 && snprintf(e, sizeof(e), "%lu", gl.embed) > 0)
+ execvp(gl.arg0, (char *[]){ gl.arg0, "-E", e, (char*)uri, NULL });
+ else
+ execvp(gl.arg0, (char *[]){ gl.arg0, (char*)uri, NULL });
+}
+
+void
+initialize(
+ const gchar *uri)
{
- struct Client *c; /* client to be */
gchar *u = NULL; /* translated uri */
- GtkWidget *e, /* event box */
- *t; /* tab box */
int i;
/* communicate uri through ipc if constructed */
- if (uri != NULL && gl.ipc == IPC_CLIENT) {
- if ((u = resolve_uri(uri)) == NULL || ipc_send(u) <= 0
- || ipc_send("\n") <= 0)
- fprintf(stderr, __NAME__": Could not send message '%s'\n", u);
+ if (gl.initialized && uri) {
+ if ((u = resolve_uri(uri)) && fork() == 0)
+ fork_url(u);
g_free(u);
- return NULL; /* the request was handled elsewhere */
+ return; /* the request was handled elsewhere */
}
+ if (gl.initialized)
+ return;
+
/* do not create a new client if existing uri was resolved to NULL, as it
* was handled as an XDG-OPEN event. Still process uri == NULL for "create"
* callback signals, such as "Open Link in New Window". */
- if (uri != NULL && (u = resolve_uri(uri)) == NULL)
- return NULL;
-
- if (!(c = calloc(1, sizeof(struct Client))))
- die(__NAME__ ": fatal: calloc failed\n");
+ if (uri && !(u = resolve_uri(uri)))
+ return;
- if (related_wv == NULL)
- c->wv = webkit_web_view_new();
- else
- c->wv = webkit_web_view_new_with_related_view(related_wv);
+ gl.wv = webkit_web_view_new();
/* connect signal callbacks */
- CB(c->wv, "button-release-event", cb_wv_hid, c);
- CB(c->wv, "close", cb_wv_close, c);
- CB(c->wv, "context-menu", cb_context_menu, c);
- CB(c->wv, "create", cb_wv_create, NULL);
- CB(c->wv, "decide-policy", cb_wv_decide_policy, NULL);
- CB(c->wv, "key-press-event", cb_wv_hid, c);
- CB(c->wv, "load-changed", cb_wv_load_changed, c);
- CB(c->wv, "load-failed-with-tls-errors", cb_wv_tls_load_failed, c);
- CB(c->wv, "mouse-target-changed", cb_wv_hover, c);
- CB(c->wv, "notify::estimated-load-progress",cb_wv_load_progress_changed, c);
- CB(c->wv, "notify::favicon", cb_favicon_changed, c);
- CB(c->wv, "notify::title", cb_title_changed, c);
- CB(c->wv, "notify::uri", cb_uri_changed, c);
- CB(c->wv, "scroll-event", cb_wv_hid, c);
- CB(c->wv, "web-process-crashed", cb_wv_crashed, c);
+ CB(gl.wv, "button-release-event", cb_wv_hid);
+ CB(gl.wv, "close", cb_wv_close);
+ CB(gl.wv, "context-menu", cb_context_menu);
+ CB(gl.wv, "create", cb_wv_create);
+ CB(gl.wv, "decide-policy", cb_wv_decide_policy);
+ CB(gl.wv, "key-press-event", cb_wv_hid);
+ CB(gl.wv, "load-changed", cb_wv_load_changed);
+ CB(gl.wv, "load-failed-with-tls-errors", cb_wv_tls_load_failed);
+ CB(gl.wv, "mouse-target-changed", cb_wv_hover);
+ CB(gl.wv, "notify::estimated-load-progress",cb_wv_load_progress_changed);
+ CB(gl.wv, "notify::favicon", cb_favicon_changed);
+ CB(gl.wv, "notify::title", cb_title_changed);
+ CB(gl.wv, "notify::uri", cb_uri_changed);
+ CB(gl.wv, "scroll-event", cb_wv_hid);
+ CB(gl.wv, "web-process-crashed", cb_wv_crashed);
+ CB(gl.wv, "enter-fullscreen", cb_wv_fullscreen_enter);
+ CB(gl.wv, "leave-fullscreen", cb_wv_fullscreen_leave);
/* load config into webkit settings */
- c->settings = webkit_settings_new();
- for (i = 0; i < LastConfig; i++)
- if (cfg[i].s != NULL)
+ gl.settings = webkit_settings_new();
+ for (i = 0; i < CFN_LAST; i++)
+ if (cfg[i].s)
g_object_set(
- G_OBJECT(c->settings),
+ G_OBJECT(gl.settings),
cfg[i].s,
cfg[i].i ? (Arg)!(cfg[i].v.b) : (cfg[i].v),
NULL
);
- webkit_web_view_set_settings(WEBKIT_WEB_VIEW(c->wv), c->settings);
+ webkit_web_view_set_settings(WEBKIT_WEB_VIEW(gl.wv), gl.settings);
- if (CFG_L(AcceptedLanguages) != NULL)
+ if (CFG_L(CFN_ACCEPTED_LANGUAGES))
webkit_web_context_set_preferred_languages(
- webkit_web_view_get_context(WEBKIT_WEB_VIEW(c->wv)),
- CFG_L(AcceptedLanguages)
+ webkit_web_view_get_context(WEBKIT_WEB_VIEW(gl.wv)),
+ CFG_L(CFN_ACCEPTED_LANGUAGES)
);
- if (CFG_S(CookieFile) != NULL)
+ if (CFG_S(CFN_COOKIE_FILE))
webkit_cookie_manager_set_persistent_storage(
webkit_web_context_get_cookie_manager(
- webkit_web_view_get_context(WEBKIT_WEB_VIEW(c->wv))
+ webkit_web_view_get_context(WEBKIT_WEB_VIEW(gl.wv))
),
- CFG_S(CookieFile),
+ CFG_S(CFN_COOKIE_FILE),
WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT
);
- if (CFG_S(ProxyUri) != NULL)
+ if (CFG_S(CFN_PROXY_URI))
webkit_website_data_manager_set_network_proxy_settings(
- webkit_web_view_get_website_data_manager(WEBKIT_WEB_VIEW(c->wv)),
+ webkit_web_view_get_website_data_manager(WEBKIT_WEB_VIEW(gl.wv)),
WEBKIT_NETWORK_PROXY_MODE_CUSTOM,
webkit_network_proxy_settings_new(
- CFG_S(ProxyUri), CFG_L(ProxyIgnore)
+ CFG_S(CFN_PROXY_URI), CFG_L(CFN_PROXY_IGNORE)
)
);
webkit_web_view_set_zoom_level(
- WEBKIT_WEB_VIEW(c->wv), CFG_F(ZoomLevel)
+ WEBKIT_WEB_VIEW(gl.wv), CFG_F(CFN_ZOOM_LEVEL)
);
/* create entry */
- c->entry = gtk_entry_new();
- CB(c->entry, "key-press-event", cb_entry_hid, c);
- CB(c->entry, "icon-release", cb_entry_icon_hid, c);
+ gl.entry = gtk_entry_new();
+ CB(gl.entry, "key-press-event", cb_entry_hid);
+ CB(gl.entry, "icon-release", cb_entry_icon_hid);
gtk_entry_set_icon_from_icon_name(
- GTK_ENTRY(c->entry), GTK_ENTRY_ICON_SECONDARY, CFG_B(DisableJavaScript)
- ? ICON_JS_OFF : ICON_JS_ON
+ GTK_ENTRY(gl.entry), GTK_ENTRY_ICON_SECONDARY,
+ CFG_B(CFN_DISABLE_JAVASCRIPT) ? ICON_JS_OFF : ICON_JS_ON
);
/* create vertical box to store the web view and the entry */
- c->vbx = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
- gtk_box_pack_start(GTK_BOX(c->vbx), c->wv, TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(c->vbx), c->entry, FALSE, FALSE, 0);
- gtk_container_set_focus_child(GTK_CONTAINER(c->vbx), c->wv);
-
- /* create tab containing an icon and a label */
- c->tab_icon = gtk_image_new_from_icon_name(ICON_GLOBE, GTK_ICON_SIZE_MENU);
- c->tab_label = gtk_label_new(__NAME__);
- gtk_label_set_ellipsize(GTK_LABEL(c->tab_label), PANGO_ELLIPSIZE_END);
- gtk_widget_set_halign(GTK_WIDGET(c->tab_label), GTK_ALIGN_START);
- gtk_widget_set_hexpand(GTK_WIDGET(c->tab_label), TRUE);
- gtk_widget_set_has_tooltip(GTK_WIDGET(c->tab_label), TRUE);
- /* pack icon and label in a horizontal box */
- t = gtk_box_new(
- GTK_ORIENTATION_HORIZONTAL, 5 * gtk_widget_get_scale_factor(mw.win)
- );
- gtk_box_pack_start(GTK_BOX(t), c->tab_icon, FALSE, FALSE, 0);
- gtk_box_pack_start(
- GTK_BOX(t),
- c->tab_label,
- TRUE,
- TRUE,
- 3 * gtk_widget_get_scale_factor(mw.win)
- );
- /* back the tab inside an event box to enable scroll and button events */
- e = gtk_event_box_new();
- gtk_container_add(GTK_CONTAINER(e), t);
- gtk_widget_add_events(e, GDK_SCROLL_MASK);
- CB(e, "button-release-event", cb_tab_hid, c);
- CB(e, "scroll-event", cb_tab_hid, c);
- /* store a (non client) reference to the label for later use */
- g_object_set_data(G_OBJECT(e), __NAME__"-tab-label", c->tab_label);
- /* show tab */
- gtk_widget_show_all(e);
-
- /* append everything reorderable to the notebook after current page */
- gtk_notebook_insert_page(
- GTK_NOTEBOOK(mw.nb),
- c->vbx,
- e,
- gtk_notebook_get_current_page(GTK_NOTEBOOK(mw.nb)) + 1
- );
- gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(mw.nb), c->vbx, TRUE);
+ gl.vbx = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_pack_start(GTK_BOX(gl.vbx), gl.wv, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(gl.vbx), gl.entry, FALSE, FALSE, 0);
+ gtk_container_set_focus_child(GTK_CONTAINER(gl.vbx), gl.wv);
+
+ /* pack everything in a vertical box */
+ gtk_container_add(GTK_CONTAINER(gl.win), gl.vbx);
/* manage which tab should be focused */
- c->focus_new_tab = focus_tab;
- if (show)
- show_web_view(c);
- else
- CB(c->wv, "ready-to-show", cb_wv_show, c);
+ gtk_widget_show_all(gl.win);
+ gtk_window_set_focus(GTK_WINDOW(gl.win), gl.wv);
/* finally load the uri */
- if (u != NULL)
- webkit_web_view_load_uri(WEBKIT_WEB_VIEW(c->wv), u);
+ if (u)
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(gl.wv), u);
g_free(u);
- gl.clients++;
- return c;
+ load_user_styles(WEBKIT_WEB_VIEW(gl.wv));
+ load_user_scripts(WEBKIT_WEB_VIEW(gl.wv));
+
+ if (uri && !strcmp(CFG_S(CFN_HOME_URI), uri))
+ gtk_widget_grab_focus(gl.entry);
+
+ gl.initialized = TRUE;
}
void
-client_destroy(struct Client *c)
+terminate(void)
{
- int i;
-
/* disconnect all handlers */
- g_signal_handlers_disconnect_by_data(G_OBJECT(c->wv), c);
- g_signal_handlers_disconnect_by_data(G_OBJECT(c->wv), NULL);
-
- if ((i = gtk_notebook_page_num(GTK_NOTEBOOK(mw.nb), c->vbx)) != -1)
- gtk_notebook_remove_page(GTK_NOTEBOOK(mw.nb), i);
- else
- fprintf(stderr, __NAME__": Page does not exist in notebook\n");
+ g_signal_handlers_disconnect_by_data(G_OBJECT(gl.wv), NULL);
- free(c);
-
- if (--gl.clients == 0)
- quit();
+ gl.initialized = FALSE;
+ quit();
}
gboolean
-command(struct Client *c,
- const gchar *t)
+command(
+ const gchar *t)
{
if (t[0] == '/') { /* in-page search */
g_free(gl.search_text);
gl.search_text = g_strdup(t + 1);
- search(c, IPS_INIT);
+ search(IPS_INIT);
return TRUE;
} else if (t[0] == 'q') { /* quit (vim-like) */
- quit();
+ terminate();
return TRUE;
}
@@ -303,9 +324,9 @@ command(struct Client *c,
}
void
-create_context_menu(struct Client *c,
- WebKitContextMenu *context_menu,
- WebKitHitTestResult *hit_test_result)
+create_context_menu(
+ WebKitContextMenu *context_menu,
+ WebKitHitTestResult *hit_test_result)
{
guint x; /* hit test result context */
@@ -316,20 +337,16 @@ create_context_menu(struct Client *c,
);
/* if document is the only context */
- if (x == WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT) {
- create_context_menu_item(
- c,
+ if (x == WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT)
+ return create_context_menu_item(
context_menu,
"open-external",
"Open Page Externally",
cb_open_external
- );
- return; /* no need to check further */
- }
+ ); /* no need to check further */
if (x & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK)
create_context_menu_item(
- c,
context_menu,
"open-external",
"Open Link Externally",
@@ -337,12 +354,11 @@ create_context_menu(struct Client *c,
);
/* requires javascript for DOM access from here on */
- if (!webkit_settings_get_enable_javascript(c->settings))
+ if (!webkit_settings_get_enable_javascript(gl.settings))
return;
if (x & WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION)
create_context_menu_item(
- c,
context_menu,
"selection-search",
"Search Selection",
@@ -351,15 +367,15 @@ create_context_menu(struct Client *c,
}
void
-create_context_menu_item(struct Client *c,
- WebKitContextMenu *context_menu,
- const gchar *name,
- const gchar *label,
- void *action)
+create_context_menu_item(
+ WebKitContextMenu *context_menu,
+ const gchar *name,
+ const gchar *label,
+ void *action)
{
GAction *a = (GAction*)g_simple_action_new(name, NULL);
- CB(a, "activate", action, c);
+ CB(a, "activate", action);
webkit_context_menu_prepend(
context_menu,
webkit_context_menu_item_new_from_gaction(a, label, NULL)
@@ -368,44 +384,30 @@ create_context_menu_item(struct Client *c,
}
void
-die(const char *msg)
+download_blob(
+ WebKitDownload *d)
{
- fprintf(stderr, msg);
- exit(EXIT_FAILURE);
+ WebKitURIResponse *r = webkit_download_get_response(d);
+ const gchar *u = webkit_uri_response_get_uri(r);
+
+ if (strncmp(u, "blob:", 5) && strncmp(u, "data:", 5))
+ return;
+
+ webkit_download_set_destination(d, CFG_S(CFN_BLOB_FILE));
}
-int
-get_memory(int *cr, /* current real memory */
- int *pr, /* peak real memory */
- int *cv, /* current virtual memory */
- int *pv) /* peak virtual memory */
+void
+download_response(
+ WebKitURIResponse *r)
{
- char b[256] = {0};
- FILE *f;
-
- *cr = *pr = *cv = *pv = -1;
-
- if (!(f = fopen("/proc/self/status", "r")))
- return 0;
-
- while (fscanf(f, " %255s", b) == 1)
- if (!strcmp(b, "VmRSS:"))
- fscanf(f, " %d", cr);
- else if (!strcmp(b, "VmHWM:"))
- fscanf(f, " %d", pr);
- else if (!strcmp(b, "VmSize:"))
- fscanf(f, " %d", cv);
- else if (!strcmp(b, "VmPeak:"))
- fscanf(f, " %d", pv);
- fclose(f);
-
- return (*cr != -1 && *pr != -1 && *cv != -1 && *pv != -1);
+ xdg_open("adjidl:", webkit_uri_response_get_uri(r), TRUE);
}
gchar*
-get_uri(GtkWidget* wv)
+get_uri(
+ GtkWidget *wv)
{
- const gchar *u;
+ const gchar *u;
if (!(u = webkit_web_view_get_uri(WEBKIT_WEB_VIEW(wv))))
return NULL;
@@ -417,219 +419,145 @@ get_uri(GtkWidget* wv)
}
gboolean
-ipc_request(GIOChannel *src,
- GIOCondition condition,
- gpointer data)
+handle_fullscreen(
+ gboolean fullscreen)
{
- gchar *u = NULL; /* uri received */
+ GdkDisplay *d = gdk_display_get_default();
+ GdkWindow *p = GTK_IS_PLUG(gl.win)
+ ? get_socket_win(gl.win)
+ : to_gdk_win(d, gl.embed);
- (void)condition; /* not used */
- (void)data; /* not used */
+ if (fullscreen) /* hide or show widgets depending on fullscreen */
+ gtk_widget_hide(gl.entry);
+ else
+ gtk_widget_show_all(gl.entry);
- g_io_channel_read_line(src, &u, NULL, NULL, NULL);
- if (u) {
- g_strstrip(u);
- client_create(u, NULL, TRUE, TRUE);
- g_free(u);
- }
- return TRUE;
-}
+ if (!p) /* if not embeded we are done! */
+ return TRUE;
-ssize_t
-ipc_send(char *data)
-{
- size_t s = 0, /* data amount sent */
- l = strlen(data); /* data length */
- ssize_t w; /* data written */
-
- while (s < l) { /* write until everything is sent */
- if ((w = write(gl.ipc_pipe_fd, data + s, l - s)) == -1) {
- if (errno == EINTR)
- continue; /* EINTR: so retry */
- perror(__NAME__": Error writing to fifo");
- return w;
- } else if (w == 0) {
- return 0;
- }
- s += w;
- }
+ gtk_widget_grab_focus(gl.wv);
- return s;
+ if (fullscreen) /* tell parent to go fullscreen */
+ gdk_window_fullscreen(p);
+ else
+ gdk_window_unfullscreen(p);
+ return TRUE;
}
-void
-ipc_setup(void)
+gboolean
+key_common(
+ GdkEventKey *event)
{
- gchar *f = NULL, /* fifo file name */
- *p = NULL; /* fifo file path */
-
- /* only setup for ipc clients */
- if (gl.ipc != IPC_CLIENT)
- return;
+ gchar *u = NULL;
+ gboolean f = is_fullscreen();
- /* create fifo file path and allow for several ipc setups by naming them */
- f = g_strdup_printf("%s_%s.fifo", __NAME__, CFG_S(FifoName));
- p = g_build_filename(g_get_user_runtime_dir(), f, NULL);
-
- /* fail hard if fifo cannot be created */
- if (!g_file_test(p, G_FILE_TEST_EXISTS) && mkfifo(p, 0600) == -1)
- die(__NAME__ ": fatal: mkfifo failed\n");
-
- /* if no one is listening create the ipc host instance */
- if ((gl.ipc_pipe_fd = open(p, O_WRONLY | O_NONBLOCK)) == -1) {
- g_io_add_watch(
- g_io_channel_new_file(p, "r+", NULL),
- G_IO_IN,
- (GIOFunc)ipc_request,
- NULL
- );
- gl.ipc = IPC_HOST; /* convert client to host */
+ /* key presses not using the alt key */
+ switch (event->keyval) {
+ case GDK_KEY_F11: /* toggle window fullscreen state */
+ if (f) {
+ gtk_window_unfullscreen(GTK_WINDOW(gl.win));
+ handle_fullscreen(!f);
+ } else {
+ gtk_window_fullscreen(GTK_WINDOW(gl.win));
+ handle_fullscreen(f);
+ }
+ return TRUE;
}
- g_free(f);
- g_free(p);
-}
+ if (event->state & GDK_CONTROL_MASK) /* ctrl key commands */
+ switch (event->keyval) {
+ case GDK_KEY_h:
+ case GDK_KEY_j:
+ case GDK_KEY_k:
+ case GDK_KEY_l: /* in-page movement by emulating arrow keys... */
+ case GDK_KEY_g:
+ case GDK_KEY_G: /* ... as well as home and end */
+ event->keyval /* translate key press accordingly */
+ = event->keyval == GDK_KEY_h ? GDK_KEY_Left
+ : event->keyval == GDK_KEY_j ? GDK_KEY_Down
+ : event->keyval == GDK_KEY_k ? GDK_KEY_Up
+ : event->keyval == GDK_KEY_l ? GDK_KEY_Right
+ : event->keyval == GDK_KEY_g ? GDK_KEY_Home
+ : /* */ GDK_KEY_End;
+ event->state = 0;
+ gtk_propagate_event(GTK_WIDGET(gl.wv), (GdkEvent*)event);
+ return TRUE;
+ }
-gboolean
-key_common(struct Client *c,
- GdkEventKey *event)
-{
- int i,
- m;
- gchar *u = NULL;
+ if (f) /* do not handle key events in fullscreen */
+ return FALSE;
/* only handle key presses using the alt key */
if (!(event->state & GDK_MOD1_MASK))
return FALSE;
- /* key presses using ctrl+alt keys */
- if (event->state & GDK_CONTROL_MASK) {
- switch (event->keyval) {
- case GDK_KEY_J:
- case GDK_KEY_K: /* move page/tab backwards or forwards in stack */
- i = gtk_notebook_page_num(GTK_NOTEBOOK(mw.nb), c->vbx);
- m = gtk_notebook_get_n_pages(GTK_NOTEBOOK(mw.nb)) - 1;
- i += event->keyval == GDK_KEY_J
- ? i == 0 ? 0 : -1
- : i == m ? m : 1;
- gtk_notebook_reorder_child(GTK_NOTEBOOK(mw.nb), c->vbx, i);
- return TRUE;
- case GDK_KEY_j: /* go to previous page/tab */
- gtk_notebook_prev_page(GTK_NOTEBOOK(mw.nb));
- return TRUE;
- case GDK_KEY_k: /* go to next page/tab */
- gtk_notebook_next_page(GTK_NOTEBOOK(mw.nb));
- return TRUE;
- }
- }
-
switch (event->keyval) {
case GDK_KEY_q: /* destroy client and close tab */
- client_destroy(c);
+ terminate();
return TRUE;
case GDK_KEY_w: /* go to home page */
- if ((u = resolve_uri(CFG_S(HomeUri))) != NULL)
- webkit_web_view_load_uri(WEBKIT_WEB_VIEW(c->wv), u);
+ if ((u = resolve_uri(CFG_S(CFN_HOME_URI))))
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(gl.wv), u);
g_free(u);
return TRUE;
- case GDK_KEY_t: /* create new client/tab */
- if ((u = resolve_uri(CFG_S(HomeUri))) != NULL) {
- c = client_create(u, NULL, TRUE, TRUE);
- g_free(u);
- gtk_widget_grab_focus(c->entry);
- }
- return TRUE;
case GDK_KEY_r: /* reload, while bypassing cache */
- webkit_web_view_reload_bypass_cache(WEBKIT_WEB_VIEW(c->wv));
+ webkit_web_view_reload_bypass_cache(WEBKIT_WEB_VIEW(gl.wv));
return TRUE;
case GDK_KEY_i:
- toggle_inspector(c);
+ toggle_inspector();
return TRUE;
case GDK_KEY_o: /* focus entry */
- gtk_widget_grab_focus(c->entry);
+ gtk_widget_grab_focus(gl.entry);
return TRUE;
case GDK_KEY_n: /* search forward */
- search(c, IPS_FORWARD);
+ search(IPS_FORWARD);
return TRUE;
case GDK_KEY_N: /* search backward */
- search(c, IPS_BACKWARD);
+ search(IPS_BACKWARD);
return TRUE;
case GDK_KEY_slash: /* initiate in-page search */
- gtk_widget_grab_focus(c->entry);
- gtk_entry_set_text(GTK_ENTRY(c->entry), ":/");
- gtk_editable_set_position(GTK_EDITABLE(c->entry), -1);
- return TRUE;
- case GDK_KEY_b: /* toggle tab visibility */
- gtk_notebook_set_show_tabs(
- GTK_NOTEBOOK(mw.nb),
- !gtk_notebook_get_show_tabs(GTK_NOTEBOOK(mw.nb))
- );
- return TRUE;
- case GDK_KEY_1:
- case GDK_KEY_2:
- case GDK_KEY_3:
- case GDK_KEY_4:
- case GDK_KEY_5:
- case GDK_KEY_6:
- case GDK_KEY_7:
- case GDK_KEY_8:
- case GDK_KEY_9: /* go to nth tab */
- gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.nb), event->keyval-0x31);
+ gtk_widget_grab_focus(gl.entry);
+ gtk_entry_set_text(GTK_ENTRY(gl.entry), ":/");
+ gtk_editable_set_position(GTK_EDITABLE(gl.entry), -1);
return TRUE;
case GDK_KEY_0:
case GDK_KEY_minus:
case GDK_KEY_equal: /* set zoom level */
webkit_web_view_set_zoom_level(
- WEBKIT_WEB_VIEW(c->wv),
+ WEBKIT_WEB_VIEW(gl.wv),
event->keyval == GDK_KEY_0
- ? CFG_F(ZoomLevel)
- : webkit_web_view_get_zoom_level(WEBKIT_WEB_VIEW(c->wv))
+ ? CFG_F(CFN_ZOOM_LEVEL)
+ : webkit_web_view_get_zoom_level(WEBKIT_WEB_VIEW(gl.wv))
+ ((event->keyval == GDK_KEY_minus) ? -0.1 : 0.1)
);
return TRUE;
case GDK_KEY_H: /* go back in history */
- webkit_web_view_go_back(WEBKIT_WEB_VIEW(c->wv));
+ webkit_web_view_go_back(WEBKIT_WEB_VIEW(gl.wv));
return TRUE;
case GDK_KEY_L: /* go forward in history */
- webkit_web_view_go_forward(WEBKIT_WEB_VIEW(c->wv));
+ webkit_web_view_go_forward(WEBKIT_WEB_VIEW(gl.wv));
return TRUE;
case GDK_KEY_s: /* toggle javascript (on or off) */
- set_javascript_policy(c, JSP_TOGGLE);
+ set_javascript_policy(JSP_TOGGLE);
return TRUE;
case GDK_KEY_c: /* toggle tls error policy (ignore or fail) */
- toggle_tls_error_policy(c);
- return TRUE;
- case GDK_KEY_h:
- case GDK_KEY_j:
- case GDK_KEY_k:
- case GDK_KEY_l: /* in-page movement by emulating arrow keys... */
- case GDK_KEY_g:
- case GDK_KEY_G: /* ... as well as home and end */
- event->keyval /* translate key press accordingly */
- = event->keyval == GDK_KEY_h ? GDK_KEY_Left
- : event->keyval == GDK_KEY_j ? GDK_KEY_Down
- : event->keyval == GDK_KEY_k ? GDK_KEY_Up
- : event->keyval == GDK_KEY_l ? GDK_KEY_Right
- : event->keyval == GDK_KEY_g ? GDK_KEY_Home
- : /* */ GDK_KEY_End;
- event->state = 0;
- gtk_propagate_event(GTK_WIDGET(c->wv), (GdkEvent*)event);
+ toggle_tls_error_policy();
return TRUE;
case GDK_KEY_p: /* open print dialog */
webkit_print_operation_run_dialog(
- webkit_print_operation_new(WEBKIT_WEB_VIEW(c->wv)),
- GTK_WINDOW(mw.win)
+ webkit_print_operation_new(WEBKIT_WEB_VIEW(gl.wv)),
+ GTK_WINDOW(gl.win)
);
return TRUE;
}
/* check external handler keys */
- if (cfg[ExternalHandlerKeys].v.b &&
+ if (cfg[CFN_EXTERNAL_HANDLER_KEYS].v.b &&
event->keyval < 256 &&
g_strv_contains(
- CFG_L(ExternalHandlerKeys), (gchar[]){(gchar)event->keyval, 0}
+ CFG_L(CFN_EXTERNAL_HANDLER_KEYS), (gchar[]){(gchar)event->keyval, 0}
)) {
- open_external(c, (gchar)event->keyval);
+ open_external((gchar)event->keyval);
return TRUE;
}
@@ -637,8 +565,8 @@ key_common(struct Client *c,
}
gboolean
-key_entry(struct Client *c,
- GdkEventKey *event)
+key_entry(
+ GdkEventKey *event)
{
const gchar *t;
gchar *u = NULL,
@@ -651,47 +579,46 @@ key_entry(struct Client *c,
switch (event->keyval) { /* movements inside entry */
case GDK_KEY_l:
case GDK_KEY_h:
- p = gtk_editable_get_position(GTK_EDITABLE(c->entry));
- m = gtk_entry_get_text_length(GTK_ENTRY(c->entry));
+ p = gtk_editable_get_position(GTK_EDITABLE(gl.entry));
+ m = gtk_entry_get_text_length(GTK_ENTRY(gl.entry));
p += event->keyval == GDK_KEY_l
? m > p ? 1 : 0 /* move right */
: 0 < p ? -1 : 0; /* move left */
- gtk_editable_set_position(GTK_EDITABLE(c->entry), p);
+ gtk_editable_set_position(GTK_EDITABLE(gl.entry), p);
return TRUE;
}
}
/* handle common key presses */
- if (key_common(c, event))
+ if (key_common(event))
return TRUE;
/* handle any key press (not just using the alt key) */
switch (event->keyval) {
case GDK_KEY_KP_Enter:
case GDK_KEY_Return:
- gtk_widget_grab_focus(c->wv);
- if ((t = gtk_entry_get_text(GTK_ENTRY(c->entry))) == NULL)
+ gtk_widget_grab_focus(gl.wv);
+ if (!(t = gtk_entry_get_text(GTK_ENTRY(gl.entry))))
return TRUE;
if (t[0] != ':') { /* if not a command */
/* store current uri before loading new uri */
- l = get_uri(c->wv);
- if ((u = resolve_uri(t)) != NULL)
- webkit_web_view_load_uri(WEBKIT_WEB_VIEW(c->wv), u);
+ l = get_uri(gl.wv);
+ if ((u = resolve_uri(t)))
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(gl.wv), u);
g_free(u);
/* fix: notify::uri won't be raised if current uri is unchanged */
- if (!strcmp(l, (u = get_uri(c->wv))))
- uri_changed(c);
- g_free(u);
- g_free(l);
+ if (!strcmp(l, (u = get_uri(gl.wv))))
+ uri_changed();
+ g_free_all((gpointer[]){u, l, NULL});
return TRUE;
- } else if (command(c, t + 1)) { /* if command */
+ } else if (command(t + 1)) { /* if command */
return TRUE;
} /* FALL THROUGH */
case GDK_KEY_Escape:
- gtk_widget_grab_focus(c->wv);
- u = get_uri(c->wv);
- gtk_entry_set_text(GTK_ENTRY(c->entry), (u == NULL ? __NAME__ : u));
- gtk_editable_set_position(GTK_EDITABLE(c->entry), -1);
+ gtk_widget_grab_focus(gl.wv);
+ u = get_uri(gl.wv);
+ gtk_entry_set_text(GTK_ENTRY(gl.entry), (!u ? __NAME__ : u));
+ gtk_editable_set_position(GTK_EDITABLE(gl.entry), -1);
g_free(u);
return TRUE;
}
@@ -700,69 +627,35 @@ key_entry(struct Client *c,
}
gboolean
-key_tab(struct Client *c,
- GdkEvent *event)
-{
- GdkScrollDirection d;
-
- if (event->type == GDK_BUTTON_RELEASE) {
- if (((GdkEventButton *)event)->button == 2) { /* scroll wheel click */
- client_destroy(c);
- return TRUE;
- }
- } else if (event->type == GDK_SCROLL) { /* scroll wheel selection */
- gdk_event_get_scroll_direction(event, &d);
- if (d == GDK_SCROLL_UP)
- gtk_notebook_next_page(GTK_NOTEBOOK(mw.nb));
- else if (d == GDK_SCROLL_DOWN)
- gtk_notebook_prev_page(GTK_NOTEBOOK(mw.nb));
- return TRUE;
- }
-
- /* regain lost focus while clicking a tab (not a perfect solution)
- * note: this won't work if the cursor is dragged while a button is
- * pressed. One pseudo solution for this would be to subscribe to
- * event-after (specifically the GDK_ENTER_NOTIFY event type) on tab hid
- * events, however this only works if the selected tab is hovered while a
- * button is released and would also cause the corresponding web view for
- * any hovering tab to grab focus (effectively stealing focus from the
- * current web view or the entry when not desirable). */
- gtk_widget_grab_focus(c->wv);
- gtk_editable_set_position(GTK_EDITABLE(c->entry), -1);
-
- return FALSE;
-}
-
-gboolean
-key_web_view(struct Client *c,
- GdkEvent *event)
+key_web_view(
+ GdkEvent *event)
{
gdouble dx, /* scroll x-delta */
dy; /* scroll y-delta */
/* handle common key presses */
- if (event->type == GDK_KEY_PRESS && key_common(c, (GdkEventKey *)event))
+ if (event->type == GDK_KEY_PRESS && key_common((GdkEventKey *)event))
return TRUE;
/* escape key: stop web rendering */
if (event->type == GDK_KEY_PRESS
&& ((GdkEventKey *)event)->keyval == GDK_KEY_Escape) {
- webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(c->wv));
- gtk_entry_set_progress_fraction(GTK_ENTRY(c->entry), 0);
+ webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(gl.wv));
+ gtk_entry_set_progress_fraction(GTK_ENTRY(gl.entry), 0);
/* mouse button events */
} else if (event->type == GDK_BUTTON_RELEASE) {
switch (((GdkEventButton *)event)->button) {
- case 2: /* mouse middle button: open in new tab */
- if (c->hover_uri != NULL) {
- client_create(c->hover_uri, NULL, TRUE, FALSE);
+ case 2: /* mouse middle button: create new client */
+ if (gl.hover_uri) {
+ initialize(gl.hover_uri);
return TRUE;
}
break;
case 8: /* mouse button back: go back in history */
- webkit_web_view_go_back(WEBKIT_WEB_VIEW(c->wv));
+ webkit_web_view_go_back(WEBKIT_WEB_VIEW(gl.wv));
return TRUE;
case 9: /* mouse button forward: go forward in history */
- webkit_web_view_go_forward(WEBKIT_WEB_VIEW(c->wv));
+ webkit_web_view_go_forward(WEBKIT_WEB_VIEW(gl.wv));
return TRUE;
}
/* scroll using alt pressed: zoom in or out */
@@ -770,10 +663,10 @@ key_web_view(struct Client *c,
&& (((GdkEventScroll *)event)->state & GDK_MOD1_MASK)) {
gdk_event_get_scroll_deltas(event, &dx, &dy);
webkit_web_view_set_zoom_level(
- WEBKIT_WEB_VIEW(c->wv),
+ WEBKIT_WEB_VIEW(gl.wv),
dx != 0
- ? CFG_F(ZoomLevel)
- : webkit_web_view_get_zoom_level(WEBKIT_WEB_VIEW(c->wv)) + -dy * 0.1
+ ? CFG_F(CFN_ZOOM_LEVEL)
+ : webkit_web_view_get_zoom_level(WEBKIT_WEB_VIEW(gl.wv)) + -dy * 0.1
);
return TRUE;
}
@@ -782,35 +675,35 @@ key_web_view(struct Client *c,
}
void
-load_changed(struct Client *c,
- WebKitLoadEvent event_type)
+load_changed(
+ WebKitLoadEvent event_type)
{
switch (event_type) {
/* when page load starts, reset everything */
case WEBKIT_LOAD_STARTED:
- c->https = FALSE;
- if (c->error_page)
- c->error_page = FALSE;
+ gl.https = FALSE;
+ if (gl.error_page)
+ gl.error_page = FALSE;
else
- g_clear_object(&c->failed_crt);
+ g_clear_object(&gl.failed_crt);
break;
/* when page load is redirected, continue as usual */
case WEBKIT_LOAD_REDIRECTED:
break;
/* when page load is committed, get https and tls state */
case WEBKIT_LOAD_COMMITTED:
- c->https = webkit_web_view_get_tls_info(
- WEBKIT_WEB_VIEW(c->wv), &c->crt, &c->tls_error
+ gl.https = webkit_web_view_get_tls_info(
+ WEBKIT_WEB_VIEW(gl.wv), &gl.crt, &gl.tls_error
);
break;
/* when page load is finished, run all user scripts */
case WEBKIT_LOAD_FINISHED:
- load_user_styles(WEBKIT_WEB_VIEW(c->wv));
- run_user_scripts(WEBKIT_WEB_VIEW(c->wv));
+ load_user_styles(WEBKIT_WEB_VIEW(gl.wv));
+ load_user_scripts(WEBKIT_WEB_VIEW(gl.wv));
break;
}
- update_title(c);
+ update_title();
}
void
@@ -820,15 +713,13 @@ load_configuration(void)
int i;
/* set global defaults */
- gl.clients = 0; /* client counter */
- gl.ipc = IPC_CLIENT; /* ipc type */
- gl.ipc_pipe_fd = 0; /* ipc pipe file descriptor */
gl.search_text = NULL; /* in page search phrase */
gl.state_lock = TRUE; /* prevents state save */
+ gl.initialized = FALSE; /* is client initialized? */
/* load default configuration */
- for (i = 0; i < LastConfig; i++) {
- if (cfg[i].e && (e = g_getenv(cfg[i].e)) != NULL) {
+ for (i = 0; i < CFN_LAST; i++) {
+ if (cfg[i].e && (e = g_getenv(cfg[i].e))) {
switch (cfg[i].t) {
case CFG_INT: cfg[i].v.i = atoi(e); break;
case CFG_FLOAT: cfg[i].v.f = atof(e); break;
@@ -841,74 +732,7 @@ load_configuration(void)
}
void
-load_state(void)
-{
- char u[URI_MAX]; /* line/uri holder */
- FILE *fp = NULL; /* file pointer */
- int c, /* character holder */
- x, /* state indicators */
- idx = 0; /* current page index */
- unsigned i = 0u;
-
- /* only load states for ipc host */
- if (CFG_S(StateFile) == NULL || gl.ipc != IPC_HOST)
- return;
-
- if (!(fp = fopen(CFG_S(StateFile), "r"))) {
- /* fail if file exists as it cannot be accessed, else remove state lock
- * to see if saving the state will create it (ie. the parent exists) */
- if (access(CFG_S(StateFile), F_OK) == 0)
- perror(__NAME__": Error opening state file");
- else
- gl.state_lock = FALSE;
- return;
- }
-
- do {
- c = fgetc(fp);
-
- if (i == URI_MAX && !(c == '\n' || c == EOF)) { /* uri is too long */
- i = 0u;
- while ((c = fgetc(fp)) != '\n' && c != EOF);
- if (c == EOF)
- break;
- }
-
- if (c != '\n' && c != EOF) {
- u[i++] = (char)c;
- continue; /* character is added to string, not more to do */
- }
-
- if (i == 0)
- continue; /* skip empty lines */
-
- u[i] = '\0';
- i = 0u;
-
- if (sscanf(u, "%d:%s", &x, u) != 2)
- continue; /* incorrect format, so skip it */
-
- set_javascript_policy(
- client_create(u, NULL, TRUE, TRUE),
- (x & STATE_JAVASCRIPT) != 0
- );
- idx = x & STATE_CURRENT ? gl.clients - 1 : idx;
-
- } while (c != EOF);
-
- fclose(fp);
-
- /* select current tab if any */
- if (gl.clients > 0)
- gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.nb), idx);
-
- /* enable state save */
- gl.state_lock = FALSE;
-
-}
-
-void
-load_stdin()
+load_stdin(void)
{
int c; /* character holder */
GString *s = g_string_new(NULL);
@@ -917,52 +741,77 @@ load_stdin()
while ((c = getc(stdin)) != EOF)
g_string_append_c(s, (gchar)c);
- /* ignore content of stdin if instance is not independent, as there is no
- * uri to send over IPC anyway */
- if (gl.ipc != IPC_NONE)
- fprintf(stderr, __NAME__": stdin detected, use with -I instead\n");
- else
- /* load the html content, which won't survive a reload */
- webkit_web_view_load_html(
- WEBKIT_WEB_VIEW(client_create(NULL, NULL, TRUE, TRUE)->wv),
- s->str,
- NULL
- );
+ /* load the html content, which won't survive a reload */
+ initialize(NULL);
+ webkit_web_view_load_html(WEBKIT_WEB_VIEW(gl.wv), s->str, NULL);
g_string_free(s, TRUE);
}
void
-load_user_styles(WebKitWebView *web_view)
+load_user_scripts(
+ WebKitWebView *web_view)
{
gchar *c = NULL, /* file content */
*p = NULL, /* path (file) */
*b = NULL; /* base directory (scripts) */
const gchar *e = NULL; /* directory file entry */
- GDir *s = NULL; /* user style directory */
+ GDir *s = NULL; /* user script directory */
- b = g_build_filename(g_get_user_config_dir(), __NAME__, CFG_S(UcDir), NULL);
- if ((s = g_dir_open(b, 0, NULL)) == NULL) {
- g_free(b);
- return;
+ webkit_user_content_manager_remove_all_scripts(
+ webkit_web_view_get_user_content_manager(web_view)
+ );
+
+ IUS(web_view, SCRIPT_ALL_FRAMES, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES);
+ IUS(web_view, SCRIPT_MAIN_FRAME, WEBKIT_USER_CONTENT_INJECT_TOP_FRAME);
+
+ b = g_build_filename(CFG_DIR, __NAME__, CFG_S(CFN_USER_SCRIPT_DIR), NULL);
+ if (!(s = g_dir_open(b, 0, NULL)))
+ return g_free(b);
+
+ while ((e = g_dir_read_name(s))) {
+ if (g_str_has_suffix((p = g_build_filename(b, e, NULL)), ".js")
+ && g_file_get_contents(p, &c, NULL, NULL)) {
+ IUS(web_view, c, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES);
+ g_free(c);
+ }
+ g_free(p);
}
+ g_dir_close(s);
+ g_free(b);
+}
+
+void
+load_user_styles(
+ WebKitWebView *web_view)
+{
+ gchar *c = NULL, /* file content */
+ *p = NULL, /* path (file) */
+ *b = NULL; /* base directory (scripts) */
+ const gchar *e = NULL, /* directory file entry */
+ *u = NULL; /* uri holder */
+ GDir *s = NULL; /* user style directory */
+ gchar **m = NULL; /* match container */
+
+ b = g_build_filename(CFG_DIR, __NAME__, CFG_S(CFN_USER_CSS_DIR), NULL);
+ if (!(s = g_dir_open(b, 0, NULL)))
+ return g_free(b);
+
+ if (!(u = webkit_web_view_get_uri(WEBKIT_WEB_VIEW(web_view))))
+ return; /* end load if no uri exists */
+
webkit_user_content_manager_remove_all_style_sheets(
webkit_web_view_get_user_content_manager(web_view)
);
- while ((e = g_dir_read_name(s)) != NULL) {
+ while ((e = g_dir_read_name(s))) {
if (g_str_has_suffix((p = g_build_filename(b, e, NULL)), ".css")
&& g_file_get_contents(p, &c, NULL, NULL)) {
- webkit_user_content_manager_add_style_sheet(
- webkit_web_view_get_user_content_manager(web_view),
- webkit_user_style_sheet_new(
- c,
- WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
- WEBKIT_USER_STYLE_LEVEL_USER,
- NULL,
- NULL
- )
- );
+ /* reject uri specific css that do not match */
+ m = g_regex_split_simple("/\\* URL -- (.*) \\*/", c, 0, 0);
+ if (!m[1] || (m[1] != NULL && !strncmp(m[1], u, strlen(m[1]))))
+ IUSS(web_view, c, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES);
+ g_free(m);
g_free(c);
}
g_free(p);
@@ -975,152 +824,52 @@ load_user_styles(WebKitWebView *web_view)
void
main_window_setup(void)
{
- GtkWidget *v; /* vertical box */
-
/* define window elements */
- mw.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- mw.nb = gtk_notebook_new();
- mw.dbx = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- v = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gl.win = gl.embed > 0
+ ? gtk_plug_new(gl.embed)
+ : gtk_window_new(GTK_WINDOW_TOPLEVEL);
/* window settings */
- gtk_window_set_default_size(GTK_WINDOW(mw.win), 800, 600);
- gtk_window_set_title(GTK_WINDOW(mw.win), __NAME__);
-
- /* notebook settings */
- gtk_notebook_set_scrollable(GTK_NOTEBOOK(mw.nb), TRUE);
- gtk_notebook_set_tab_pos(GTK_NOTEBOOK(mw.nb), GTK_POS_TOP);
-
- /* prevent notebook (including tabs) from stealing focus */
- gtk_widget_set_can_focus(mw.nb, FALSE);
-
- /* pack everything in a vertical box */
- gtk_box_pack_start(GTK_BOX(v), mw.nb, TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(v), mw.dbx, FALSE, FALSE, 0);
- gtk_container_add(GTK_CONTAINER(mw.win), v);
+ gtk_window_set_default_size(GTK_WINDOW(gl.win), 800, 600);
+ gtk_window_set_title(GTK_WINDOW(gl.win), __NAME__);
/* connect signal callbacks */
- CB(mw.win, "destroy", cb_quit, NULL);
- CB(mw.nb, "switch-page", cb_notebook_switch_page, NULL);
- CBA(mw.nb, "switch-page", cb_notebook_modified, NULL);
- CB(mw.nb, "page-added", cb_notebook_modified, NULL);
- CB(mw.nb, "page-removed", cb_notebook_modified, NULL);
- CB(mw.nb, "page-reordered", cb_notebook_modified, NULL);
+ CB(gl.win, "destroy", cb_quit);
+
+ if (gl.embed)
+ CB(gl.win, "unmap-event", cb_unmap);
+ CB(gl.win, "map-event", cb_map);
}
void
-open_external(struct Client *c, const gchar s)
+open_external(
+ const gchar s)
{
char b[URI_MAX]; /* command line buffer */
gchar *p = NULL; /* external handler path */
p = g_build_filename(
- g_get_user_config_dir(), __NAME__, CFG_S(ExternalHandlerFile), NULL
+ CFG_DIR, __NAME__, CFG_S(CFN_EXTERNAL_HANDLER_FILE), NULL
);
if (s)
- sprintf(b, "%s %c:%s &", p, s, gtk_entry_get_text(GTK_ENTRY(c->entry)));
+ sprintf(b, "%s %c:%s &", p, s, gtk_entry_get_text(GTK_ENTRY(gl.entry)));
else
- sprintf(b, "%s %s &", p, gtk_entry_get_text(GTK_ENTRY(c->entry)));
+ sprintf(b, "%s %s &", p, gtk_entry_get_text(GTK_ENTRY(gl.entry)));
g_free(p);
system(b);
}
-void
-prepare_download(WebKitDownload *d,
- gchar *suggested_filename)
-{
- gchar *s = g_strdup(suggested_filename),
- *p = NULL, /* proposed path */
- *f = NULL, /* final path */
- *u = NULL; /* uri */
- GtkWidget *b; /* button */
- int i;
- static gboolean c = FALSE; /* condition, TRUE=finished */
-
- /* make suggested filename safe, by replacing directory separators */
- for (i = 0; s[i]; i++)
- if (s[i] == G_DIR_SEPARATOR)
- s[i] = '_';
-
- p = g_build_filename(CFG_S(DownloadDirectory), s, NULL);
- f = g_strdup(p);
-
- /* check for a free suffix */
- for (i = 1; g_file_test(f, G_FILE_TEST_EXISTS) && i < SUFFIX_MAX; i++) {
- g_free(f);
- f = rebuild_filename(p, i);
- }
-
- if (i < SUFFIX_MAX) {
- u = g_filename_to_uri(f, NULL, NULL);
- webkit_download_set_destination(d, u);
-
- b = gtk_button_new_with_label(s);
- gtk_button_set_always_show_image(GTK_BUTTON(b), TRUE);
- gtk_button_set_image(
- GTK_BUTTON(b),
- gtk_image_new_from_icon_name(ICON_DOWNLOAD, GTK_ICON_SIZE_BUTTON)
- );
- gtk_widget_set_margin_end(b, 1);
- gtk_box_pack_start(GTK_BOX(mw.dbx), b, FALSE, FALSE, 0);
- gtk_box_reorder_child(GTK_BOX(mw.dbx), b, 0);
- gtk_widget_show_all(mw.dbx);
-
- g_object_set_data(G_OBJECT(b), __NAME__"-finished", (gpointer)&c);
-
- CB(d, "notify::estimated-progress", cb_download_changed_progress, b);
- CB(d, "finished", cb_download_finished, b);
- g_object_ref(d);
- CB(b, "button-press-event", cb_download_press, d);
- } else { /* could not find a free suffix under the SUFFIX_MAX limit */
- fprintf(stderr, __NAME__": Limit reached for filename suffix\n");
- webkit_download_cancel(d);
- }
-
- g_free(p);
- g_free(s);
- g_free(f);
- g_free(u);
-}
-
void
quit(void)
{
- save_state();
gtk_main_quit();
}
-gchar *
-rebuild_filename(
- gchar *p,
- int n)
-{
- int i, l = strlen(p);
- gchar *f;
-
- for (i = l; i >= 0; i--)
- if (p[i] == '.' || (p[i] == '/' && (i = l) >= 0))
- break;
-
- if (i == -1)
- die(__NAME__ ": fatal: invalid download path\n");
-
- if (i < l) {
- p[i] = '\0';
- f = g_strdup_printf("%s.%d.%s", p, n, &p[i + 1]);
- p[i] = '.';
- } else {
- f = g_strdup_printf("%s.%d", p, n);
- }
-
- return f;
-}
-
void
-render_tls_error(struct Client *c,
- gchar *uri,
- GTlsCertificate *crt,
- GTlsCertificateFlags cert_flags)
+render_tls_error(
+ gchar *uri,
+ GTlsCertificate *crt,
+ GTlsCertificateFlags crt_flags)
{
GString *m = NULL; /* message (error) */
gchar *h = NULL, /* html code */
@@ -1133,24 +882,24 @@ render_tls_error(struct Client *c,
*ad = NULL; /* not after date */
m = g_string_new(NULL);
- c->failed_crt = g_object_ref(crt);
- c->tls_error = cert_flags;
- c->error_page = TRUE;
+ gl.failed_crt = g_object_ref(crt);
+ gl.tls_error = crt_flags;
+ gl.error_page = TRUE;
/* translate all flags to messages */
- if (c->tls_error & G_TLS_CERTIFICATE_UNKNOWN_CA)
+ if (gl.tls_error & G_TLS_CERTIFICATE_UNKNOWN_CA)
g_string_append(m, MSG_TLS_CERTIFICATE_UNKNOWN_CA);
- if (c->tls_error & G_TLS_CERTIFICATE_BAD_IDENTITY)
+ if (gl.tls_error & G_TLS_CERTIFICATE_BAD_IDENTITY)
g_string_append(m, MSG_TLS_CERTIFICATE_BAD_IDENTITY);
- if (c->tls_error & G_TLS_CERTIFICATE_NOT_ACTIVATED)
+ if (gl.tls_error & G_TLS_CERTIFICATE_NOT_ACTIVATED)
g_string_append(m, MSG_TLS_CERTIFICATE_NOT_ACTIVATED);
- if (c->tls_error & G_TLS_CERTIFICATE_EXPIRED)
+ if (gl.tls_error & G_TLS_CERTIFICATE_EXPIRED)
g_string_append(m, MSG_TLS_CERTIFICATE_EXPIRED);
- if (c->tls_error & G_TLS_CERTIFICATE_REVOKED)
+ if (gl.tls_error & G_TLS_CERTIFICATE_REVOKED)
g_string_append(m, MSG_TLS_CERTIFICATE_REVOKED);
- if (c->tls_error & G_TLS_CERTIFICATE_INSECURE)
+ if (gl.tls_error & G_TLS_CERTIFICATE_INSECURE)
g_string_append(m, MSG_TLS_CERTIFICATE_INSECURE);
- if (c->tls_error & G_TLS_CERTIFICATE_GENERIC_ERROR)
+ if (gl.tls_error & G_TLS_CERTIFICATE_GENERIC_ERROR)
g_string_append(m, MSG_TLS_CERTIFICATE_GENERIC_ERROR);
/* construct html code and load it */
@@ -1162,118 +911,44 @@ render_tls_error(struct Client *c,
b = g_date_time_format_iso8601(bd);
a = g_date_time_format_iso8601(ad);
h = g_strdup_printf(TLS_MSG_FORMAT, uri, m->str, s, i, b, a, p);
- webkit_web_view_load_alternate_html(WEBKIT_WEB_VIEW(c->wv), h, uri, NULL);
+ webkit_web_view_load_alternate_html(WEBKIT_WEB_VIEW(gl.wv), h, uri, NULL);
g_string_free(m, TRUE);
- g_free(h);
- g_free(s);
- g_free(i);
- g_free(b);
- g_free(a);
- g_free(p);
+ g_free_all((gpointer[]){h, s, i, b, a, p, NULL});
g_date_time_unref(ad);
g_date_time_unref(bd);
}
void
-run_user_scripts(WebKitWebView *web_view)
+save_history(
+ const gchar *t)
{
- gchar *c = NULL, /* file content */
- *p = NULL, /* path (file) */
- *b = NULL; /* base directory (scripts) */
- const gchar *e = NULL; /* directory file entry */
- GDir *s = NULL; /* user script directory */
-
- b = g_build_filename(g_get_user_config_dir(), __NAME__, CFG_S(UsDir), NULL);
- if ((s = g_dir_open(b, 0, NULL)) == NULL) {
- g_free(b);
- return;
- }
-
- while ((e = g_dir_read_name(s)) != NULL) {
- if (g_str_has_suffix((p = g_build_filename(b, e, NULL)), ".js")
- && g_file_get_contents(p, &c, NULL, NULL)) {
- webkit_web_view_evaluate_javascript(
- web_view, c, -1, NULL, NULL, NULL, NULL, NULL
- );
- g_free(c);
- }
- g_free(p);
- }
-
- g_dir_close(s);
- g_free(b);
-}
-
-void
-save_history(const gchar *t)
-{
- FILE *fp;
-
- if (CFG_S(HistoryFile) == NULL)
- return;
-
- if ((fp = fopen(CFG_S(HistoryFile), "a")) != NULL) {
- fprintf(fp, "%s\n", t);
- fclose(fp);
- } else {
- perror(__NAME__": Error opening history file");
- }
-}
-
-void
-save_state(void)
-{
- GList *c; /* child (notebook page) */
- int x, /* state indicators */
- i,
- l; /* length (number of tabs) */
FILE *fp;
- WebKitWebView *wv;
- WebKitSettings *s;
- gchar *u = NULL;
- /* only save state for ipc host, when state isn't locked for loading */
- if (CFG_S(StateFile) == NULL || gl.ipc != IPC_HOST || gl.state_lock)
+ if (!CFG_S(CFN_HISTORY_FILE))
return;
- if ((fp = fopen(CFG_S(StateFile), "w")) == NULL) {
- perror(__NAME__": Error opening state file");
+ if (!strcmp(t, ABOUT_BLANK))
return;
- }
- /* save uri from each tab into state file */
- for (i = 0, l = gtk_notebook_get_n_pages(GTK_NOTEBOOK(mw.nb)); i < l; i++) {
- c = gtk_container_get_children(
- GTK_CONTAINER(gtk_notebook_get_nth_page(GTK_NOTEBOOK(mw.nb), i))
- );
- if (strcmp(gtk_widget_get_name((c->data)), "WebKitWebView"))
- continue;
- wv = WEBKIT_WEB_VIEW(c->data);
- s = webkit_web_view_get_settings(wv);
- x = 0;
- if (gtk_notebook_get_current_page(GTK_NOTEBOOK(mw.nb)) == i)
- x |= STATE_CURRENT;
- if (webkit_settings_get_enable_javascript_markup(s))
- x |= STATE_JAVASCRIPT;
- fprintf(fp, "%d:%s\n", x, (u = get_uri((GtkWidget*)wv)));
- g_free(u);
- }
+ if (!(fp = fopen(CFG_S(CFN_HISTORY_FILE), "a")))
+ return perror(__NAME__": Error opening history file");
+ fprintf(fp, "%s\n", t);
fclose(fp);
}
void
-search(struct Client *c,
- enum inpage_search_type type)
+search(
+ enum inpage_search_type type)
{
- if (gl.search_text == NULL)
+ if (!gl.search_text)
return;
switch (type) {
case IPS_INIT:
webkit_find_controller_search(
- webkit_web_view_get_find_controller(WEBKIT_WEB_VIEW(c->wv)),
+ webkit_web_view_get_find_controller(WEBKIT_WEB_VIEW(gl.wv)),
gl.search_text,
WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE
| WEBKIT_FIND_OPTIONS_WRAP_AROUND,
@@ -1282,53 +957,55 @@ search(struct Client *c,
break;
case IPS_FORWARD:
webkit_find_controller_search_next(
- webkit_web_view_get_find_controller(WEBKIT_WEB_VIEW(c->wv))
+ webkit_web_view_get_find_controller(WEBKIT_WEB_VIEW(gl.wv))
);
break;
case IPS_BACKWARD:
webkit_find_controller_search_previous(
- webkit_web_view_get_find_controller(WEBKIT_WEB_VIEW(c->wv))
+ webkit_web_view_get_find_controller(WEBKIT_WEB_VIEW(gl.wv))
);
break;
}
}
void
-selection_search(struct Client *c)
+selection_search(void)
{
webkit_web_view_evaluate_javascript(
- WEBKIT_WEB_VIEW(c->wv),
- "window.getSelection().toString();",
+ WEBKIT_WEB_VIEW(gl.wv),
+ gl.first_search ? SCRIPT_SEARCH : SCRIPT_SEARCH_EXTRA,
-1,
NULL,
NULL,
NULL,
cb_selection_search_finished,
- c
+ NULL
);
}
void
-selection_search_finished(struct Client *c,
- GAsyncResult *result)
+selection_search_finished(
+ GAsyncResult *result)
{
JSCValue *v = NULL;
gchar *s = NULL,
*u = NULL;
- if ((v = webkit_web_view_evaluate_javascript_finish(
- WEBKIT_WEB_VIEW(c->wv), result, NULL
- )) == NULL)
+ if (!(v = webkit_web_view_evaluate_javascript_finish(
+ WEBKIT_WEB_VIEW(gl.wv), result, NULL)))
return;
if (jsc_value_is_string(v)
&& strlen(s = jsc_value_to_string(v))
&& !jsc_context_get_exception(jsc_value_get_context(v))
- && (u = resolve_uri(s)) != NULL)
- client_create(u, NULL, TRUE, FALSE);
+ && (u = resolve_uri(s)))
+ initialize(u);
+ else if (gl.first_search) {
+ gl.first_search = FALSE;
+ selection_search();
+ }
- g_free(u);
- g_free(s);
+ g_free_all((gpointer[]){u, s, NULL});
}
void
@@ -1337,13 +1014,9 @@ set_default_web_context(void)
gchar *p = NULL; /* web extensions path */
WebKitWebContext *c; /* web context */
- /* no context needed for clients */
- if (gl.ipc == IPC_CLIENT)
- return;
-
c = webkit_web_context_get_default();
- p = g_build_filename(g_get_user_config_dir(), __NAME__, CFG_S(WeDir), NULL);
+ p = g_build_filename(CFG_DIR, __NAME__, CFG_S(CFN_WEB_EXTENSION_DIR), NULL);
#if GTK_CHECK_VERSION(3, 98, 0) /* seems to be fixed in 3.98.0, we'll see */
webkit_web_context_set_sandbox_enabled(c, TRUE);
webkit_web_context_add_path_to_sandbox(c, p, TRUE);
@@ -1351,7 +1024,7 @@ set_default_web_context(void)
webkit_web_context_set_web_extensions_directory(c, p);
#endif
- CB(c, "download-started", cb_download_start, NULL);
+ CB(c, "download-started", cb_download_start);
webkit_web_context_set_favicon_database_directory(c, NULL);
webkit_web_context_register_uri_scheme(
c, ABOUT_SCHEME, (WebKitURISchemeRequestCallback)about_scheme_request,
@@ -1362,88 +1035,55 @@ set_default_web_context(void)
}
void
-set_hover_uri(struct Client *c,
- WebKitHitTestResult *hit_test_result)
+set_hover_uri(
+ WebKitHitTestResult *hit_test_result)
{
const char *t; /* entry text holder */
gchar *u = NULL; /* uri text holder */
- g_free(c->hover_uri);
+ g_free(gl.hover_uri);
/* only display hovered links */
if (webkit_hit_test_result_context_is_link(hit_test_result)) {
t = webkit_hit_test_result_get_link_uri(hit_test_result);
- c->hover_uri = g_strdup(t);
+ gl.hover_uri = g_strdup(t);
} else {
- u = get_uri(c->wv);
- c->hover_uri = NULL;
+ u = get_uri(gl.wv);
+ gl.hover_uri = NULL;
}
- if (!gtk_widget_is_focus(c->entry))
- gtk_entry_set_text(GTK_ENTRY(c->entry), u ? u : t);
+ if (!gtk_widget_is_focus(gl.entry))
+ gtk_entry_set_text(GTK_ENTRY(gl.entry), u ? u : t);
g_free(u);
}
void
-set_javascript_policy(struct Client *c,
- enum javascript_policy policy)
+set_javascript_policy(
+ enum javascript_policy policy)
{
webkit_settings_set_enable_javascript_markup(
- c->settings,
+ gl.settings,
policy == JSP_TOGGLE
- ? !webkit_settings_get_enable_javascript_markup(c->settings)
+ ? !webkit_settings_get_enable_javascript_markup(gl.settings)
: policy
);
gtk_entry_set_icon_from_icon_name(
- GTK_ENTRY(c->entry),
+ GTK_ENTRY(gl.entry),
GTK_ENTRY_ICON_SECONDARY,
- webkit_settings_get_enable_javascript_markup(c->settings)
+ webkit_settings_get_enable_javascript_markup(gl.settings)
? ICON_JS_ON
: ICON_JS_OFF
);
- webkit_web_view_reload_bypass_cache(WEBKIT_WEB_VIEW(c->wv));
- save_state();
+ webkit_web_view_reload_bypass_cache(WEBKIT_WEB_VIEW(gl.wv));
}
void
-set_window_title(gint i)
-{
- GtkWidget *c; /* notebook child/page */
-
- if ((c = gtk_notebook_get_nth_page(GTK_NOTEBOOK(mw.nb), i)) == NULL)
- return;
-
- gtk_window_set_title(GTK_WINDOW(mw.win),
- gtk_label_get_text(
- GTK_LABEL((GtkWidget *)g_object_get_data(
- G_OBJECT(gtk_notebook_get_tab_label(GTK_NOTEBOOK(mw.nb), c)),
- __NAME__"-tab-label"
- ))
- )
- );
-}
-
-void
-show_web_view(struct Client *c)
-{
- gint i;
-
- gtk_widget_show_all(mw.win);
-
- if (c->focus_new_tab) {
- if ((i = gtk_notebook_page_num(GTK_NOTEBOOK(mw.nb), c->vbx)) != -1)
- gtk_notebook_set_current_page(GTK_NOTEBOOK(mw.nb), i);
- gtk_widget_grab_focus(c->wv);
- }
-}
-
-void
-toggle_inspector(struct Client *c)
+toggle_inspector(void)
{
WebKitWebInspector *i;
- i = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(c->wv));
+ i = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(gl.wv));
/* assumes that the inspector has not been detached by the user */
if (webkit_web_inspector_is_attached(i))
@@ -1453,19 +1093,20 @@ toggle_inspector(struct Client *c)
}
void
-toggle_tls_error_policy(struct Client *c)
+toggle_tls_error_policy(void)
{
webkit_website_data_manager_set_tls_errors_policy(
- webkit_web_view_get_website_data_manager(WEBKIT_WEB_VIEW(c->wv)),
+ webkit_web_view_get_website_data_manager(WEBKIT_WEB_VIEW(gl.wv)),
!webkit_website_data_manager_get_tls_errors_policy(
- webkit_web_view_get_website_data_manager(WEBKIT_WEB_VIEW(c->wv))
+ webkit_web_view_get_website_data_manager(WEBKIT_WEB_VIEW(gl.wv))
)
);
- webkit_web_view_reload_bypass_cache(WEBKIT_WEB_VIEW(c->wv));
+ webkit_web_view_reload_bypass_cache(WEBKIT_WEB_VIEW(gl.wv));
}
gchar *
-resolve_uri(const gchar *t)
+resolve_uri(
+ const gchar *t)
{
gchar *u = NULL, /* uri to return */
*l = NULL, /* temporary string */
@@ -1479,18 +1120,20 @@ resolve_uri(const gchar *t)
return resolve_uri(t + 7);
/* use internal about page so that about: prefix is ignored by WebKit */
- if (!strncmp(t, "about:", 6) && strcmp(t, "about:blank"))
+ if (!strncmp(t, "about:", 6) && strcmp(t, ABOUT_BLANK))
u = g_strdup_printf(ABOUT_SCHEME":%s", t + 6);
/* check if valid scheme, and if so just create a copy of the text */
- else if ((s = g_uri_peek_scheme(t)) && g_strv_contains(CFG_L(UriSchemes), s))
+ else if ((s = g_uri_peek_scheme(t))
+ && g_strv_contains(CFG_L(CFN_URI_SCHEMES), s))
u = g_strdup(t);
/* if no match, then test xdg schemes (schemes that are redirected) */
- else if (s && CFG_L(XdgSchemes) && g_strv_contains(CFG_L(XdgSchemes), s))
- xdg_open(s, t);
+ else if (s && CFG_L(CFN_XDG_SCHEMES)
+ && g_strv_contains(CFG_L(CFN_XDG_SCHEMES), s))
+ xdg_open(s, t, FALSE);
/* if path is local, use the file scheme, else try to see if the string is
* expandable and is a local path */
- else if ((l = realpath(t, NULL)) != NULL || ((r = wordexp(t, &x, 0)) == 0
- && (l = resolve_uri_words(x.we_wordc, x.we_wordv)) != NULL))
+ else if ((l = realpath(t, NULL)) || ((r = wordexp(t, &x, 0)) == 0
+ && (l = resolve_uri_words(x.we_wordc, x.we_wordv))))
u = g_strdup_printf("file://%s", l);
/* else, check if the text can be interpreted as a valid https uri; it's
* not enough to check if uri is valid - check for period and no spaces */
@@ -1500,19 +1143,20 @@ resolve_uri(const gchar *t)
/* fallback to web search, using a specified search engine */
else
u = g_strdup_printf(
- CFG_S(SearchEngineUriFormat),
+ CFG_S(CFN_SEARCH_ENGINE_URI_FORMAT),
(e = g_uri_escape_string(t, NULL, FALSE))
);
if (r == 0 || r == WRDE_NOSPACE) /* free on success (r == 0) and NOSPACE */
wordfree(&x);
- g_free(e);
- g_free(l);
+ g_free_all((gpointer[]){e, l, NULL});
return u; /* return a pointer that the caller is responsible for freeing */
}
char *
-resolve_uri_words(int c, char **w)
+resolve_uri_words(
+ int c,
+ char **w)
{
gchar *d = NULL, /* uri decoded string */
*p = NULL, /* path to return */
@@ -1534,200 +1178,151 @@ resolve_uri_words(int c, char **w)
p = realpath((d = g_uri_unescape_string(s, NULL)), NULL);
- g_free(d);
- g_free(s);
+ g_free_all((gpointer[]){d, s, NULL});
return p; /* return a pointer that the caller is responsible for freeing */
}
void
-update_download_button(WebKitDownload *d,
- GtkButton *btn,
- gboolean done)
-{
- gdouble p, /* percent completed */
- l; /* response length (bytes) */
- gchar *t = NULL, /* text holder*/
- *f = NULL, /* file name */
- *b = NULL; /* base name */
-
- if ((f = g_filename_from_uri(webkit_download_get_destination(d), NULL, NULL)
- ) == NULL)
- return; /* should never happen, but just in case... */
-
- p = webkit_download_get_estimated_progress(d);
- p = (p > 1 ? 1 : p < 0 ? 0 : p) * 100;
- l = webkit_uri_response_get_content_length(webkit_download_get_response(d));
- b = g_path_get_basename(f);
-
- gtk_button_set_label(btn, !done /* set label based on progress */
- ? (t = g_strdup_printf(" %s (%.0f%% of %.1f MB)", b, p, l / 1e6))
- : (t = g_strdup_printf(" %s", b))
- );
-
- g_free(t);
- g_free(f);
- g_free(b);
-}
-
-void
-update_favicon(struct Client *c)
+update_favicon(void)
{
- cairo_surface_t *f; /* favicon */
- GdkPixbuf *b, /* pix buffer */
- *s; /* pix buffer (scaled) */
+ cairo_surface_t *f; /* favicon */
+ GdkPixbuf *b, /* pix buffer */
+ *s; /* pix buffer (scaled) */
+ int d; /* scaled dimension */
/* set fallback favicon */
- gtk_image_set_from_icon_name(
- GTK_IMAGE(c->tab_icon), ICON_GLOBE, GTK_ICON_SIZE_SMALL_TOOLBAR
- );
+ gtk_window_set_icon_name(GTK_WINDOW(gl.win), ICON_GLOBE);
- if ((f = webkit_web_view_get_favicon(WEBKIT_WEB_VIEW(c->wv))) == NULL)
+ if (!(f = webkit_web_view_get_favicon(WEBKIT_WEB_VIEW(gl.wv))))
return;
- if ((b = gdk_pixbuf_get_from_surface(f, 0, 0,
+ if (!(b = gdk_pixbuf_get_from_surface(f, 0, 0,
cairo_image_surface_get_width(f),
- cairo_image_surface_get_height(f))) == NULL)
+ cairo_image_surface_get_height(f))))
return;
- s = gdk_pixbuf_scale_simple(b,
- 16 * gtk_widget_get_scale_factor(c->tab_icon),
- 16 * gtk_widget_get_scale_factor(c->tab_icon),
- GDK_INTERP_BILINEAR
- );
- gtk_image_set_from_pixbuf(GTK_IMAGE(c->tab_icon), s);
+ /* setting the window icon enables other programs to retrieve the icon */
+ d = 16 * gtk_widget_get_scale_factor(gl.win);
+ s = gdk_pixbuf_scale_simple(b, d, d, GDK_INTERP_BILINEAR);
+ gtk_window_set_icon(GTK_WINDOW(gl.win), s);
g_object_unref(s);
g_object_unref(b);
}
void
-update_load_progress(struct Client *c)
+update_load_progress(void)
{
gdouble p;
- p = webkit_web_view_get_estimated_load_progress(WEBKIT_WEB_VIEW(c->wv));
- gtk_entry_set_progress_fraction(GTK_ENTRY(c->entry), (p == 1 ? 0 : p));
+ p = webkit_web_view_get_estimated_load_progress(WEBKIT_WEB_VIEW(gl.wv));
+ gtk_entry_set_progress_fraction(GTK_ENTRY(gl.entry), (p == 1 ? 0 : p));
}
void
-update_title(struct Client *c)
+update_title(void)
{
const gchar *t;
- gchar *m = NULL,
- *u;
+ gchar *u;
- u = get_uri(c->wv);
- t = webkit_web_view_get_title(WEBKIT_WEB_VIEW(c->wv));
+ u = get_uri(gl.wv);
+ t = webkit_web_view_get_title(WEBKIT_WEB_VIEW(gl.wv));
/* title priority: title, url, __NAME__ */
- t = t == NULL || t[0] == 0 ? (u == NULL || u[0] == 0 ? __NAME__ : u) : t;
-
- /* set label markup and certificate icon based on tls status */
- if (c->failed_crt
- || (c->https && c->tls_error != G_TLS_CERTIFICATE_NO_FLAGS)) {
- m = g_markup_printf_escaped(CFG_S(BadTlsTabFormat), t);
- gtk_entry_set_icon_from_icon_name(
- GTK_ENTRY(c->entry), GTK_ENTRY_ICON_PRIMARY, ICON_BAD_TLS
- );
- } else {
- m = g_markup_printf_escaped(CFG_S(NormalTabFormat), t);
- if (c->https)
- gtk_entry_set_icon_from_icon_name(
- GTK_ENTRY(c->entry), GTK_ENTRY_ICON_PRIMARY, ICON_TLS
- );
- else
- gtk_entry_set_icon_from_icon_name(
- GTK_ENTRY(c->entry), GTK_ENTRY_ICON_PRIMARY, NULL
- );
- }
+ t = !t || t[0] == 0 ? (!u || u[0] == 0 ? __NAME__ : u) : t;
- gtk_label_set_markup(GTK_LABEL(c->tab_label), m);
- gtk_widget_set_tooltip_text(c->tab_label, t);
- set_window_title(gtk_notebook_get_current_page(GTK_NOTEBOOK(mw.nb)));
- g_free(m);
- g_free(u);
+ gtk_entry_set_icon_from_icon_name(
+ GTK_ENTRY(gl.entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ gl.failed_crt ? ICON_BAD_TLS
+ : gl.https && gl.tls_error != G_TLS_CERTIFICATE_NO_FLAGS ? ICON_BAD_TLS
+ : gl.https ? ICON_TLS
+ : NULL
+ );
+
+ gtk_window_set_title(GTK_WINDOW(gl.win), t);
}
void
-uri_changed(struct Client *c)
+uri_changed(void)
{
gchar *t = NULL;
/* make sure to not overwrite the "WEB PROCESS CRASHED" message */
- if ((t = get_uri(c->wv)) != NULL && strlen(t) > 0) {
- gtk_entry_set_text(GTK_ENTRY(c->entry), t);
+ if ((t = get_uri(gl.wv)) && strlen(t) > 0) {
+ gtk_entry_set_text(GTK_ENTRY(gl.entry), t);
save_history(t);
- save_state();
}
g_free(t);
}
void
-web_view_crashed(struct Client *c)
+web_view_crashed(void)
{
gchar *t = NULL,
*u = NULL;
gtk_entry_set_text(
- GTK_ENTRY(c->entry),
- (t = g_strdup_printf("WEB PROCESS CRASHED: %s", (u = get_uri(c->wv))))
+ GTK_ENTRY(gl.entry),
+ (t = g_strdup_printf("WEB PROCESS CRASHED: %s", (u = get_uri(gl.wv))))
);
- g_free(t);
- g_free(u);
+ g_free_all((gpointer[]){t, u, NULL});
}
void
-xdg_open(const gchar *s,
- const gchar *t)
+xdg_open(
+ const gchar *s,
+ const gchar *t,
+ gboolean keep)
{
char b[URI_MAX]; /* command line buffer */
- /* make sure to send the scheme the way it was matched */
- sprintf(b, "%s %s%s &", XDG_OPEN, s, t+strlen(s));
- system(b);
+ if (fork() == 0) {
+ /* if not keep, make sure to send the scheme the way it was matched */
+ sprintf(b, "%s%s", s, keep ? t : t+strlen(s));
+ execvp(XDG_OPEN, (char *[]){ XDG_OPEN, b, NULL });
+ fprintf(stderr, "child process (execvp) failed: %s %s\n", XDG_OPEN, b);
+ exit(EXIT_FAILURE);
+ }
}
int
-main(int argc, char **argv)
+main(
+ int argc,
+ char **argv)
{
int opt,
i;
+ sigchld(0);
+
+ gl.arg0 = argv[0];
gtk_init(&argc, &argv);
/* load default configuration before reading command-line arguments */
load_configuration();
- while ((opt = getopt(argc, argv, "I")) != -1)
+ while ((opt = getopt(argc, argv, "E:")) != -1)
switch (opt) {
- case 'I':
- gl.ipc = IPC_NONE;
- break;
- default:
- die("Usage: " __NAME__ " [-I [-]] [URI ...] [FILE ...]\n");
+ case 'E': to_win(&gl.embed, optarg); break;
+ default: die("Usage: " __NAME__ " [-E WINID] [URI ...] [FILE ...]\n");
}
- ipc_setup();
set_default_web_context();
main_window_setup();
- load_state();
/* load a default home uri if no clients and no arguments exist */
- if (optind >= argc && gl.clients == 0)
- client_create(CFG_S(HomeUri), NULL, TRUE, TRUE);
+ if (optind >= argc)
+ initialize(CFG_S(CFN_HOME_URI));
/* load stdin if first argument is '-' */
if (optind < argc && !strcmp(argv[optind], "-"))
load_stdin();
/* load remaining command line arguments as uris into new clients */
else if (optind < argc)
- for (i = optind; i < argc; i++)
- client_create(argv[i], NULL, TRUE, TRUE);
+ for (i = optind; i < argc; initialize(argv[i++]));
- /* don't load gtk for ipc clients, they have done their bit, and make sure
- * there are at least one client to view */
- if (gl.ipc != IPC_CLIENT && gl.clients > 0)
- gtk_main();
+ gtk_main();
exit(EXIT_SUCCESS);
}
diff --git a/browser.h b/browser.h
@@ -24,8 +24,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <JavaScriptCore/JavaScript.h>
#include <gdk/gdkkeysyms.h>
@@ -44,19 +46,16 @@
#define ICON_BAD_TLS "channel-insecure-symbolic"
#define ICON_JS_ON "emblem-ok-symbolic"
#define ICON_JS_OFF "action-unavailable-symbolic"
-#define CB(C, E, F, D) \
+#define CB(C, E, F) \
{ \
- g_signal_connect(G_OBJECT(C), (E), G_CALLBACK(F), (D)); \
- }
-#define CBA(C, E, F, D) \
- { \
- g_signal_connect_after(G_OBJECT(C), (E), G_CALLBACK(F), (D)); \
+ g_signal_connect(G_OBJECT(C), (E), G_CALLBACK(F), NULL); \
}
#define CFG_B(X) cfg[(X)].v.b
#define CFG_F(X) cfg[(X)].v.f
#define CFG_I(X) cfg[(X)].v.i
#define CFG_L(X) (const gchar* const*)cfg[(X)].v.l
#define CFG_S(X) cfg[(X)].v.s
+#define CFG_DIR g_get_user_config_dir()
#define TLS_MSG_FORMAT "<h2>Could not validate TLS for: %s</h2><pre>%s" \
"</pre><pre>s:%s\ni:%s\nv:NotBefore:%s; NotAfter:" \
@@ -88,6 +87,55 @@
#define STATE_JAVASCRIPT 1 << 1
#define BROWSER_ERROR (browser_error_quark())
#define ABOUT_SCHEME __NAME__"-about"
+#define ABOUT_BLANK "about:blank"
+#define SCRIPT_MAIN_FRAME "window.onmessage = (e) => {" \
+ " window.adji_selection = e.data;" \
+ "};"
+#define SCRIPT_ALL_FRAMES "window.onmessage = (e) => {" \
+ " if (e.data == 'selection') {" \
+ " let r = window.getSelection().toString();" \
+ " e.source.postMessage(r, e.origin);" \
+ " }" \
+ "};"
+#define SCRIPT_SEARCH_EXTRA "cw = document.activeElement.contentWindow;" \
+ "if (cw) {" \
+ " cw.postMessage('selection','*');" \
+ "} else {" \
+ " let r = window.getSelection().toString();" \
+ " window.adji_selection = r;" \
+ "} window.adji_selection;"
+#define SCRIPT_SEARCH "window.adji_selection = '';"SCRIPT_SEARCH_EXTRA
+#define IUS(W, S, C) /* Inject User Script */ \
+ { \
+ webkit_user_content_manager_add_script( \
+ webkit_web_view_get_user_content_manager((W)), \
+ webkit_user_script_new( \
+ (S), \
+ (C), \
+ WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START, \
+ NULL, \
+ NULL)); \
+ }
+#define IUSS(W, S, C) /* Inject User Style Sheet */ \
+ { \
+ webkit_user_content_manager_add_style_sheet( \
+ webkit_web_view_get_user_content_manager((W)), \
+ webkit_user_style_sheet_new( \
+ (S), \
+ (C), \
+ WEBKIT_USER_STYLE_LEVEL_USER, \
+ NULL, \
+ NULL)); \
+ }
+
+/*** Name translations ***/
+/* name original name */
+#define request_path(R) webkit_uri_scheme_request_get_path((R))
+#define get_socket_win(W) gtk_plug_get_socket_window(GTK_PLUG((W)))
+#define get_widget_win(W) gtk_widget_get_window((W))
+#define get_win_state(W) gdk_window_get_state(get_widget_win(W))
+#define is_fullscreen() get_win_state(gl.win) & GDK_WINDOW_STATE_FULLSCREEN
+#define to_gdk_win(D, W) gdk_x11_window_foreign_new_for_display((D), (W))
enum javascript_policy {
JSP_DISABLE = 0,
@@ -101,97 +149,69 @@ enum inpage_search_type {
IPS_BACKWARD
};
-enum ipc_type {
- IPC_NONE,
- IPC_HOST,
- IPC_CLIENT
-};
-
enum config_type {
CFG_INT,
CFG_FLOAT,
CFG_BOOL,
CFG_STRING,
- CFG_LIST,
+ CFG_LIST
};
+/** Enumerators for configurables */
enum config_name {
- AcceptedLanguages,
- BadTlsTabFormat,
- ConsoleToStdout,
- CookieFile,
- DnsPrefetching,
- DefaultCharset,
- DefaultFont,
- DefaultFontSize,
- DeveloperExtras,
- DisableAutoLoadImages,
- DisableJavaScript,
- DownloadDirectory,
- EncryptedMedia,
- ExternalHandlerFile,
- ExternalHandlerKeys,
- FifoName,
- HistoryFile,
- HomeUri,
- HyperlinkAuditing,
- JsAccessClipboard,
- JsOpenWindows,
- MonospaceFont,
- NormalTabFormat,
- ProxyIgnore,
- ProxyUri,
- SansSerifFont,
- SearchEngineUriFormat,
- SerifFont,
- SmoothScrolling,
- StateFile,
- UcDir, /* user (cascading) style sheets directory */
- UriSchemes,
- UsDir, /* user scripts directory */
- UserAgent,
- WeDir, /* web extension directory */
- WebRtc,
- XdgSchemes,
- ZoomLevel,
+ CFN_ACCEPTED_LANGUAGES,
+ CFN_BLOB_FILE,
+ CFN_CONSOLE_TO_STDOUT,
+ CFN_COOKIE_FILE,
+ CFN_DNS_PREFETCHING,
+ CFN_DEFAULT_CHARSET,
+ CFN_DEFAULT_FONT,
+ CFN_DEFAULT_FONT_SIZE,
+ CFN_DEVELOPER_EXTRAS,
+ CFN_DISABLE_AUTOLOAD_IMAGES,
+ CFN_DISABLE_JAVASCRIPT,
+ CFN_ENCRYPTED_MEDIA,
+ CFN_EXTERNAL_HANDLER_FILE,
+ CFN_EXTERNAL_HANDLER_KEYS,
+ CFN_HISTORY_FILE,
+ CFN_HOME_URI,
+ CFN_HYPERLINK_AUDITING,
+ CFN_JS_ACCESS_CLIPBOARD,
+ CFN_JS_OPEN_WINDOWS,
+ CFN_MONOSPACE_FONT,
+ CFN_NORMAL_TAB_FORMAT,
+ CFN_PROXY_IGNORE,
+ CFN_PROXY_URI,
+ CFN_SANS_SERIF_FONT,
+ CFN_SEARCH_ENGINE_URI_FORMAT,
+ CFN_SERIF_FONT,
+ CFN_SMOOTH_SCROLLING,
+ CFN_STATE_FILE,
+ CFN_TAB_HOST,
+ CFN_USER_CSS_DIR,
+ CFN_URI_SCHEMES,
+ CFN_USER_SCRIPT_DIR,
+ CFN_USER_AGENT,
+ CFN_WEB_EXTENSION_DIR,
+ CFN_WEB_RTC,
+ CFN_XDG_SCHEMES,
+ CFN_ZOOM_LEVEL,
/* must be last to represent number of config items */
- LastConfig
+ CFN_LAST
};
enum browser_error {
- BROWSER_ERROR_INVALID_ABOUT_PATH
+ BER_INVALID_ABOUT_PATH
};
-static GQuark browser_error_quark()
-{
- return g_quark_from_string(__NAME__"-quark");
-}
-
typedef union {
- gint i; /* union integer */
- gdouble f; /* union float/double */
- gboolean b; /* union boolean */
- gchar *s; /* union string */
- gchar **l; /* union string list/array */
+ gint i;
+ gdouble f;
+ gboolean b;
+ gchar *s;
+ gchar **l;
} Arg;
-struct Client
-{
- GTlsCertificate *crt; /* last certificate */
- GtkWidget *entry; /* uri/command/entry */
- gboolean error_page; /* flag if error page */
- GTlsCertificate *failed_crt; /* last failed certificate */
- gboolean focus_new_tab; /* flag for focusing tab */
- gchar *hover_uri; /* uri last hovered */
- gboolean https; /* flag if https site */
- WebKitSettings *settings; /* reference to webkit settings */
- GtkWidget *tab_icon; /* holder for favicon in tab */
- GtkWidget *tab_label; /* holder for title in tab */
- GTlsCertificateFlags tls_error; /* last tls error */
- GtkWidget *vbx; /* vertical box (view + entry) */
- GtkWidget *wv; /* web view */
-};
-
typedef struct {
const char *e;
const char *s;
@@ -201,192 +221,236 @@ typedef struct {
} Config;
struct Global {
- int clients;
+ GTlsCertificate *crt;
+ gboolean error_page;
+ gboolean first_search;
+ gchar *hover_uri;
+ GTlsCertificate *failed_crt;
gboolean state_lock;
- enum ipc_type ipc;
- int ipc_pipe_fd;
+ gboolean initialized;
+ gboolean https;
+ Window embed;
+ GtkWidget *win;
+ GtkWidget *vbx;
+ GtkWidget *wv;
+ GtkWidget *entry;
+ gchar *arg0;
+ WebKitSettings *settings;
gchar *search_text;
+ GTlsCertificateFlags tls_error;
} gl;
-struct MainWindow
+
+/*** "Special" functions ***/
+static GQuark
+browser_error_quark()
{
- GtkWidget *dbx;
- GtkWidget *nb;
- GtkWidget *win;
-} mw;
-
-/* "normal" functions */
-static void about_scheme_request(WebKitURISchemeRequest *, gpointer);
-static struct Client *client_create(const gchar *, WebKitWebView *, gboolean,
- gboolean);
-static void client_destroy(struct Client *);
-static gboolean command(struct Client *, const gchar*);
-static void create_context_menu(struct Client *, WebKitContextMenu *,
- WebKitHitTestResult *);
-static void create_context_menu_item(struct Client *, WebKitContextMenu *,
- const gchar *, const gchar *, void *);
-static void die(const char *);
-static int get_memory(int *, int *, int *, int *);
-static gchar *get_uri(GtkWidget*);
-static gboolean ipc_request(GIOChannel *, GIOCondition, gpointer);
-static ssize_t ipc_send(char *);
-static void ipc_setup(void);
-static gboolean key_common(struct Client *, GdkEventKey *);
-static gboolean key_entry(struct Client *, GdkEventKey *);
-static gboolean key_tab(struct Client *, GdkEvent *);
-static gboolean key_web_view(struct Client *, GdkEvent *);
-static void load_changed(struct Client *, WebKitLoadEvent);
+ return g_quark_from_string(__NAME__"-quark");
+}
+
+
+/*** Function prototypes ***/
+static void about_scheme_request(
+ WebKitURISchemeRequest *request,
+ gpointer data
+);
+
+static void attach_to_host(
+ GtkWidget *self
+);
+
+static void attach_to_window(
+ GtkWidget *self
+);
+
+static void initialize(
+ const gchar *uri
+);
+
+static void terminate(void);
+
+static gboolean command(
+ const gchar *t
+);
+
+static void create_context_menu(
+ WebKitContextMenu *context_menu,
+ WebKitHitTestResult *hit_test_result
+);
+
+static void create_context_menu_item(
+ WebKitContextMenu *context_menu,
+ const gchar *name,
+ const gchar *label,
+ void *action
+);
+
+static void download_blob(
+ WebKitDownload *d
+);
+
+static void download_response(
+ WebKitURIResponse *r
+);
+
+static gchar *get_uri(
+ GtkWidget *wv
+);
+
+static gboolean handle_fullscreen(
+ gboolean fullscreen
+);
+
+static gboolean key_common(
+ GdkEventKey *event
+);
+
+static gboolean key_entry(
+ GdkEventKey *event
+);
+
+static gboolean key_web_view(
+ GdkEvent *event
+);
+
+static void load_changed(
+ WebKitLoadEvent event_type
+);
+
static void load_configuration(void);
-static void load_state(void);
+
static void load_stdin(void);
-static void load_user_styles(WebKitWebView *);
+
+static void load_user_scripts(
+ WebKitWebView *web_view
+);
+
+static void load_user_styles(
+ WebKitWebView *web_view
+);
+
static void main_window_setup(void);
-static void open_external(struct Client *, const gchar);
-static void prepare_download(WebKitDownload *, gchar *);
+
+static void open_external(
+ const gchar s
+);
+
static void quit(void);
-static gchar *rebuild_filename(gchar *, int);
-static void render_tls_error(struct Client *, gchar *, GTlsCertificate *,
- GTlsCertificateFlags);
-static void run_user_scripts(WebKitWebView *);
-static void save_history(const gchar *);
-static void save_state(void);
-static void search(struct Client *, enum inpage_search_type);
-static void selection_search(struct Client *);
-static void selection_search_finished(struct Client *, GAsyncResult *);
+
+static void render_tls_error(
+ gchar *uri,
+ GTlsCertificate *crt,
+ GTlsCertificateFlags crt_flags
+);
+
+static void save_history(
+ const gchar *t
+);
+
+static void search(
+ enum inpage_search_type type
+);
+
+static void selection_search(void);
+
+static void selection_search_finished(
+ GAsyncResult *result
+);
+
static void set_default_web_context(void);
-static void set_hover_uri(struct Client *, WebKitHitTestResult *);
-static void set_javascript_policy(struct Client *, enum javascript_policy);
-static void set_window_title(gint);
-static void show_web_view(struct Client *);
-static void toggle_inspector(struct Client *);
-static void toggle_tls_error_policy(struct Client *);
-static gchar *resolve_uri(const gchar *);
-static char *resolve_uri_words(int, char **);
-static void update_download_button(WebKitDownload *, GtkButton *, gboolean);
-static void update_favicon(struct Client *);
-static void update_load_progress(struct Client *);
-static void update_title(struct Client *);
-static void uri_changed(struct Client *);
-static void web_view_crashed(struct Client *);
-static void xdg_open(const gchar *, const gchar *);
-
-/* callback functions */
-static gboolean cb_context_menu(WebKitWebView *, WebKitContextMenu *,
- GdkEvent *, WebKitHitTestResult *, gpointer);
-static void cb_download_changed_progress(GObject *, GParamSpec *, gpointer);
-static void cb_download_finished(GObject *, gpointer);
-static gboolean cb_download_prepare(WebKitDownload *, gchar *, gpointer);
-static void cb_download_press(GtkWidget *, GdkEventButton *, gpointer);
-static void cb_download_start(WebKitWebView *, WebKitDownload *, gpointer);
-static void cb_favicon_changed(GObject *, GParamSpec *, gpointer);
-static gboolean cb_entry_hid(GtkWidget *, GdkEvent *, gpointer);
-static void cb_entry_icon_hid(GtkEntry *, GtkEntryIconPosition, GdkEvent *,
- gpointer);
-static void cb_notebook_modified(GtkNotebook *, GtkWidget *, guint, gpointer);
-static void cb_notebook_switch_page(GtkNotebook *, GtkWidget *, guint,
- gpointer);
-static gboolean cb_open_external(GSimpleAction *, GVariant *, gpointer);
-static gboolean cb_selection_search(GSimpleAction *, GVariant *, gpointer);
-static void cb_selection_search_finished(GObject *, GAsyncResult *, gpointer);
-static void cb_quit(GObject *, gpointer);
-static gboolean cb_tab_hid(GtkWidget *, GdkEvent *, gpointer);
-static void cb_title_changed(GObject *, GParamSpec *, gpointer);
-static void cb_uri_changed(GObject *, GParamSpec *, gpointer);
-static void cb_wv_close(GtkWidget *, gpointer);
-static gboolean cb_wv_crashed(WebKitWebView *, gpointer);
-static WebKitWebView *cb_wv_create(WebKitWebView *, WebKitNavigationAction *,
- gpointer);
-static gboolean cb_wv_decide_policy(WebKitWebView *, WebKitPolicyDecision *,
- WebKitPolicyDecisionType, gpointer);
-static gboolean cb_wv_hid(GtkWidget *, GdkEvent *, gpointer);
-static void cb_wv_hover(WebKitWebView *, WebKitHitTestResult *, guint,
- gpointer);
-static void cb_wv_load_changed(GObject *, GParamSpec *, gpointer);
-static void cb_wv_load_progress_changed(GObject *, GParamSpec *, gpointer);
-static void cb_wv_show(WebKitWebView *, gpointer);
-static gboolean cb_wv_tls_load_failed(GObject *, gchar *, GTlsCertificate *,
- GTlsCertificateFlags, gpointer);
+static void set_hover_uri(
+ WebKitHitTestResult *hit_test_result
+);
-gboolean
-cb_context_menu(WebKitWebView *web_view,
- WebKitContextMenu *context_menu,
- GdkEvent *event,
- WebKitHitTestResult *hit_test_result,
- gpointer data)
-{
- (void)web_view;
- (void)event;
+static void set_javascript_policy(
+ enum javascript_policy policy
+);
- create_context_menu((struct Client *)data, context_menu, hit_test_result);
- return FALSE;
-}
+static void toggle_inspector(void);
+
+static void toggle_tls_error_policy(void);
+static gchar *resolve_uri(
+ const gchar *t
+);
+
+static char *resolve_uri_words(
+ int c,
+ char **w
+);
+
+static void update_favicon(void);
+
+static void update_load_progress(void);
+
+static void update_title(void);
+
+static void uri_changed(void);
+
+static void web_view_crashed(void);
+
+static void xdg_open(
+ const gchar *s,
+ const gchar *t,
+ gboolean keep
+);
+
+
+/*** Utility functions ***/
void
-cb_download_changed_progress(GObject *obj,
- GParamSpec *pspec,
- gpointer data)
+die(
+ const char *msg)
{
- (void)pspec;
-
- update_download_button(WEBKIT_DOWNLOAD(obj), GTK_BUTTON(data), FALSE);
+ fprintf(stderr, msg);
+ exit(EXIT_FAILURE);
}
void
-cb_download_finished(GObject *obj,
- gpointer data)
+g_free_all(
+ gpointer *p)
{
- if (!GTK_IS_BUTTON(data))
- return;
-
- (*((gboolean*)g_object_get_data(data, __NAME__"-finished"))) = TRUE;
-
- update_download_button(WEBKIT_DOWNLOAD(obj), GTK_BUTTON(data), TRUE);
- gtk_button_set_image(
- GTK_BUTTON(data),
- gtk_image_new_from_icon_name(ICON_FINISHED, GTK_ICON_SIZE_BUTTON)
- );
+ for (; *p; g_free(*(p++)));
}
-gboolean
-cb_download_prepare(WebKitDownload *download,
- gchar *suggested_filename,
- gpointer data)
+void
+to_win(
+ Window *i,
+ const char *s)
{
- (void)data;
+ char *e;
- prepare_download(download, suggested_filename);
- return FALSE;
+ *i = strtol(s, &e, 0);
+ if (e == s || *e != 0)
+ *i = -1;
}
void
-cb_download_press(GtkWidget *btn,
- GdkEventButton *event,
- gpointer data)
+sigchld(
+ int s)
{
- switch (event->button) {
- case 3: /* right click: */
- case 2: /* middle click: cancel and/or remove */
- if (!(*((gboolean*)g_object_get_data(G_OBJECT(btn), __NAME__"-finished"))))
- webkit_download_cancel(WEBKIT_DOWNLOAD(data));
- g_object_unref(WEBKIT_DOWNLOAD(data));
- gtk_widget_destroy(btn);
- break;
- case 1: /* left click: open downloaded file */
- if ((*((gboolean*)g_object_get_data(G_OBJECT(btn), __NAME__"-finished"))))
- xdg_open("", webkit_download_get_destination(WEBKIT_DOWNLOAD(data)));
- break;
- }
+ (void) s;
+
+ if (signal(SIGCHLD, sigchld) == SIG_ERR)
+ die("Failed to initialize SIGCHLD handler");
+ while (waitpid(-1, NULL, WNOHANG) > 0);
}
-void
-cb_download_start(WebKitWebView *web_view,
- WebKitDownload *download,
- gpointer data)
+
+/*** Callback function wrappers ***/
+gboolean
+cb_context_menu(WebKitWebView *web_view,
+ WebKitContextMenu *context_menu,
+ GdkEvent *event,
+ WebKitHitTestResult *hit_test_result,
+ gpointer data)
{
+ (void)data;
+ (void)event;
(void)web_view;
- CB(download, "decide-destination", cb_download_prepare, data);
+ create_context_menu(context_menu, hit_test_result);
+ return FALSE;
}
void
@@ -396,8 +460,9 @@ cb_favicon_changed(GObject *obj,
{
(void)obj;
(void)pspec;
+ (void)data;
- update_favicon((struct Client *)data);
+ update_favicon();
}
gboolean
@@ -406,10 +471,11 @@ cb_entry_hid(GtkWidget *widget,
gpointer data)
{
(void)widget;
+ (void)data;
/* only handle key presses */
if (event->type == GDK_KEY_PRESS)
- return key_entry((struct Client *)data, (GdkEventKey*)event);
+ return key_entry((GdkEventKey*)event);
return FALSE;
@@ -423,38 +489,39 @@ cb_entry_icon_hid(GtkEntry *entry,
{
(void)entry;
(void)event;
+ (void)data;
if (icon_pos == GTK_ENTRY_ICON_PRIMARY)
- toggle_tls_error_policy((struct Client *)data);
+ toggle_tls_error_policy();
else if (icon_pos == GTK_ENTRY_ICON_SECONDARY)
- set_javascript_policy((struct Client *)data, JSP_TOGGLE);
+ set_javascript_policy(JSP_TOGGLE);
}
void
-cb_notebook_modified(GtkNotebook *notebook,
- GtkWidget *child,
- guint idx,
- gpointer data)
+cb_download_prepare(WebKitDownload *download,
+ GParamSpec *param,
+ gpointer data)
{
- (void)notebook;
- (void)child;
- (void)idx;
+ (void)param;
(void)data;
- save_state();
+ /* check if blob */
+ download_blob(download);
+
+ /* forward to external download handler */
+ download_response(webkit_download_get_response(download));
+ webkit_download_cancel(download);
}
void
-cb_notebook_switch_page(GtkNotebook *notebook,
- GtkWidget *child,
- guint idx,
- gpointer data)
+cb_download_start(WebKitWebContext *context,
+ WebKitDownload *download,
+ gpointer data)
{
- (void)notebook;
- (void)child;
+ (void)context;
(void)data;
- set_window_title(idx);
+ CB(download, "decide-destination", cb_download_prepare);
}
gboolean
@@ -464,8 +531,9 @@ cb_open_external(GSimpleAction *action,
{
(void)action;
(void)parameter;
+ (void)data;
- open_external((struct Client *)data, 0);
+ open_external(0);
return FALSE;
}
@@ -486,8 +554,10 @@ cb_selection_search(GSimpleAction *action,
{
(void)action;
(void)parameter;
+ (void)data;
- selection_search((struct Client *)data);
+ gl.first_search = TRUE;
+ selection_search();
return FALSE;
}
@@ -496,21 +566,10 @@ cb_selection_search_finished(GObject *object,
GAsyncResult *result,
gpointer data)
{
- struct Client *c = (struct Client *)data;
-
+ (void)data;
(void)object;
- selection_search_finished(c, result);
-}
-
-gboolean
-cb_tab_hid(GtkWidget *widget,
- GdkEvent *event,
- gpointer data)
-{
- (void)widget;
-
- return key_tab((struct Client *)data, event);
+ selection_search_finished(result);
}
void
@@ -520,8 +579,32 @@ cb_title_changed(GObject *obj,
{
(void)obj;
(void)pspec;
+ (void)data;
+
+ update_title();
+}
+
+void
+cb_map(GObject *obj,
+ GdkEvent event,
+ gpointer data)
+{
+ (void)event;
+ (void)data;
- update_title((struct Client *)data);
+ attach_to_host((GtkWidget *)obj);
+}
+
+
+void
+cb_unmap(GObject *obj,
+ GdkEvent event,
+ gpointer data)
+{
+ (void)event;
+ (void)data;
+
+ attach_to_window((GtkWidget *)obj);
}
void
@@ -531,8 +614,9 @@ cb_uri_changed(GObject *obj,
{
(void)obj;
(void)pspec;
+ (void)data;
- uri_changed((struct Client *)data);
+ uri_changed();
}
void
@@ -540,8 +624,9 @@ cb_wv_close(GtkWidget *widget,
gpointer data)
{
(void)widget;
+ (void)data;
- client_destroy((struct Client *)data);
+ terminate();
}
gboolean
@@ -549,8 +634,9 @@ cb_wv_crashed(WebKitWebView *web_view,
gpointer data)
{
(void)web_view;
+ (void)data;
- web_view_crashed((struct Client *)data);
+ web_view_crashed();
return TRUE;
}
@@ -559,15 +645,14 @@ cb_wv_create(WebKitWebView *web_view,
WebKitNavigationAction *navigation_action,
gpointer data)
{
- struct Client *c;
-
- (void)navigation_action;
+ (void)web_view;
(void)data;
- if ((c = client_create(NULL, web_view, FALSE, FALSE)) == NULL)
- return NULL;
+ initialize(
+ webkit_uri_request_get_uri(
+ webkit_navigation_action_get_request(navigation_action)));
- return WEBKIT_WEB_VIEW(c->wv);
+ return NULL;
}
gboolean
@@ -580,35 +665,60 @@ cb_wv_decide_policy(WebKitWebView *web_view,
(void)data;
/* only handle policy decisions */
- if (type != WEBKIT_POLICY_DECISION_TYPE_RESPONSE)
+ if (type != WEBKIT_POLICY_DECISION_TYPE_RESPONSE) {
return FALSE;
/* check if: 'HTTP/1.1 204 No Content'
* this should be ignored, but isn't
* see: https://bugs.webkit.org/show_bug.cgi?id=60206
* */
- else if (webkit_uri_response_get_status_code(
+ } else if (webkit_uri_response_get_status_code(
webkit_response_policy_decision_get_response(
WEBKIT_RESPONSE_POLICY_DECISION(decision))) == 204
- )
+ ) {
webkit_policy_decision_ignore(decision);
/* continue as normal */
- else if (!webkit_response_policy_decision_is_mime_type_supported(
+ } else if (webkit_response_policy_decision_is_mime_type_supported(
WEBKIT_RESPONSE_POLICY_DECISION(decision))
- )
- webkit_policy_decision_download(decision);
- else
+ ) {
webkit_policy_decision_use(decision);
+ } else {
+ webkit_policy_decision_ignore(decision);
+ download_response(
+ webkit_response_policy_decision_get_response(
+ WEBKIT_RESPONSE_POLICY_DECISION(decision)));
+ }
return TRUE;
}
+gboolean
+cb_wv_fullscreen_enter(WebKitWebView *web_view,
+ gpointer data)
+{
+ (void)web_view;
+ (void)data;
+
+ return !handle_fullscreen(TRUE);
+}
+
+gboolean
+cb_wv_fullscreen_leave(WebKitWebView *web_view,
+ gpointer data)
+{
+ (void)web_view;
+ (void)data;
+
+ return !handle_fullscreen(FALSE);
+}
+
gboolean
cb_wv_hid(GtkWidget *widget,
GdkEvent *event,
gpointer data)
{
(void)widget;
+ (void)data;
- return key_web_view((struct Client *)data, event);
+ return key_web_view(event);
}
void
@@ -619,8 +729,9 @@ cb_wv_hover(WebKitWebView *web_view,
{
(void)web_view;
(void)modifiers;
+ (void)data;
- set_hover_uri((struct Client *)data, hit_test_result);
+ set_hover_uri(hit_test_result);
}
void
@@ -629,8 +740,9 @@ cb_wv_load_changed(GObject *obj,
gpointer data)
{
(void)obj;
+ (void)data;
- load_changed((struct Client *)data, (WebKitLoadEvent)pspec);
+ load_changed((WebKitLoadEvent)pspec);
}
void
@@ -640,17 +752,9 @@ cb_wv_load_progress_changed(GObject *obj,
{
(void)obj;
(void)pspec;
+ (void)data;
- update_load_progress((struct Client *)data);
-}
-
-void
-cb_wv_show(WebKitWebView *web_view,
- gpointer data)
-{
- (void)web_view;
-
- show_web_view((struct Client *)data);
+ update_load_progress();
}
gboolean
@@ -661,8 +765,9 @@ cb_wv_tls_load_failed(GObject *obj,
gpointer data)
{
(void)obj;
+ (void)data;
- render_tls_error((struct Client *)data, uri, crt, err);
+ render_tls_error(uri, crt, err);
return TRUE;
}
diff --git a/config.h b/config.h
@@ -1,4 +1,7 @@
/**
+ * @file
+ * @brief Configuration file
+ *
* Copyright (C) 2023 Chris Noxz
* Author(s): Chris Noxz <chris@noxz.tech>
*
@@ -19,46 +22,48 @@
#ifndef CONFIG_H
#define CONFIG_H
-static Config cfg[LastConfig] = {
- /* config name enviornment variable name webkit web view setting name config type invert default value */
- [AcceptedLanguages] = { __NAME_UPPERCASE__"_ACCEPTED_LANGUAGES", NULL, CFG_LIST, FALSE, {.l = NULL }},
- [BadTlsTabFormat] = { NULL, NULL, CFG_STRING, FALSE, {.s = "<span foreground=\"yellow\" style=\"italic\">%s</span>" }},
- [ConsoleToStdout] = { __NAME_UPPERCASE__"_ENABLE_CONSOLE_TO_STDOUT", "enable-write-console-messages-to-stdout", CFG_BOOL, FALSE, {.b = FALSE }},
- [CookieFile] = { __NAME_UPPERCASE__"_COOKIE_FILE", NULL, CFG_STRING, FALSE, {.s = NULL }},
- [DnsPrefetching] = { NULL, "enable-dns-prefetching", CFG_BOOL, FALSE, {.b = FALSE }},
- [DefaultCharset] = { __NAME_UPPERCASE__"_CHARSET", "default-charset", CFG_STRING, FALSE, {.s = "UTF-8" }},
- [DefaultFontSize] = { __NAME_UPPERCASE__"_DEFAULT_FONT_SIZE", "default-font-size", CFG_INT, FALSE, {.i = 12 }},
- [DefaultFont] = { __NAME_UPPERCASE__"_DEFAULT_FONT", "default-font-family", CFG_STRING, FALSE, {.s = "monospace" }},
- [DeveloperExtras] = { NULL, "enable-developer-extras", CFG_BOOL, FALSE, {.b = TRUE }},
- [DisableAutoLoadImages] = { __NAME_UPPERCASE__"_DISABLE_AUTO_LOAD_IMAGES", "auto-load-images", CFG_BOOL, TRUE, {.b = FALSE }},
- [DisableJavaScript] = { __NAME_UPPERCASE__"_DISABLE_JAVASCRIPT", "enable-javascript-markup", CFG_BOOL, TRUE, {.b = FALSE }},
- [DownloadDirectory] = { __NAME_UPPERCASE__"_DOWNLOAD_DIR", NULL, CFG_STRING, FALSE, {.s = "/var/tmp" }},
- [EncryptedMedia] = { NULL, "enable-encrypted-media", CFG_BOOL, FALSE, {.b = FALSE }},
- [ExternalHandlerFile] = { NULL, NULL, CFG_STRING, FALSE, {.s = "exthandler" }},
- [ExternalHandlerKeys] = { __NAME_UPPERCASE__"_EXTERNAL_HANDLER_KEYS", NULL, CFG_LIST, FALSE, {.l = NULL }},
- [FifoName] = { __NAME_UPPERCASE__"_FIFO_NAME", NULL, CFG_STRING, FALSE, {.s = "default" }},
- [HistoryFile] = { __NAME_UPPERCASE__"_HISTORY_FILE", NULL, CFG_STRING, FALSE, {.s = NULL }},
- [HomeUri] = { __NAME_UPPERCASE__"_HOME_URI", NULL, CFG_STRING, FALSE, {.s = "about:blank" }},
- [HyperlinkAuditing] = { NULL, "enable-hyperlink-auditing", CFG_BOOL, FALSE, {.b = FALSE }},
- [JsAccessClipboard] = { NULL, "javascript-can-access-clipboard", CFG_BOOL, FALSE, {.b = FALSE }},
- [JsOpenWindows] = { NULL, "javascript-can-access-clipboard", CFG_BOOL, FALSE, {.b = FALSE }},
- [MonospaceFont] = { __NAME_UPPERCASE__"_MONOSPACE_FONT", "monospace-font-family", CFG_STRING, FALSE, {.s = "monospace" }},
- [NormalTabFormat] = { NULL, NULL, CFG_STRING, FALSE, {.s = "<span>%s</span>" }},
- [ProxyIgnore] = { __NAME_UPPERCASE__"_PROXY_IGNORE", NULL, CFG_LIST, FALSE, {.l = NULL }},
- [ProxyUri] = { __NAME_UPPERCASE__"_PROXY_URI", NULL, CFG_STRING, FALSE, {.s = NULL }},
- [SansSerifFont] = { __NAME_UPPERCASE__"_SANS_SERIF_FONT", "sans-serif-font-family", CFG_STRING, FALSE, {.s = "sans-serif" }},
- [SearchEngineUriFormat] = { __NAME_UPPERCASE__"_SE_URI_FORMAT", NULL, CFG_STRING, FALSE, {.s = "https://ddg.gg?q=%s" }},
- [SerifFont] = { __NAME_UPPERCASE__"_SERIF_FONT", "serif-font-family", CFG_STRING, FALSE, {.s = "serif" }},
- [SmoothScrolling] = { __NAME_UPPERCASE__"_ENABLE_SMOOTH_SCROLLING", "enable-smooth-scrolling", CFG_BOOL, FALSE, {.b = FALSE }},
- [StateFile] = { __NAME_UPPERCASE__"_STATE_FILE", NULL, CFG_STRING, FALSE, {.s = NULL }},
- [UcDir] = { NULL, NULL, CFG_STRING, FALSE, {.s = "styles" }},
- [UriSchemes] = { NULL, NULL, CFG_LIST, FALSE, {.l = (gchar*[]){ "http", "https", "file", "about", __NAME__"-about", "data", "webkit", NULL } }},
- [UsDir] = { NULL, NULL, CFG_STRING, FALSE, {.s = "scripts" }},
- [UserAgent] = { __NAME_UPPERCASE__"_USER_AGENT", "user-agent", CFG_STRING, FALSE, {.s = NULL }},
- [WeDir] = { NULL, NULL, CFG_STRING, FALSE, {.s = "web_extensions" }},
- [WebRtc] = { NULL, "enable-webrtc", CFG_BOOL, FALSE, {.b = FALSE }},
- [XdgSchemes] = { __NAME_UPPERCASE__"_XDG_SCHEMES", NULL, CFG_LIST, FALSE, {.l = NULL }},
- [ZoomLevel] = { __NAME_UPPERCASE__"_ZOOM_LEVEL", NULL, CFG_FLOAT, FALSE, {.f = 1.0 }},
+/**
+ * @brief Contains dynamically loaded configuration
+ */
+static Config cfg[CFN_LAST] = {
+ /* config name enviornment variable name webkit web view setting name config type invert default value */
+ [CFN_ACCEPTED_LANGUAGES] = { __NAME_UPPERCASE__"_ACCEPTED_LANGUAGES", NULL, CFG_LIST, FALSE, {.l = NULL }},
+ [CFN_BLOB_FILE] = { __NAME_UPPERCASE__"_BLOB_FILE", NULL, CFG_STRING, FALSE, {.s = "/tmp/." __NAME__ "_blob" }},
+ [CFN_CONSOLE_TO_STDOUT] = { __NAME_UPPERCASE__"_ENABLE_CONSOLE_TO_STDOUT", "enable-write-console-messages-to-stdout", CFG_BOOL, FALSE, {.b = FALSE }},
+ [CFN_COOKIE_FILE] = { __NAME_UPPERCASE__"_COOKIE_FILE", NULL, CFG_STRING, FALSE, {.s = NULL }},
+ [CFN_DNS_PREFETCHING] = { NULL, "enable-dns-prefetching", CFG_BOOL, FALSE, {.b = FALSE }},
+ [CFN_DEFAULT_CHARSET] = { __NAME_UPPERCASE__"_CHARSET", "default-charset", CFG_STRING, FALSE, {.s = "UTF-8" }},
+ [CFN_DEFAULT_FONT] = { __NAME_UPPERCASE__"_DEFAULT_FONT", "default-font-family", CFG_STRING, FALSE, {.s = "monospace" }},
+ [CFN_DEFAULT_FONT_SIZE] = { __NAME_UPPERCASE__"_DEFAULT_FONT_SIZE", "default-font-size", CFG_INT, FALSE, {.i = 12 }},
+ [CFN_DEVELOPER_EXTRAS] = { NULL, "enable-developer-extras", CFG_BOOL, FALSE, {.b = TRUE }},
+ [CFN_DISABLE_AUTOLOAD_IMAGES] = { __NAME_UPPERCASE__"_DISABLE_AUTO_LOAD_IMAGES", "auto-load-images", CFG_BOOL, TRUE, {.b = FALSE }},
+ [CFN_DISABLE_JAVASCRIPT] = { __NAME_UPPERCASE__"_DISABLE_JAVASCRIPT", "enable-javascript-markup", CFG_BOOL, TRUE, {.b = FALSE }},
+ [CFN_ENCRYPTED_MEDIA] = { NULL, "enable-encrypted-media", CFG_BOOL, FALSE, {.b = FALSE }},
+ [CFN_EXTERNAL_HANDLER_FILE] = { NULL, NULL, CFG_STRING, FALSE, {.s = "exthandler" }},
+ [CFN_EXTERNAL_HANDLER_KEYS] = { __NAME_UPPERCASE__"_EXTERNAL_HANDLER_KEYS", NULL, CFG_LIST, FALSE, {.l = NULL }},
+ [CFN_HISTORY_FILE] = { __NAME_UPPERCASE__"_HISTORY_FILE", NULL, CFG_STRING, FALSE, {.s = NULL }},
+ [CFN_HOME_URI] = { __NAME_UPPERCASE__"_HOME_URI", NULL, CFG_STRING, FALSE, {.s = "about:blank" }},
+ [CFN_HYPERLINK_AUDITING] = { NULL, "enable-hyperlink-auditing", CFG_BOOL, FALSE, {.b = FALSE }},
+ [CFN_JS_ACCESS_CLIPBOARD] = { NULL, "javascript-can-access-clipboard", CFG_BOOL, FALSE, {.b = FALSE }},
+ [CFN_JS_OPEN_WINDOWS] = { NULL, "javascript-can-open-windows-automatically",CFG_BOOL, FALSE, {.b = FALSE }},
+ [CFN_MONOSPACE_FONT] = { __NAME_UPPERCASE__"_MONOSPACE_FONT", "monospace-font-family", CFG_STRING, FALSE, {.s = "monospace" }},
+ [CFN_NORMAL_TAB_FORMAT] = { NULL, NULL, CFG_STRING, FALSE, {.s = "<span>%s</span>" }},
+ [CFN_PROXY_IGNORE] = { __NAME_UPPERCASE__"_PROXY_IGNORE", NULL, CFG_LIST, FALSE, {.l = NULL }},
+ [CFN_PROXY_URI] = { __NAME_UPPERCASE__"_PROXY_URI", NULL, CFG_STRING, FALSE, {.s = NULL }},
+ [CFN_SANS_SERIF_FONT] = { __NAME_UPPERCASE__"_SANS_SERIF_FONT", "sans-serif-font-family", CFG_STRING, FALSE, {.s = "sans-serif" }},
+ [CFN_SEARCH_ENGINE_URI_FORMAT] = { __NAME_UPPERCASE__"_SE_URI_FORMAT", NULL, CFG_STRING, FALSE, {.s = "https://ddg.gg?q=%s" }},
+ [CFN_SERIF_FONT] = { __NAME_UPPERCASE__"_SERIF_FONT", "serif-font-family", CFG_STRING, FALSE, {.s = "serif" }},
+ [CFN_SMOOTH_SCROLLING] = { __NAME_UPPERCASE__"_ENABLE_SMOOTH_SCROLLING", "enable-smooth-scrolling", CFG_BOOL, FALSE, {.b = FALSE }},
+ [CFN_STATE_FILE] = { __NAME_UPPERCASE__"_STATE_FILE", NULL, CFG_STRING, FALSE, {.s = NULL }},
+ [CFN_TAB_HOST] = { __NAME_UPPERCASE__"_TAB_HOST", NULL, CFG_STRING, FALSE, {.s = "_TABBED_HOST" }},
+ [CFN_USER_CSS_DIR] = { NULL, NULL, CFG_STRING, FALSE, {.s = "styles" }},
+ [CFN_URI_SCHEMES] = { NULL, NULL, CFG_LIST, FALSE, {.l = (gchar*[]){ "http", "https", "file", "about", __NAME__"-about", "data", "blob", "webkit", NULL } }},
+ [CFN_USER_SCRIPT_DIR] = { NULL, NULL, CFG_STRING, FALSE, {.s = "scripts" }},
+ [CFN_USER_AGENT] = { __NAME_UPPERCASE__"_USER_AGENT", "user-agent", CFG_STRING, FALSE, {.s = NULL }},
+ [CFN_WEB_EXTENSION_DIR] = { NULL, NULL, CFG_STRING, FALSE, {.s = "web_extensions" }},
+ [CFN_WEB_RTC] = { NULL, "enable-webrtc", CFG_BOOL, FALSE, {.b = FALSE }},
+ [CFN_XDG_SCHEMES] = { __NAME_UPPERCASE__"_XDG_SCHEMES", NULL, CFG_LIST, FALSE, {.l = NULL }},
+ [CFN_ZOOM_LEVEL] = { __NAME_UPPERCASE__"_ZOOM_LEVEL", NULL, CFG_FLOAT, FALSE, {.f = 1.0 }},
};
#endif /* !CONFIG_H */
diff --git a/config.mk b/config.mk
@@ -6,7 +6,7 @@ __NAME__ = adji
__NAME_UPPERCASE__ = ADJI
# paths
-PREFIX = /usr/local
+PREFIX = ${HOME}/.local
MANPREFIX = ${PREFIX}/share/man
# flags
diff --git a/we_redirect.c b/we_redirect.c
@@ -108,6 +108,9 @@ cb_web_page_send_request(WebKitWebPage *web_page, WebKitURIRequest *request,
i = webkit_uri_request_get_uri(request);
+ if (verbose)
+ fprintf(stderr, " [req]: %s\n", i);
+
/* go through every rule and apply accordingly */
while (p && d) {
/* find matching rule for incoming uri */