summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrien Plazas <kekun.plazas@laposte.net>2018-05-07 13:24:07 +0200
committerAdrien Plazas <kekun.plazas@laposte.net>2018-06-21 23:36:34 +0200
commit7941615d3ab4efd9b72528ee75f1dd09d7dacc2c (patch)
treeb96a7ec4b19b2c073eb51a07697a6c8fd466605a
parent8e75d98af7c4c8a36741dd26b8e361b1539a89b5 (diff)
downloadepiphany-7941615d3ab4efd9b72528ee75f1dd09d7dacc2c.tar.gz
Add EphyActionBarStart
This contains the elements at the beginning of the header bar and will be used to have both in the hader bar and in a new action bar in a factorized way.
-rw-r--r--po/POTFILES.in2
-rw-r--r--src/ephy-action-bar-start.c529
-rw-r--r--src/ephy-action-bar-start.h37
-rw-r--r--src/meson.build1
-rw-r--r--src/resources/epiphany.gresource.xml1
-rw-r--r--src/resources/gtk/action-bar-start.ui91
6 files changed, 661 insertions, 0 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1ee501cff..dc5756b24 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -38,6 +38,7 @@ src/bookmarks/ephy-bookmarks-manager.h
src/bookmarks/ephy-bookmarks-popover.c
src/clear-data-dialog.c
src/cookies-dialog.c
+src/ephy-action-bar-start.c
src/ephy-encoding-dialog.c
src/ephy-header-bar.c
src/ephy-history-dialog.c
@@ -51,6 +52,7 @@ src/passwords-dialog.c
src/popup-commands.c
src/prefs-dialog.c
src/profile-migrator/ephy-profile-migrator.c
+src/resources/gtk/action-bar-start.ui
src/resources/gtk/application-menu.ui
src/resources/gtk/bookmark-properties-grid.ui
src/resources/gtk/bookmarks-popover.ui
diff --git a/src/ephy-action-bar-start.c b/src/ephy-action-bar-start.c
new file mode 100644
index 000000000..2f544a76d
--- /dev/null
+++ b/src/ephy-action-bar-start.c
@@ -0,0 +1,529 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2018 Purism SPC
+ * Copyright © 2018 Adrien Plazas <kekun.plazas@laposte.net>
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ephy-action-bar-start.h"
+
+#include "ephy-embed.h"
+#include "ephy-embed-container.h"
+#include "ephy-embed-prefs.h"
+#include "ephy-embed-utils.h"
+#include "ephy-favicon-helpers.h"
+#include "ephy-settings.h"
+#include "ephy-shell.h"
+#include "ephy-window.h"
+
+/* Translators: tooltip for the refresh button */
+static const char *REFRESH_BUTTON_TOOLTIP = N_("Reload the current page");
+
+struct _EphyActionBarStart {
+ GtkBox parent_instance;
+
+ GtkWidget *navigation_box;
+ GtkWidget *navigation_back;
+ GtkWidget *navigation_forward;
+ GtkWidget *combined_stop_reload_button;
+ GtkWidget *combined_stop_reload_image;
+ GtkWidget *homepage_button;
+
+ guint navigation_buttons_menu_timeout;
+};
+
+G_DEFINE_TYPE (EphyActionBarStart, ephy_action_bar_start, GTK_TYPE_BOX)
+
+typedef enum {
+ EPHY_NAVIGATION_HISTORY_DIRECTION_BACK,
+ EPHY_NAVIGATION_HISTORY_DIRECTION_FORWARD
+} EphyNavigationHistoryDirection;
+
+typedef enum {
+ WEBKIT_HISTORY_BACKWARD,
+ WEBKIT_HISTORY_FORWARD
+} WebKitHistoryType;
+
+typedef struct {
+ GtkWidget *button;
+ EphyWindow *window;
+ EphyNavigationHistoryDirection direction;
+ GdkEventButton *event;
+} PopupData;
+
+#define MAX_LABEL_LENGTH 48
+#define HISTORY_ITEM_DATA_KEY "history-item-data-key"
+
+static gboolean
+item_enter_notify_event_cb (GtkWidget *widget,
+ GdkEvent *event,
+ EphyWebView *view)
+{
+ char *text;
+
+ text = g_object_get_data (G_OBJECT (widget), "link-message");
+ ephy_web_view_set_link_message (view, text);
+
+ return FALSE;
+}
+
+static gboolean
+item_leave_notify_event_cb (GtkWidget *widget,
+ GdkEvent *event,
+ EphyWebView *view)
+{
+ ephy_web_view_set_link_message (view, NULL);
+ return FALSE;
+}
+
+static void
+icon_loaded_cb (GObject *source,
+ GAsyncResult *result,
+ GtkWidget *image)
+{
+ WebKitFaviconDatabase *database = WEBKIT_FAVICON_DATABASE (source);
+ GdkPixbuf *favicon = NULL;
+ cairo_surface_t *icon_surface = webkit_favicon_database_get_favicon_finish (database, result, NULL);
+
+ if (icon_surface) {
+ favicon = ephy_pixbuf_get_from_surface_scaled (icon_surface, FAVICON_SIZE, FAVICON_SIZE);
+ cairo_surface_destroy (icon_surface);
+ }
+
+ if (favicon) {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (image), favicon);
+ gtk_widget_show (image);
+
+ g_object_unref (favicon);
+ }
+
+ g_object_unref (image);
+}
+
+static GtkWidget *
+new_history_menu_item (EphyWebView *view,
+ const char *origtext,
+ const char *address)
+{
+ GtkWidget *menu_item;
+ GtkWidget *box;
+ GtkWidget *image;
+ GtkWidget *label;
+ WebKitFaviconDatabase *database;
+ EphyEmbedShell *shell = ephy_embed_shell_get_default ();
+
+ g_assert (address != NULL && origtext != NULL);
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+ image = gtk_image_new ();
+ gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
+
+ label = gtk_label_new (origtext);
+ gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
+ gtk_label_set_max_width_chars (GTK_LABEL (label), MAX_LABEL_LENGTH);
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
+ gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 6);
+
+ menu_item = gtk_menu_item_new ();
+ gtk_container_add (GTK_CONTAINER (menu_item), box);
+
+ database = webkit_web_context_get_favicon_database (ephy_embed_shell_get_web_context (shell));
+ webkit_favicon_database_get_favicon (database, address,
+ NULL,
+ (GAsyncReadyCallback)icon_loaded_cb,
+ g_object_ref (image));
+
+ g_object_set_data_full (G_OBJECT (menu_item), "link-message", g_strdup (address), (GDestroyNotify)g_free);
+
+ g_signal_connect (menu_item, "enter-notify-event",
+ G_CALLBACK (item_enter_notify_event_cb), view);
+ g_signal_connect (menu_item, "leave-notify-event",
+ G_CALLBACK (item_leave_notify_event_cb), view);
+
+ gtk_widget_show_all (menu_item);
+
+ return menu_item;
+}
+
+static void
+middle_click_handle_on_history_menu_item (EphyEmbed *embed,
+ WebKitBackForwardListItem *item)
+{
+ EphyEmbed *new_embed = NULL;
+ const gchar *url;
+
+ new_embed = ephy_shell_new_tab (ephy_shell_get_default (),
+ EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (embed))),
+ embed,
+ 0);
+ g_assert (new_embed != NULL);
+
+ /* Load the new URL */
+ url = webkit_back_forward_list_item_get_original_uri (item);
+ ephy_web_view_load_url (ephy_embed_get_web_view (new_embed), url);
+}
+
+static gboolean
+navigation_menu_item_pressed_cb (GtkWidget *menuitem,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ EphyWindow *window = EPHY_WINDOW (user_data);
+ WebKitBackForwardListItem *item;
+ EphyEmbed *embed;
+
+ embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
+
+ item = (WebKitBackForwardListItem *)g_object_get_data (G_OBJECT (menuitem), HISTORY_ITEM_DATA_KEY);
+
+ if (((GdkEventButton *)event)->button == GDK_BUTTON_MIDDLE) {
+ middle_click_handle_on_history_menu_item (embed, item);
+ } else {
+ WebKitWebView *web_view;
+
+ web_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
+ webkit_web_view_go_to_back_forward_list_item (web_view, item);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static GList *
+construct_webkit_history_list (WebKitWebView *web_view,
+ WebKitHistoryType hist_type,
+ int limit)
+{
+ WebKitBackForwardList *back_forward_list;
+
+ back_forward_list = webkit_web_view_get_back_forward_list (web_view);
+ return hist_type == WEBKIT_HISTORY_FORWARD ?
+ g_list_reverse (webkit_back_forward_list_get_forward_list_with_limit (back_forward_list, limit)) :
+ webkit_back_forward_list_get_back_list_with_limit (back_forward_list, limit);
+}
+
+static GtkWidget *
+build_dropdown_menu (EphyWindow *window,
+ EphyNavigationHistoryDirection direction)
+{
+ GtkMenuShell *menu;
+ EphyEmbed *embed;
+ GList *list, *l;
+ WebKitWebView *web_view;
+
+ embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
+ g_assert (embed != NULL);
+
+ menu = GTK_MENU_SHELL (gtk_menu_new ());
+
+ web_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
+
+ if (direction == EPHY_NAVIGATION_HISTORY_DIRECTION_BACK)
+ list = construct_webkit_history_list (web_view,
+ WEBKIT_HISTORY_BACKWARD, 10);
+ else
+ list = construct_webkit_history_list (web_view,
+ WEBKIT_HISTORY_FORWARD, 10);
+
+ for (l = list; l != NULL; l = l->next) {
+ GtkWidget *item;
+ WebKitBackForwardListItem *hitem;
+ const char *uri;
+ char *title;
+
+ hitem = (WebKitBackForwardListItem *)l->data;
+ uri = webkit_back_forward_list_item_get_uri (hitem);
+ title = g_strdup (webkit_back_forward_list_item_get_title (hitem));
+
+ if (title == NULL || g_strstrip (title)[0] == '\0')
+ item = new_history_menu_item (EPHY_WEB_VIEW (web_view), uri, uri);
+ else
+ item = new_history_menu_item (EPHY_WEB_VIEW (web_view), title, uri);
+
+ g_free (title);
+
+ g_object_set_data_full (G_OBJECT (item), HISTORY_ITEM_DATA_KEY,
+ g_object_ref (hitem), g_object_unref);
+
+ g_signal_connect (item, "button-release-event",
+ G_CALLBACK (navigation_menu_item_pressed_cb), window);
+
+ gtk_menu_shell_append (menu, item);
+ gtk_widget_show_all (item);
+ }
+
+ g_list_free (list);
+
+ return GTK_WIDGET (menu);
+}
+
+static void
+popup_history_menu (GtkWidget *widget,
+ EphyWindow *window,
+ EphyNavigationHistoryDirection direction,
+ GdkEventButton *event)
+{
+ GtkWidget *menu;
+
+ menu = build_dropdown_menu (window, direction);
+ gtk_menu_popup_at_widget (GTK_MENU (menu),
+ widget,
+ GDK_GRAVITY_SOUTH_WEST,
+ GDK_GRAVITY_NORTH_WEST,
+ (GdkEvent *)event);
+}
+
+static gboolean
+menu_timeout_cb (PopupData *data)
+{
+ if (data != NULL && data->window)
+ popup_history_menu (data->button, data->window, data->direction, data->event);
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+navigation_button_press_event_cb (GtkButton *button,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (user_data);
+ EphyNavigationHistoryDirection direction;
+ const gchar *action_name;
+
+ action_name = gtk_actionable_get_action_name (GTK_ACTIONABLE (button));
+
+ direction = strstr (action_name, "back") ? EPHY_NAVIGATION_HISTORY_DIRECTION_BACK
+ : EPHY_NAVIGATION_HISTORY_DIRECTION_FORWARD;
+
+ if (((GdkEventButton *)event)->button == GDK_BUTTON_SECONDARY) {
+ popup_history_menu (GTK_WIDGET (button), EPHY_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (action_bar_start), EPHY_TYPE_WINDOW)),
+ direction, (GdkEventButton *)event);
+ } else {
+ PopupData *data;
+
+ data = g_new (PopupData, 1);
+ data->button = GTK_WIDGET (button);
+ data->window = EPHY_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (action_bar_start), EPHY_TYPE_WINDOW));
+ data->direction = direction;
+ data->event = (GdkEventButton *)event;
+
+ action_bar_start->navigation_buttons_menu_timeout = g_timeout_add_full (G_PRIORITY_DEFAULT, 500,
+ (GSourceFunc)menu_timeout_cb,
+ data,
+ (GDestroyNotify)g_free);
+ g_source_set_name_by_id (action_bar_start->navigation_buttons_menu_timeout, "[epiphany] menu_timeout_cb");
+ }
+
+ return FALSE;
+}
+
+static gboolean
+navigation_button_release_event_cb (GtkButton *button,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (user_data);
+ GActionGroup *action_group;
+ GAction *action;
+ EphyNavigationHistoryDirection direction;
+ const gchar *action_name;
+
+ if (action_bar_start->navigation_buttons_menu_timeout > 0) {
+ g_source_remove (action_bar_start->navigation_buttons_menu_timeout);
+ action_bar_start->navigation_buttons_menu_timeout = 0;
+ }
+
+ action_name = gtk_actionable_get_action_name (GTK_ACTIONABLE (button));
+ action_group = gtk_widget_get_action_group (gtk_widget_get_ancestor (GTK_WIDGET (action_bar_start), EPHY_TYPE_WINDOW), "toolbar");
+
+ direction = strcmp (action_name, "toolbar.navigation-back") == 0 ? EPHY_NAVIGATION_HISTORY_DIRECTION_BACK
+ : EPHY_NAVIGATION_HISTORY_DIRECTION_FORWARD;
+
+ switch (((GdkEventButton *)event)->button) {
+ case GDK_BUTTON_MIDDLE:
+ if (direction == EPHY_NAVIGATION_HISTORY_DIRECTION_BACK) {
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "navigation-back-new-tab");
+ g_action_activate (action, NULL);
+ } else if (direction == EPHY_NAVIGATION_HISTORY_DIRECTION_FORWARD) {
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "navigation-forward-new-tab");
+ g_action_activate (action, NULL);
+ }
+ break;
+ case GDK_BUTTON_SECONDARY:
+ popup_history_menu (GTK_WIDGET (button), EPHY_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (action_bar_start), EPHY_TYPE_WINDOW)),
+ direction, (GdkEventButton *)event);
+ break;
+ default:
+ break;
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+navigation_leave_notify_event_cb (GtkButton *button,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (user_data);
+
+ if (action_bar_start->navigation_buttons_menu_timeout > 0) {
+ g_source_remove (action_bar_start->navigation_buttons_menu_timeout);
+ action_bar_start->navigation_buttons_menu_timeout = 0;
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+homepage_url_changed (GSettings *settings,
+ const char *key,
+ GtkWidget *button)
+{
+ char *setting;
+ gboolean show_button;
+
+ setting = g_settings_get_string (settings, key);
+ show_button = setting && setting[0] && g_strcmp0 (setting, "about:blank") != 0;
+
+ gtk_widget_set_visible (button, show_button);
+ g_free (setting);
+}
+
+static void
+ephy_action_bar_start_dispose (GObject *object)
+{
+ EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (object);
+
+ if (action_bar_start->navigation_buttons_menu_timeout > 0) {
+ g_source_remove (action_bar_start->navigation_buttons_menu_timeout);
+ action_bar_start->navigation_buttons_menu_timeout = 0;
+ }
+
+ G_OBJECT_CLASS (ephy_action_bar_start_parent_class)->dispose (object);
+}
+
+static void
+ephy_action_bar_start_constructed (GObject *object)
+{
+ EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (object);
+ EphyEmbedShell *embed_shell;
+
+ gtk_widget_init_template (GTK_WIDGET (action_bar_start));
+
+ /* Back */
+ g_signal_connect (action_bar_start->navigation_back, "button-press-event",
+ G_CALLBACK (navigation_button_press_event_cb), action_bar_start);
+ g_signal_connect (action_bar_start->navigation_back, "button-release-event",
+ G_CALLBACK (navigation_button_release_event_cb), action_bar_start);
+ g_signal_connect (action_bar_start->navigation_back, "leave-notify-event",
+ G_CALLBACK (navigation_leave_notify_event_cb), action_bar_start);
+
+ /* Forward */
+ g_signal_connect (action_bar_start->navigation_forward, "button-press-event",
+ G_CALLBACK (navigation_button_press_event_cb), action_bar_start);
+ g_signal_connect (action_bar_start->navigation_forward, "button-release-event",
+ G_CALLBACK (navigation_button_release_event_cb), action_bar_start);
+ g_signal_connect (action_bar_start->navigation_forward, "leave-notify-event",
+ G_CALLBACK (navigation_leave_notify_event_cb), action_bar_start);
+
+ /* Combined_stop_reload */
+ gtk_widget_set_tooltip_text (action_bar_start->combined_stop_reload_button, _(REFRESH_BUTTON_TOOLTIP));
+
+ /* Homepage */
+ embed_shell = ephy_embed_shell_get_default ();
+ if (ephy_embed_shell_get_mode (embed_shell) != EPHY_EMBED_SHELL_MODE_APPLICATION) {
+ homepage_url_changed (EPHY_SETTINGS_MAIN, EPHY_PREFS_HOMEPAGE_URL, action_bar_start->homepage_button);
+ g_signal_connect (EPHY_SETTINGS_MAIN,
+ "changed::" EPHY_PREFS_HOMEPAGE_URL,
+ G_CALLBACK (homepage_url_changed),
+ action_bar_start->homepage_button);
+ }
+}
+
+static void
+ephy_action_bar_start_class_init (EphyActionBarStartClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->dispose = ephy_action_bar_start_dispose;
+ gobject_class->constructed = ephy_action_bar_start_constructed;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/epiphany/gtk/action-bar-start.ui");
+
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarStart,
+ navigation_box);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarStart,
+ navigation_back);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarStart,
+ navigation_forward);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarStart,
+ combined_stop_reload_button);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarStart,
+ combined_stop_reload_image);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarStart,
+ homepage_button);
+}
+
+static void
+ephy_action_bar_start_init (EphyActionBarStart *action_bar_start)
+{
+}
+
+EphyActionBarStart *
+ephy_action_bar_start_new (void)
+{
+ return g_object_new (EPHY_TYPE_ACTION_BAR_START,
+ NULL);
+}
+
+GtkWidget *
+ephy_action_bar_start_get_navigation_box (EphyActionBarStart *action_bar_start)
+{
+ return action_bar_start->navigation_box;
+}
+
+void
+ephy_action_bar_start_change_combined_stop_reload_state (EphyActionBarStart *action_bar_start,
+ gboolean loading)
+{
+ if (loading) {
+ gtk_image_set_from_icon_name (GTK_IMAGE (action_bar_start->combined_stop_reload_image),
+ "process-stop-symbolic",
+ GTK_ICON_SIZE_BUTTON);
+ /* Translators: tooltip for the stop button */
+ gtk_widget_set_tooltip_text (action_bar_start->combined_stop_reload_button,
+ _("Stop loading the current page"));
+ } else {
+ gtk_image_set_from_icon_name (GTK_IMAGE (action_bar_start->combined_stop_reload_image),
+ "view-refresh-symbolic",
+ GTK_ICON_SIZE_BUTTON);
+ gtk_widget_set_tooltip_text (action_bar_start->combined_stop_reload_button,
+ _(REFRESH_BUTTON_TOOLTIP));
+ }
+}
diff --git a/src/ephy-action-bar-start.h b/src/ephy-action-bar-start.h
new file mode 100644
index 000000000..e64b8178a
--- /dev/null
+++ b/src/ephy-action-bar-start.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2018 Purism SPC
+ * Copyright © 2018 Adrien Plazas <kekun.plazas@laposte.net>
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_ACTION_BAR_START (ephy_action_bar_start_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyActionBarStart, ephy_action_bar_start, EPHY, ACTION_BAR_START, GtkBox);
+
+EphyActionBarStart *ephy_action_bar_start_new (void);
+GtkWidget *ephy_action_bar_start_get_navigation_box (EphyActionBarStart *action_bar_start);
+void ephy_action_bar_start_change_combined_stop_reload_state (EphyActionBarStart *action_bar_start,
+ gboolean loading);
+
+G_END_DECLS
diff --git a/src/meson.build b/src/meson.build
index b0781a170..d560c91e5 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -21,6 +21,7 @@ libephymain_sources = [
'bookmarks/ephy-bookmarks-popover.c',
'clear-data-dialog.c',
'cookies-dialog.c',
+ 'ephy-action-bar-start.c',
'ephy-action-helper.c',
'ephy-completion-model.c',
'ephy-encoding-dialog.c',
diff --git a/src/resources/epiphany.gresource.xml b/src/resources/epiphany.gresource.xml
index 09f5d634d..fe6b6b36b 100644
--- a/src/resources/epiphany.gresource.xml
+++ b/src/resources/epiphany.gresource.xml
@@ -12,6 +12,7 @@
<file alias="page-templates/error.css" compressed="true">error.css</file>
<file alias="page-templates/error.html" compressed="true">error.html</file>
<file preprocess="xml-stripblanks" compressed="true">mime-types-permissions.xml</file>
+ <file preprocess="xml-stripblanks" compressed="true">gtk/action-bar-start.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/application-menu.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/bookmark-properties-grid.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/bookmark-row.ui</file>
diff --git a/src/resources/gtk/action-bar-start.ui b/src/resources/gtk/action-bar-start.ui
new file mode 100644
index 000000000..29866afed
--- /dev/null
+++ b/src/resources/gtk/action-bar-start.ui
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="EphyActionBarStart" parent="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox" id="navigation_box">
+ <property name="visible">True</property>
+ <property name="orientation">horizontal</property>
+ <property name="homogeneous">True</property>
+ <style>
+ <class name="raised"/>
+ <class name="linked"/>
+ </style>
+ <child>
+ <object class="GtkButton" id="navigation_back">
+ <property name="visible">True</property>
+ <property name="action-name">toolbar.navigation-back</property>
+ <property name="valign">center</property>
+ <!-- Translators: tooltip for the back button -->
+ <property name="tooltip_text" translatable="yes">Go back to the previous page</property>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="back_image">
+ <property name="visible">True</property>
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="navigation_forward">
+ <property name="visible">True</property>
+ <property name="action-name">toolbar.navigation-forward</property>
+ <property name="valign">center</property>
+ <!-- Translators: tooltip for the forward button -->
+ <property name="tooltip_text" translatable="yes">Go forward to the next page</property>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="forward_image">
+ <property name="visible">True</property>
+ <property name="icon-name">go-next-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="combined_stop_reload_button">
+ <property name="visible">True</property>
+ <property name="action-name">toolbar.combined-stop-reload</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="combined_stop_reload_image">
+ <property name="visible">True</property>
+ <property name="icon-name">view-refresh-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="homepage_button">
+ <property name="visible">True</property>
+ <property name="action-name">win.home</property>
+ <property name="valign">center</property>
+ <!-- Translators: tooltip for the secret homepage button -->
+ <property name="tooltip_text" translatable="yes">Go to your homepage</property>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="homepage_image">
+ <property name="visible">True</property>
+ <property name="icon-name">go-home-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>