logo

badwolf

Unnamed repository; edit this file 'description' to name the repository.
commit: 9a186b4bc0dca9533c0697cde7cc36fe35a9c978
parent: 1b868aad609d9c3460af8df0e2c151d4f755f210
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Mon, 13 May 2019 10:44:58 +0200

Release 0.2.0

Diffstat:

M.gitignore4++--
MMakefile12++++++------
Mbadwolf.132+++++++++++++++++++++++++++-----
Mbadwolf.c205+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mpo/fr.po33+++++++++++++++++++--------------
Mpo/messages.pot33+++++++++++++++++++--------------
6 files changed, 274 insertions(+), 45 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1 +1,2 @@ -badwolf- \ No newline at end of file +/badwolf +/locale diff --git a/Makefile b/Makefile @@ -12,21 +12,21 @@ TRANS = fr.mo CC = cc CFLAGS = -g -Wall -Wextra -CDEPS = `pkg-config --cflags $(DEPS)` -DDATADIR=\"$(DATADIR)\" -DPACKAGE=\"$(PACKAGE)\" +CDEPS = `pkg-config --cflags $(DEPS)` -DDATADIR=\"$(DATADIR)\" -DPACKAGE=\"$(PACKAGE)\" -D_DEFAULT_SOURCE LIBS = `pkg-config --libs $(DEPS)` all: $(OBJS) $(TRANS) -%.mo: - mkdir -p locale/$*/LC_MESSAGES - msgfmt -o locale/$*/LC_MESSAGES/$(PACKAGE).mo po/$*.po - -po/messages.pot: +po/messages.pot: badwolf.c xgettext --keyword=_ --language=C -o $@ --add-comments --sort-output -j badwolf.c po/%.po: po/messages.pot msgmerge --update $@ $< +${TRANS}: po/${@:.mo=.po} + mkdir -p locale/${@:.mo=}/LC_MESSAGES + msgfmt -o locale/${@:.mo=}/LC_MESSAGES/$(PACKAGE).mo po/${@:.mo=.po} + .c: $(CC) -std=c11 $(CFLAGS) $(CDEPS) -o $@ $< $(LDFLAGS) $(LIBS) diff --git a/badwolf.1 b/badwolf.1 @@ -9,7 +9,7 @@ .Sh SYNOPSIS .Nm .Op Ar webkit/gtk options -.Op Ar url +.Op Ar url or path .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. @@ -18,12 +18,34 @@ Runtime configuration specific to .Nm will probably get added at a later release. .Sh KEYBINDINGS -For now it only has the default Webkit/GTK keybindings, which notably are (C for Control, S for Shift): +The following section lists the keybinding by their action, each item is described by the widget the focus is on or +.Aq any +if it works for the whole window, followed by the keybind it grabs. C is short for Control, S is short for Shift. .Bl -width Ds -tag -.It any C-PageUp, any C-PageDown, tabs arrows -When WebView isn't focused (bug to fix) this allows to move from one tab to another. -.It search C-g, search C-S-g +.It webview C-Scroll +Zooms the webpage in/out. +.It any C-t +Creates a new tab (in a new session, similar as pressing the button) +.It browser C-F4 +Closes the current tab +.It browser C-f +Focuses on the search entry +.It browser C-l +Focuses on the location(URL) entry +.It browser C-S-r / C-r +Reloads the current tab (with/without clearing cache) +.It browser Alt-[ / C-] +Go back/forward in current tab’s history +.El +.Ss DEFAULT ONES +Here is a incomplete list of the default Webkit/GTK keybindings: +.Bl -width Ds -tag +.It any C-PageUp / C-PageDown +Go to the previous/next tab +.It search C-g / C-S-g When the search box is focused it goes to the Next/Previous search term. +.It search Escape +Cancels current search .El .Sh BUGS You can submit contributions or tickets to diff --git a/badwolf.c b/badwolf.c @@ -8,8 +8,12 @@ #include <glib/gprintf.h> /* g_fprintf() */ #include <gtk/gtk.h> #include <locale.h> /* LC_* */ +#include <stdlib.h> /* realpath() */ #include <webkit2/webkit2.h> +const gchar *homepage = "https://hacktivis.me/projects/badwolf"; +const gchar *version = "0.2.0"; + struct Window { GtkWidget *main_window; @@ -33,7 +37,15 @@ struct Client 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); @@ -70,6 +82,49 @@ static void notebookCb_switch__page(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data); gint get_tab_position(GtkContainer *notebook, GtkWidget *child); +gchar * +ensure_uri_scheme(gchar *text, gboolean try_file) +{ + if(text == NULL) return "about:blank"; + + char *scheme = g_uri_parse_scheme(text); + + if(scheme != NULL) return text; + + if(try_file) + { + gchar *f; + char *path; + path = realpath(text, NULL); + + if(path != NULL) + { + f = g_strdup_printf("file://%s", path); + free(path); + return f; + } + } + + 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) { @@ -86,6 +141,113 @@ 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) && browser != NULL) + { + 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(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, @@ -124,6 +286,11 @@ WebViewCb_notify__uri(WebKitWebView *webView, GParamSpec *pspec, gpointer user_d gtk_entry_set_text(GTK_ENTRY(browser->location), location_uri); + if(webkit_uri_for_display(location_uri) != location_uri) + gtk_widget_set_tooltip_text(browser->location, webkit_uri_for_display(location_uri)); + else + gtk_widget_set_has_tooltip(browser->location, false); + return TRUE; } @@ -239,11 +406,31 @@ WebViewCb_mouse_target_changed(WebKitWebView *webView, struct Client *browser = (struct Client *)user_data; const gchar *link_uri = webkit_hit_test_result_get_link_uri(hit); - gtk_label_set_text(GTK_LABEL(browser->statuslabel), link_uri); + gtk_label_set_text(GTK_LABEL(browser->statuslabel), webkit_uri_for_display(link_uri)); return TRUE; } +static gboolean +WebViewCb_scroll_event(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + (void)widget; + struct Client *browser = (struct Client *)data; + gdouble delta_x, delta_y; + gfloat zoom; + + if(((GdkEventScroll *)event)->state & GDK_CONTROL_MASK) + { + gdk_event_get_scroll_deltas(event, &delta_x, &delta_y); + zoom = webkit_web_view_get_zoom_level(WEBKIT_WEB_VIEW(browser->webView)); + zoom -= delta_y * 0.1; + webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(browser->webView), zoom); + return TRUE; + } + + return FALSE; +} + static WebKitWebView * WebViewCb_create(WebKitWebView *related_web_view, WebKitNavigationAction *navigation_action, @@ -266,10 +453,10 @@ WebViewCb_create(WebKitWebView *related_web_view, static gboolean locationCb_activate(GtkEntry *location, gpointer user_data) { - const char *target_url; + char *target_url; struct Client *browser = (struct Client *)user_data; - target_url = gtk_entry_get_text(location); + target_url = ensure_uri_scheme((char *)gtk_entry_get_text(location), FALSE); if(target_url != NULL) webkit_web_view_load_uri(browser->webView, target_url); @@ -343,7 +530,7 @@ struct Client * new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web_view) { struct Client *browser = g_malloc(sizeof(struct Client)); - if(target_url == NULL) target_url = "about:blank"; + target_url = ensure_uri_scheme(target_url, (related_web_view != NULL)); browser->window = window; browser->box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); @@ -437,6 +624,9 @@ new_browser(struct Window *window, gchar *target_url, WebKitWebView *related_web browser); g_signal_connect(browser->webView, "create", G_CALLBACK(WebViewCb_create), window); g_signal_connect(browser->webView, "close", G_CALLBACK(WebViewCb_close), browser); + 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->search, "next-match", G_CALLBACK(SearchEntryCb_next__match), browser); g_signal_connect( @@ -445,6 +635,8 @@ 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); + 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); return browser; @@ -523,6 +715,7 @@ main(int argc, char *argv[]) bind_textdomain_codeset(PACKAGE, "UTF-8"); textdomain(PACKAGE); + g_fprintf(stderr, _("Running Badwolf version: %s\n"), version); g_fprintf(stderr, _("Buildtime WebKit version: %d.%d.%d\n"), WEBKIT_MAJOR_VERSION, @@ -557,12 +750,16 @@ main(int argc, char *argv[]) badwolf_new_tab(GTK_NOTEBOOK(window->notebook), new_browser(window, target_url, NULL)); + g_signal_connect( + window->main_window, "key-press-event", G_CALLBACK(main_windowCb_key_press_event), window); + g_signal_connect(window->main_window, "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(window->new_tab, "clicked", G_CALLBACK(new_tabCb_clicked), window); g_signal_connect(window->notebook, "switch-page", G_CALLBACK(notebookCb_switch__page), window); gtk_widget_show(window->new_tab); gtk_widget_show_all(window->main_window); + gtk_main(); return 0; } diff --git a/po/fr.po b/po/fr.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Badwolf 0.1.0\n" -"POT-Creation-Date: 2019-04-18 13:16+0200\n" -"PO-Revision-Date: 2019-04-11 09:28+0200\n" +"POT-Creation-Date: 2019-05-11 05:03+0200\n" +"PO-Revision-Date: 2019-05-11 05:03+0200\n" "Last-Translator: <contact@hacktivis.me>\n" "Language-Team: French\n" "Language: fr\n" @@ -16,55 +16,60 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: badwolf.c:527 +#: badwolf.c:527 badwolf.c:692 #, c-format msgid "Buildtime WebKit version: %d.%d.%d\n" msgstr "Version WebKit à la compilation: %d.%d.%d\n" -#: badwolf.c:457 +#: badwolf.c:457 badwolf.c:621 msgid "New tab" msgstr "Nouvel onglet" -#: badwolf.c:549 +#: badwolf.c:549 badwolf.c:714 msgid "Open new tab" msgstr "Ouvrir un nouvel onglet" -#: badwolf.c:532 +#: badwolf.c:690 +#, c-format +msgid "Running Badwolf version: %s\n" +msgstr "Version de Badwolf: %s\n" + +#: badwolf.c:532 badwolf.c:697 #, c-format msgid "Runtime WebKit version: %d.%d.%d\n" msgstr "Version WebKit au lancement: %d.%d.%d\n" -#: badwolf.c:373 +#: badwolf.c:373 badwolf.c:532 msgid "Toggle javascript" msgstr "Activer/Désactiver javascript" -#: badwolf.c:413 +#: badwolf.c:413 badwolf.c:572 msgid "search in current page" msgstr "recherche dans la page courante" -#: badwolf.c:100 +#: badwolf.c:100 badwolf.c:234 #, fuzzy msgid "the web process crashed.\n" msgstr "le processus web à cessé de fonctionner.\n" -#: badwolf.c:104 +#: badwolf.c:104 badwolf.c:238 #, 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:108 badwolf.c:242 #, 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:101 badwolf.c:235 msgid "title|Crashed" msgstr "title|Crash" -#: badwolf.c:105 +#: badwolf.c:105 badwolf.c:239 msgid "title|Out of Memory" msgstr "title|Dépassement Mémoire" -#: badwolf.c:109 +#: badwolf.c:109 badwolf.c:243 msgid "title|Unknown Crash" msgstr "title|Crash inconnu" diff --git a/po/messages.pot b/po/messages.pot @@ -6,8 +6,8 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Badwolf 0.1.0\n" -"POT-Creation-Date: 2019-04-18 13:16+0200\n" +"Project-Id-Version: Badwolf 0.1.1\n" +"POT-Creation-Date: 2019-05-11 05:03+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: \"Haelwenn (lanodan) Monnier <contact@hacktivis.me>\"\n" "Language: en\n" @@ -15,52 +15,57 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: badwolf.c:527 +#: badwolf.c:527 badwolf.c:692 #, c-format msgid "Buildtime WebKit version: %d.%d.%d\n" msgstr "" -#: badwolf.c:457 +#: badwolf.c:457 badwolf.c:621 msgid "New tab" msgstr "" -#: badwolf.c:549 +#: badwolf.c:549 badwolf.c:714 msgid "Open new tab" msgstr "" -#: badwolf.c:532 +#: badwolf.c:690 +#, c-format +msgid "Running Badwolf version: %s\n" +msgstr "" + +#: badwolf.c:532 badwolf.c:697 #, c-format msgid "Runtime WebKit version: %d.%d.%d\n" msgstr "" -#: badwolf.c:373 +#: badwolf.c:373 badwolf.c:532 msgid "Toggle javascript" msgstr "" -#: badwolf.c:413 +#: badwolf.c:413 badwolf.c:572 msgid "search in current page" msgstr "" -#: badwolf.c:100 +#: badwolf.c:100 badwolf.c:234 msgid "the web process crashed.\n" msgstr "" -#: badwolf.c:104 +#: badwolf.c:104 badwolf.c:238 msgid "the web process exceeded the memory limit.\n" msgstr "" -#: badwolf.c:108 +#: badwolf.c:108 badwolf.c:242 msgid "the web process terminated for an unknown reason.\n" msgstr "" -#: badwolf.c:101 +#: badwolf.c:101 badwolf.c:235 msgid "title|Crashed" msgstr "" -#: badwolf.c:105 +#: badwolf.c:105 badwolf.c:239 msgid "title|Out of Memory" msgstr "" -#: badwolf.c:109 +#: badwolf.c:109 badwolf.c:243 msgid "title|Unknown Crash" msgstr ""