logo

badwolf

minimalist and privacy-oriented web browser based on WebKitGTK git clone https://hacktivis.me/git/badwolf.git
commit: a49df8ad9869a47a10138738b38fd0ffdb95e402
parent c3cadbabf760fd86a0b21bf1869e01653fa5dbbe
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Mon, 18 May 2020 04:50:42 +0200

Merge branch 'release-1.0' for v1.0.0

Diffstat:

A.editorconfig10++++++++++
MMakefile25+++++++++++++++++++++----
MREADME.md6++++--
Mbadwolf.117++++++++++++++++-
Mbadwolf.c306++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mbadwolf.desktop2+-
Mbadwolf.h8++++++--
Abadwolf.inkscape.svg164+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abadwolf.svg134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mconfig.h12++++++------
Mdecisions.md11+++++++++++
Adownloads.c218+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adownloads.h28++++++++++++++++++++++++++++
Aicons/hicolor/128x128/apps/badwolf.png0
Aicons/hicolor/24x24/apps/badwolf.png0
Aicons/hicolor/256x256/apps/badwolf.png0
Aicons/hicolor/32x32/apps/badwolf.png0
Aicons/hicolor/48x48/apps/badwolf.png0
Aicons/hicolor/64x64/apps/badwolf.png0
Aicons/hicolor/scalable/apps/badwolf.svg2++
Aicons_size.sh4++++
Ainterface.css2++
Ainterface.txt43+++++++++++++++++++++++++++++++++++++++++++
Mkeybindings.c6++++++
Mpo/fr.po102++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Mpo/messages.pot98+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mpo/pt_BR.po128+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mversion.sh5+++--
28 files changed, 1141 insertions(+), 190 deletions(-)

diff --git a/.editorconfig b/.editorconfig @@ -0,0 +1,10 @@ +# https://EditorConfig.org +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = tab +indent_size = tab +max_line_length = 100 diff --git a/Makefile b/Makefile @@ -4,7 +4,7 @@ # - Usage of += for appending to a variable PACKAGE = Badwolf -VERSION = 0.5.1 +VERSION = 1.0.0 VERSION_FULL = $(VERSION)`./version.sh` PREFIX ?= /usr/local @@ -19,15 +19,19 @@ CFLAGS ?= -g -Wall -Wextra -Wconversion -Wsign-conversion -O2 DBG ?= PKGCONFIG ?= pkg-config MSGFMT ?= msgfmt +INKSCAPE ?= inkscape + +# for i in 24 32 48 64 128 256; do echo icons/hicolor/${i}x${i}/apps/badwolf.png; done | tr '\n' ' ' +ICON_SIZES = icons/hicolor/24x24/apps/badwolf.png icons/hicolor/32x32/apps/badwolf.png icons/hicolor/48x48/apps/badwolf.png icons/hicolor/64x64/apps/badwolf.png icons/hicolor/128x128/apps/badwolf.png icons/hicolor/256x256/apps/badwolf.png DEPS = gtk+-3.0 webkit2gtk-4.0 libsoup-2.4 -SRCS = uri.c uri_test.c keybindings.c badwolf.c -OBJS = uri.o keybindings.o badwolf.o +SRCS = uri.c uri_test.c keybindings.c downloads.c badwolf.c +OBJS = uri.o keybindings.o downloads.o badwolf.o OBJS_test = uri_test.o EXE = badwolf EXE_test = uri_test TRANS = fr.mo pt_BR.mo -DOCS = usr.bin.badwolf README.md KnowledgeBase.md +DOCS = usr.bin.badwolf README.md KnowledgeBase.md interface.txt CDEPS = -DDATADIR=\"$(DATADIR)\" -DPACKAGE=\"$(PACKAGE)\" -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION_FULL)\" CDEPS += `$(PKGCONFIG) --cflags $(DEPS)` @@ -35,6 +39,16 @@ LIBS = `$(PKGCONFIG) --libs $(DEPS)` all: $(EXE) $(TRANS) po/messages.pot +icons: $(ICON_SIZES) + +icons/hicolor/scalable/apps/badwolf.svg: badwolf.svg + mkdir -p icons/hicolor/scalable/apps + scour --no-line-breaks --enable-id-stripping --remove-metadata $< $@ + +icons/hicolor/%/apps/badwolf.png: icons/hicolor/scalable/apps/badwolf.svg + mkdir -p `dirname $@` + $(INKSCAPE) `echo $@ | cut -d/ -f3 | ./icons_size.sh` $< -o $@ + po/messages.pot: $(SRCS) xgettext --keyword=_ --language=C --from-code=UTF-8 -o $@ --add-comments --sort-output --copyright-holder="Badwolf Authors <https://hacktivis.me/projects/badwolf>" --package-name="$(PACKAGE)" --package-version="$(VERSION_FULL)" --msgid-bugs-address="contact+badwolf-msgid@hacktivis.me" $(SRCS) @@ -69,10 +83,13 @@ install: all cp -p badwolf.1 $(DESTDIR)$(MANDIR)/man1 mkdir -p $(DESTDIR)$(DATADIR)/locale cp -r locale/ $(DESTDIR)$(DATADIR) + cp interface.css $(DESTDIR)$(DATADIR) mkdir -p $(DESTDIR)$(APPSDIR) cp -p badwolf.desktop $(DESTDIR)$(APPSDIR)/ mkdir -p $(DESTDIR)$(DOCDIR) cp -p $(DOCS) $(DESTDIR)$(DOCDIR)/ + mkdir -p $(DESTDIR)$(PREFIX)/share + cp -r icons $(DESTDIR)$(PREFIX)/share/ @printf '\nNote: An example AppArmor profile has been installed at '$(DOCDIR)/usr.bin.badwolf'\n' .PHONY: clean diff --git a/README.md b/README.md @@ -19,7 +19,7 @@ Comparing from other small WebKit browsers for unixes found in the wild: - not queryabe by WebKit (so the web can't use it) - done in a standard format (like XBEL for bookmarks) - Static UI, no element should be added at runtime, this is to avoid potential tracking via viewport changes -- Small codebase, right now we are under 1 500 lines total +- Small codebase, should be possible to read and understand it completely over an afternoon. - Does not use modal editing (from vi) as that was designed for editing, not browsing - UTF-8 encoding by default @@ -54,7 +54,9 @@ Dependencies are: - A pkg-config implementation (pkgconf is recommended) - (optionnal) gettext implementation (such as GNU Gettext) -Compilation is done with `make CC=${CC:-cc}`, install with `make install`. An example AppArmor profile is provided at `usr.bin.badwolf`, please do runtime checks before deploying. +Compilation is done with `make`, install with `make install` (`DESTDIR` and `PREFIX` environment variables are supported, amongs other common ones). An example AppArmor profile is provided at `usr.bin.badwolf`, please do some long runtime checks before shipping it or a modified version, help can be provided but with no support. + +You'll also need `rsvg-convert(1)` (from librsvg) and scour if you want to regenerate the icons, for example after modifying them or adding a new size. These aren't needed for normal installation as it is bundled. ## Notes Most of the privacy/security stuff will be done with patches against WebKit as quite a lot isn’t into [WebKitSettings](https://webkitgtk.org/reference/webkit2gtk/stable/WebKitSettings.html) and with generic WebKit extensions that should be resuseable. diff --git a/badwolf.1 b/badwolf.1 @@ -35,13 +35,17 @@ Focuses on the search entry .It browser C-l Focuses on the location(URL) entry .It browser C-S-r / C-r, browser F5 -Reloads the current tab (with/without clearing cache) +Reloads the content in the current tab (with/without clearing cache) +.It browser Escape +Stops loading the content in the current tab .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 browser C-p +Print the current page. (spawns a dialog) .It any A-Left / A-Right Go to the previous/next tab .It any F1 @@ -79,6 +83,17 @@ Examples of useful extensions may be found at: .Lk https://hacktivis.me/git/badwolf-extensions .Lk https://github.com/jun7/wyebadblock .El +.It Pa ${DATADIR:-/usr/local/share}/badwolf/interface.css +.It Pa ${XDG_DATA_HOME:-$HOME/.local/share}/badwolf/interface.css +CSS files (respectively system and user-level) for styling badwolf interface. See +.Lk https://developer.gnome.org/gtk3/stable/chap-css-properties.html +for the properties being available. +.Pp +For testing your styles I would recommend using the +.Ev GTK_DEBUG=interactive +environment variable on launching +.Nm +and going to the CSS tab. .El .Sh BUGS You can submit contributions or tickets to diff --git a/badwolf.c b/badwolf.c @@ -5,6 +5,7 @@ #include "badwolf.h" #include "config.h" +#include "downloads.h" #include "keybindings.h" #include "uri.h" @@ -13,12 +14,12 @@ #include <locale.h> /* LC_* */ #include <stdio.h> /* perror(), fprintf() */ #include <stdlib.h> /* malloc() */ +#include <unistd.h> /* access() */ +gchar *web_extensions_directory; const gchar *homepage = "https://hacktivis.me/projects/badwolf"; const gchar *version = VERSION; -gchar *web_extensions_directory; - static gboolean WebViewCb_close(WebKitWebView *webView, gpointer user_data); static gboolean WebViewCb_web_process_terminated(WebKitWebView *webView, WebKitWebProcessTerminationReason reason, @@ -46,14 +47,17 @@ static gboolean WebViewCb_decide_policy(WebKitWebView *web_view, WebKitPolicyDecision *decision, WebKitPolicyDecisionType decision_type, gpointer user_data); +static void +WebViewCb_load_changed(WebKitWebView *webView, WebKitLoadEvent load_event, gpointer user_data); static void web_contextCb_download_started(WebKitWebContext *web_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 auto_load_imagesCb_toggled(GtkButton *auto_load_images, gpointer user_data); +static void backCb_clicked(GtkButton *back, gpointer user_data); +static void forwardCb_clicked(GtkButton *forward, gpointer user_data); +static void printCb_clicked(GtkButton *forward, gpointer user_data); static gboolean SearchEntryCb_next__match(GtkSearchEntry *search, gpointer user_data); static gboolean SearchEntryCb_previous__match(GtkSearchEntry *search, gpointer user_data); static gboolean SearchEntryCb_search__changed(GtkSearchEntry *search, gpointer user_data); @@ -131,11 +135,15 @@ badwolf_new_tab_box(const gchar *title, struct Client *browser) { (void)browser; GtkWidget *tab_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(tab_box, "browser__tabbox"); GtkWidget *close = - gtk_button_new_from_icon_name("window-close-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_button_new_from_icon_name("window-close-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_widget_set_name(close, "browser__tabbox__close"); GtkWidget *label = gtk_label_new(title); + gtk_widget_set_name(label, "browser__tabbox__label"); GtkWidget *playing = gtk_image_new_from_icon_name("audio-volume-high-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_widget_set_name(playing, "browser__tabbox__playing"); #ifdef BADWOLF_TAB_BOX_WIDTH gtk_widget_set_size_request(label, BADWOLF_TAB_BOX_WIDTH, -1); @@ -193,7 +201,7 @@ webView_tab_label_change(struct Client *browser, const gchar *title) { GtkWidget *notebook = browser->window->notebook; -#define title_IS_EMPTY (title == NULL) || (title == (const gchar *)"") +#define title_IS_EMPTY (title == NULL) || strnlen(title, 2) == 0 if(title_IS_EMPTY) title = webkit_web_view_get_title(browser->webView); if(title_IS_EMPTY) title = webkit_web_view_get_uri(browser->webView); @@ -325,6 +333,17 @@ WebViewCb_decide_policy(WebKitWebView *web_view, return TRUE; } +static void +WebViewCb_load_changed(WebKitWebView *webView, WebKitLoadEvent load_event, gpointer user_data) +{ + (void)webView; + (void)load_event; + struct Client *browser = (struct Client *)user_data; + + gtk_widget_set_sensitive(browser->back, webkit_web_view_can_go_back(browser->webView)); + gtk_widget_set_sensitive(browser->forward, webkit_web_view_can_go_forward(browser->webView)); +} + static char * detail_tls_certificate_flags(GTlsCertificateFlags tls_errors) { @@ -381,7 +400,7 @@ WebViewCb_load_failed_with_tls_errors(WebKitWebView *web_view, _("TLS Error for %s."), failing_text); gtk_dialog_add_buttons( - GTK_DIALOG(dialog), _("Temporarly Add Exception"), 1, _("Continue"), 0, NULL); + GTK_DIALOG(dialog), _("Temporarily Add Exception"), 1, _("Continue"), 0, NULL); gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s\n", error_details); @@ -403,72 +422,106 @@ WebViewCb_load_failed_with_tls_errors(WebKitWebView *web_view, static void web_contextCb_download_started(WebKitWebContext *web_context, - WebKitDownload *download, + WebKitDownload *webkit_download, gpointer user_data) { (void)web_context; + struct Client *browser = (struct Client *)user_data; + struct Download *download = malloc(sizeof(struct Client)); + + if(download != NULL) + { + download->window = browser->window; + + download_new_entry(webkit_download, download); + + g_signal_connect( + G_OBJECT(webkit_download), "received-data", G_CALLBACK(downloadCb_received_data), download); + g_signal_connect(G_OBJECT(webkit_download), + "created-destination", + G_CALLBACK(downloadCb_created_destination), + download); + g_signal_connect(G_OBJECT(webkit_download), "failed", G_CALLBACK(downloadCb_failed), download); + g_signal_connect( + G_OBJECT(webkit_download), "finished", G_CALLBACK(downloadCb_finished), download); + } - g_signal_connect(G_OBJECT(download), + g_signal_connect(G_OBJECT(webkit_download), "decide-destination", G_CALLBACK(downloadCb_decide_destination), user_data); } static gboolean -downloadCb_decide_destination(WebKitDownload *download, - gchar *suggested_filename, - gpointer user_data) +locationCb_activate(GtkEntry *location, gpointer user_data) { struct Client *browser = (struct Client *)user_data; - gint chooser_response; - GtkWindow *parent_window = GTK_WINDOW(browser->window->main_window); - - GtkFileChooserNative *file_dialog = - gtk_file_chooser_native_new(NULL, parent_window, GTK_FILE_CHOOSER_ACTION_SAVE, NULL, 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_native_dialog_run(GTK_NATIVE_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); - - g_object_unref(file_dialog); + webkit_web_view_load_uri(browser->webView, + badwolf_ensure_uri_scheme(gtk_entry_get_text(location), TRUE)); - return FALSE; /* Let it propagate */ + return TRUE; } static gboolean -locationCb_activate(GtkEntry *location, gpointer user_data) +javascriptCb_toggled(GtkButton *javascript, gpointer user_data) { struct Client *browser = (struct Client *)user_data; - webkit_web_view_load_uri(browser->webView, - badwolf_ensure_uri_scheme(gtk_entry_get_text(location), TRUE)); + WebKitSettings *settings = webkit_web_view_get_settings(browser->webView); + + webkit_settings_set_enable_javascript_markup( + settings, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(javascript))); + + webkit_web_view_set_settings(browser->webView, settings); return TRUE; } static gboolean -javascriptCb_toggled(GtkButton *javascript, gpointer user_data) +auto_load_imagesCb_toggled(GtkButton *auto_load_images, gpointer user_data) { struct Client *browser = (struct Client *)user_data; WebKitSettings *settings = webkit_web_view_get_settings(browser->webView); - webkit_settings_set_enable_javascript_markup( - settings, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(javascript))); + webkit_settings_set_auto_load_images( + settings, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(auto_load_images))); webkit_web_view_set_settings(browser->webView, settings); return TRUE; } +static void +backCb_clicked(GtkButton *back, gpointer user_data) +{ + (void)back; + struct Client *browser = (struct Client *)user_data; + + webkit_web_view_go_back(browser->webView); +} + +static void +forwardCb_clicked(GtkButton *forward, gpointer user_data) +{ + (void)forward; + struct Client *browser = (struct Client *)user_data; + + webkit_web_view_go_forward(browser->webView); +} + +static void +printCb_clicked(GtkButton *print, gpointer user_data) +{ + (void)print; + struct Client *browser = (struct Client *)user_data; + + WebKitPrintOperation *print_operation = webkit_print_operation_new(browser->webView); + + webkit_print_operation_run_dialog(print_operation, GTK_WINDOW(browser->window)); +} + static gboolean SearchEntryCb_next__match(GtkSearchEntry *search, gpointer user_data) { @@ -517,6 +570,16 @@ SearchEntryCb_stop__search(GtkSearchEntry *search, gpointer user_data) return TRUE; } +static gboolean +widgetCb_drop_button3_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + (void)widget; + (void)user_data; + + // Button3 being right-click on right-handed mode, left-click on left-handed mode + return ((GdkEventButton *)event)->button == 3; +} + struct Client * new_browser(struct Window *window, const gchar *target_url, WebKitWebView *related_web_view) { @@ -526,15 +589,47 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat if(browser == NULL) return NULL; - browser->window = window; - browser->box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - browser->toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - browser->location = gtk_entry_new(); - browser->javascript = gtk_check_button_new(); + browser->window = window; + browser->box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_name(browser->box, "browser__box"); + + browser->toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(browser->toolbar, "browser__toolbar"); + + browser->back = + gtk_button_new_from_icon_name("go-previous-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_widget_set_name(browser->back, "browser__back"); + + browser->forward = gtk_button_new_from_icon_name("go-next-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_widget_set_name(browser->forward, "browser__forward"); + + GtkWidget *toolbar_separator = gtk_separator_new(GTK_ORIENTATION_VERTICAL); + + browser->javascript = gtk_toggle_button_new_with_mnemonic(_("_JS")); + gtk_widget_set_name(browser->javascript, "browser__javascript"); + gtk_widget_set_tooltip_text(browser->javascript, _("Toggle javascript")); + gtk_button_set_relief(GTK_BUTTON(browser->javascript), GTK_RELIEF_NONE); + + browser->auto_load_images = gtk_toggle_button_new_with_mnemonic(_("_IMG")); + gtk_widget_set_name(browser->auto_load_images, "browser__load_images"); + gtk_widget_set_tooltip_text(browser->auto_load_images, _("Toggle loading images automatically")); + gtk_button_set_relief(GTK_BUTTON(browser->auto_load_images), GTK_RELIEF_NONE); - browser->statusbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + browser->location = gtk_entry_new(); + gtk_widget_set_name(browser->location, "browser__location"); + + GtkWidget *print = + gtk_button_new_from_icon_name("document-print-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_widget_set_name(browser->back, "browser__print"); + + browser->statusbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(browser->statusbar, "browser__statusbar"); + browser->search = gtk_search_entry_new(); + gtk_widget_set_name(browser->search, "browser__search"); browser->statuslabel = gtk_label_new(NULL); - browser->search = gtk_search_entry_new(); + gtk_widget_set_name(browser->statuslabel, "browser__statuslabel"); + + setenv("GTK_THEME", ":light", 0); WebKitWebContext *web_context = webkit_web_context_new_ephemeral(); webkit_web_context_set_sandbox_enabled(web_context, TRUE); @@ -558,6 +653,8 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(browser->javascript), webkit_settings_get_enable_javascript_markup(settings)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(browser->auto_load_images), + webkit_settings_get_auto_load_images(settings)); browser->webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, "web-context", @@ -567,19 +664,39 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat "settings", settings, NULL)); + gtk_widget_set_name(GTK_WIDGET(browser->webView), "browser__webView"); - gtk_widget_set_tooltip_text(browser->javascript, _("Toggle javascript")); - + gtk_box_pack_start( + GTK_BOX(browser->toolbar), GTK_WIDGET(browser->back), FALSE, FALSE, BADWOLF_TOOLBAR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->toolbar), + GTK_WIDGET(browser->forward), + FALSE, + FALSE, + BADWOLF_TOOLBAR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->toolbar), + toolbar_separator, + FALSE, + FALSE, + BADWOLF_TOOLBAR_SEPARATOR_PADDING); gtk_box_pack_start(GTK_BOX(browser->toolbar), GTK_WIDGET(browser->javascript), FALSE, FALSE, BADWOLF_TOOLBAR_PADDING); gtk_box_pack_start(GTK_BOX(browser->toolbar), + GTK_WIDGET(browser->auto_load_images), + FALSE, + FALSE, + BADWOLF_TOOLBAR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->toolbar), GTK_WIDGET(browser->location), TRUE, TRUE, BADWOLF_TOOLBAR_PADDING); + gtk_box_pack_start(GTK_BOX(browser->toolbar), print, FALSE, FALSE, BADWOLF_TOOLBAR_PADDING); + + gtk_container_set_focus_child(GTK_CONTAINER(browser->box), browser->toolbar); + gtk_container_set_focus_child(GTK_CONTAINER(browser->toolbar), browser->location); gtk_box_pack_start( GTK_BOX(browser->box), GTK_WIDGET(browser->toolbar), FALSE, FALSE, BADWOLF_BOX_PADDING); @@ -606,17 +723,52 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat 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); gtk_entry_set_input_purpose(GTK_ENTRY(browser->location), GTK_INPUT_PURPOSE_URL); 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 back/forward buttons */ + g_signal_connect(browser->back, "clicked", G_CALLBACK(backCb_clicked), browser); + g_signal_connect(browser->forward, "clicked", G_CALLBACK(forwardCb_clicked), browser); + /* prevents GtkNotebook from spawning it's context-menu */ + g_signal_connect( + browser->back, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + g_signal_connect( + browser->back, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + g_signal_connect( + browser->forward, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + g_signal_connect( + browser->forward, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); /* signals for javacript toggle widget */ g_signal_connect(browser->javascript, "toggled", G_CALLBACK(javascriptCb_toggled), browser); + /* prevents GtkNotebook from spawning it's context-menu */ + g_signal_connect( + browser->javascript, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + g_signal_connect( + browser->javascript, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + + /* signals for auto_load_images toggle widget */ + g_signal_connect( + browser->auto_load_images, "toggled", G_CALLBACK(auto_load_imagesCb_toggled), browser); + /* prevents GtkNotebook from spawning it's context-menu */ + g_signal_connect(browser->auto_load_images, + "button-press-event", + G_CALLBACK(widgetCb_drop_button3_event), + NULL); + g_signal_connect(browser->auto_load_images, + "button-release-event", + G_CALLBACK(widgetCb_drop_button3_event), + NULL); + + /* signals for location entry widget */ + g_signal_connect(browser->location, "activate", G_CALLBACK(locationCb_activate), browser); + + /* signals for print button */ + g_signal_connect(print, "clicked", G_CALLBACK(printCb_clicked), browser); + /* prevents GtkNotebook from spawning it's context-menu */ + g_signal_connect(print, "button-press-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); + g_signal_connect(print, "button-release-event", G_CALLBACK(widgetCb_drop_button3_event), NULL); /* signals for WebView widget */ g_signal_connect(browser->webView, @@ -649,6 +801,7 @@ new_browser(struct Window *window, const gchar *target_url, WebKitWebView *relat "load-failed-with-tls-errors", G_CALLBACK(WebViewCb_load_failed_with_tls_errors), browser); + g_signal_connect(browser->webView, "load-changed", G_CALLBACK(WebViewCb_load_changed), browser); /* signals for WebView's WebContext */ g_signal_connect(G_OBJECT(web_context), @@ -744,7 +897,7 @@ badwolf_get_tab_position(GtkContainer *notebook, GtkWidget *child) int main(int argc, char *argv[]) { - struct Window *window = &(struct Window){NULL}; + struct Window *window = &(struct Window){NULL, NULL, NULL, NULL}; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, DATADIR "/locale"); bind_textdomain_codeset(PACKAGE, "UTF-8"); @@ -752,13 +905,6 @@ main(int argc, char *argv[]) gtk_init(&argc, &argv); -#ifdef BADWOLF_PREFER_DARK_THEME - g_object_set(gtk_settings_get_default(), - "gtk-application-prefer-dark-theme", - BADWOLF_PREFER_DARK_THEME, - NULL); -#endif - fprintf(stderr, _("Running Badwolf version: %s\n"), version); fprintf(stderr, _("Buildtime WebKit version: %d.%d.%d\n"), @@ -778,10 +924,37 @@ main(int argc, char *argv[]) window->main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); window->notebook = gtk_notebook_new(); window->new_tab = gtk_button_new_from_icon_name("tab-new-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + window->downloads_tab = badwolf_downloads_tab_new(); gtk_window_set_default_size( GTK_WINDOW(window->main_window), BADWOLF_DEFAULT_WIDTH, BADWOLF_DEFAULT_HEIGHT); gtk_window_set_role(GTK_WINDOW(window->main_window), "browser"); + gtk_window_set_icon_name(GTK_WINDOW(window->main_window), "badwolf"); + + GtkCssProvider *css_provider_app = gtk_css_provider_new(); + gchar *provider_path_app = g_build_filename(DATADIR, "interface.css", NULL); + if(access(provider_path_app, R_OK) == 0) + { + gtk_css_provider_load_from_path(css_provider_app, provider_path_app, NULL); + gtk_style_context_add_provider_for_screen( + gtk_widget_get_screen(GTK_WIDGET(window->main_window)), + GTK_STYLE_PROVIDER(css_provider_app), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } + g_free(provider_path_app); + + GtkCssProvider *css_provider_user = gtk_css_provider_new(); + gchar *provider_path_user = + g_build_filename(g_get_user_data_dir(), "badwolf", "interface.css", NULL); + if(access(provider_path_user, R_OK) == 0) + { + gtk_css_provider_load_from_path(css_provider_user, provider_path_user, NULL); + gtk_style_context_add_provider_for_screen( + gtk_widget_get_screen(GTK_WIDGET(window->main_window)), + GTK_STYLE_PROVIDER(css_provider_user), + GTK_STYLE_PROVIDER_PRIORITY_USER); + } + g_free(provider_path_user); gtk_widget_set_tooltip_text(window->new_tab, _("Open new tab")); @@ -791,12 +964,9 @@ main(int argc, char *argv[]) gtk_notebook_popup_enable(GTK_NOTEBOOK(window->notebook)); gtk_container_add(GTK_CONTAINER(window->main_window), window->notebook); + gtk_widget_queue_draw(window->notebook); - 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)); + badwolf_downloads_tab_attach(window); g_signal_connect( window->main_window, "key-press-event", G_CALLBACK(main_windowCb_key_press_event), window); @@ -808,6 +978,14 @@ main(int argc, char *argv[]) gtk_widget_show(window->new_tab); gtk_widget_show_all(window->main_window); + 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)); + + gtk_notebook_set_current_page(GTK_NOTEBOOK(window->notebook), 1); + gtk_main(); #if 0 diff --git a/badwolf.desktop b/badwolf.desktop @@ -8,7 +8,7 @@ Comment[fr]=Un navigateur web minimaliste et orienté vers le respect de la vie Exec=badwolf %U GenericName=Web Browser GenericName[fr]=Navigateur Web -Icon=web-browser +Icon=badwolf 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 diff --git a/badwolf.h b/badwolf.h @@ -4,14 +4,15 @@ #include <gtk/gtk.h> #include <webkit2/webkit2.h> -const gchar *homepage; -const gchar *version; +extern const gchar *homepage; +extern const gchar *version; struct Window { GtkWidget *main_window; GtkWidget *notebook; GtkWidget *new_tab; + GtkWidget *downloads_tab; }; struct Client @@ -19,7 +20,10 @@ struct Client GtkWidget *box; GtkWidget *toolbar; + GtkWidget *back; + GtkWidget *forward; GtkWidget *javascript; + GtkWidget *auto_load_images; GtkWidget *location; WebKitWebView *webView; diff --git a/badwolf.inkscape.svg b/badwolf.inkscape.svg @@ -0,0 +1,164 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + inkscape:version="1.0rc1 (09960d6f05, 2020-04-09)" + sodipodi:docname="badwolf.inkscape.svg" + id="svg17" + viewBox="0 0 16.93333 16.93333" + version="1.1" + height="64" + width="64"> + <metadata + id="metadata21"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + inkscape:current-layer="g16" + inkscape:window-maximized="0" + inkscape:window-y="18" + inkscape:window-x="0" + inkscape:cy="32" + inkscape:cx="-34.886275" + inkscape:zoom="5.9765625" + showgrid="false" + id="namedview19" + inkscape:window-height="1062" + inkscape:window-width="1920" + inkscape:pageshadow="2" + inkscape:pageopacity="0" + guidetolerance="10" + gridtolerance="10" + objecttolerance="10" + borderopacity="1" + bordercolor="#666666" + pagecolor="#ffffff" + inkscape:document-rotation="0" /> + <defs + id="defs9"> + <linearGradient + id="linearGradient880"> + <stop + style="stop-color:#00ffd6;stop-opacity:1" + stop-color="#139e7c" + offset="0" + id="stop876" /> + <stop + style="stop-color:#007f64;stop-opacity:1" + stop-color="#122548" + offset="1" + id="stop878" /> + </linearGradient> + <linearGradient + id="linearGradient844" + inkscape:collect="always"> + <stop + id="stop840" + offset="0" + style="stop-color:#000000;stop-opacity:1;" /> + <stop + id="stop842" + offset="1" + style="stop-color:#000000;stop-opacity:0;" /> + </linearGradient> + <clipPath + id="clippy"> + <rect + ry="1" + y="0" + x="0" + height="16.933333" + width="16.933333" + id="rect4" /> + </clipPath> + <linearGradient + id="a"> + <stop + id="stop2" + offset="0" + stop-color="#139e7c" /> + <stop + id="stop4" + offset="1" + stop-color="#122548" /> + </linearGradient> + <radialGradient + fy="-4.2398162" + fx="8.6972151" + xlink:href="#a" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.612,0.05608289,-0.03812291,-1.775534,30.49128,-9.106413)" + r="8.4666672" + cy="-4.2398162" + cx="8.6972151" + id="b" /> + <linearGradient + xlink:href="#a" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.340793,0,0,1.340793,-5.009645,-4.9950368)" + y2="13.79657" + y1="9.051465" + x2="6.0263619" + x1="9.1526928" + id="c" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="4.7058144" + x2="-10.735905" + y1="4.7058144" + x1="-10.466779" + id="linearGradient846" + xlink:href="#linearGradient844" + inkscape:collect="always" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.681454" + x2="6.7958536" + y1="8.9934816" + x1="7.463346" + id="linearGradient874" + xlink:href="#linearGradient880" + inkscape:collect="always" /> + </defs> + <g + clip-path="url(#clippy)" + id="g16"> + <rect + style="fill-opacity:1;fill:url(#b)" + id="rect11" + fill="url(#b)" + ry="0" + height="16.93333" + width="16.93333" /> + <path + style="stroke-width:0.50270823;stroke-miterlimit:4;stroke-dasharray:none;stroke:#23e0b7;stroke-opacity:1;fill-opacity:1;fill:url(#linearGradient846)" + id="path13" + stroke-width="0.264583" + stroke="#47b79f" + d="m 21.86801,-1.9920238 a 13.40211,8.185254 0 0 1 -6.713234,7.092927 13.40211,8.185254 0 0 1 -13.41427,-0.012891 13.40211,8.185254 0 0 1 -6.676652,-7.105795 l 13.40204,0.025759 z" + inkscape:connector-curvature="0" /> + <path + id="wolf" + style="mix-blend-mode:luminosity;fill:#120d09;fill-opacity:1;stroke:url(#linearGradient874);stroke-width:0.674952;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + stroke-width="0.569064" + stroke="url(#c)" + fill-rule="evenodd" + fill="#0f0805" + d="M 5.954321,19.118114 C 6.279375,16.458717 6.8910042,15.96845 5.7885535,13.873872 5.195892,12.824843 3.5059475,11.558594 2.6479315,10.539665 2.1673827,9.7904655 1.0434685,9.2171762 0.3615065,7.7493392 0.201822,6.7648665 2.5855305,8.9732112 3.2563495,8.9366162 3.5137348,8.6517205 1.6556185,6.7595682 1.8277525,6.0733512 1.97089,5.5027309 2.0400037,4.9353402 2.6089912,4.5036212 c 1.197317,-0.3311996 3.39131,2.812714 4.927271,3.260379 2.110609,-0.7248708 3.1742058,1.490123 4.8202378,1.830078 1.322712,0.1565739 3.207405,1.5936848 4.252409,2.9707628 -0.845016,0.590474 -3.044526,-0.706301 -4.410436,-0.108108 -0.538115,0.825242 1.099559,5.219231 1.386259,5.733128" + inkscape:connector-curvature="0" /> + </g> +</svg> diff --git a/badwolf.svg b/badwolf.svg @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + id="svg17" + viewBox="0 0 16.93333 16.93333" + version="1.1" + height="64" + width="64"> + <metadata + id="metadata21"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs9"> + <linearGradient + id="linearGradient880"> + <stop + style="stop-color:#00ffd6;stop-opacity:1" + stop-color="#139e7c" + offset="0" + id="stop876" /> + <stop + style="stop-color:#007f64;stop-opacity:1" + stop-color="#122548" + offset="1" + id="stop878" /> + </linearGradient> + <linearGradient + id="linearGradient844"> + <stop + id="stop840" + offset="0" + style="stop-color:#000000;stop-opacity:1;" /> + <stop + id="stop842" + offset="1" + style="stop-color:#000000;stop-opacity:0;" /> + </linearGradient> + <clipPath + id="clippy"> + <rect + ry="1" + y="0" + x="0" + height="16.933333" + width="16.933333" + id="rect4" /> + </clipPath> + <linearGradient + id="a"> + <stop + id="stop2" + offset="0" + stop-color="#139e7c" /> + <stop + id="stop4" + offset="1" + stop-color="#122548" /> + </linearGradient> + <radialGradient + fy="-4.2398162" + fx="8.6972151" + xlink:href="#a" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-2.612,0.05608289,-0.03812291,-1.775534,30.49128,-9.106413)" + r="8.4666672" + cy="-4.2398162" + cx="8.6972151" + id="b" /> + <linearGradient + xlink:href="#a" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.340793,0,0,1.340793,-5.009645,-4.9950368)" + y2="13.79657" + y1="9.051465" + x2="6.0263619" + x1="9.1526928" + id="c" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="4.7058144" + x2="-10.735905" + y1="4.7058144" + x1="-10.466779" + id="linearGradient846" + xlink:href="#linearGradient844" /> + <linearGradient + gradientUnits="userSpaceOnUse" + y2="11.681454" + x2="6.7958536" + y1="8.9934816" + x1="7.463346" + id="linearGradient874" + xlink:href="#linearGradient880" /> + </defs> + <g + clip-path="url(#clippy)" + id="g16"> + <rect + style="fill-opacity:1;fill:url(#b)" + id="rect11" + fill="url(#b)" + ry="0" + height="16.93333" + width="16.93333" /> + <path + style="stroke-width:0.50270823;stroke-miterlimit:4;stroke-dasharray:none;stroke:#23e0b7;stroke-opacity:1;fill-opacity:1;fill:url(#linearGradient846)" + id="path13" + stroke-width="0.264583" + stroke="#47b79f" + d="m 21.86801,-1.9920238 a 13.40211,8.185254 0 0 1 -6.713234,7.092927 13.40211,8.185254 0 0 1 -13.41427,-0.012891 13.40211,8.185254 0 0 1 -6.676652,-7.105795 l 13.40204,0.025759 z" /> + <path + id="wolf" + style="mix-blend-mode:luminosity;fill:#120d09;fill-opacity:1;stroke:url(#linearGradient874);stroke-width:0.674952;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + stroke-width="0.569064" + stroke="url(#c)" + fill-rule="evenodd" + fill="#0f0805" + d="M 5.954321,19.118114 C 6.279375,16.458717 6.8910042,15.96845 5.7885535,13.873872 5.195892,12.824843 3.5059475,11.558594 2.6479315,10.539665 2.1673827,9.7904655 1.0434685,9.2171762 0.3615065,7.7493392 0.201822,6.7648665 2.5855305,8.9732112 3.2563495,8.9366162 3.5137348,8.6517205 1.6556185,6.7595682 1.8277525,6.0733512 1.97089,5.5027309 2.0400037,4.9353402 2.6089912,4.5036212 c 1.197317,-0.3311996 3.39131,2.812714 4.927271,3.260379 2.110609,-0.7248708 3.1742058,1.490123 4.8202378,1.830078 1.322712,0.1565739 3.207405,1.5936848 4.252409,2.9707628 -0.845016,0.590474 -3.044526,-0.706301 -4.410436,-0.108108 -0.538115,0.825242 1.099559,5.219231 1.386259,5.733128" /> + </g> +</svg> diff --git a/config.h b/config.h @@ -39,9 +39,15 @@ // BADWOLF_TOOLBAR_PADDING: Amount of padding between toolbar elements #define BADWOLF_TOOLBAR_PADDING 0 +// BADWOLF_TOOLBAR_PADDING: Amount of padding between toolbar elements +#define BADWOLF_TOOLBAR_SEPARATOR_PADDING 4 + // BADWOLF_STATUSBAR_PADDING: Amount of padding between statusbar elements #define BADWOLF_STATUSBAR_PADDING 0 +// BADWOLF_DOWNLOAD_PADDING: Amount of padding between download list row-elements +#define BADWOLF_DOWNLOAD_PADDING 5 + /* BADWOLF_DEFAULT_WIDTH / BADWOLF_DEFAULT_HEIGHT: * Used to define the default width/height of the window, * useful for floating Window Managers, probably useless in tiling ones @@ -87,10 +93,4 @@ */ #define BADWOLF_STATUSLABEL_ELLIPSIZE PANGO_ELLIPSIZE_MIDDLE -/* BADWOLF_PREFER_DARK_THEME: Overwrites user GtkSettings for gtk-application-prefer-dark-theme - * Done as a temporary workaround against https://bugs.webkit.org/show_bug.cgi?id=197947 - * Remove definition to keep user settings, should only be done once the bug is fixed. - */ -#define BADWOLF_PREFER_DARK_THEME FALSE - #endif /* CONFIG_H_INCLUDED */ diff --git a/decisions.md b/decisions.md @@ -5,6 +5,17 @@ Bascially, the idea is to have a file in your projects repo, where you record the decisions you make over the course of the project's lifetime. Rewriting history will not be done but Post-Scriptum notices will. +## 2020-02-04 & 2020-02-09 : Use BSD extensions in the Makefile +The BSD extensions += and ?= for variable extension is used to avoid having to explicitely pass a list of variables to make, thus making build recipies simpler. +They are also compatible with GNU make so portability shouldn't have significantly dropped. +Which also meant dropping `.POSIX` into the file so `CC` wouldn't be set by default to `c99` (which isn't what I want, the codebase is in c11). + +## 2020-01-30 02:59 : Make window declaration static +This allows to avoid a quite useless memory allocation that would only be freed at the end of the program. + +## 2020-01-22 15:30 : Update copyright to Badwolf Authors +I don't want copyright assignment to me or any organisation, it should belong to every contributor, meaning that any copyright change will need to be accepted by them or their contribution would need to be replaced if need to be. + ## 2020-01-08 08:42:00Z : Start of the decisions.md file From memory and git log: diff --git a/downloads.c b/downloads.c @@ -0,0 +1,218 @@ +// BadWolf: Minimalist and privacy-oriented WebKitGTK+ browser +// Copyright © 2019 Haelwenn (lanodan) Monnier <contact@hacktivis.me> +// SPDX-License-Identifier: BSD-3-Clause + +#include "downloads.h" + +#include "badwolf.h" +#include "config.h" + +#include <glib/gi18n.h> /* _() and other internationalization/localization helpers */ + +static void +download_stop_iconCb_clicked(GtkButton *stop_icon, gpointer user_data) +{ + (void)stop_icon; + WebKitDownload *webkit_download = (WebKitDownload *)user_data; + + webkit_download_cancel(webkit_download); +} + +void +download_format_elapsed(char *formatted, size_t formatted_size, char *format, int total) +{ + snprintf(formatted, + formatted_size, + format, + total / 3600, /* hours */ + (total % 3600) / 60, /* minutes */ + total % 60); /* seconds */ +} + +void +download_new_entry(WebKitDownload *webkit_download, struct Download *download) +{ + download->error = 0; + download->container = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, BADWOLF_DOWNLOAD_PADDING); + download->progress = gtk_progress_bar_new(); + download->file_path = gtk_label_new(NULL); + download->status = gtk_label_new(_("Download starting…")); + download->icon = + gtk_image_new_from_icon_name("network-idle-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + download->stop_icon = gtk_button_new_from_icon_name("process-stop", GTK_ICON_SIZE_SMALL_TOOLBAR); + + gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(download->progress), TRUE); + + g_signal_connect( + download->stop_icon, "clicked", G_CALLBACK(download_stop_iconCb_clicked), webkit_download); + + gtk_box_pack_start(GTK_BOX(download->container), download->icon, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(download->container), download->progress, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(download->container), download->stop_icon, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(download->container), download->status, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(download->container), download->file_path, FALSE, FALSE, 0); + + gtk_box_pack_start( + GTK_BOX(download->window->downloads_tab), download->container, FALSE, FALSE, 0); + + gtk_widget_show_all(download->container); +} + +void +downloadCb_created_destination(WebKitDownload *webkit_download, + gchar *destination, + gpointer user_data) +{ + (void)webkit_download; + char *markup; + struct Download *download = (struct Download *)user_data; + + markup = g_markup_printf_escaped( + "<a href=\"%s\">%s</a>", destination, webkit_uri_for_display(destination)); + + gtk_label_set_markup(GTK_LABEL(download->file_path), markup); + g_free(markup); +} + +gboolean +downloadCb_decide_destination(WebKitDownload *webkit_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); + + GtkFileChooserNative *file_dialog = + gtk_file_chooser_native_new(NULL, parent_window, GTK_FILE_CHOOSER_ACTION_SAVE, NULL, 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(webkit_download, TRUE); + + chooser_response = gtk_native_dialog_run(GTK_NATIVE_DIALOG(file_dialog)); + + if(chooser_response == GTK_RESPONSE_ACCEPT) + webkit_download_set_destination(webkit_download, gtk_file_chooser_get_uri(file_chooser)); + else + webkit_download_cancel(webkit_download); + + g_object_unref(file_dialog); + + return FALSE; /* Let it propagate */ +} + +void +downloadCb_failed(WebKitDownload *webkit_download, GError *error, gpointer user_data) +{ + struct Download *download = (struct Download *)user_data; + char formatted[BUFSIZ]; + int total = (int)webkit_download_get_elapsed_time(webkit_download); + char *format; + + download->error = error; + + if(g_error_matches(error, WEBKIT_DOWNLOAD_ERROR, WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER)) + format = _("%02i:%02i:%02i Download cancelled"); + else + format = _("%02i:%02i:%02i Download error"); + + download_format_elapsed(formatted, sizeof(formatted), format, total); + + gtk_label_set_text(GTK_LABEL(download->status), formatted); + + gtk_widget_destroy(download->stop_icon); + + gtk_image_set_from_icon_name( + GTK_IMAGE(download->icon), "network-error-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); +} + +void +downloadCb_finished(WebKitDownload *webkit_download, gpointer user_data) +{ + struct Download *download = (struct Download *)user_data; + char formatted[BUFSIZ]; + int total = (int)webkit_download_get_elapsed_time(webkit_download); + + gchar *format_size = g_format_size(webkit_download_get_received_data_length(webkit_download)); + + download_format_elapsed( + formatted, sizeof(formatted), _("%02i:%02i:%02i Download finished"), total); + + gtk_widget_destroy(download->stop_icon); + + if(download->error == 0) + { + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(download->progress), 1); + gtk_progress_bar_set_text(GTK_PROGRESS_BAR(download->progress), format_size); + gtk_label_set_text(GTK_LABEL(download->status), formatted); + gtk_image_set_from_icon_name( + GTK_IMAGE(download->icon), "network-idle-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + } + + // TODO: Send notification +} + +void +downloadCb_received_data(WebKitDownload *webkit_download, guint64 data_lenght, gpointer user_data) +{ + (void)data_lenght; + struct Download *download = (struct Download *)user_data; + char formatted[BUFSIZ]; + int total = (int)webkit_download_get_elapsed_time(webkit_download); + + gchar *format_size = g_format_size(webkit_download_get_received_data_length(webkit_download)); + + download_format_elapsed(formatted, sizeof(formatted), _("%02i:%02i:%02i Downloading…"), total); + + gtk_image_set_from_icon_name( + GTK_IMAGE(download->icon), "network-receive-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_label_set_text(GTK_LABEL(download->status), formatted); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(download->progress), + webkit_download_get_estimated_progress(webkit_download)); + gtk_progress_bar_set_text(GTK_PROGRESS_BAR(download->progress), format_size); + + g_free(format_size); +} + +GtkWidget * +badwolf_downloads_tab_new() +{ + return gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); +} + +void +badwolf_downloads_tab_attach(struct Window *window) +{ + gtk_notebook_insert_page(GTK_NOTEBOOK(window->notebook), window->downloads_tab, NULL, 0); + gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(window->notebook), window->downloads_tab, TRUE); + + GtkWidget *tab_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_set_name(tab_box, "browser__tabbox"); + GtkWidget *icon = gtk_image_new_from_icon_name("emblem-downloads", GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_widget_set_name(icon, "browser__tabbox__icon"); + GtkWidget *label = gtk_label_new(_("Badwolf Downloads")); + gtk_widget_set_name(label, "browser__tabbox__label"); + +#ifdef BADWOLF_TAB_BOX_WIDTH + gtk_widget_set_size_request(label, BADWOLF_TAB_BOX_WIDTH, -1); +#endif +#ifdef BADWOLF_TAB_LABEL_CHARWIDTH + gtk_label_set_width_chars(GTK_LABEL(label), BADWOLF_TAB_LABEL_CHARWIDTH); +#endif + gtk_widget_set_hexpand(tab_box, BADWOLF_TAB_HEXPAND); + + gtk_label_set_ellipsize(GTK_LABEL(label), BADWOLF_TAB_LABEL_ELLIPSIZE); + gtk_label_set_single_line_mode(GTK_LABEL(label), TRUE); + + gtk_box_pack_start(GTK_BOX(tab_box), icon, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(tab_box), label, TRUE, TRUE, 0); + + gtk_widget_set_tooltip_text(tab_box, _("Badwolf Downloads")); + gtk_notebook_set_tab_label(GTK_NOTEBOOK(window->notebook), window->downloads_tab, tab_box); + gtk_notebook_set_menu_label_text( + GTK_NOTEBOOK(window->notebook), window->downloads_tab, _("Badwolf Downloads")); + + gtk_widget_show_all(tab_box); +} diff --git a/downloads.h b/downloads.h @@ -0,0 +1,28 @@ +#include "badwolf.h" + +#include <gtk/gtk.h> + +struct Download +{ + struct Window *window; + + GtkWidget *container; + GtkWidget *icon; + GtkWidget *stop_icon; + GtkWidget *file_path; + GtkWidget *progress; + GtkWidget *status; + GError *error; +}; + +void download_new_entry(WebKitDownload *webkit_download, struct Download *download); +void +downloadCb_created_destination(WebKitDownload *download, gchar *destination, gpointer user_data); +gboolean downloadCb_decide_destination(WebKitDownload *download, + gchar *suggested_filename, + gpointer user_data); +void downloadCb_failed(WebKitDownload *webkit_download, GError *error, gpointer user_data); +void downloadCb_finished(WebKitDownload *download, gpointer user_data); +void downloadCb_received_data(WebKitDownload *download, guint64 data_lenght, gpointer user_data); +GtkWidget *badwolf_downloads_tab_new(); +void badwolf_downloads_tab_attach(struct Window *window); diff --git a/icons/hicolor/128x128/apps/badwolf.png b/icons/hicolor/128x128/apps/badwolf.png Binary files differ. diff --git a/icons/hicolor/24x24/apps/badwolf.png b/icons/hicolor/24x24/apps/badwolf.png Binary files differ. diff --git a/icons/hicolor/256x256/apps/badwolf.png b/icons/hicolor/256x256/apps/badwolf.png Binary files differ. diff --git a/icons/hicolor/32x32/apps/badwolf.png b/icons/hicolor/32x32/apps/badwolf.png Binary files differ. diff --git a/icons/hicolor/48x48/apps/badwolf.png b/icons/hicolor/48x48/apps/badwolf.png Binary files differ. diff --git a/icons/hicolor/64x64/apps/badwolf.png b/icons/hicolor/64x64/apps/badwolf.png Binary files differ. diff --git a/icons/hicolor/scalable/apps/badwolf.svg b/icons/hicolor/scalable/apps/badwolf.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="64" height="64" version="1.1" viewBox="0 0 16.933 16.933" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><clipPath id="clippy"><rect width="16.933" height="16.933" ry="1"/></clipPath><radialGradient id="b" cx="8.6972" cy="-4.2398" r="8.4667" gradientTransform="matrix(-2.612 .056083 -.038123 -1.7755 30.491 -9.1064)" gradientUnits="userSpaceOnUse"><stop stop-color="#139e7c" offset="0"/><stop stop-color="#122548" offset="1"/></radialGradient><linearGradient id="linearGradient846" x1="-10.467" x2="-10.736" y1="4.7058" y2="4.7058" gradientUnits="userSpaceOnUse"><stop offset="0"/><stop stop-opacity="0" offset="1"/></linearGradient><linearGradient id="linearGradient874" x1="7.4633" x2="6.7959" y1="8.9935" y2="11.681" gradientUnits="userSpaceOnUse"><stop stop-color="#00ffd6" offset="0"/><stop stop-color="#007f64" offset="1"/></linearGradient></defs><g clip-path="url(#clippy)"><rect width="16.933" height="16.933" ry="0" fill="url(#b)"/><path d="m21.868-1.992a13.402 8.1853 0 0 1-6.7132 7.0929 13.402 8.1853 0 0 1-13.414-0.012891 13.402 8.1853 0 0 1-6.6767-7.1058l13.402 0.025759z" fill="url(#linearGradient846)" stroke="#23e0b7" stroke-width=".50271"/><path d="m5.9543 19.118c0.32505-2.6594 0.93668-3.1497-0.16577-5.2442-0.59266-1.049-2.2826-2.3153-3.1406-3.3342-0.48055-0.7492-1.6045-1.3225-2.2864-2.7903-0.15968-0.98447 2.224 1.2239 2.8948 1.1873 0.25739-0.2849-1.6007-2.177-1.4286-2.8633 0.14314-0.57062 0.21225-1.138 0.78124-1.5697 1.1973-0.3312 3.3913 2.8127 4.9273 3.2604 2.1106-0.72487 3.1742 1.4901 4.8202 1.8301 1.3227 0.15657 3.2074 1.5937 4.2524 2.9708-0.84502 0.59047-3.0445-0.7063-4.4104-0.10811-0.53812 0.82524 1.0996 5.2192 1.3863 5.7331" fill="#120d09" fill-rule="evenodd" stroke="url(#linearGradient874)" stroke-width=".67495" style="mix-blend-mode:luminosity"/></g></svg> diff --git a/icons_size.sh b/icons_size.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# Transforms an icon size from the Icon Theme Specification to rsvg-convert(1) options +#sed -r -e 's;^([^x]*)x([^@]*)$;-w \1 -h \2;' -e 's;^([^x]*)x([^@]*)@(.*)$;-w \1 -h \2 -z \3;' +sed -r 's;^([^x]*)x([^@]*)$;-w \1 -h \2;' diff --git a/interface.css b/interface.css @@ -0,0 +1,2 @@ +#browser__location, #browser__statuslabel { font-family: monospace; } +button:checked label { font-weight: bold; } diff --git a/interface.txt b/interface.txt @@ -0,0 +1,43 @@ +# Badwolf +- A tablist with a new tab button at the end, right-clicking on the tablist gives you the list in a context-menu format +- Each tab contains a Browser View or the Downloads View + +## Tab Labels +- An icon to indicate if a media is playing +- The title of the web view +- A close button + +## Browser View + +The Browser View contains the following items: +- Toolbar +- WebKit WebView +- Status Bar + +### Toolbar +- Backward navigation button followed by a smaller forward navigation button +- Separator +- Javascript-markup toggler marked "JS" followed by an image-loading toggler marked "IMG" +- Potentially some future elements +- Location entry linked to the WebKit WebView, with integrated progress indication also linked to the WebKit WebView +- Potentially some future elements +- Print button +- Potentially some future elements + +The element focused by default is the location entry. + +### Status bar +- Search entry linked to the WebKit WebView +- Potentially some future elements +- Label showing where the mouse is pointing +- Potentially some future elements + +## Downloads View + +The download view is a table contains the following items on each row corresponding to each download: +- Icon linked to the network status +- Progress bar, with integrated received-size indication +- (when downloading) Cancelling button +- Label about the current status +- Link to download destination +- Potentially some future elements diff --git a/keybindings.c b/keybindings.c @@ -46,6 +46,7 @@ badwolf_about_dialog(GtkWindow *main_window, gpointer user_data) gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about_dialog), homepage); gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about_dialog), comments); gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about_dialog), version); + gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(about_dialog), "badwolf"); g_signal_connect(about_dialog, "activate-link", G_CALLBACK(about_dialogCb_activate_link), window); @@ -99,6 +100,10 @@ commonCb_key_press_event(struct Window *window, GdkEvent *event, struct Client * case GDK_KEY_0: webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(browser->webView), 1); return TRUE; + case GDK_KEY_p: + webkit_print_operation_run_dialog(webkit_print_operation_new(browser->webView), + GTK_WINDOW(browser->window)); + return TRUE; } } else @@ -135,6 +140,7 @@ commonCb_key_press_event(struct Window *window, GdkEvent *event, struct Client * switch(((GdkEventKey *)event)->keyval) { case GDK_KEY_F5: webkit_web_view_reload(browser->webView); return TRUE; + case GDK_KEY_Escape: webkit_web_view_stop_loading(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)); diff --git a/po/fr.po b/po/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Badwolf 0.3.0+gd88f2e7\n" "Report-Msgid-Bugs-To: contact+badwolf-msgid@hacktivis.me\n" -"POT-Creation-Date: 2020-02-09 19:39+0100\n" +"POT-Creation-Date: 2020-05-15 06:00+0200\n" "PO-Revision-Date: 2019-12-22 00:57+0100\n" "Last-Translator: Haelwenn (lanodan) Monnier <contact@hacktivis.me>\n" "Language-Team: French\n" @@ -17,16 +17,40 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: badwolf.c:764 +#: downloads.c:117 +#, fuzzy, c-format +msgid "%02i:%02i:%02i Download cancelled" +msgstr "%02i:%02i:%02i Téléchargement annulé" + +#: downloads.c:119 +#, fuzzy, c-format +msgid "%02i:%02i:%02i Download error" +msgstr "%02i:%02i:%02i Erreur du téléchargement" + +#: downloads.c:141 +#, fuzzy, c-format +msgid "%02i:%02i:%02i Download finished" +msgstr "%02i:%02i:%02i Téléchargement finit" + +#: downloads.c:167 +#, c-format +msgid "%02i:%02i:%02i Downloading…" +msgstr "%02i:%02i:%02i Téléchargement en cours…" + +#: downloads.c:195 downloads.c:212 downloads.c:215 +msgid "Badwolf Downloads" +msgstr "Téléchargements Badwolf" + +#: badwolf.c:861 #, c-format msgid "Buildtime WebKit version: %d.%d.%d\n" msgstr "Version WebKit à la compilation: %d.%d.%d\n" -#: badwolf.c:384 +#: badwolf.c:391 msgid "Continue" msgstr "Continuer" -#: badwolf.c:334 +#: badwolf.c:341 msgid "" "Couldn't verify the TLS certificate to ensure a better security of the " "connection. You might want to verify your machine and network.\n" @@ -37,109 +61,127 @@ msgstr "" "et son réseau.\n" "\n" -#: badwolf.c:95 +#: badwolf.c:98 msgid "Crashed" msgstr "Crash" -#: badwolf.c:357 +#: downloads.c:39 +msgid "Download starting…" +msgstr "Démarrage du téléchargement" + +#: badwolf.c:364 msgid "Error: Some unknown error occurred validating the certificate.\n" msgstr "" "Erreur : Une erreur inconnue est apparue pendant la validation du " "certificat.\n" -#: badwolf.c:338 +#: badwolf.c:345 msgid "Error: The X509 Certificate Authority is unknown.\n" msgstr "Erreur : L'autorité de certification (CA X509) est inconnue.\n" -#: badwolf.c:351 +#: badwolf.c:358 msgid "Error: The certificate has been revoked.\n" msgstr "Erreur : Le certificat à été révoqué.\n" -#: badwolf.c:348 +#: badwolf.c:355 msgid "Error: The certificate has expired. Check your system's clock.\n" msgstr "Erreur : Le certificat a expiré.\n" -#: badwolf.c:354 +#: badwolf.c:361 msgid "Error: The certificate is considered to be insecure.\n" msgstr "Erreur : Le certificat est considéré comme non-sécurisé.\n" -#: badwolf.c:345 +#: badwolf.c:352 msgid "Error: The certificate isn't valid yet. Check your system's clock.\n" msgstr "Erreur : Le certificat n'est pas encore valide.\n" -#: badwolf.c:341 +#: badwolf.c:348 msgid "Error: The given identity doesn't match the expected one.\n" msgstr "Erreur : L'identité ne correspond pas à celle attendue.\n" -#: keybindings.c:33 +#: keybindings.c:32 #, c-format msgid "" "Minimalist and privacy-oriented WebKitGTK+ browser\n" "Runtime WebKit version: %d.%d.%d" -msgstr "Navigateur WebKitGTK+ minimaliste et orienté vie privée\n" +msgstr "" +"Navigateur WebKitGTK+ minimaliste et orienté vie privée\n" "Version WebKit au lancement: %d.%d.%d" -#: badwolf.c:686 +#: badwolf.c:790 msgid "New tab" msgstr "Nouvel onglet" -#: badwolf.c:786 +#: badwolf.c:910 msgid "Open new tab" msgstr "Ouvrir un nouvel onglet" -#: badwolf.c:99 +#: badwolf.c:102 msgid "Out of Memory" msgstr "Dépassement Mémoire" -#: badwolf.c:762 +#: badwolf.c:859 #, c-format msgid "Running Badwolf version: %s\n" msgstr "Version de Badwolf: %s\n" -#: badwolf.c:769 +#: badwolf.c:866 #, c-format msgid "Runtime WebKit version: %d.%d.%d\n" msgstr "Version WebKit au lancement: %d.%d.%d\n" -#: badwolf.c:381 +#: badwolf.c:388 #, c-format msgid "TLS Error for %s." msgstr "Erreur TLS pour %s." -#: badwolf.c:384 -msgid "Temporarly Add Exception" +#: badwolf.c:391 +#, fuzzy +msgid "Temporarily Add Exception" msgstr "Ajouter Temporairement une Exception" -#: badwolf.c:571 +#: badwolf.c:588 msgid "Toggle javascript" msgstr "Activer/Désactiver javascript" -#: badwolf.c:103 +#: badwolf.c:593 +msgid "Toggle loading images automatically" +msgstr "" + +#: badwolf.c:106 msgid "Unknown Crash" msgstr "Crash inconnu" -#: badwolf.c:612 +#: badwolf.c:591 +msgid "_IMG" +msgstr "_IMG" + +#: badwolf.c:586 +msgid "_JS" +msgstr "_JS" + +#: badwolf.c:706 msgid "search in current page" msgstr "recherche dans la page courante" -#: badwolf.c:94 +#: badwolf.c:97 msgid "the web process crashed.\n" msgstr "le processus web a cessé de fonctionner.\n" -#: badwolf.c:98 +#: badwolf.c:101 msgid "the web process exceeded the memory limit.\n" msgstr "le processus web a dépassé la limitation de mémoire.\n" -#: badwolf.c:102 +#: badwolf.c:105 msgid "the web process terminated for an unknown reason.\n" msgstr "le processus web s’est interrompu pour une raison inconnue.\n" -#: badwolf.c:776 +#: badwolf.c:873 #, c-format msgid "webkit-web-extension directory set to: %s\n" msgstr "Répertoire webkit-web-extension configuré à %s\n" #. TRANSLATOR Ignore this entry. Done for forcing Unicode in xgettext. -#: badwolf.c:815 +#: badwolf.c:944 msgid "ø" msgstr "" diff --git a/po/messages.pot b/po/messages.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Badwolf 0.5.0+gcba1cf3\n" +"Project-Id-Version: Badwolf 0.5.1+gf25fc89.HEAD\n" "Report-Msgid-Bugs-To: contact+badwolf-msgid@hacktivis.me\n" -"POT-Creation-Date: 2020-03-11 16:00+0100\n" +"POT-Creation-Date: 2020-05-18 04:14+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,51 +17,79 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: badwolf.c:764 +#: downloads.c:117 +#, c-format +msgid "%02i:%02i:%02i Download cancelled" +msgstr "" + +#: downloads.c:119 +#, c-format +msgid "%02i:%02i:%02i Download error" +msgstr "" + +#: downloads.c:141 +#, c-format +msgid "%02i:%02i:%02i Download finished" +msgstr "" + +#: downloads.c:167 +#, c-format +msgid "%02i:%02i:%02i Downloading…" +msgstr "" + +#: downloads.c:195 downloads.c:212 downloads.c:215 +msgid "Badwolf Downloads" +msgstr "" + +#: badwolf.c:910 #, c-format msgid "Buildtime WebKit version: %d.%d.%d\n" msgstr "" -#: badwolf.c:384 +#: badwolf.c:403 msgid "Continue" msgstr "" -#: badwolf.c:334 +#: badwolf.c:353 msgid "" "Couldn't verify the TLS certificate to ensure a better security of the " "connection. You might want to verify your machine and network.\n" "\n" msgstr "" -#: badwolf.c:95 +#: badwolf.c:99 msgid "Crashed" msgstr "" -#: badwolf.c:357 +#: downloads.c:39 +msgid "Download starting…" +msgstr "" + +#: badwolf.c:376 msgid "Error: Some unknown error occurred validating the certificate.\n" msgstr "" -#: badwolf.c:338 +#: badwolf.c:357 msgid "Error: The X509 Certificate Authority is unknown.\n" msgstr "" -#: badwolf.c:351 +#: badwolf.c:370 msgid "Error: The certificate has been revoked.\n" msgstr "" -#: badwolf.c:348 +#: badwolf.c:367 msgid "Error: The certificate has expired. Check your system's clock.\n" msgstr "" -#: badwolf.c:354 +#: badwolf.c:373 msgid "Error: The certificate is considered to be insecure.\n" msgstr "" -#: badwolf.c:345 +#: badwolf.c:364 msgid "Error: The certificate isn't valid yet. Check your system's clock.\n" msgstr "" -#: badwolf.c:341 +#: badwolf.c:360 msgid "Error: The given identity doesn't match the expected one.\n" msgstr "" @@ -72,67 +100,79 @@ msgid "" "Runtime WebKit version: %d.%d.%d" msgstr "" -#: badwolf.c:686 +#: badwolf.c:839 msgid "New tab" msgstr "" -#: badwolf.c:786 +#: badwolf.c:959 msgid "Open new tab" msgstr "" -#: badwolf.c:99 +#: badwolf.c:103 msgid "Out of Memory" msgstr "" -#: badwolf.c:762 +#: badwolf.c:908 #, c-format msgid "Running Badwolf version: %s\n" msgstr "" -#: badwolf.c:769 +#: badwolf.c:915 #, c-format msgid "Runtime WebKit version: %d.%d.%d\n" msgstr "" -#: badwolf.c:381 +#: badwolf.c:400 #, c-format msgid "TLS Error for %s." msgstr "" -#: badwolf.c:384 -msgid "Temporarly Add Exception" +#: badwolf.c:403 +msgid "Temporarily Add Exception" msgstr "" -#: badwolf.c:571 +#: badwolf.c:610 msgid "Toggle javascript" msgstr "" -#: badwolf.c:103 +#: badwolf.c:615 +msgid "Toggle loading images automatically" +msgstr "" + +#: badwolf.c:107 msgid "Unknown Crash" msgstr "" -#: badwolf.c:612 +#: badwolf.c:613 +msgid "_IMG" +msgstr "" + +#: badwolf.c:608 +msgid "_JS" +msgstr "" + +#: badwolf.c:728 msgid "search in current page" msgstr "" -#: badwolf.c:94 +#: badwolf.c:98 msgid "the web process crashed.\n" msgstr "" -#: badwolf.c:98 +#: badwolf.c:102 msgid "the web process exceeded the memory limit.\n" msgstr "" -#: badwolf.c:102 +#: badwolf.c:106 msgid "the web process terminated for an unknown reason.\n" msgstr "" -#: badwolf.c:776 +#: badwolf.c:922 #, c-format msgid "webkit-web-extension directory set to: %s\n" msgstr "" #. TRANSLATOR Ignore this entry. Done for forcing Unicode in xgettext. -#: badwolf.c:815 +#: badwolf.c:993 msgid "ø" msgstr "" diff --git a/po/pt_BR.po b/po/pt_BR.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Badwolf 0.4.0+g607300e\n" "Report-Msgid-Bugs-To: contact+badwolf-msgid@hacktivis.me\n" -"POT-Creation-Date: 2020-02-04 07:54+0100\n" -"PO-Revision-Date: 2020-01-20 22:17-0300\n" +"POT-Creation-Date: 2020-05-18 03:06+0200\n" +"PO-Revision-Date: 2020-05-17 20:18-0300\n" "Last-Translator: Pedro Lucas Porcellis <porcellis@eletrotupi.com>\n" "Language-Team: Brazilian Portuguese\n" "Language: pt_BR\n" @@ -16,16 +16,40 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: badwolf.c:764 +#: downloads.c:117 +#, c-format +msgid "%02i:%02i:%02i Download cancelled" +msgstr "%02i:%02i:%02i Transferência Cancelada" + +#: downloads.c:119 +#, c-format +msgid "%02i:%02i:%02i Download error" +msgstr "%02i:%02i:%02i Erro durante a transferência" + +#: downloads.c:141 +#, c-format +msgid "%02i:%02i:%02i Download finished" +msgstr "%02i:%02i:%02i Transferência Concluída" + +#: downloads.c:167 +#, c-format +msgid "%02i:%02i:%02i Downloading…" +msgstr "%02i:%02i:%02i Baixando…" + +#: downloads.c:195 downloads.c:212 downloads.c:215 +msgid "Badwolf Downloads" +msgstr "Transferências do Badwolf" + +#: badwolf.c:874 #, c-format msgid "Buildtime WebKit version: %d.%d.%d\n" msgstr "Versão do WebKit %d.%d.%d\n" -#: badwolf.c:384 +#: badwolf.c:403 msgid "Continue" msgstr "Continuar" -#: badwolf.c:334 +#: badwolf.c:353 msgid "" "Couldn't verify the TLS certificate to ensure a better security of the " "connection. You might want to verify your machine and network.\n" @@ -35,121 +59,127 @@ msgstr "" "segurança da conexão. Talvez você deva verificar a sua máquina e rede.\n" "\n" -#: badwolf.c:95 -#, fuzzy +#: badwolf.c:99 msgid "Crashed" msgstr "Erro" -#: badwolf.c:357 +#: downloads.c:39 +msgid "Download starting…" +msgstr "Transferência Iniciada…" + +#: badwolf.c:376 msgid "Error: Some unknown error occurred validating the certificate.\n" msgstr "" "Erro: Algum erro desconhecido ocorreu enquanto validava o certificado.\n" -#: badwolf.c:338 +#: badwolf.c:357 msgid "Error: The X509 Certificate Authority is unknown.\n" msgstr "Erro: A Autoridade de Certificados X509 é desconhecida.\n" -#: badwolf.c:351 +#: badwolf.c:370 msgid "Error: The certificate has been revoked.\n" msgstr "Erro: O certificado foi revogado.\n" -#: badwolf.c:348 +#: badwolf.c:367 msgid "Error: The certificate has expired. Check your system's clock.\n" msgstr "" "Erro: O certificado foi expirado. Verifique o relógio do seu sistema.\n" -#: badwolf.c:354 +#: badwolf.c:373 msgid "Error: The certificate is considered to be insecure.\n" msgstr "Erro: O certificado é considerado inseguro.\n" -#: badwolf.c:345 +#: badwolf.c:364 msgid "Error: The certificate isn't valid yet. Check your system's clock.\n" msgstr "" "Erro: O certificado não é válido ainda. Verifique o relógio do seu sistema.\n" -#: badwolf.c:341 +#: badwolf.c:360 msgid "Error: The given identity doesn't match the expected one.\n" msgstr "Erro: A identidade não confere com a esperada.\n" -#: keybindings.c:39 -msgid "Minimalist and privacy-oriented WebKitGTK+ browser" -msgstr "Navegador orientado pela privacidade e minimalismo" +#: keybindings.c:32 +#, c-format +msgid "" +"Minimalist and privacy-oriented WebKitGTK+ browser\n" +"Runtime WebKit version: %d.%d.%d" +msgstr "" +"Navegador orientado pela privacidade e minimalismo\n" +"Versão do WebKit: %d.%d.%d" -#: badwolf.c:686 +#: badwolf.c:803 msgid "New tab" msgstr "Nova aba" -#: badwolf.c:786 +#: badwolf.c:923 msgid "Open new tab" msgstr "Abrir uma Nova aba" -#: badwolf.c:99 -#, fuzzy +#: badwolf.c:103 msgid "Out of Memory" msgstr "Sem memória" -#: badwolf.c:762 +#: badwolf.c:872 #, c-format msgid "Running Badwolf version: %s\n" msgstr "Rodando versão %s do Badwolf\n" -#: badwolf.c:769 +#: badwolf.c:879 #, c-format msgid "Runtime WebKit version: %d.%d.%d\n" msgstr "Versão do WebKit: %d.%d.%d\n" -#: badwolf.c:381 +#: badwolf.c:400 #, c-format msgid "TLS Error for %s." msgstr "Erro TLS para %s." -#: badwolf.c:384 -msgid "Temporarly Add Exception" -msgstr "Temporáriamente adicionar exceção" +#: badwolf.c:403 +msgid "Temporarily Add Exception" +msgstr "Adicionar exceção temporária" -#: badwolf.c:571 +#: badwolf.c:600 msgid "Toggle javascript" msgstr "Habilitar Javascript" -#: badwolf.c:103 -#, fuzzy +#: badwolf.c:605 +msgid "Toggle loading images automatically" +msgstr "Habilitar carregamento de imagens automático" + +#: badwolf.c:107 msgid "Unknown Crash" msgstr "Erro desconhecido" -#: badwolf.c:612 +#: badwolf.c:603 +msgid "_IMG" +msgstr "_IMG" + +#: badwolf.c:598 +msgid "_JS" +msgstr "_JS" + +#: badwolf.c:718 msgid "search in current page" msgstr "buscar na página atual" -#: badwolf.c:94 +#: badwolf.c:98 msgid "the web process crashed.\n" msgstr "o processo web travou.\n" -#: badwolf.c:98 +#: badwolf.c:102 msgid "the web process exceeded the memory limit.\n" msgstr "o processo web excedeu o limite de memória.\n" -#: badwolf.c:102 +#: badwolf.c:106 msgid "the web process terminated for an unknown reason.\n" msgstr "o processo web terminou por uma razão desconhecida.\n" -#: badwolf.c:95 -msgid "title|Crashed" -msgstr "Erro" - -#: badwolf.c:99 -msgid "title|Out of Memory" -msgstr "Sem memória" - -#: badwolf.c:103 -msgid "title|Unknown Crash" -msgstr "Erro desconhecido" - -#: badwolf.c:776 +#: badwolf.c:886 #, c-format msgid "webkit-web-extension directory set to: %s\n" msgstr "diretório de extensões configurado para: %s\n" #. TRANSLATOR Ignore this entry. Done for forcing Unicode in xgettext. -#: badwolf.c:815 +#: badwolf.c:957 msgid "ø" -msgstr "ø" +msgstr "" diff --git a/version.sh b/version.sh @@ -1,8 +1,9 @@ #!/bin/sh hash=$(git --git-dir="$(dirname $0)/.git" rev-parse --short HEAD 2>/dev/null) +branch=$(git --git-dir="$(dirname $0)/.git" rev-parse --abbrev-ref HEAD | sed -r 's/.*[^0-9A-Za-z-]([0-9A-Za-z-]*)$/\1/g') -if [ -n "$hash" ] +if [ -n "$hash" ] || [ -n "$branch" ] then - printf '+g%s' "$hash" + printf '+g%s.%s' "$hash" "$branch" fi echo