logo

badwolf

Unnamed repository; edit this file 'description' to name the repository.
commit: 5030dbfd170c3eb35eac9e2be08365f72f52161b
parent: 9a30193a956daea1a88a903437e01e4759a729c8
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Fri,  5 Jul 2019 08:31:23 +0200

Merge branch 'release-0.3' for 0.3.0

Diffstat:

MMakefile2+-
Mbadwolf.111++++++++++-
Mbadwolf.c157++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 163 insertions(+), 7 deletions(-)

diff --git a/Makefile b/Makefile @@ -11,7 +11,7 @@ OBJS = badwolf TRANS = fr.mo CC = cc -CFLAGS = -g -Wall -Wextra +CFLAGS = -g -Wall -Wextra -Wconversion -Wsign-conversion CDEPS = `pkg-config --cflags $(DEPS)` -DDATADIR=\"$(DATADIR)\" -DPACKAGE=\"$(PACKAGE)\" -D_DEFAULT_SOURCE LIBS = `pkg-config --libs $(DEPS)` diff --git a/badwolf.1 b/badwolf.1 @@ -28,7 +28,7 @@ Zooms the webpage in/out. Resets webpage zoom to 100%. .It any C-t Creates a new tab (in a new session, similar as pressing the button) -.It browser C-F4 +.It browser C-F4, browser A-d Closes the current tab .It browser C-f Focuses on the search entry @@ -42,6 +42,8 @@ Go back/forward in current tab’s history Go to the previous/next tab .It any F1 Shows the about dialog +.It any Alt-n +Where n is any numeric-row key. Go to the n-th tab, 0 goes to the last one. .El .Ss DEFAULT ONES Here is a incomplete list of the default Webkit/GTK keybindings: @@ -53,6 +55,13 @@ When the search box is focused it goes to the Next/Previous search term. .It search Escape Cancels current search .El +.Sh ENVIRONMENT +.Bl -width Ds -tag +.It Ev BADWOLF_L10N +A colon-separated list in the form lang_COUNTRY where lang is in ISO-639 and COUNTRY in ISO-3166. For example +.Ic BADWOLF_L10N="en_GB:fr_FR:de_DE" . +When this variable isn't set, spelling isn't activated. A more generic variable name is also intended to be used in the future. +.El .Sh BUGS You can submit contributions or tickets to .Lk https://gitlab.com/lanodan/badwolf diff --git a/badwolf.c b/badwolf.c @@ -8,11 +8,11 @@ #include <glib/gprintf.h> /* g_fprintf() */ #include <gtk/gtk.h> #include <locale.h> /* LC_* */ -#include <stdlib.h> /* realpath() */ +#include <stdlib.h> /* realpath(), malloc() */ #include <webkit2/webkit2.h> const gchar *homepage = "https://hacktivis.me/projects/badwolf"; -const gchar *version = "0.2.1"; +const gchar *version = "0.3.0"; struct Window { @@ -67,6 +67,19 @@ static gboolean WebViewCb_mouse_target_changed(WebKitWebView *webView, static WebKitWebView *WebViewCb_create(WebKitWebView *related_web_view, WebKitNavigationAction *navigation_action, gpointer user_data); +static gboolean WebViewCb_permission_request(WebKitWebView *web_view, + WebKitPermissionRequest *request, + gpointer user_data); +static gboolean WebViewCb_decide_policy(WebKitWebView *web_view, + WebKitPolicyDecision *decision, + WebKitPolicyDecisionType decision_type, + gpointer user_data); +static void web_contentCb_download_started(WebKitWebContext *context, + WebKitDownload *download, + gpointer user_data); +static gboolean downloadCb_decide_destination(WebKitDownload *download, + gchar *suggested_filename, + gpointer user_data); static gboolean locationCb_activate(GtkEntry *location, gpointer user_data); static gboolean javascriptCb_toggled(GtkButton *javascript, gpointer user_data); static gboolean SearchEntryCb_next__match(GtkSearchEntry *search, gpointer user_data); @@ -82,6 +95,17 @@ static void notebookCb_switch__page(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data); gint get_tab_position(GtkContainer *notebook, GtkWidget *child); +/* ensure_uri_scheme: tries to add a scheme on a pseudo-URL missing a scheme + * - gchar text: pseudo-URL missing a scheme + * - gboolean try_file: when TRUE check try first if it can be a file:// path + * + * When `text` isn't exploitable (ie. NULL), returns "about:blank", + * when the URL seems to be valid, return it, + * if try_file is TRUE, check if it can be file:// path, + * some other checks might be added. + * In the end use the fallback (`http://` for now, might get configuration), + * might get some safeguard. + */ gchar * ensure_uri_scheme(gchar *text, gboolean try_file) { @@ -189,13 +213,22 @@ commonCb_key_press_event(struct Window *window, GdkEvent *event, struct Client * } } - if((((GdkEventKey *)event)->state & GDK_MOD1_MASK) && browser != NULL) + if((((GdkEventKey *)event)->state & GDK_MOD1_MASK)) { + if((browser != NULL) && (((GdkEventKey *)event)->keyval == GDK_KEY_d)) + { + webkit_web_view_try_close(browser->webView); + return TRUE; + } + switch(((GdkEventKey *)event)->keyval) { case GDK_KEY_Left: gtk_notebook_prev_page(notebook); return TRUE; case GDK_KEY_Right: gtk_notebook_next_page(notebook); return TRUE; } + if((((GdkEventKey *)event)->keyval >= GDK_KEY_0) && + (((GdkEventKey *)event)->keyval <= GDK_KEY_9)) + gtk_notebook_set_current_page(notebook, (gint)(((GdkEventKey *)event)->keyval - GDK_KEY_1)); } if(browser != NULL) @@ -425,7 +458,7 @@ WebViewCb_scroll_event(GtkWidget *widget, GdkEvent *event, gpointer data) (void)widget; struct Client *browser = (struct Client *)data; gdouble delta_x, delta_y; - gfloat zoom; + gdouble zoom; if(((GdkEventScroll *)event)->state & GDK_CONTROL_MASK) { @@ -459,6 +492,94 @@ WebViewCb_create(WebKitWebView *related_web_view, } static gboolean +WebViewCb_permission_request(WebKitWebView *web_view, + WebKitPermissionRequest *request, + gpointer user_data) +{ + (void)web_view; + (void)user_data; + + webkit_permission_request_deny(request); + + return TRUE; /* Stop other handlers */ +} + +static gboolean +WebViewCb_decide_policy(WebKitWebView *web_view, + WebKitPolicyDecision *decision, + WebKitPolicyDecisionType decision_type, + gpointer user_data) +{ + WebKitResponsePolicyDecision *r; + (void)web_view; + (void)user_data; + + switch(decision_type) + { + case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: + r = WEBKIT_RESPONSE_POLICY_DECISION(decision); + if(!webkit_response_policy_decision_is_mime_type_supported(r)) + webkit_policy_decision_download(decision); + else + webkit_policy_decision_use(decision); + break; + default: + /* Use whatever default there is. */ + return FALSE; + } + + return TRUE; +} + +static void +web_contentCb_download_started(WebKitWebContext *context, + WebKitDownload *download, + gpointer user_data) +{ + (void)context; + + g_signal_connect(G_OBJECT(download), + "decide-destination", + G_CALLBACK(downloadCb_decide_destination), + user_data); +} + +static gboolean +downloadCb_decide_destination(WebKitDownload *download, + gchar *suggested_filename, + gpointer user_data) +{ + struct Client *browser = (struct Client *)user_data; + gint chooser_response; + GtkWindow *parent_window = GTK_WINDOW(browser->window->main_window); + + GtkWidget *file_dialog = gtk_file_chooser_dialog_new(NULL, + parent_window, + GTK_FILE_CHOOSER_ACTION_SAVE, + _("_Cancel"), + GTK_RESPONSE_CANCEL, + _("_Save"), + GTK_RESPONSE_ACCEPT, + NULL); + GtkFileChooser *file_chooser = GTK_FILE_CHOOSER(file_dialog); + + gtk_file_chooser_set_current_name(file_chooser, suggested_filename); + gtk_file_chooser_set_do_overwrite_confirmation(file_chooser, TRUE); + webkit_download_set_allow_overwrite(download, TRUE); + + chooser_response = gtk_dialog_run(GTK_DIALOG(file_dialog)); + + if(chooser_response == GTK_RESPONSE_ACCEPT) + webkit_download_set_destination(download, gtk_file_chooser_get_uri(file_chooser)); + else + webkit_download_cancel(download); + + gtk_widget_destroy(file_dialog); + + return FALSE; /* Let it propagate */ +} + +static gboolean locationCb_activate(GtkEntry *location, gpointer user_data) { char *target_url; @@ -537,8 +658,9 @@ SearchEntryCb_stop__search(GtkSearchEntry *search, gpointer user_data) struct Client * new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web_view) { - struct Client *browser = g_try_malloc(sizeof(struct Client)); + struct Client *browser = malloc(sizeof(struct Client)); target_url = ensure_uri_scheme(target_url, (related_web_view == NULL)); + char *badwolf_l10n = NULL; if(browser == NULL) return NULL; @@ -556,6 +678,17 @@ new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web webkit_web_context_set_process_model(web_context, WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES); + badwolf_l10n = getenv("BADWOLF_L10N"); + + if(badwolf_l10n != NULL) + { + gchar **languages = g_strsplit(badwolf_l10n, ":", -1); + webkit_web_context_set_spell_checking_languages(web_context, (const gchar *const *)languages); + g_strfreev(languages); + + webkit_web_context_set_spell_checking_enabled(web_context, TRUE); + } + WebKitSettings *settings = webkit_settings_new_with_settings(BADWOLF_WEBKIT_SETTINGS); browser->webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, @@ -610,10 +743,13 @@ new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web gtk_entry_set_placeholder_text(GTK_ENTRY(browser->search), _("search in current page")); gtk_entry_set_has_frame(GTK_ENTRY(browser->search), FALSE); + /* signals for location entry widget */ g_signal_connect(browser->location, "activate", G_CALLBACK(locationCb_activate), browser); + /* signals for javacript toggle widget */ g_signal_connect(browser->javascript, "toggled", G_CALLBACK(javascriptCb_toggled), browser); + /* signals for WebView widget */ g_signal_connect(browser->webView, "web-process-terminated", G_CALLBACK(WebViewCb_web_process_terminated), @@ -637,7 +773,17 @@ new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web g_signal_connect( browser->webView, "key-press-event", G_CALLBACK(WebViewCb_key_press_event), browser); g_signal_connect(browser->webView, "scroll-event", G_CALLBACK(WebViewCb_scroll_event), browser); + g_signal_connect( + browser->webView, "permission-request", G_CALLBACK(WebViewCb_permission_request), NULL); + g_signal_connect(browser->webView, "decide-policy", G_CALLBACK(WebViewCb_decide_policy), NULL); + + /* signals for WebView's WebContext */ + g_signal_connect(G_OBJECT(web_context), + "download-started", + G_CALLBACK(web_contentCb_download_started), + browser); + /* signals for search widget */ g_signal_connect(browser->search, "next-match", G_CALLBACK(SearchEntryCb_next__match), browser); g_signal_connect( browser->search, "previous-match", G_CALLBACK(SearchEntryCb_previous__match), browser); @@ -645,6 +791,7 @@ new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web browser->search, "search-changed", G_CALLBACK(SearchEntryCb_search__changed), browser); g_signal_connect(browser->search, "stop-search", G_CALLBACK(SearchEntryCb_stop__search), browser); + /* signals for box container */ g_signal_connect(browser->box, "key-press-event", G_CALLBACK(boxCb_key_press_event), browser); if(related_web_view == NULL) webkit_web_view_load_uri(browser->webView, target_url);