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:
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 ""