logo

badwolf

Unnamed repository; edit this file 'description' to name the repository.
commit: 66289e480b2b3dca550628352675abc7b7b4f6ee
parent: 5030dbfd170c3eb35eac9e2be08365f72f52161b
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Thu, 31 Oct 2019 18:22:40 +0100

Merge branch 'release-0.4' for 0.4.0

Diffstat:

MMakefile22++++++++++++++++------
Mbadwolf.124+++++++++++++++++++++---
Mbadwolf.c236++++++++++++-------------------------------------------------------------------
Abadwolf.desktop15+++++++++++++++
Abadwolf.h51+++++++++++++++++++++++++++++++++++++++++++++++++++
Mconfig.h19+++++++++++++++++--
Akeybindings.c152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Akeybindings.h12++++++++++++
Mpo/fr.po50++++++++++++++++++++++++++++++++------------------
Mpo/messages.pot57++++++++++++++++++++++++++++++++++++---------------------
Aversion.sh9+++++++++
11 files changed, 396 insertions(+), 251 deletions(-)

diff --git a/Makefile b/Makefile @@ -4,21 +4,23 @@ PREFIX = /usr/local BINDIR = $(PREFIX)/bin MANDIR = $(PREFIX)/share/man DATADIR = $(PREFIX)/share/badwolf +APPSDIR = $(PREFIX)/share/applications PACKAGE = Badwolf DEPS = gtk+-3.0 webkit2gtk-4.0 -OBJS = badwolf +OBJS = keybindings.o badwolf.o +EXE = badwolf TRANS = fr.mo CC = cc CFLAGS = -g -Wall -Wextra -Wconversion -Wsign-conversion -CDEPS = `pkg-config --cflags $(DEPS)` -DDATADIR=\"$(DATADIR)\" -DPACKAGE=\"$(PACKAGE)\" -D_DEFAULT_SOURCE +CDEPS = `pkg-config --cflags $(DEPS)` -DDATADIR=\"$(DATADIR)\" -DPACKAGE=\"$(PACKAGE)\" -D_DEFAULT_SOURCE -DVERSION=\"$(shell ./version.sh)\" LIBS = `pkg-config --libs $(DEPS)` -all: $(OBJS) $(TRANS) +all: $(EXE) $(TRANS) po/messages.pot: badwolf.c - xgettext --keyword=_ --language=C -o $@ --add-comments --sort-output -j badwolf.c + xgettext --keyword=_ --language=C -o $@ --add-comments --sort-output -j --copyright-holder="Haelwenn (lanodan) Monnier <contact+badwolf-copyright@hacktivis.me>" --package-name="$(PACKAGE)" --package-version="$(shell ./version.sh)" --msgid-bugs-address="contact+badwolf-msgid@hacktivis.me" badwolf.c po/%.po: po/messages.pot msgmerge --update $@ $< @@ -27,8 +29,14 @@ ${TRANS}: po/${@:.mo=.po} mkdir -p locale/${@:.mo=}/LC_MESSAGES msgfmt -o locale/${@:.mo=}/LC_MESSAGES/$(PACKAGE).mo po/${@:.mo=.po} +badwolf: $(OBJS) + $(CC) -std=c11 -o $@ $(OBJS) $(LDFLAGS) $(LIBS) + .c: - $(CC) -std=c11 $(CFLAGS) $(CDEPS) -o $@ $< $(LDFLAGS) $(LIBS) + $(CC) -std=c11 $(CFLAGS) $(CDEPS) $(LDFLAGS) $(LIBS) -o $@ $< + +.c.o: + $(CC) -std=c11 $(CFLAGS) $(CDEPS) -c -o $@ $< install: all mkdir -p $(DESTDIR)$(BINDIR) @@ -37,9 +45,11 @@ install: all cp -p badwolf.1 $(DESTDIR)$(MANDIR)/man1 mkdir -p $(DESTDIR)$(DATADIR)/locale cp -r locale/ $(DESTDIR)$(DATADIR) + mkdir -p $(DESTDIR)$(APPSDIR) + cp -p badwolf.desktop $(DESTDIR)$(APPSDIR)/ clean: - rm -fr locale $(OBJS) + rm -fr locale $(OBJS) $(EXE) format: *.c *.h clang-format -style=file -assume-filename=.clang-format -i *.c *.h diff --git a/badwolf.1 b/badwolf.1 @@ -1,7 +1,7 @@ ./" BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser ./" Copyright © 2019 Haelwenn (lanodan) Monnier <contact@hacktivis.me> ./" SPDX-License-Identifier: BSD-3-Clause -.Dd 2019-04-02 +.Dd 2019-10-31 .Dt badwolf 1 .Sh NAME .Nm badwolf @@ -9,10 +9,10 @@ .Sh SYNOPSIS .Nm .Op Ar webkit/gtk options -.Op Ar url or path +.Op Ar URLs or paths .Sh DESCRIPTION .Nm -is a minimalist browser that care about privacy, it is based on WebKitGTK and thus also accepts WebKitGTK (and depdendencies) flags and environment variables, unfortunately there doesn't seems to be manpages for theses. +is a minimalist browser that cares about privacy, it is based on WebKitGTK and thus also accepts WebKitGTK (and dependencies) flags and environment variables, unfortunately there doesn't seems to be manpages for theses. .Pp Runtime configuration specific to .Nm @@ -36,6 +36,10 @@ Focuses on the search entry Focuses on the location(URL) entry .It browser C-S-r / C-r, browser F5 Reloads the current tab (with/without clearing cache) +.It browser F7 +Toggles caret browsing. +.It browser F12 +Opens the web inspector. .It browser C-[ / C-] Go back/forward in current tab’s history .It any A-Left / A-Right @@ -62,6 +66,20 @@ A colon-separated list in the form lang_COUNTRY where lang is in ISO-639 and COU .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 FILES +.Bl -tag -width Ds -compact +.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/webkit-web-extensions/ +Directory containing the +.Lk https://webkitgtk.org/reference/webkit2gtk/stable/WebKitWebExtension.html WebKitWebExtensions +to be loaded into +.Nm . Note: They aren't the JavaScript-based Web-Extensions supported by Firefox or Chrome, but native code in shared objects using the WebKitGTK API. +.Pp +Examples of useful extensions may be found at: +.Bl -compact +.Lk https://hacktivis.me/git/badwolf-extensions +.Lk https://github.com/jun7/wyebadblock +.El +.El .Sh BUGS You can submit contributions or tickets to .Lk https://gitlab.com/lanodan/badwolf diff --git a/badwolf.c b/badwolf.c @@ -2,61 +2,31 @@ // Copyright © 2019 Haelwenn (lanodan) Monnier <contact@hacktivis.me> // SPDX-License-Identifier: BSD-3-Clause +#include "badwolf.h" + #include "config.h" +#include "keybindings.h" #include <glib/gi18n.h> /* _() and other internationalization/localization helpers */ #include <glib/gprintf.h> /* g_fprintf() */ -#include <gtk/gtk.h> -#include <locale.h> /* LC_* */ -#include <stdlib.h> /* realpath(), malloc() */ -#include <webkit2/webkit2.h> +#include <locale.h> /* LC_* */ +#include <stdlib.h> /* realpath(), malloc() */ const gchar *homepage = "https://hacktivis.me/projects/badwolf"; -const gchar *version = "0.3.0"; - -struct Window -{ - GtkWidget *main_window; - GtkWidget *notebook; - GtkWidget *new_tab; -}; - -struct Client -{ - GtkWidget *box; - - GtkWidget *toolbar; - GtkWidget *javascript; - GtkWidget *location; +const gchar *version = VERSION; - WebKitWebView *webView; - struct Window *window; +gchar *web_extensions_directory; - GtkWidget *statusbar; - GtkWidget *statuslabel; - GtkWidget *search; -}; - -gchar *ensure_uri_scheme(gchar *text, gboolean try_file); static gboolean WebViewCb_close(WebKitWebView *webView, gpointer user_data); -static gboolean -commonCb_key_press_event(struct Window *window, GdkEvent *event, struct Client *browser); -static gboolean -WebViewCb_key_press_event(WebKitWebView *webView, GdkEvent *event, gpointer user_data); -static gboolean -main_windowCb_key_press_event(GtkWidget *widget, GdkEvent *event, gpointer user_data); -static gboolean boxCb_key_press_event(GtkWidget *widget, GdkEvent *event, gpointer user_data); static gboolean WebViewCb_web_process_terminated(WebKitWebView *webView, WebKitWebProcessTerminationReason reason, gpointer user_data); static gboolean WebViewCb_notify__uri(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); -GtkWidget *badwolf_new_tab_box(const gchar *title, struct Client *browser); static gboolean WebViewCb_notify__title(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); static gboolean WebViewCb_notify__is__playing__audio(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); -void webView_tab_label_change(struct Client *browser, const gchar *title); static gboolean WebViewCb_notify__estimated_load_progress(WebKitWebView *webView, GParamSpec *pspec, gpointer user_data); @@ -74,7 +44,7 @@ static gboolean WebViewCb_decide_policy(WebKitWebView *web_view, WebKitPolicyDecision *decision, WebKitPolicyDecisionType decision_type, gpointer user_data); -static void web_contentCb_download_started(WebKitWebContext *context, +static void web_contextCb_download_started(WebKitWebContext *web_context, WebKitDownload *download, gpointer user_data); static gboolean downloadCb_decide_destination(WebKitDownload *download, @@ -86,28 +56,13 @@ static gboolean SearchEntryCb_next__match(GtkSearchEntry *search, gpointer user_ static gboolean SearchEntryCb_previous__match(GtkSearchEntry *search, gpointer user_data); static gboolean SearchEntryCb_search__changed(GtkSearchEntry *search, gpointer user_data); static gboolean SearchEntryCb_stop__search(GtkSearchEntry *search, gpointer user_data); -struct Client * -new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web_view); -int badwolf_new_tab(GtkNotebook *notebook, struct Client *browser); static void new_tabCb_clicked(GtkButton *new_tab, gpointer user_data); static void closeCb_clicked(GtkButton *close, gpointer user_data); 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) +badwolf_ensure_uri_scheme(gchar *text, gboolean try_file) { if(text == NULL) return "about:blank"; @@ -132,23 +87,6 @@ ensure_uri_scheme(gchar *text, gboolean try_file) return g_strdup_printf("http://%s", text); } -static void -badwolf_about_dialog(GtkWindow *main_window) -{ - // clang-format off - gtk_show_about_dialog( - main_window, - "license", "SPDX-License-Identifier: BSD-3-Clause", - "copyright", "2019 Haelwenn (lanodan) Monnier <contact+badwolf@hacktivis.me>", - "website", homepage, - "comments", "Minimalist and privacy-oriented WebKitGTK+ browser", - "version", version, - //FIXME: "logo-icon-name", g_get_application_name(), - NULL - ); - // clang-format on -} - static gboolean WebViewCb_close(WebKitWebView *webView, gpointer user_data) { @@ -156,7 +94,8 @@ WebViewCb_close(WebKitWebView *webView, gpointer user_data) struct Client *browser = (struct Client *)user_data; GtkNotebook *notebook = GTK_NOTEBOOK(browser->window->notebook); - gtk_notebook_remove_page(notebook, get_tab_position(GTK_CONTAINER(notebook), browser->box)); + gtk_notebook_remove_page(notebook, + badwolf_get_tab_position(GTK_CONTAINER(notebook), browser->box)); gtk_widget_destroy(browser->box); @@ -165,122 +104,6 @@ WebViewCb_close(WebKitWebView *webView, gpointer user_data) return TRUE; } -/* commonCb_key_press_event: Global callback for keybindings - * - * Theses shortcuts should be avoided as much as possible: - * - Single key shortcuts (ie. backspace and space) - * - Triple key shortcuts (except for Ctrl+Shift) - * - Unix Terminal shortcuts (specially Ctrl-W) - * - * loosely follows https://developer.gnome.org/hig/stable/keyboard-input.html - */ -static gboolean -commonCb_key_press_event(struct Window *window, GdkEvent *event, struct Client *browser) -{ - GtkNotebook *notebook = GTK_NOTEBOOK(window->notebook); - - if(((GdkEventKey *)event)->state & GDK_CONTROL_MASK) - { - if(browser != NULL) - { - switch(((GdkEventKey *)event)->keyval) - { - case GDK_KEY_F4: webkit_web_view_try_close(browser->webView); return TRUE; - case GDK_KEY_r: - if(((GdkEventKey *)event)->state & GDK_SHIFT_MASK) - webkit_web_view_reload_bypass_cache(browser->webView); - else - webkit_web_view_reload(browser->webView); - - return TRUE; - case GDK_KEY_f: gtk_widget_grab_focus(browser->search); return TRUE; - case GDK_KEY_l: gtk_widget_grab_focus(browser->location); return TRUE; - case GDK_KEY_bracketleft: webkit_web_view_go_back(browser->webView); return TRUE; - case GDK_KEY_bracketright: webkit_web_view_go_forward(browser->webView); return TRUE; - case GDK_KEY_0: - webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(browser->webView), 1); - return TRUE; - } - } - else - { - switch(((GdkEventKey *)event)->keyval) - { - case GDK_KEY_Page_Down: gtk_notebook_next_page(notebook); return TRUE; - case GDK_KEY_Page_Up: gtk_notebook_prev_page(notebook); return TRUE; - case GDK_KEY_t: badwolf_new_tab(notebook, new_browser(window, NULL, NULL)); return TRUE; - } - } - } - - 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) - { - switch(((GdkEventKey *)event)->keyval) - { - case GDK_KEY_F5: webkit_web_view_reload(browser->webView); return TRUE; - } - } - else - { - switch(((GdkEventKey *)event)->keyval) - { - case GDK_KEY_F1: badwolf_about_dialog(GTK_WINDOW(window->main_window)); return TRUE; - } - } - - return FALSE; -} - -static gboolean -WebViewCb_key_press_event(WebKitWebView *webView, GdkEvent *event, gpointer user_data) -{ - (void)webView; - struct Client *browser = (struct Client *)user_data; - - if(commonCb_key_press_event(browser->window, event, browser)) return TRUE; - - return FALSE; -} - -static gboolean -boxCb_key_press_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) -{ - (void)widget; - struct Client *browser = (struct Client *)user_data; - - if(commonCb_key_press_event(browser->window, event, browser)) return TRUE; - - return FALSE; -} - -static gboolean -main_windowCb_key_press_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) -{ - (void)widget; - struct Window *window = (struct Window *)user_data; - - if(commonCb_key_press_event(window, event, NULL)) return TRUE; - - return FALSE; -} static gboolean WebViewCb_web_process_terminated(WebKitWebView *webView, WebKitWebProcessTerminationReason reason, @@ -405,7 +228,7 @@ webView_tab_label_change(struct Client *browser, const gchar *title) gtk_notebook_set_menu_label_text(GTK_NOTEBOOK(notebook), browser->box, title); // Set the window title if the title change was on the current tab - if(get_tab_position(GTK_CONTAINER(notebook), browser->box) == + if(badwolf_get_tab_position(GTK_CONTAINER(notebook), browser->box) == gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))) gtk_window_set_title(GTK_WINDOW(browser->window->main_window), title); } @@ -532,11 +355,11 @@ WebViewCb_decide_policy(WebKitWebView *web_view, } static void -web_contentCb_download_started(WebKitWebContext *context, +web_contextCb_download_started(WebKitWebContext *web_context, WebKitDownload *download, gpointer user_data) { - (void)context; + (void)web_context; g_signal_connect(G_OBJECT(download), "decide-destination", @@ -585,7 +408,7 @@ locationCb_activate(GtkEntry *location, gpointer user_data) char *target_url; struct Client *browser = (struct Client *)user_data; - target_url = ensure_uri_scheme((char *)gtk_entry_get_text(location), TRUE); + target_url = badwolf_ensure_uri_scheme((char *)gtk_entry_get_text(location), TRUE); if(target_url != NULL) webkit_web_view_load_uri(browser->webView, target_url); @@ -599,7 +422,7 @@ javascriptCb_toggled(GtkButton *javascript, gpointer user_data) WebKitSettings *settings = webkit_web_view_get_settings(browser->webView); - webkit_settings_set_enable_javascript( + webkit_settings_set_enable_javascript_markup( settings, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(javascript))); webkit_web_view_set_settings(browser->webView, settings); @@ -659,7 +482,7 @@ struct Client * new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web_view) { struct Client *browser = malloc(sizeof(struct Client)); - target_url = ensure_uri_scheme(target_url, (related_web_view == NULL)); + target_url = badwolf_ensure_uri_scheme(target_url, (related_web_view == NULL)); char *badwolf_l10n = NULL; if(browser == NULL) return NULL; @@ -675,9 +498,12 @@ new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web browser->search = gtk_search_entry_new(); WebKitWebContext *web_context = webkit_web_context_new_ephemeral(); + webkit_web_context_set_sandbox_enabled(web_context, TRUE); webkit_web_context_set_process_model(web_context, WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES); + webkit_web_context_set_web_extensions_directory(web_context, web_extensions_directory); + badwolf_l10n = getenv("BADWOLF_L10N"); if(badwolf_l10n != NULL) @@ -691,6 +517,9 @@ new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web WebKitSettings *settings = webkit_settings_new_with_settings(BADWOLF_WEBKIT_SETTINGS); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(browser->javascript), + webkit_settings_get_enable_javascript_markup(settings)); + browser->webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, "web-context", web_context, @@ -735,6 +564,7 @@ new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web gtk_widget_set_halign(browser->statusbar, GTK_ALIGN_START); gtk_label_set_single_line_mode(GTK_LABEL(browser->statuslabel), TRUE); + gtk_label_set_ellipsize(GTK_LABEL(browser->statuslabel), BADWOLF_STATUSLABEL_ELLIPSIZE); gtk_entry_set_text(GTK_ENTRY(browser->location), target_url); gtk_entry_set_has_frame(GTK_ENTRY(browser->location), FALSE); @@ -780,7 +610,7 @@ new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web /* signals for WebView's WebContext */ g_signal_connect(G_OBJECT(web_context), "download-started", - G_CALLBACK(web_contentCb_download_started), + G_CALLBACK(web_contextCb_download_started), browser); /* signals for search widget */ @@ -861,7 +691,7 @@ notebookCb_switch__page(GtkNotebook *notebook, GtkWidget *page, guint page_num, } gint -get_tab_position(GtkContainer *notebook, GtkWidget *child) +badwolf_get_tab_position(GtkContainer *notebook, GtkWidget *child) { GValue position = G_VALUE_INIT; g_value_init(&position, G_TYPE_INT); @@ -876,13 +706,14 @@ main(int argc, char *argv[]) { // getting an abort if this one fails to alloc struct Window *window = g_malloc(sizeof(struct Window)); - gchar *target_url = NULL; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, DATADIR "/locale"); bind_textdomain_codeset(PACKAGE, "UTF-8"); textdomain(PACKAGE); + gtk_init(&argc, &argv); + g_fprintf(stderr, _("Running Badwolf version: %s\n"), version); g_fprintf(stderr, _("Buildtime WebKit version: %d.%d.%d\n"), @@ -895,9 +726,8 @@ main(int argc, char *argv[]) webkit_get_minor_version(), webkit_get_micro_version()); - gtk_init(&argc, &argv); - - if(argv[1]) target_url = argv[1]; + web_extensions_directory = g_build_filename(g_get_user_data_dir(), "badwolf", "webkit-web-extension", NULL); + g_fprintf(stderr, _("webkit-web-extension directory set to: %s\n"), web_extensions_directory); window->main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); window->notebook = gtk_notebook_new(); @@ -916,7 +746,11 @@ main(int argc, char *argv[]) gtk_container_add(GTK_CONTAINER(window->main_window), window->notebook); - badwolf_new_tab(GTK_NOTEBOOK(window->notebook), new_browser(window, target_url, NULL)); + if(argc == 1) + badwolf_new_tab(GTK_NOTEBOOK(window->notebook), new_browser(window, NULL, NULL)); + else + for(int i = 1; i < argc; ++i) + badwolf_new_tab(GTK_NOTEBOOK(window->notebook), new_browser(window, argv[i], NULL)); g_signal_connect( window->main_window, "key-press-event", G_CALLBACK(main_windowCb_key_press_event), window); diff --git a/badwolf.desktop b/badwolf.desktop @@ -0,0 +1,15 @@ +# https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/ +[Desktop Entry] +Version=1.1 +Type=Application +Categories=Network;WebBrowser +Comment=A minimalist and privacy-oriented web browser +Comment[fr]=Un navigateur web minimaliste et orienté vers le respect de la vie privée +Exec=badwolf %U +GenericName=Web Browser +GenericName[fr]=Navigateur Web +Icon=web-browser +Keywords=Internet;WWW;Browser;Web;WebKit;WebKitGTK +Keywords[fr]=Internet;WWW;Browser;Web;Surfer;Navigateur;WebKit;WebKitGTK +MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https +Name=Badwolf diff --git a/badwolf.h b/badwolf.h @@ -0,0 +1,51 @@ +#ifndef BADWOLF_H_INCLUDED +#define BADWOLF_H_INCLUDED + +#include <gtk/gtk.h> +#include <webkit2/webkit2.h> + +const gchar *homepage; +const gchar *version; + +struct Window +{ + GtkWidget *main_window; + GtkWidget *notebook; + GtkWidget *new_tab; +}; + +struct Client +{ + GtkWidget *box; + + GtkWidget *toolbar; + GtkWidget *javascript; + GtkWidget *location; + + WebKitWebView *webView; + struct Window *window; + + GtkWidget *statusbar; + GtkWidget *statuslabel; + GtkWidget *search; +}; + +/* badwolf_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 *badwolf_ensure_uri_scheme(gchar *text, gboolean try_file); +GtkWidget *badwolf_new_tab_box(const gchar *title, struct Client *browser); +void webView_tab_label_change(struct Client *browser, const gchar *title); +struct Client * +new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web_view); +int badwolf_new_tab(GtkNotebook *notebook, struct Client *browser); +gint badwolf_get_tab_position(GtkContainer *notebook, GtkWidget *child); +#endif /* BADWOLF_H_INCLUDED */ diff --git a/config.h b/config.h @@ -1,3 +1,5 @@ +#ifndef CONFIG_H_INCLUDED +#define CONFIG_H_INCLUDED /* BADWOLF_TAB_POSITION: Position of the tab listing, can be one of: * - GTK_POS_TOP * - GTK_POS_BOTTOM @@ -58,10 +60,11 @@ // clang-format off #define BADWOLF_WEBKIT_SETTINGS \ "default-charset", "utf-8", \ - "enable-caret-browsing", TRUE, \ + "enable-caret-browsing", FALSE, \ "enable-developer-extras", TRUE, \ "enable-java", FALSE, \ - "enable-javascript", FALSE, \ + "enable-javascript", TRUE, \ + "enable-javascript-markup", FALSE, \ "enable-plugins", FALSE, \ "javascript-can-access-clipboard", FALSE, \ "javascript-can-open-windows-automatically", FALSE, \ @@ -69,3 +72,15 @@ "minimum-font-size", 9, \ NULL // clang-format on + +/* BADWOLF_STATUSLABEL_ELLIPSIZE: pango ellipsize mode of the status bar label text, can be one of: + * - PANGO_ELLIPSIZE_NONE + * - PANGO_ELLIPSIZE_START + * - PANGO_ELLIPSIZE_MIDDLE + * - PANGO_ELLIPSIZE_END + * + * See https://developer.gnome.org/pango/stable/pango-Layout-Objects.html#PangoEllipsizeMode + */ +#define BADWOLF_STATUSLABEL_ELLIPSIZE PANGO_ELLIPSIZE_MIDDLE + +#endif /* CONFIG_H_INCLUDED */ diff --git a/keybindings.c b/keybindings.c @@ -0,0 +1,152 @@ +#include "keybindings.h" + +#include "badwolf.h" + +static void +badwolf_about_dialog(GtkWindow *main_window) +{ + // clang-format off + gtk_show_about_dialog( + main_window, + "license", "SPDX-License-Identifier: BSD-3-Clause", + "copyright", "2019 Haelwenn (lanodan) Monnier <contact+badwolf@hacktivis.me>", + "website", homepage, + "comments", "Minimalist and privacy-oriented WebKitGTK+ browser", + "version", version, + //FIXME: "logo-icon-name", g_get_application_name(), + NULL + ); + // clang-format on +} + +static void +toggle_caret_browsing(WebKitWebView *webView) +{ + WebKitSettings *settings = webkit_web_view_get_settings(webView); + + webkit_settings_set_enable_caret_browsing(settings, + !webkit_settings_get_enable_caret_browsing(settings)); + + webkit_web_view_set_settings(webView, settings); +} + +/* commonCb_key_press_event: Global callback for keybindings + * + * Theses shortcuts should be avoided as much as possible: + * - Single key shortcuts (ie. backspace and space) + * - Triple key shortcuts (except for Ctrl+Shift) + * - Unix Terminal shortcuts (specially Ctrl-W) + * + * loosely follows https://developer.gnome.org/hig/stable/keyboard-input.html + */ +gboolean +commonCb_key_press_event(struct Window *window, GdkEvent *event, struct Client *browser) +{ + GtkNotebook *notebook = GTK_NOTEBOOK(window->notebook); + + if(((GdkEventKey *)event)->state & GDK_CONTROL_MASK) + { + if(browser != NULL) + { + switch(((GdkEventKey *)event)->keyval) + { + case GDK_KEY_F4: webkit_web_view_try_close(browser->webView); return TRUE; + case GDK_KEY_r: + if(((GdkEventKey *)event)->state & GDK_SHIFT_MASK) + webkit_web_view_reload_bypass_cache(browser->webView); + else + webkit_web_view_reload(browser->webView); + + return TRUE; + case GDK_KEY_f: gtk_widget_grab_focus(browser->search); return TRUE; + case GDK_KEY_l: gtk_widget_grab_focus(browser->location); return TRUE; + case GDK_KEY_bracketleft: webkit_web_view_go_back(browser->webView); return TRUE; + case GDK_KEY_bracketright: webkit_web_view_go_forward(browser->webView); return TRUE; + case GDK_KEY_0: + webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(browser->webView), 1); + return TRUE; + } + } + else + { + switch(((GdkEventKey *)event)->keyval) + { + case GDK_KEY_Page_Down: gtk_notebook_next_page(notebook); return TRUE; + case GDK_KEY_Page_Up: gtk_notebook_prev_page(notebook); return TRUE; + case GDK_KEY_t: badwolf_new_tab(notebook, new_browser(window, NULL, NULL)); return TRUE; + } + } + } + + 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) + { + switch(((GdkEventKey *)event)->keyval) + { + case GDK_KEY_F5: webkit_web_view_reload(browser->webView); return TRUE; + case GDK_KEY_F7: toggle_caret_browsing(browser->webView); return TRUE; + case GDK_KEY_F12: + webkit_web_inspector_show(webkit_web_view_get_inspector(browser->webView)); + return TRUE; + } + } + else + { + switch(((GdkEventKey *)event)->keyval) + { + case GDK_KEY_F1: badwolf_about_dialog(GTK_WINDOW(window->main_window)); return TRUE; + } + } + + return FALSE; +} + +gboolean +WebViewCb_key_press_event(WebKitWebView *webView, GdkEvent *event, gpointer user_data) +{ + (void)webView; + struct Client *browser = (struct Client *)user_data; + + if(commonCb_key_press_event(browser->window, event, browser)) return TRUE; + + return FALSE; +} + +gboolean +boxCb_key_press_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + (void)widget; + struct Client *browser = (struct Client *)user_data; + + if(commonCb_key_press_event(browser->window, event, browser)) return TRUE; + + return FALSE; +} + +gboolean +main_windowCb_key_press_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + (void)widget; + struct Window *window = (struct Window *)user_data; + + if(commonCb_key_press_event(window, event, NULL)) return TRUE; + + return FALSE; +} diff --git a/keybindings.h b/keybindings.h @@ -0,0 +1,12 @@ +#ifndef KEYBINDINGS_H_INCLUDED +#define KEYBINDINGS_H_INCLUDED +#include "badwolf.h" + +#include <gtk/gtk.h> +#include <webkit2/webkit2.h> + +gboolean boxCb_key_press_event(GtkWidget *widget, GdkEvent *event, gpointer user_data); +gboolean commonCb_key_press_event(struct Window *window, GdkEvent *event, struct Client *browser); +gboolean main_windowCb_key_press_event(GtkWidget *widget, GdkEvent *event, gpointer user_data); +gboolean WebViewCb_key_press_event(WebKitWebView *webView, GdkEvent *event, gpointer user_data); +#endif /* KEYBINDINGS_H_INCLUDED */ diff --git a/po/fr.po b/po/fr.po @@ -5,10 +5,11 @@ # msgid "" msgstr "" -"Project-Id-Version: Badwolf 0.1.0\n" -"POT-Creation-Date: 2019-05-11 05:03+0200\n" +"Project-Id-Version: Badwolf 0.3.0+gd88f2e7\n" +"Report-Msgid-Bugs-To: contact+badwolf-msgid@hacktivis.me\n" +"POT-Creation-Date: 2019-10-31 14:09+0100\n" "PO-Revision-Date: 2019-05-11 05:03+0200\n" -"Last-Translator: <contact@hacktivis.me>\n" +"Last-Translator: Haelwenn (lanodan) Monnier <contact@hacktivis.me>\n" "Language-Team: French\n" "Language: fr\n" "MIME-Version: 1.0\n" @@ -16,25 +17,25 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: badwolf.c:527 badwolf.c:692 +#: badwolf.c:527 badwolf.c:692 badwolf.c:719 #, c-format msgid "Buildtime WebKit version: %d.%d.%d\n" msgstr "Version WebKit à la compilation: %d.%d.%d\n" -#: badwolf.c:457 badwolf.c:621 +#: badwolf.c:457 badwolf.c:621 badwolf.c:643 msgid "New tab" msgstr "Nouvel onglet" -#: badwolf.c:549 badwolf.c:714 +#: badwolf.c:549 badwolf.c:714 badwolf.c:740 msgid "Open new tab" msgstr "Ouvrir un nouvel onglet" -#: badwolf.c:690 +#: badwolf.c:690 badwolf.c:717 #, c-format msgid "Running Badwolf version: %s\n" msgstr "Version de Badwolf: %s\n" -#: badwolf.c:532 badwolf.c:697 +#: badwolf.c:532 badwolf.c:697 badwolf.c:724 #, c-format msgid "Runtime WebKit version: %d.%d.%d\n" msgstr "Version WebKit au lancement: %d.%d.%d\n" @@ -43,33 +44,46 @@ msgstr "Version WebKit au lancement: %d.%d.%d\n" msgid "Toggle javascript" msgstr "Activer/Désactiver javascript" -#: badwolf.c:413 badwolf.c:572 +#: badwolf.c:382 +msgid "_Cancel" +msgstr "A_rrêter" + +#: badwolf.c:384 +msgid "_Save" +msgstr "_Sauvegarder" + +#: badwolf.c:413 badwolf.c:572 badwolf.c:573 msgid "search in current page" msgstr "recherche dans la page courante" -#: badwolf.c:100 badwolf.c:234 +#: badwolf.c:100 badwolf.c:234 badwolf.c:118 #, fuzzy msgid "the web process crashed.\n" msgstr "le processus web à cessé de fonctionner.\n" -#: badwolf.c:104 badwolf.c:238 +#: badwolf.c:104 badwolf.c:238 badwolf.c:122 #, fuzzy msgid "the web process exceeded the memory limit.\n" msgstr "le processus web à dépassé la limitation de mémoire.\n" -#: badwolf.c:108 badwolf.c:242 +#: badwolf.c:108 badwolf.c:242 badwolf.c:126 #, fuzzy msgid "the web process terminated for an unknown reason.\n" msgstr "le processus web s’est interrompu pour une raison inconnue.\n" -#: badwolf.c:101 badwolf.c:235 +#: badwolf.c:101 badwolf.c:235 badwolf.c:119 msgid "title|Crashed" -msgstr "title|Crash" +msgstr "Crash" -#: badwolf.c:105 badwolf.c:239 +#: badwolf.c:105 badwolf.c:239 badwolf.c:123 msgid "title|Out of Memory" -msgstr "title|Dépassement Mémoire" +msgstr "Dépassement Mémoire" -#: badwolf.c:109 badwolf.c:243 +#: badwolf.c:109 badwolf.c:243 badwolf.c:127 msgid "title|Unknown Crash" -msgstr "title|Crash inconnu" +msgstr "Crash inconnu" + +#: badwolf.c:730 +#, c-format +msgid "webkit-web-extension directory set to: %s\n" +msgstr "Répertoire webkit-web-extension configuré à %s\n" diff --git a/po/messages.pot b/po/messages.pot @@ -1,39 +1,41 @@ -# BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser -# Copyright (C) 2019 Haelwenn (lanodan) Monnier <contact@hacktivis.me> +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Haelwenn (lanodan) Monnier <contact+badwolf-copyright@hacktivis.me> # This file is distributed under the same license as the Badwolf package. -# Haelwenn (lanodan) Monnier <contact@hacktivis.me>, 2019 +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Badwolf 0.1.1\n" -"POT-Creation-Date: 2019-05-11 05:03+0200\n" +"Project-Id-Version: Badwolf 0.3.0+g4b96925\n" +"Report-Msgid-Bugs-To: contact+badwolf-msgid@hacktivis.me\n" +"POT-Creation-Date: 2019-10-31 17:40+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: \"Haelwenn (lanodan) Monnier <contact@hacktivis.me>\"\n" -"Language: en\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: badwolf.c:527 badwolf.c:692 +#: badwolf.c:527 badwolf.c:692 badwolf.c:719 #, c-format msgid "Buildtime WebKit version: %d.%d.%d\n" msgstr "" -#: badwolf.c:457 badwolf.c:621 +#: badwolf.c:457 badwolf.c:621 badwolf.c:643 msgid "New tab" msgstr "" -#: badwolf.c:549 badwolf.c:714 +#: badwolf.c:549 badwolf.c:714 badwolf.c:740 msgid "Open new tab" msgstr "" -#: badwolf.c:690 +#: badwolf.c:690 badwolf.c:717 #, c-format msgid "Running Badwolf version: %s\n" msgstr "" -#: badwolf.c:532 badwolf.c:697 +#: badwolf.c:532 badwolf.c:697 badwolf.c:724 #, c-format msgid "Runtime WebKit version: %d.%d.%d\n" msgstr "" @@ -42,30 +44,43 @@ msgstr "" msgid "Toggle javascript" msgstr "" -#: badwolf.c:413 badwolf.c:572 +#: badwolf.c:382 +msgid "_Cancel" +msgstr "" + +#: badwolf.c:384 +msgid "_Save" +msgstr "" + +#: badwolf.c:413 badwolf.c:572 badwolf.c:573 msgid "search in current page" msgstr "" -#: badwolf.c:100 badwolf.c:234 +#: badwolf.c:100 badwolf.c:234 badwolf.c:118 msgid "the web process crashed.\n" msgstr "" -#: badwolf.c:104 badwolf.c:238 +#: badwolf.c:104 badwolf.c:238 badwolf.c:122 msgid "the web process exceeded the memory limit.\n" msgstr "" -#: badwolf.c:108 badwolf.c:242 +#: badwolf.c:108 badwolf.c:242 badwolf.c:126 msgid "the web process terminated for an unknown reason.\n" msgstr "" -#: badwolf.c:101 badwolf.c:235 +#: badwolf.c:101 badwolf.c:235 badwolf.c:119 msgid "title|Crashed" -msgstr "" +msgstr "Crashed" -#: badwolf.c:105 badwolf.c:239 +#: badwolf.c:105 badwolf.c:239 badwolf.c:123 msgid "title|Out of Memory" -msgstr "" +msgstr "Out of Memory" -#: badwolf.c:109 badwolf.c:243 +#: badwolf.c:109 badwolf.c:243 badwolf.c:127 msgid "title|Unknown Crash" +msgstr "Unknown Crash" + +#: badwolf.c:730 +#, c-format +msgid "webkit-web-extension directory set to: %s\n" msgstr "" diff --git a/version.sh b/version.sh @@ -0,0 +1,9 @@ +#!/bin/sh +echo -n '0.4.0' +hash=$(git --git-dir="$(dirname $0)/.git" rev-parse --short HEAD 2>/dev/null) + +if [ -n "$hash" ] +then + printf '+g%s' "$hash" +fi +echo