[epiphany/wip/exalm/tabs: 4/5] Port to HdyTabView/HdyTabBar
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/wip/exalm/tabs: 4/5] Port to HdyTabView/HdyTabBar
- Date: Wed, 3 Feb 2021 14:14:34 +0000 (UTC)
commit 5323b0df9f42a5e9d58c2284ee736816ebfa8b4d
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Wed Jan 27 18:04:52 2021 +0500
Port to HdyTabView/HdyTabBar
Replace the aging GtkNotebook-based tabs with a new implementation.
HACKING.md | 2 +-
embed/ephy-embed-container.c | 11 +-
embed/ephy-embed-container.h | 6 +-
src/ephy-action-bar.c | 26 +-
src/ephy-action-bar.h | 3 -
src/ephy-desktop-utils.c | 4 +-
src/ephy-header-bar.c | 1 -
src/ephy-location-controller.c | 35 +-
src/ephy-notebook.c | 1122 ---------------------
src/ephy-notebook.h | 62 --
src/ephy-page-row.c | 163 +--
src/ephy-page-row.h | 10 +-
src/ephy-pages-popover.c | 187 ++--
src/ephy-pages-popover.h | 9 +-
src/ephy-pages-view.c | 164 +--
src/ephy-pages-view.h | 9 +-
src/ephy-session.c | 185 ++--
src/ephy-shell.c | 33 +-
src/ephy-shell.h | 4 +-
src/ephy-suggestion-model.c | 15 +-
src/ephy-tab-label.c | 461 ---------
src/ephy-tab-label.h | 41 -
src/ephy-tab-view.c | 652 ++++++++++++
src/ephy-tab-view.h | 84 ++
src/ephy-window.c | 712 ++++++-------
src/ephy-window.h | 6 +-
src/meson.build | 3 +-
src/resources/ephy-missing-favicon-symbolic.svg | 32 -
src/resources/epiphany.gresource.xml | 2 -
src/resources/gtk/page-row.ui | 1 +
src/resources/gtk/pages-popover.ui | 2 +-
src/resources/gtk/tab-label.ui | 90 --
src/resources/themes/_Adwaita-base.scss | 33 -
src/resources/themes/_Adwaita-colored-window.scss | 145 ++-
src/resources/themes/elementary.scss | 6 -
src/webextension/api/tabs.c | 10 +-
src/webextension/ephy-web-extension-manager.c | 35 +-
src/window-commands.c | 239 +----
src/window-commands.h | 12 -
tests/ephy-shell-test.c | 51 +-
40 files changed, 1584 insertions(+), 3084 deletions(-)
---
diff --git a/HACKING.md b/HACKING.md
index 038711d67..7dc2ba628 100644
--- a/HACKING.md
+++ b/HACKING.md
@@ -93,7 +93,7 @@ not `EphyShell`.
`EphyWindow` is a subclass of `GtkApplicationWindow`, which is a subclass of
`GtkWindow`. It's the window. You can have any number of windows open at a time.
`EphyWindow` contains (a) an `EphyHeaderBar` (subclass of `GtkHeaderBar`), and
-(b) an `EphyNotebook` (subclass of `GtkNotebook`). `EphyNotebook` contains one
+(b) an `EphyTabView` (contains a `HdyTabView`). `EphyTabView` contains one
or more tabs, and each tab is an `EphyEmbed`. That's worth repeating: an
`EphyEmbed` corresponds to one browser tab. Each `EphyEmbed` contains an
`EphyWebView` (subclass of `WebKitWebView`). This is the object that actually
diff --git a/embed/ephy-embed-container.c b/embed/ephy-embed-container.c
index cbd66e19e..edb86445f 100644
--- a/embed/ephy-embed-container.c
+++ b/embed/ephy-embed-container.c
@@ -43,18 +43,21 @@ ephy_embed_container_default_init (EphyEmbedContainerInterface *iface)
* ephy_embed_container_add_child:
* @container: an #EphyEmbedContainer
* @child: an #EphyEmbed
- * @position: the position in @container's
+ * @parent: (nullable): the parent #EphyEmbed, or %NULL
+ * @position: the position in @container if @parent is %NULL
* @set_active: whether to set @embed as the active child of @container
* after insertion
*
- * Inserts @child into @container.
+ * Inserts @child into @container. The new embed will be inserted after @parent,
+ * or at @position if it's %NULL.
*
* Return value: @child's new position inside @container.
**/
gint
ephy_embed_container_add_child (EphyEmbedContainer *container,
EphyEmbed *child,
- gint position,
+ EphyEmbed *parent,
+ int position,
gboolean set_active)
{
EphyEmbedContainerInterface *iface;
@@ -63,7 +66,7 @@ ephy_embed_container_add_child (EphyEmbedContainer *container,
g_assert (EPHY_IS_EMBED (child));
iface = EPHY_EMBED_CONTAINER_GET_IFACE (container);
- return iface->add_child (container, child, position, set_active);
+ return iface->add_child (container, child, parent, position, set_active);
}
/**
diff --git a/embed/ephy-embed-container.h b/embed/ephy-embed-container.h
index 18b8ee01a..86a573d3c 100644
--- a/embed/ephy-embed-container.h
+++ b/embed/ephy-embed-container.h
@@ -38,7 +38,8 @@ struct _EphyEmbedContainerInterface
gint (* add_child) (EphyEmbedContainer *container,
EphyEmbed *child,
- gint position,
+ EphyEmbed *parent,
+ int position,
gboolean set_active);
void (* set_active_child) (EphyEmbedContainer *container,
@@ -58,7 +59,8 @@ struct _EphyEmbedContainerInterface
gint ephy_embed_container_add_child (EphyEmbedContainer *container,
EphyEmbed *child,
- gint position,
+ EphyEmbed *parent,
+ int position,
gboolean set_active);
void ephy_embed_container_set_active_child (EphyEmbedContainer *container,
EphyEmbed *child);
diff --git a/src/ephy-action-bar.c b/src/ephy-action-bar.c
index 9404877fa..17fbfa481 100644
--- a/src/ephy-action-bar.c
+++ b/src/ephy-action-bar.c
@@ -21,9 +21,9 @@
#include "ephy-action-bar.h"
#include "ephy-pages-button.h"
-#include "ephy-pages-popover.h"
#include "ephy-settings.h"
#include "ephy-shell.h"
+#include "ephy-tab-view.h"
enum {
PROP_0,
@@ -41,7 +41,6 @@ struct _EphyActionBar {
EphyActionBarStart *action_bar_start;
EphyActionBarEnd *action_bar_end;
EphyPagesButton *pages_button;
- GtkNotebook *notebook;
EphyAdaptiveMode adaptive_mode;
gboolean can_reveal;
@@ -62,15 +61,6 @@ sync_chromes_visibility (EphyActionBar *action_bar)
chrome & EPHY_WINDOW_CHROME_BOOKMARKS);
}
-static void
-update_pages_button (EphyActionBar *action_bar)
-{
- int n_pages;
-
- n_pages = gtk_notebook_get_n_pages (action_bar->notebook);
- ephy_pages_button_set_n_pages (action_bar->pages_button, n_pages);
-}
-
static void
update_revealer (EphyActionBar *action_bar)
{
@@ -129,21 +119,19 @@ static void
ephy_action_bar_constructed (GObject *object)
{
EphyActionBar *action_bar = EPHY_ACTION_BAR (object);
+ EphyTabView *view;
G_OBJECT_CLASS (ephy_action_bar_parent_class)->constructed (object);
- action_bar->notebook = GTK_NOTEBOOK (ephy_window_get_notebook (action_bar->window));
- update_pages_button (action_bar);
+ view = ephy_window_get_tab_view (action_bar->window);
g_signal_connect_object (action_bar->window, "notify::chrome",
G_CALLBACK (sync_chromes_visibility), action_bar,
G_CONNECT_SWAPPED);
- g_signal_connect_object (action_bar->notebook, "page-added",
- G_CALLBACK (update_pages_button), action_bar,
- G_CONNECT_SWAPPED);
- g_signal_connect_object (action_bar->notebook, "page-removed",
- G_CALLBACK (update_pages_button), action_bar,
- G_CONNECT_SWAPPED);
+
+ g_object_bind_property (view, "n-pages",
+ action_bar->pages_button, "n-pages",
+ G_BINDING_SYNC_CREATE);
}
static void
diff --git a/src/ephy-action-bar.h b/src/ephy-action-bar.h
index da94137af..390e92007 100644
--- a/src/ephy-action-bar.h
+++ b/src/ephy-action-bar.h
@@ -26,7 +26,6 @@
#include "ephy-action-bar-end.h"
#include "ephy-action-bar-start.h"
#include "ephy-adaptive-mode.h"
-#include "ephy-notebook.h"
#include "ephy-window.h"
G_BEGIN_DECLS
@@ -38,8 +37,6 @@ G_DECLARE_FINAL_TYPE (EphyActionBar, ephy_action_bar, EPHY, ACTION_BAR, GtkRevea
EphyActionBar *ephy_action_bar_new (EphyWindow *window);
EphyActionBarStart *ephy_action_bar_get_action_bar_start (EphyActionBar *action_bar);
EphyActionBarEnd *ephy_action_bar_get_action_bar_end (EphyActionBar *action_bar);
-void ephy_action_bar_set_notebook (EphyActionBar *action_bar,
- EphyNotebook *notebook);
void ephy_action_bar_set_adaptive_mode (EphyActionBar *action_bar,
EphyAdaptiveMode adaptive_mode);
diff --git a/src/ephy-desktop-utils.c b/src/ephy-desktop-utils.c
index 008ed4d6c..5f52bb784 100644
--- a/src/ephy-desktop-utils.c
+++ b/src/ephy-desktop-utils.c
@@ -61,10 +61,10 @@ ephy_get_fallback_favicon_name (const char *uri,
{
if (uri) {
if (g_str_has_prefix (uri, "ephy-about:overview") || g_str_has_prefix (uri, "about:overview"))
- return "view-grid-symbolic";
+ return type == EPHY_FAVICON_TYPE_SHOW_MISSING_PLACEHOLDER ? "view-grid-symbolic" : NULL;
else if (g_str_has_prefix (uri, "ephy-about:") || g_str_has_prefix (uri, "about:"))
return "web-browser-symbolic";
}
- return type == EPHY_FAVICON_TYPE_SHOW_MISSING_PLACEHOLDER ? "ephy-missing-favicon-symbolic" : NULL;
+ return NULL;
}
diff --git a/src/ephy-header-bar.c b/src/ephy-header-bar.c
index 15569a365..104374628 100644
--- a/src/ephy-header-bar.c
+++ b/src/ephy-header-bar.c
@@ -29,7 +29,6 @@
#include "ephy-file-helpers.h"
#include "ephy-flatpak-utils.h"
#include "ephy-location-entry.h"
-#include "ephy-notebook.h"
#include "ephy-settings.h"
#include "ephy-shell.h"
#include "ephy-title-box.h"
diff --git a/src/ephy-location-controller.c b/src/ephy-location-controller.c
index 01175c445..cc2178ecc 100644
--- a/src/ephy-location-controller.c
+++ b/src/ephy-location-controller.c
@@ -147,15 +147,14 @@ entry_activate_cb (GtkEntry *entry,
return;
if (g_str_has_prefix (content, "ephy-tab://")) {
- GtkWidget *notebook = ephy_window_get_notebook (controller->window);
+ EphyTabView *tab_view = ephy_window_get_tab_view (controller->window);
GtkWidget *tab;
EphyWebView *webview;
- gint current = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
g_auto (GStrv) split = g_strsplit (content + strlen ("ephy-tab://"), "@", -1);
g_assert (g_strv_length (split) == 2);
- tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), current);
+ tab = ephy_tab_view_get_selected_page (tab_view);
webview = ephy_embed_get_web_view (EPHY_EMBED (tab));
if (atoi (split[1]) != 0) {
@@ -169,15 +168,15 @@ entry_activate_cb (GtkEntry *entry,
windows = gtk_application_get_windows (GTK_APPLICATION (application));
window = g_list_nth_data (windows, atoi (split[1]));
- notebook = ephy_window_get_notebook (window);
+ tab_view = ephy_window_get_tab_view (window);
gtk_window_present (GTK_WINDOW (window));
}
- gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), atoi (split[0]));
+ ephy_tab_view_select_nth_page (tab_view, atoi (split[0]));
if (ephy_web_view_is_overview (webview))
- g_signal_emit_by_name (GTK_NOTEBOOK (notebook), "tab-close-request", tab);
+ ephy_tab_view_close (tab_view, tab);
return;
}
@@ -295,10 +294,7 @@ focus_out_event_cb (GtkWidget *entry,
}
static void
-switch_page_cb (GtkNotebook *notebook,
- GtkWidget *page,
- guint page_num,
- EphyLocationController *controller)
+notify_selected_index_cb (EphyLocationController *controller)
{
if (controller->sync_address_is_blocked == TRUE) {
controller->sync_address_is_blocked = FALSE;
@@ -343,15 +339,17 @@ ephy_location_controller_constructed (GObject *object)
EphyHistoryService *history_service;
EphyBookmarksManager *bookmarks_manager;
EphySuggestionModel *model;
- GtkWidget *notebook, *widget, *reader_mode, *entry;
+ EphyTabView *tab_view;
+ GtkWidget *widget, *reader_mode, *entry;
G_OBJECT_CLASS (ephy_location_controller_parent_class)->constructed (object);
- notebook = ephy_window_get_notebook (controller->window);
+ tab_view = ephy_window_get_tab_view (controller->window);
widget = GTK_WIDGET (controller->title_widget);
- g_signal_connect (notebook, "switch-page",
- G_CALLBACK (switch_page_cb), controller);
+ g_signal_connect_object (tab_view, "notify::selected-index",
+ G_CALLBACK (notify_selected_index_cb), controller,
+ G_CONNECT_SWAPPED);
sync_address (controller, NULL, widget);
g_signal_connect_object (controller, "notify::address",
@@ -446,14 +444,9 @@ static void
ephy_location_controller_dispose (GObject *object)
{
EphyLocationController *controller = EPHY_LOCATION_CONTROLLER (object);
- GtkWidget *notebook;
- notebook = ephy_window_get_notebook (controller->window);
-
- if (notebook == NULL ||
- controller->title_widget == NULL) {
+ if (!controller->title_widget)
return;
- }
g_clear_object (&controller->longpress_gesture);
@@ -463,8 +456,6 @@ ephy_location_controller_dispose (GObject *object)
g_signal_handlers_disconnect_matched (controller->title_widget, G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL, controller);
}
- g_signal_handlers_disconnect_matched (notebook, G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, controller);
controller->title_widget = NULL;
G_OBJECT_CLASS (ephy_location_controller_parent_class)->dispose (object);
diff --git a/src/ephy-page-row.c b/src/ephy-page-row.c
index 5616ee093..8e8d694d3 100644
--- a/src/ephy-page-row.c
+++ b/src/ephy-page-row.c
@@ -22,16 +22,10 @@
#include "config.h"
#include "ephy-desktop-utils.h"
-#include "ephy-embed-utils.h"
+#include "ephy-embed.h"
#include "ephy-page-row.h"
#include "ephy-web-view.h"
-enum {
- CLOSED,
-
- LAST_SIGNAL
-};
-
struct _EphyPageRow {
GtkPopover parent_instance;
@@ -42,47 +36,17 @@ struct _EphyPageRow {
GtkSpinner *spinner;
GtkLabel *title;
GtkButton *close_button;
-};
-static guint signals[LAST_SIGNAL];
+ HdyTabPage *page;
+ EphyTabView *tab_view;
+};
G_DEFINE_TYPE (EphyPageRow, ephy_page_row, GTK_TYPE_LIST_BOX_ROW)
-static void
-sync_load_status (EphyWebView *view,
- GParamSpec *pspec,
- EphyPageRow *self)
-{
- EphyEmbed *embed;
-
- g_assert (EPHY_IS_WEB_VIEW (view));
- g_assert (EPHY_IS_PAGE_ROW (self));
-
- embed = EPHY_GET_EMBED_FROM_EPHY_WEB_VIEW (view);
-
- g_assert (EPHY_IS_EMBED (embed));
-
- if (ephy_web_view_is_loading (view) && !ephy_embed_has_load_pending (embed)) {
- gtk_stack_set_visible_child (self->icon_stack, GTK_WIDGET (self->spinner));
- gtk_spinner_start (GTK_SPINNER (self->spinner));
- } else {
- gtk_stack_set_visible_child (self->icon_stack, GTK_WIDGET (self->icon));
- gtk_spinner_stop (GTK_SPINNER (self->spinner));
- }
-}
-
-static void
-load_changed_cb (EphyWebView *view,
- WebKitLoadEvent load_event,
- EphyPageRow *self)
-{
- sync_load_status (view, NULL, self);
-}
-
static void
close_clicked_cb (EphyPageRow *self)
{
- g_signal_emit (self, signals[CLOSED], 0);
+ hdy_tab_view_close_page (ephy_tab_view_get_tab_view (self->tab_view), self->page);
}
static gboolean
@@ -93,7 +57,7 @@ button_release_event (GtkWidget *widget,
GdkEventButton *button_event = (GdkEventButton *)event;
if (button_event->button == GDK_BUTTON_MIDDLE) {
- g_signal_emit (self, signals[CLOSED], 0);
+ hdy_tab_view_close_page (ephy_tab_view_get_tab_view (self->tab_view), self->page);
return GDK_EVENT_STOP;
}
@@ -106,13 +70,6 @@ ephy_page_row_class_init (EphyPageRowClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- signals[CLOSED] =
- g_signal_new ("closed",
- EPHY_TYPE_PAGE_ROW,
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/epiphany/gtk/page-row.ui");
gtk_widget_class_bind_template_child (widget_class, EphyPageRow, box);
gtk_widget_class_bind_template_child (widget_class, EphyPageRow, icon);
@@ -131,52 +88,92 @@ ephy_page_row_init (EphyPageRow *self)
gtk_widget_init_template (GTK_WIDGET (self));
}
+static gboolean
+loading_to_visible_child (GBinding *binding,
+ const GValue *input,
+ GValue *output,
+ EphyPageRow *self)
+{
+ if (g_value_get_boolean (input))
+ g_value_set_object (output, self->spinner);
+ else
+ g_value_set_object (output, self->icon);
+
+ return TRUE;
+}
+
static void
-sync_favicon (EphyWebView *view,
- GParamSpec *pspec,
- EphyPageRow *self)
+update_icon_cb (EphyPageRow *self)
{
- GdkPixbuf *pixbuf = ephy_web_view_get_icon (view);
+ EphyEmbed *embed = EPHY_EMBED (hdy_tab_page_get_child (self->page));
+ EphyWebView *view = ephy_embed_get_web_view (embed);
+ GIcon *icon = G_ICON (ephy_web_view_get_icon (view));
+ const char *uri, *favicon_name;
+ HdyTabView *tab_view;
- if (pixbuf)
- gtk_image_set_from_gicon (GTK_IMAGE (self->icon), G_ICON (pixbuf), GTK_ICON_SIZE_MENU);
- else {
- const char *favicon_name = ephy_get_fallback_favicon_name (ephy_web_view_get_display_address (view),
EPHY_FAVICON_TYPE_SHOW_MISSING_PLACEHOLDER);
+ if (icon) {
+ gtk_image_set_from_gicon (self->icon, icon, GTK_ICON_SIZE_MENU);
- gtk_image_set_from_icon_name (GTK_IMAGE (self->icon), favicon_name, GTK_ICON_SIZE_MENU);
+ return;
}
+
+ uri = webkit_web_view_get_uri (WEBKIT_WEB_VIEW (view));
+ favicon_name = ephy_get_fallback_favicon_name (uri, EPHY_FAVICON_TYPE_SHOW_MISSING_PLACEHOLDER);
+
+ if (favicon_name) {
+ g_autoptr (GIcon) fallback_icon = g_themed_icon_new (favicon_name);
+
+ gtk_image_set_from_gicon (self->icon, fallback_icon, GTK_ICON_SIZE_MENU);
+
+ return;
+ }
+
+ tab_view = ephy_tab_view_get_tab_view (self->tab_view);
+
+ gtk_image_set_from_gicon (self->icon, hdy_tab_view_get_default_icon (tab_view), GTK_ICON_SIZE_MENU);
}
EphyPageRow *
-ephy_page_row_new (EphyNotebook *notebook,
- gint position)
+ephy_page_row_new (EphyTabView *tab_view,
+ HdyTabPage *page)
{
EphyPageRow *self;
- GtkWidget *embed;
- GtkWidget *tab_label;
+ GtkWidget *embed = hdy_tab_page_get_child (page);
EphyWebView *view;
- g_assert (notebook != NULL);
- g_assert (position >= 0);
-
- self = g_object_new (EPHY_TYPE_PAGE_ROW, NULL);
-
- embed = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), position);
-
+ g_assert (HDY_IS_TAB_PAGE (page));
g_assert (EPHY_IS_EMBED (embed));
- tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), embed);
view = ephy_embed_get_web_view (EPHY_EMBED (embed));
- sync_favicon (view, NULL, self);
- g_signal_connect_object (view, "notify::icon", G_CALLBACK (sync_favicon), self, 0);
- g_object_bind_property (embed, "title", self->title, "label", G_BINDING_SYNC_CREATE);
- g_object_bind_property (embed, "title", self->title, "tooltip-text", G_BINDING_SYNC_CREATE);
- g_object_bind_property (view, "is-playing-audio", self->speaker_icon, "visible", G_BINDING_SYNC_CREATE);
- g_object_bind_property (tab_label, "pinned", self->close_button, "visible", G_BINDING_SYNC_CREATE |
G_BINDING_INVERT_BOOLEAN);
- sync_load_status (view, NULL, self);
- g_signal_connect_object (view, "load-changed",
- G_CALLBACK (load_changed_cb), self, 0);
+ self = g_object_new (EPHY_TYPE_PAGE_ROW, NULL);
+ self->tab_view = tab_view;
+ self->page = page;
+
+ g_object_bind_property (page, "title",
+ self->title, "label",
+ G_BINDING_SYNC_CREATE);
+ g_object_bind_property (page, "indicator-icon",
+ self->speaker_icon, "gicon",
+ G_BINDING_SYNC_CREATE);
+ g_object_bind_property (page, "pinned",
+ self->close_button, "visible",
+ G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+ g_object_bind_property_full (page, "loading",
+ self->icon_stack, "visible-child",
+ G_BINDING_SYNC_CREATE,
+ (GBindingTransformFunc)loading_to_visible_child,
+ NULL,
+ self, NULL);
+
+ g_signal_connect_object (view, "notify::icon",
+ G_CALLBACK (update_icon_cb), self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (view, "notify::uri",
+ G_CALLBACK (update_icon_cb), self,
+ G_CONNECT_SWAPPED);
+
+ update_icon_cb (self);
return self;
}
@@ -202,3 +199,11 @@ ephy_page_row_set_adaptive_mode (EphyPageRow *self,
break;
}
}
+
+HdyTabPage *
+ephy_page_row_get_page (EphyPageRow *self)
+{
+ g_assert (EPHY_IS_PAGE_ROW (self));
+
+ return self->page;
+}
diff --git a/src/ephy-page-row.h b/src/ephy-page-row.h
index 337a7ba92..bff823af3 100644
--- a/src/ephy-page-row.h
+++ b/src/ephy-page-row.h
@@ -21,9 +21,9 @@
#pragma once
-#include <gtk/gtk.h>
+#include <handy.h>
#include "ephy-adaptive-mode.h"
-#include "ephy-notebook.h"
+#include "ephy-tab-view.h"
G_BEGIN_DECLS
@@ -31,10 +31,12 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (EphyPageRow, ephy_page_row, EPHY, PAGE_ROW, GtkListBoxRow)
-EphyPageRow *ephy_page_row_new (EphyNotebook *notebook,
- int position);
+EphyPageRow *ephy_page_row_new (EphyTabView *view,
+ HdyTabPage *page);
void ephy_page_row_set_adaptive_mode (EphyPageRow *self,
EphyAdaptiveMode adaptive_mode);
+HdyTabPage *ephy_page_row_get_page (EphyPageRow *self);
+
G_END_DECLS
diff --git a/src/ephy-pages-popover.c b/src/ephy-pages-popover.c
index 6cc8c477b..04c190e40 100644
--- a/src/ephy-pages-popover.c
+++ b/src/ephy-pages-popover.c
@@ -27,8 +27,8 @@
#include <gdk/gdkx.h>
#endif
-#include "ephy-notebook.h"
#include "ephy-page-row.h"
+#include "ephy-window.h"
struct _EphyPagesPopover {
GtkPopover parent_instance;
@@ -36,120 +36,79 @@ struct _EphyPagesPopover {
GtkListBox *list_box;
GtkScrolledWindow *scrolled_window;
- GListStore *list_store;
- EphyNotebook *notebook;
+ GListModel *model;
+ EphyTabView *tab_view;
};
G_DEFINE_TYPE (EphyPagesPopover, ephy_pages_popover, GTK_TYPE_POPOVER)
static void
-drop_notebook (EphyPagesPopover *self)
+drop_tab_view (EphyPagesPopover *self)
{
- self->notebook = NULL;
- g_list_store_remove_all (self->list_store);
+ self->tab_view = NULL;
}
static void
-release_notebook (EphyPagesPopover *self)
+release_tab_view (EphyPagesPopover *self)
{
- GMenu *pages_menu;
-
- if (self->notebook) {
- pages_menu = ephy_notebook_get_pages_menu (self->notebook);
- g_signal_handlers_disconnect_by_data (pages_menu, self);
- g_signal_handlers_disconnect_by_data (self->notebook, self);
-
- g_object_weak_unref (G_OBJECT (self->notebook), (GWeakNotify)drop_notebook, self);
- drop_notebook (self);
+ if (self->tab_view) {
+ g_object_weak_unref (G_OBJECT (self->tab_view), (GWeakNotify)drop_tab_view, self);
+ drop_tab_view (self);
}
}
-static GtkWidget *
-create_row (gpointer item,
- gpointer user_data)
-{
- return GTK_WIDGET (g_object_ref (G_OBJECT (item)));
-}
-
static void
-row_selected_cb (EphyPagesPopover *self,
- GtkListBoxRow *row)
+row_activated_cb (EphyPagesPopover *self,
+ EphyPageRow *row)
{
- gint current_page;
- gint new_page;
+ EphyWindow *window;
+ GApplication *application;
+ HdyTabPage *page;
g_assert (EPHY_IS_PAGES_POPOVER (self));
- g_assert (!row || GTK_IS_LIST_BOX_ROW (row));
-
- if (!row)
- return;
-
- current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (self->notebook));
- new_page = gtk_list_box_row_get_index (row);
- if (current_page == new_page)
- return;
+ g_assert (EPHY_IS_PAGE_ROW (row));
- gtk_notebook_set_current_page (GTK_NOTEBOOK (self->notebook), new_page);
-}
+ application = g_application_get_default ();
+ window = EPHY_WINDOW (gtk_application_get_active_window (GTK_APPLICATION (application)));
+ page = ephy_page_row_get_page (EPHY_PAGE_ROW (row));
-static void
-row_closed_cb (EphyPagesPopover *self,
- EphyPageRow *row)
-{
- g_assert (EPHY_IS_PAGES_POPOVER (self));
- g_assert (EPHY_IS_PAGE_ROW (row));
+ hdy_tab_view_set_selected_page (ephy_tab_view_get_tab_view (self->tab_view), page);
+ ephy_window_close_pages_view (window);
- gtk_notebook_remove_page (GTK_NOTEBOOK (self->notebook),
- gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row)));
+ gtk_popover_popdown (GTK_POPOVER (self));
}
-static void
-current_page_changed_cb (EphyPagesPopover *self)
+static GtkWidget *
+create_row (HdyTabPage *page,
+ EphyPagesPopover *self)
{
- GtkListBoxRow *current_row, *new_row;
- gint current_page;
+ EphyPageRow *row = ephy_page_row_new (self->tab_view, page);
- g_assert (EPHY_IS_PAGES_POPOVER (self));
+ ephy_page_row_set_adaptive_mode (row, EPHY_ADAPTIVE_MODE_NORMAL);
- current_row = gtk_list_box_get_selected_row (self->list_box);
- current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (self->notebook));
- if (current_row != NULL && gtk_list_box_row_get_index (current_row) == current_page)
- return;
+ gtk_widget_show (GTK_WIDGET (row));
- new_row = gtk_list_box_get_row_at_index (self->list_box, current_page);
- gtk_list_box_select_row (self->list_box, new_row);
+ return GTK_WIDGET (row);
}
static void
-items_changed_cb (EphyPagesPopover *self,
- gint position,
- gint removed,
- gint added,
- GMenuModel *menu_model)
+selected_page_changed_cb (HdyTabView *tab_view,
+ GParamSpec *pspec,
+ EphyPagesPopover *self)
{
- g_autofree EphyPageRow **items = g_new (EphyPageRow *, added);
+ HdyTabPage *page = hdy_tab_view_get_selected_page (tab_view);
+ gint position;
+ GtkListBoxRow *row;
- if ((guint)(position + removed) > g_list_model_get_n_items (G_LIST_MODEL (self->list_store)))
- return;
+ if (!page) {
+ gtk_list_box_unselect_all (self->list_box);
- for (int i = 0; i < added; i++) {
- items[i] = ephy_page_row_new (self->notebook, position + i);
- g_signal_connect_swapped (items[i], "closed", G_CALLBACK (row_closed_cb), self);
+ return;
}
- g_list_store_splice (self->list_store, position, removed, (gpointer)items, added);
-
- current_page_changed_cb (self);
-}
-
-static void
-ephy_pages_popover_finalize (GObject *object)
-{
- EphyPagesPopover *self = EPHY_PAGES_POPOVER (object);
-
- g_object_unref (self->list_store);
-
- G_OBJECT_CLASS (ephy_pages_popover_parent_class)->finalize (object);
+ position = hdy_tab_view_get_page_position (tab_view, page);
+ row = gtk_list_box_get_row_at_index (self->list_box, position);
+ gtk_list_box_select_row (self->list_box, row);
}
static void
@@ -157,7 +116,7 @@ ephy_pages_popover_dispose (GObject *object)
{
EphyPagesPopover *self = EPHY_PAGES_POPOVER (object);
- release_notebook (self);
+ release_tab_view (self);
G_OBJECT_CLASS (ephy_pages_popover_parent_class)->dispose (object);
}
@@ -175,7 +134,7 @@ ephy_pages_popover_get_preferred_height (GtkWidget *widget,
minimum_height,
natural_height);
/* Ensure that popover won't leave current window */
- height = gtk_widget_get_allocated_height (GTK_WIDGET (self->notebook));
+ height = gtk_widget_get_allocated_height (GTK_WIDGET (self->tab_view));
gtk_scrolled_window_set_max_content_height (self->scrolled_window, height);
}
@@ -193,7 +152,6 @@ ephy_pages_popover_class_init (EphyPagesPopoverClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = ephy_pages_popover_dispose;
- object_class->finalize = ephy_pages_popover_finalize;
#ifdef GDK_WINDOWING_X11
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) {
@@ -205,21 +163,13 @@ ephy_pages_popover_class_init (EphyPagesPopoverClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/epiphany/gtk/pages-popover.ui");
gtk_widget_class_bind_template_child (widget_class, EphyPagesPopover, list_box);
gtk_widget_class_bind_template_child (widget_class, EphyPagesPopover, scrolled_window);
- gtk_widget_class_bind_template_callback (widget_class, row_selected_cb);
+ gtk_widget_class_bind_template_callback (widget_class, row_activated_cb);
}
static void
ephy_pages_popover_init (EphyPagesPopover *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
-
- self->list_store = g_list_store_new (EPHY_TYPE_PAGE_ROW);
-
- gtk_list_box_bind_model (self->list_box,
- G_LIST_MODEL (self->list_store),
- create_row,
- NULL,
- NULL);
}
EphyPagesPopover *
@@ -232,43 +182,40 @@ ephy_pages_popover_new (GtkWidget *relative_to)
NULL);
}
-EphyNotebook *
-ephy_pages_popover_get_notebook (EphyPagesPopover *self)
+EphyTabView *
+ephy_pages_popover_get_tab_view (EphyPagesPopover *self)
{
g_assert (EPHY_IS_PAGES_POPOVER (self));
- return self->notebook;
+ return self->tab_view;
}
void
-ephy_pages_popover_set_notebook (EphyPagesPopover *self,
- EphyNotebook *notebook)
+ephy_pages_popover_set_tab_view (EphyPagesPopover *self,
+ EphyTabView *tab_view)
{
- GMenu *pages_menu;
-
g_assert (EPHY_IS_PAGES_POPOVER (self));
- if (self->notebook)
- release_notebook (self);
+ if (self->tab_view)
+ release_tab_view (self);
- if (!notebook)
+ if (!tab_view)
return;
- g_object_weak_ref (G_OBJECT (notebook), (GWeakNotify)drop_notebook, self);
- self->notebook = notebook;
- pages_menu = ephy_notebook_get_pages_menu (EPHY_NOTEBOOK (notebook));
-
- items_changed_cb (self, 0, 0,
- g_menu_model_get_n_items (G_MENU_MODEL (pages_menu)),
- G_MENU_MODEL (pages_menu));
- current_page_changed_cb (self);
-
- g_signal_connect_swapped (pages_menu,
- "items-changed",
- G_CALLBACK (items_changed_cb),
- self);
- g_signal_connect_swapped (notebook,
- "notify::page",
- G_CALLBACK (current_page_changed_cb),
- self);
+ g_object_weak_ref (G_OBJECT (tab_view), (GWeakNotify)drop_tab_view, self);
+ self->tab_view = tab_view;
+
+ self->model = hdy_tab_view_get_pages (ephy_tab_view_get_tab_view (tab_view));
+
+ gtk_list_box_bind_model (self->list_box,
+ self->model,
+ (GtkListBoxCreateWidgetFunc)create_row,
+ self,
+ NULL);
+
+ g_signal_connect_object (ephy_tab_view_get_tab_view (tab_view),
+ "notify::selected-page",
+ G_CALLBACK (selected_page_changed_cb),
+ self,
+ 0);
}
diff --git a/src/ephy-pages-popover.h b/src/ephy-pages-popover.h
index 1fd757b7f..1c148d403 100644
--- a/src/ephy-pages-popover.h
+++ b/src/ephy-pages-popover.h
@@ -23,8 +23,7 @@
#include <gtk/gtk.h>
-#include "ephy-adaptive-mode.h"
-#include "ephy-notebook.h"
+#include "ephy-tab-view.h"
G_BEGIN_DECLS
@@ -34,8 +33,8 @@ G_DECLARE_FINAL_TYPE (EphyPagesPopover, ephy_pages_popover, EPHY, PAGES_POPOVER,
EphyPagesPopover *ephy_pages_popover_new (GtkWidget *relative_to);
-EphyNotebook *ephy_pages_popover_get_notebook (EphyPagesPopover *popover);
-void ephy_pages_popover_set_notebook (EphyPagesPopover *popover,
- EphyNotebook *notebook);
+EphyTabView *ephy_pages_popover_get_tab_view (EphyPagesPopover *self);
+void ephy_pages_popover_set_tab_view (EphyPagesPopover *self,
+ EphyTabView *tab_view);
G_END_DECLS
diff --git a/src/ephy-pages-view.c b/src/ephy-pages-view.c
index 3fe63c216..c4f565e11 100644
--- a/src/ephy-pages-view.c
+++ b/src/ephy-pages-view.c
@@ -24,7 +24,6 @@
#include "ephy-pages-view.h"
-#include "ephy-notebook.h"
#include "ephy-page-row.h"
#include "ephy-window.h"
@@ -33,126 +32,77 @@ struct _EphyPagesView {
GtkListBox *list_box;
- GListStore *list_store;
- EphyNotebook *notebook;
+ GListModel *model;
+ EphyTabView *tab_view;
};
G_DEFINE_TYPE (EphyPagesView, ephy_pages_view, GTK_TYPE_BOX)
static void
-drop_notebook (EphyPagesView *self)
+drop_tab_view (EphyPagesView *self)
{
- self->notebook = NULL;
- g_list_store_remove_all (self->list_store);
+ self->tab_view = NULL;
}
static void
-release_notebook (EphyPagesView *self)
+release_tab_view (EphyPagesView *self)
{
- if (self->notebook) {
- g_object_weak_unref (G_OBJECT (self->notebook), (GWeakNotify)drop_notebook, self);
- drop_notebook (self);
+ if (self->tab_view) {
+ g_object_weak_unref (G_OBJECT (self->tab_view), (GWeakNotify)drop_tab_view, self);
+ drop_tab_view (self);
}
}
-static GtkWidget *
-create_row (gpointer item,
- gpointer user_data)
-{
- return GTK_WIDGET (g_object_ref (G_OBJECT (item)));
-}
-
static void
row_activated_cb (EphyPagesView *self,
- GtkListBoxRow *row)
+ EphyPageRow *row)
{
- gint new_page;
EphyWindow *window;
GApplication *application;
+ HdyTabPage *page;
g_assert (EPHY_IS_PAGES_VIEW (self));
- g_assert (!row || GTK_IS_LIST_BOX_ROW (row));
+ g_assert (EPHY_IS_PAGE_ROW (row));
application = g_application_get_default ();
window = EPHY_WINDOW (gtk_application_get_active_window (GTK_APPLICATION (application)));
+ page = ephy_page_row_get_page (EPHY_PAGE_ROW (row));
- if (!row)
- return;
-
- new_page = gtk_list_box_row_get_index (row);
-
- gtk_notebook_set_current_page (GTK_NOTEBOOK (self->notebook), new_page);
+ hdy_tab_view_set_selected_page (ephy_tab_view_get_tab_view (self->tab_view), page);
ephy_window_close_pages_view (window);
}
-static void
-row_closed_cb (EphyPagesView *self,
- EphyPageRow *row)
+static GtkWidget *
+create_row (HdyTabPage *page,
+ EphyPagesView *self)
{
- GtkWindow *window;
- GtkWidget *embed;
- EphyEmbedShell *shell;
+ EphyPageRow *row = ephy_page_row_new (self->tab_view, page);
- g_assert (EPHY_IS_PAGES_VIEW (self));
- g_assert (EPHY_IS_PAGE_ROW (row));
+ ephy_page_row_set_adaptive_mode (row, EPHY_ADAPTIVE_MODE_NARROW);
- shell = ephy_embed_shell_get_default ();
- window = gtk_application_get_active_window (GTK_APPLICATION (shell));
+ gtk_widget_show (GTK_WIDGET (row));
- embed = gtk_notebook_get_nth_page (GTK_NOTEBOOK (self->notebook),
- gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row)));
- g_signal_emit_by_name (self->notebook,
- "tab-close-request",
- embed, window);
+ return GTK_WIDGET (row);
}
-
static void
-current_page_changed (EphyPagesView *self)
+selected_page_changed_cb (HdyTabView *tab_view,
+ GParamSpec *pspec,
+ EphyPagesView *self)
{
- GtkListBoxRow *current_row, *new_row;
- gint current_page;
+ HdyTabPage *page = hdy_tab_view_get_selected_page (tab_view);
+ gint position;
+ GtkListBoxRow *row;
- g_assert (EPHY_IS_PAGES_VIEW (self));
+ if (!page) {
+ gtk_list_box_unselect_all (self->list_box);
- current_row = gtk_list_box_get_selected_row (self->list_box);
- current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (self->notebook));
- if (current_row && gtk_list_box_row_get_index (current_row) == current_page)
return;
-
- new_row = gtk_list_box_get_row_at_index (self->list_box, current_page);
- gtk_list_box_select_row (self->list_box, new_row);
-}
-
-static void
-items_changed_cb (EphyPagesView *self,
- gint position,
- gint removed,
- gint added,
- GMenuModel *menu_model)
-{
- g_autofree EphyPageRow **items = g_new (EphyPageRow *, added);
-
- for (int i = 0; i < added; i++) {
- items[i] = ephy_page_row_new (self->notebook, position + i);
- ephy_page_row_set_adaptive_mode (EPHY_PAGE_ROW (items[i]),
- EPHY_ADAPTIVE_MODE_NARROW);
- g_signal_connect_swapped (items[i], "closed", G_CALLBACK (row_closed_cb), self);
}
- g_list_store_splice (self->list_store, position, removed, (gpointer)items, added);
-
- current_page_changed (self);
-}
-
-static void
-ephy_pages_view_finalize (GObject *object)
-{
- EphyPagesView *self = EPHY_PAGES_VIEW (object);
-
- g_object_unref (self->list_store);
-
- G_OBJECT_CLASS (ephy_pages_view_parent_class)->finalize (object);
+ position = hdy_tab_view_get_page_position (tab_view, page);
+ row = gtk_list_box_get_row_at_index (self->list_box, position);
+ gtk_list_box_select_row (self->list_box, row);
}
static void
@@ -160,7 +110,7 @@ ephy_pages_view_dispose (GObject *object)
{
EphyPagesView *self = EPHY_PAGES_VIEW (object);
- release_notebook (self);
+ release_tab_view (self);
G_OBJECT_CLASS (ephy_pages_view_parent_class)->dispose (object);
}
@@ -172,7 +122,6 @@ ephy_pages_view_class_init (EphyPagesViewClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = ephy_pages_view_dispose;
- object_class->finalize = ephy_pages_view_finalize;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/epiphany/gtk/pages-view.ui");
gtk_widget_class_bind_template_child (widget_class, EphyPagesView, list_box);
@@ -183,14 +132,6 @@ static void
ephy_pages_view_init (EphyPagesView *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
-
- self->list_store = g_list_store_new (EPHY_TYPE_PAGE_ROW);
-
- gtk_list_box_bind_model (self->list_box,
- G_LIST_MODEL (self->list_store),
- create_row,
- NULL,
- NULL);
}
EphyPagesView *
@@ -199,39 +140,40 @@ ephy_pages_view_new (void)
return g_object_new (EPHY_TYPE_PAGES_VIEW, NULL);
}
-EphyNotebook *
-ephy_pages_view_get_notebook (EphyPagesView *self)
+EphyTabView *
+ephy_pages_view_get_tab_view (EphyPagesView *self)
{
g_assert (EPHY_IS_PAGES_VIEW (self));
- return self->notebook;
+ return self->tab_view;
}
void
-ephy_pages_view_set_notebook (EphyPagesView *self,
- EphyNotebook *notebook)
+ephy_pages_view_set_tab_view (EphyPagesView *self,
+ EphyTabView *tab_view)
{
- GMenu *pages_menu;
-
g_assert (EPHY_IS_PAGES_VIEW (self));
- if (self->notebook)
- release_notebook (self);
+ if (self->tab_view)
+ release_tab_view (self);
- if (!notebook)
+ if (!tab_view)
return;
- g_object_weak_ref (G_OBJECT (notebook), (GWeakNotify)drop_notebook, self);
- self->notebook = notebook;
- pages_menu = ephy_notebook_get_pages_menu (EPHY_NOTEBOOK (notebook));
+ g_object_weak_ref (G_OBJECT (tab_view), (GWeakNotify)drop_tab_view, self);
+ self->tab_view = tab_view;
- items_changed_cb (self, 0, 0,
- g_menu_model_get_n_items (G_MENU_MODEL (pages_menu)),
- G_MENU_MODEL (pages_menu));
+ self->model = hdy_tab_view_get_pages (ephy_tab_view_get_tab_view (tab_view));
+
+ gtk_list_box_bind_model (self->list_box,
+ self->model,
+ (GtkListBoxCreateWidgetFunc)create_row,
+ self,
+ NULL);
- g_signal_connect_object (pages_menu,
- "items-changed",
- G_CALLBACK (items_changed_cb),
+ g_signal_connect_object (ephy_tab_view_get_tab_view (tab_view),
+ "notify::selected-page",
+ G_CALLBACK (selected_page_changed_cb),
self,
- G_CONNECT_SWAPPED);
+ 0);
}
diff --git a/src/ephy-pages-view.h b/src/ephy-pages-view.h
index db910d1b8..0ad828b35 100644
--- a/src/ephy-pages-view.h
+++ b/src/ephy-pages-view.h
@@ -22,8 +22,7 @@
#include <gtk/gtk.h>
-#include "ephy-adaptive-mode.h"
-#include "ephy-notebook.h"
+#include "ephy-tab-view.h"
G_BEGIN_DECLS
@@ -33,8 +32,8 @@ G_DECLARE_FINAL_TYPE (EphyPagesView, ephy_pages_view, EPHY, PAGES_VIEW, GtkBox)
EphyPagesView *ephy_pages_view_new (void);
-EphyNotebook *ephy_pages_view_get_notebook (EphyPagesView *view);
-void ephy_pages_view_set_notebook (EphyPagesView *view,
- EphyNotebook *notebook);
+EphyTabView *ephy_pages_view_get_tab_view (EphyPagesView *self);
+void ephy_pages_view_set_tab_view (EphyPagesView *self,
+ EphyTabView *tab_view);
G_END_DECLS
diff --git a/src/ephy-session.c b/src/ephy-session.c
index cd7f71c8f..544b4200a 100644
--- a/src/ephy-session.c
+++ b/src/ephy-session.c
@@ -32,11 +32,12 @@
#include "ephy-file-helpers.h"
#include "ephy-gui.h"
#include "ephy-link.h"
-#include "ephy-notebook.h"
+#include "ephy-tab-view.h"
#include "ephy-prefs.h"
#include "ephy-settings.h"
#include "ephy-shell.h"
#include "ephy-string.h"
+#include "ephy-tab-view.h"
#include "ephy-window.h"
#include <glib/gi18n.h>
@@ -45,12 +46,12 @@
#include <libxml/xmlwriter.h>
typedef struct {
- EphyNotebook *notebook;
+ EphyTabView *tab_view;
gint ref_count;
-} NotebookTracker;
+} TabViewTracker;
typedef struct {
- NotebookTracker *notebook_tracker;
+ TabViewTracker *tab_view_tracker;
int position;
char *url;
WebKitWebViewSessionState *state;
@@ -132,35 +133,34 @@ load_changed_cb (WebKitWebView *view,
}
static void
-notebook_tracker_set_notebook (NotebookTracker *tracker,
- EphyNotebook *notebook)
+tab_view_tracker_set_tab_view (TabViewTracker *tracker,
+ EphyTabView *tab_view)
{
- if (tracker->notebook == notebook) {
+ if (tracker->tab_view == tab_view)
return;
- }
- if (tracker->notebook) {
- g_object_remove_weak_pointer (G_OBJECT (tracker->notebook), (gpointer *)&tracker->notebook);
- }
- tracker->notebook = notebook;
- if (tracker->notebook) {
- g_object_add_weak_pointer (G_OBJECT (tracker->notebook), (gpointer *)&tracker->notebook);
- }
+ if (tracker->tab_view)
+ g_object_remove_weak_pointer (G_OBJECT (tracker->tab_view), (gpointer *)&tracker->tab_view);
+
+ tracker->tab_view = tab_view;
+
+ if (tracker->tab_view)
+ g_object_add_weak_pointer (G_OBJECT (tracker->tab_view), (gpointer *)&tracker->tab_view);
}
-static NotebookTracker *
-notebook_tracker_new (EphyNotebook *notebook)
+static TabViewTracker *
+tab_view_tracker_new (EphyTabView *tab_view)
{
- NotebookTracker *tracker = g_new0 (NotebookTracker, 1);
+ TabViewTracker *tracker = g_new0 (TabViewTracker, 1);
tracker->ref_count = 1;
- notebook_tracker_set_notebook (tracker, notebook);
+ tab_view_tracker_set_tab_view (tracker, tab_view);
return tracker;
}
-static NotebookTracker *
-notebook_tracker_ref (NotebookTracker *tracker)
+static TabViewTracker *
+tab_view_tracker_ref (TabViewTracker *tracker)
{
g_atomic_int_inc (&tracker->ref_count);
@@ -168,57 +168,57 @@ notebook_tracker_ref (NotebookTracker *tracker)
}
static void
-notebook_tracker_unref (NotebookTracker *tracker)
+tab_view_tracker_unref (TabViewTracker *tracker)
{
if (!g_atomic_int_dec_and_test (&tracker->ref_count))
return;
- notebook_tracker_set_notebook (tracker, NULL);
+ tab_view_tracker_set_tab_view (tracker, NULL);
g_free (tracker);
}
-static EphyNotebook *
-closed_tab_get_notebook (ClosedTab *tab)
+static EphyTabView *
+closed_tab_get_tab_view (ClosedTab *tab)
{
- return tab->notebook_tracker->notebook;
+ return tab->tab_view_tracker->tab_view;
}
static int
-compare_func (ClosedTab *iter,
- EphyNotebook *notebook)
+compare_func (ClosedTab *iter,
+ EphyTabView *tab_view)
{
- return GTK_NOTEBOOK (closed_tab_get_notebook (iter)) - GTK_NOTEBOOK (notebook);
+ return (gpointer)closed_tab_get_tab_view (iter) - (gpointer)tab_view;
}
-static NotebookTracker *
-ephy_session_ref_or_create_notebook_tracker (EphySession *session,
- EphyNotebook *notebook)
+static TabViewTracker *
+ephy_session_ref_or_create_tab_view_tracker (EphySession *session,
+ EphyTabView *tab_view)
{
- GList *item = g_queue_find_custom (session->closed_tabs, notebook, (GCompareFunc)compare_func);
- return item ? notebook_tracker_ref (((ClosedTab *)item->data)->notebook_tracker) : notebook_tracker_new
(notebook);
+ GList *item = g_queue_find_custom (session->closed_tabs, tab_view, (GCompareFunc)compare_func);
+ return item ? tab_view_tracker_ref (((ClosedTab *)item->data)->tab_view_tracker) : tab_view_tracker_new
(tab_view);
}
static void
closed_tab_free (ClosedTab *tab)
{
g_free (tab->url);
- notebook_tracker_unref (tab->notebook_tracker);
+ tab_view_tracker_unref (tab->tab_view_tracker);
webkit_web_view_session_state_unref (tab->state);
g_free (tab);
}
static ClosedTab *
-closed_tab_new (EphyWebView *web_view,
- int position,
- NotebookTracker *notebook_tracker)
+closed_tab_new (EphyWebView *web_view,
+ int position,
+ TabViewTracker *tab_view_tracker)
{
ClosedTab *tab = g_new0 (ClosedTab, 1);
tab->url = g_strdup (ephy_web_view_get_address (web_view));
tab->position = position;
/* Takes the ownership of the tracker */
- tab->notebook_tracker = notebook_tracker;
+ tab->tab_view_tracker = tab_view_tracker;
tab->state = webkit_web_view_get_session_state (WEBKIT_WEB_VIEW (web_view));
return tab;
@@ -233,7 +233,7 @@ ephy_session_undo_close_tab (EphySession *session)
WebKitBackForwardListItem *item;
ClosedTab *tab;
EphyWindow *window;
- EphyNotebook *notebook;
+ EphyTabView *tab_view;
EphyNewTabFlags flags = EPHY_NEW_TAB_JUMP;
g_assert (EPHY_IS_SESSION (session));
@@ -243,12 +243,12 @@ ephy_session_undo_close_tab (EphySession *session)
return;
LOG ("UNDO CLOSE TAB: %s", tab->url);
- notebook = closed_tab_get_notebook (tab);
- if (notebook) {
+ tab_view = closed_tab_get_tab_view (tab);
+ if (tab_view) {
if (tab->position > 0) {
/* Append in the n-th position. */
- embed = EPHY_EMBED (gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook),
- tab->position - 1));
+ embed = EPHY_EMBED (ephy_tab_view_get_nth_page (tab_view,
+ tab->position - 1));
flags |= EPHY_NEW_TAB_APPEND_AFTER;
} else {
/* Just prepend in the first position. */
@@ -256,7 +256,7 @@ ephy_session_undo_close_tab (EphySession *session)
flags |= EPHY_NEW_TAB_FIRST;
}
- window = EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (notebook)));
+ window = EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab_view)));
new_tab = ephy_shell_new_tab (ephy_shell_get_default (),
window, embed,
flags);
@@ -264,8 +264,8 @@ ephy_session_undo_close_tab (EphySession *session)
window = ephy_window_new ();
new_tab = ephy_shell_new_tab (ephy_shell_get_default (),
window, NULL, flags);
- notebook_tracker_set_notebook (tab->notebook_tracker,
- EPHY_NOTEBOOK (ephy_window_get_notebook (window)));
+ tab_view_tracker_set_tab_view (tab->tab_view_tracker,
+ ephy_window_get_tab_view (window));
}
web_view = WEBKIT_WEB_VIEW (ephy_embed_get_web_view (new_tab));
@@ -288,10 +288,10 @@ ephy_session_undo_close_tab (EphySession *session)
}
static void
-ephy_session_tab_closed (EphySession *session,
- EphyNotebook *notebook,
- EphyEmbed *embed,
- gint position)
+ephy_session_tab_closed (EphySession *session,
+ EphyTabView *tab_view,
+ EphyEmbed *embed,
+ gint position)
{
EphyWebView *view;
WebKitWebView *wk_view;
@@ -306,7 +306,7 @@ ephy_session_tab_closed (EphySession *session,
}
tab = closed_tab_new (view, position,
- ephy_session_ref_or_create_notebook_tracker (session, notebook));
+ ephy_session_ref_or_create_tab_view_tracker (session, tab_view));
g_queue_push_head (session->closed_tabs, tab);
if (g_queue_get_length (session->closed_tabs) == 1)
@@ -325,33 +325,38 @@ ephy_session_get_can_undo_tab_closed (EphySession *session)
}
static void
-notebook_page_added_cb (GtkWidget *notebook,
- EphyEmbed *embed,
- guint position,
- EphySession *session)
+tab_view_page_attached_cb (HdyTabView *tab_view,
+ HdyTabPage *page,
+ guint position,
+ EphySession *session)
{
+ EphyEmbed *embed = EPHY_EMBED (hdy_tab_page_get_child (page));
+
g_signal_connect (ephy_embed_get_web_view (embed), "load-changed",
G_CALLBACK (load_changed_cb), session);
}
static void
-notebook_page_removed_cb (GtkWidget *notebook,
- EphyEmbed *embed,
- guint position,
- EphySession *session)
+tab_view_page_detached_cb (HdyTabView *tab_view,
+ HdyTabPage *page,
+ gint position,
+ EphySession *session)
{
+ EphyEmbed *embed = EPHY_EMBED (hdy_tab_page_get_child (page));
+ EphyTabView *ephy_tab_view = EPHY_TAB_VIEW (g_object_get_data (G_OBJECT (tab_view), "ephy-tab-view"));
+
ephy_session_save (session);
g_signal_handlers_disconnect_by_func
(ephy_embed_get_web_view (embed), G_CALLBACK (load_changed_cb),
session);
- ephy_session_tab_closed (session, EPHY_NOTEBOOK (notebook), embed, position);
+ ephy_session_tab_closed (session, ephy_tab_view, embed, position);
}
static void
-notebook_page_reordered_cb (GtkWidget *notebook,
- GtkWidget *tab,
+tab_view_page_reordered_cb (HdyTabView *tab_view,
+ HdyTabPage *page,
guint position,
EphySession *session)
{
@@ -359,10 +364,9 @@ notebook_page_reordered_cb (GtkWidget *notebook,
}
static void
-notebook_switch_page_cb (GtkNotebook *notebook,
- GtkWidget *page,
- guint page_num,
- EphySession *session)
+tab_view_notify_selected_page_cb (HdyTabView *tab_view,
+ GParamSpec *pspec,
+ EphySession *session)
{
ephy_session_save (session);
}
@@ -386,8 +390,8 @@ window_added_cb (GtkApplication *application,
GtkWindow *window,
EphySession *session)
{
- GtkWidget *notebook;
EphyWindow *ephy_window;
+ HdyTabView *tab_view;
ephy_session_save (session);
@@ -396,15 +400,16 @@ window_added_cb (GtkApplication *application,
ephy_window = EPHY_WINDOW (window);
- notebook = ephy_window_get_notebook (ephy_window);
- g_signal_connect (notebook, "page-added",
- G_CALLBACK (notebook_page_added_cb), session);
- g_signal_connect (notebook, "page-removed",
- G_CALLBACK (notebook_page_removed_cb), session);
- g_signal_connect (notebook, "page-reordered",
- G_CALLBACK (notebook_page_reordered_cb), session);
- g_signal_connect_after (notebook, "switch-page",
- G_CALLBACK (notebook_switch_page_cb), session);
+ tab_view = ephy_tab_view_get_tab_view (ephy_window_get_tab_view (ephy_window));
+ g_signal_connect_object (tab_view, "page-attached",
+ G_CALLBACK (tab_view_page_attached_cb), session, 0);
+ g_signal_connect_object (tab_view, "page-detached",
+ G_CALLBACK (tab_view_page_detached_cb), session, 0);
+ g_signal_connect_object (tab_view, "page-reordered",
+ G_CALLBACK (tab_view_page_reordered_cb), session, 0);
+ g_signal_connect_object (tab_view, "notify::selected-page",
+ G_CALLBACK (tab_view_notify_selected_page_cb), session,
+ G_CONNECT_AFTER);
/* Set unique identifier as role, so that on restore, the WM can
* place the window on the right workspace
@@ -563,7 +568,7 @@ typedef struct {
static SessionTab *
session_tab_new (EphyEmbed *embed,
EphySession *session,
- GtkNotebook *notebook)
+ EphyTabView *tab_view)
{
SessionTab *session_tab;
const char *address;
@@ -592,7 +597,7 @@ session_tab_new (EphyEmbed *embed,
session_tab->crashed = (error_page == EPHY_WEB_VIEW_ERROR_PAGE_CRASH ||
error_page == EPHY_WEB_VIEW_ERROR_PROCESS_CRASH);
session_tab->state = webkit_web_view_get_session_state (WEBKIT_WEB_VIEW (web_view));
- session_tab->pinned = ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), embed);
+ session_tab->pinned = ephy_tab_view_get_is_pinned (tab_view, GTK_WIDGET (embed));
return session_tab;
}
@@ -613,7 +618,7 @@ session_window_new (EphyWindow *window,
{
SessionWindow *session_window;
GList *tabs, *l;
- GtkNotebook *notebook;
+ EphyTabView *tab_view;
tabs = ephy_embed_container_get_children (EPHY_EMBED_CONTAINER (window));
/* Do not save an empty EphyWindow.
@@ -626,18 +631,18 @@ session_window_new (EphyWindow *window,
session_window = g_new0 (SessionWindow, 1);
get_window_geometry (window, session_window);
session_window->role = g_strdup (gtk_window_get_role (GTK_WINDOW (window)));
- notebook = GTK_NOTEBOOK (ephy_window_get_notebook (window));
+ tab_view = ephy_window_get_tab_view (window);
for (l = tabs; l != NULL; l = l->next) {
SessionTab *tab;
- tab = session_tab_new (EPHY_EMBED (l->data), session, notebook);
+ tab = session_tab_new (EPHY_EMBED (l->data), session, tab_view);
session_window->tabs = g_list_prepend (session_window->tabs, tab);
}
g_list_free (tabs);
session_window->tabs = g_list_reverse (session_window->tabs);
- session_window->active_tab = gtk_notebook_get_current_page (notebook);
+ session_window->active_tab = ephy_tab_view_get_selected_index (tab_view);
return session_window;
}
@@ -1184,7 +1189,7 @@ session_parse_embed (SessionParserContext *context,
const gchar **names,
const gchar **values)
{
- GtkWidget *notebook;
+ HdyTabView *tab_view;
const char *url = NULL;
const char *title = NULL;
const char *history = NULL;
@@ -1201,7 +1206,7 @@ session_parse_embed (SessionParserContext *context,
return;
}
- notebook = ephy_window_get_notebook (context->window);
+ tab_view = ephy_tab_view_get_tab_view (ephy_window_get_tab_view (context->window));
for (i = 0; names[i]; i++) {
if (strcmp (names[i], "url") == 0) {
@@ -1251,7 +1256,9 @@ session_parse_embed (SessionParserContext *context,
context->window, NULL, flags,
0);
- ephy_notebook_tab_set_pinned (EPHY_NOTEBOOK (notebook), GTK_WIDGET (embed), is_pin);
+ hdy_tab_view_set_page_pinned (tab_view,
+ hdy_tab_view_get_page (tab_view, GTK_WIDGET (embed)),
+ is_pin);
web_view = ephy_embed_get_web_view (embed);
if (history) {
@@ -1327,7 +1334,7 @@ session_end_element (GMarkupParseContext *ctx,
SessionParserContext *context = (SessionParserContext *)user_data;
if (strcmp (element_name, "window") == 0) {
- GtkWidget *notebook;
+ EphyTabView *tab_view;
EphyEmbedShell *shell = ephy_embed_shell_get_default ();
if (!context->window) {
@@ -1337,8 +1344,8 @@ session_end_element (GMarkupParseContext *ctx,
return;
}
- notebook = ephy_window_get_notebook (context->window);
- gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), context->active_tab);
+ tab_view = ephy_window_get_tab_view (context->window);
+ ephy_tab_view_select_nth_page (tab_view, context->active_tab);
if (ephy_embed_shell_get_mode (ephy_embed_shell_get_default ()) != EPHY_EMBED_SHELL_MODE_TEST) {
EphyEmbed *active_child;
diff --git a/src/ephy-shell.c b/src/ephy-shell.c
index 18ac9ff84..650531da8 100644
--- a/src/ephy-shell.c
+++ b/src/ephy-shell.c
@@ -935,23 +935,22 @@ webkit_notification_clicked_cb (WebKitNotification *notification,
for (guint win_idx = 0; win_idx < g_list_length (windows); win_idx++) {
EphyWindow *window;
- GtkWidget *notebook;
+ EphyTabView *tab_view;
int n_pages;
window = EPHY_WINDOW (g_list_nth_data (windows, win_idx));
-
- notebook = ephy_window_get_notebook (window);
- n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
+ tab_view = ephy_window_get_tab_view (window);
+ n_pages = ephy_tab_view_get_n_pages (tab_view);
for (int i = 0; i < n_pages; i++) {
EphyEmbed *embed;
WebKitWebView *webview;
- embed = EPHY_EMBED (gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i));
+ embed = EPHY_EMBED (ephy_tab_view_get_nth_page (tab_view, i));
webview = WEBKIT_WEB_VIEW (ephy_embed_get_web_view (embed));
if (webview == notification_webview) {
- gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), i);
+ ephy_tab_view_select_page (tab_view, GTK_WIDGET (embed));
gtk_window_present (GTK_WINDOW (window));
return;
}
@@ -1025,6 +1024,7 @@ ephy_shell_new_tab_full (EphyShell *shell,
EphyEmbed *embed = NULL;
gboolean jump_to = FALSE;
int position = -1;
+ EphyEmbed *parent = NULL;
g_assert (EPHY_IS_SHELL (shell));
g_assert (EPHY_IS_WINDOW (window));
@@ -1040,7 +1040,7 @@ ephy_shell_new_tab_full (EphyShell *shell,
if (flags & EPHY_NEW_TAB_APPEND_AFTER) {
if (previous_embed)
- position = ephy_window_get_position_for_new_embed (window, previous_embed);
+ parent = previous_embed;
else
g_warning ("Requested to append new tab after parent, but 'previous_embed' was NULL");
}
@@ -1061,7 +1061,7 @@ ephy_shell_new_tab_full (EphyShell *shell,
"progress-bar-enabled", ephy_embed_shell_get_mode (embed_shell) ==
EPHY_EMBED_SHELL_MODE_APPLICATION,
NULL));
gtk_widget_show (GTK_WIDGET (embed));
- ephy_embed_container_add_child (EPHY_EMBED_CONTAINER (window), embed, position, jump_to);
+ ephy_embed_container_add_child (EPHY_EMBED_CONTAINER (window), embed, parent, position, jump_to);
if ((flags & EPHY_NEW_TAB_DONT_SHOW_WINDOW) == 0 &&
ephy_embed_shell_get_mode (embed_shell) != EPHY_EMBED_SHELL_MODE_TEST) {
@@ -1556,16 +1556,16 @@ ephy_shell_get_web_view (EphyShell *shell,
{
GList *windows;
GtkWindow *window;
- GtkWidget *notebook;
+ EphyTabView *tab_view;
windows = gtk_application_get_windows (GTK_APPLICATION (shell));
for (GList *list = windows; list && list->data; list = list->next) {
window = GTK_WINDOW (list->data);
- notebook = ephy_window_get_notebook (EPHY_WINDOW (window));
+ tab_view = ephy_window_get_tab_view (EPHY_WINDOW (window));
- for (int i = 0; i < gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)); i++) {
- GtkWidget *page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i);
+ for (int i = 0; i < ephy_tab_view_get_n_pages (tab_view); i++) {
+ GtkWidget *page = ephy_tab_view_get_nth_page (tab_view, i);
EphyWebView *web_view = ephy_embed_get_web_view (EPHY_EMBED (page));
if (ephy_web_view_get_uid (web_view) == id)
@@ -1580,18 +1580,15 @@ EphyWebView *
ephy_shell_get_active_web_view (EphyShell *shell)
{
GtkWindow *window;
- GtkWidget *notebook;
+ EphyTabView *tab_view;
GtkWidget *page;
- gint page_num;
window = gtk_application_get_active_window (GTK_APPLICATION (shell));
if (!window)
return NULL;
- notebook = ephy_window_get_notebook (EPHY_WINDOW (window));
-
- page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
- page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), page_num);
+ tab_view = ephy_window_get_tab_view (EPHY_WINDOW (window));
+ page = ephy_tab_view_get_selected_page (tab_view);
return ephy_embed_get_web_view (EPHY_EMBED (page));
}
diff --git a/src/ephy-shell.h b/src/ephy-shell.h
index 4abeed70e..64012311c 100644
--- a/src/ephy-shell.h
+++ b/src/ephy-shell.h
@@ -48,9 +48,9 @@ G_DECLARE_FINAL_TYPE (EphyShell, ephy_shell, EPHY, SHELL, EphyEmbedShell)
* @EPHY_NEW_TAB_DONT_SHOW_WINDOW: do not show the window where the new
* tab is attached.
* @EPHY_NEW_TAB_APPEND_LAST: appends the new tab at the end of the
- * notebook.
+ * tab bar.
* @EPHY_NEW_TAB_APPEND_AFTER: appends the new tab right after the
- * current one in the notebook.
+ * current one in the tab bar.
* @EPHY_NEW_TAB_FROM_EXTERNAL: tries to open the new tab in the current
* active tab if it is currently not loading anything and is
* blank.
diff --git a/src/ephy-suggestion-model.c b/src/ephy-suggestion-model.c
index 1c5fb6793..d8948e7f6 100644
--- a/src/ephy-suggestion-model.c
+++ b/src/ephy-suggestion-model.c
@@ -407,10 +407,9 @@ add_tabs (EphySuggestionModel *self,
GApplication *application;
EphyEmbedShell *shell;
EphyWindow *window;
- GtkWidget *notebook;
+ EphyTabView *tab_view;
GList *windows;
- gint n_pages;
- gint current;
+ gint n_pages, selected;
guint added = 0;
shell = ephy_embed_shell_get_default ();
@@ -420,9 +419,9 @@ add_tabs (EphySuggestionModel *self,
for (guint win_idx = 0; win_idx < g_list_length (windows); win_idx++) {
window = EPHY_WINDOW (g_list_nth_data (windows, win_idx));
- notebook = ephy_window_get_notebook (window);
- n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
- current = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
+ tab_view = ephy_window_get_tab_view (window);
+ n_pages = ephy_tab_view_get_n_pages (tab_view);
+ selected = ephy_tab_view_get_selected_index (tab_view);
for (int i = 0; i < n_pages; i++) {
EphyEmbed *embed;
@@ -438,10 +437,10 @@ add_tabs (EphySuggestionModel *self,
g_autofree gchar *display_address_casefold = NULL;
g_autofree gchar *query_casefold = NULL;
- if (win_idx == 0 && i == current)
+ if (win_idx == 0 && i == selected)
continue;
- embed = EPHY_EMBED (gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i));
+ embed = EPHY_EMBED (ephy_tab_view_get_nth_page (tab_view, i));
webview = ephy_embed_get_web_view (embed);
display_address = ephy_web_view_get_display_address (webview);
url = ephy_web_view_get_address (webview);
diff --git a/src/ephy-tab-view.c b/src/ephy-tab-view.c
new file mode 100644
index 000000000..18de36110
--- /dev/null
+++ b/src/ephy-tab-view.c
@@ -0,0 +1,652 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2020 Alexander Mikhaylenko <exalm7659 gmail com>
+ *
+ * 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 "config.h"
+#include "ephy-tab-view.h"
+
+#include "ephy-desktop-utils.h"
+#include "ephy-dnd.h"
+#include "ephy-embed-utils.h"
+#include "ephy-link.h"
+#include "ephy-settings.h"
+#include "ephy-shell.h"
+
+#define MAX_NUMBER_OF_URLS 20
+
+struct _EphyTabView {
+ GtkBin parent_instance;
+
+ HdyTabView *tab_view;
+ HdyTabBar *tab_bar;
+ HdyTabPage *current_page;
+};
+
+G_DEFINE_TYPE (EphyTabView, ephy_tab_view, GTK_TYPE_BIN)
+
+enum {
+ PROP_0,
+ PROP_N_PAGES,
+ PROP_SELECTED_INDEX,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+static void
+notify_n_pages_cb (EphyTabView *self)
+{
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_PAGES]);
+}
+
+static void
+notify_selected_page_cb (EphyTabView *self)
+{
+ HdyTabPage *page = hdy_tab_view_get_selected_page (self->tab_view);
+
+ if (page)
+ hdy_tab_page_set_needs_attention (page, FALSE);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_INDEX]);
+}
+
+static void
+indicator_activated_cb (EphyTabView *self,
+ HdyTabPage *page)
+{
+ EphyEmbed *embed = EPHY_EMBED (hdy_tab_page_get_child (page));
+ EphyWebView *view = ephy_embed_get_web_view (embed);
+ gboolean muted = webkit_web_view_get_is_muted (WEBKIT_WEB_VIEW (view));
+
+ webkit_web_view_set_is_muted (WEBKIT_WEB_VIEW (view), !muted);
+}
+
+static void
+setup_menu_cb (EphyTabView *self,
+ HdyTabPage *page)
+{
+ self->current_page = page;
+}
+
+static HdyTabPage *
+get_current_page (EphyTabView *self)
+{
+ if (self->current_page)
+ return self->current_page;
+
+ return hdy_tab_view_get_selected_page (self->tab_view);
+}
+
+static void
+ephy_tab_view_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyTabView *self = EPHY_TAB_VIEW (object);
+
+ switch (prop_id) {
+ case PROP_N_PAGES:
+ g_value_set_int (value, ephy_tab_view_get_n_pages (self));
+ break;
+
+ case PROP_SELECTED_INDEX:
+ g_value_set_int (value, ephy_tab_view_get_selected_index (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_tab_view_class_init (EphyTabViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = ephy_tab_view_get_property;
+
+ properties[PROP_N_PAGES] =
+ g_param_spec_int ("n-pages",
+ "Number of pages",
+ "The number of pages in the tab view",
+ 0,
+ G_MAXINT,
+ 0,
+ (G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_EXPLICIT_NOTIFY));
+
+ properties[PROP_SELECTED_INDEX] =
+ g_param_spec_int ("selected-index",
+ "Selected index",
+ "The index of the currently selected page",
+ 0,
+ G_MAXINT,
+ 0,
+ (G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_EXPLICIT_NOTIFY));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ephy_tab_view_init (EphyTabView *self)
+{
+ self->tab_view = HDY_TAB_VIEW (hdy_tab_view_new ());
+ gtk_widget_show (GTK_WIDGET (self->tab_view));
+
+ g_object_set_data (G_OBJECT (self->tab_view), "ephy-tab-view", self);
+
+ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->tab_view));
+
+ g_signal_connect_object (self->tab_view,
+ "notify::n-pages",
+ G_CALLBACK (notify_n_pages_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->tab_view,
+ "notify::selected-page",
+ G_CALLBACK (notify_selected_page_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->tab_view,
+ "setup-menu",
+ G_CALLBACK (setup_menu_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (self->tab_view,
+ "indicator-activated",
+ G_CALLBACK (indicator_activated_cb),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+EphyTabView *
+ephy_tab_view_new (void)
+{
+ return g_object_new (EPHY_TYPE_TAB_VIEW, NULL);
+}
+
+void
+ephy_tab_view_next (EphyTabView *self)
+{
+ hdy_tab_view_select_next_page (self->tab_view);
+}
+
+void
+ephy_tab_view_pin (EphyTabView *self)
+{
+ hdy_tab_view_set_page_pinned (self->tab_view, get_current_page (self), TRUE);
+}
+
+void
+ephy_tab_view_unpin (EphyTabView *self)
+{
+ hdy_tab_view_set_page_pinned (self->tab_view, get_current_page (self), FALSE);
+}
+
+void
+ephy_tab_view_close (EphyTabView *self,
+ GtkWidget *widget)
+{
+ HdyTabPage *page = hdy_tab_view_get_page (self->tab_view, widget);
+
+ hdy_tab_view_close_page (self->tab_view, page);
+}
+
+void
+ephy_tab_view_close_selected (EphyTabView *self)
+{
+ hdy_tab_view_close_page (self->tab_view, get_current_page (self));
+}
+
+void
+ephy_tab_view_close_left (EphyTabView *self)
+{
+ hdy_tab_view_close_pages_before (self->tab_view, get_current_page (self));
+}
+
+void
+ephy_tab_view_close_right (EphyTabView *self)
+{
+ hdy_tab_view_close_pages_after (self->tab_view, get_current_page (self));
+}
+
+void
+ephy_tab_view_close_other (EphyTabView *self)
+{
+ hdy_tab_view_close_other_pages (self->tab_view, get_current_page (self));
+}
+
+void
+ephy_tab_view_foreach (EphyTabView *self,
+ GtkCallback callback,
+ gpointer user_data)
+{
+ int i, n;
+
+ n = hdy_tab_view_get_n_pages (self->tab_view);
+
+ for (i = 0; i < n; i++) {
+ HdyTabPage *page = hdy_tab_view_get_nth_page (self->tab_view, i);
+
+ callback (hdy_tab_page_get_child (page), user_data);
+ }
+}
+
+int
+ephy_tab_view_get_n_pages (EphyTabView *self)
+{
+ return hdy_tab_view_get_n_pages (self->tab_view);
+}
+
+int
+ephy_tab_view_get_selected_index (EphyTabView *self)
+{
+ HdyTabPage *page = hdy_tab_view_get_selected_page (self->tab_view);
+
+ if (!page)
+ return -1;
+
+ return hdy_tab_view_get_page_position (self->tab_view, page);
+}
+
+int
+ephy_tab_view_get_page_index (EphyTabView *self,
+ GtkWidget *widget)
+{
+ HdyTabPage *page = hdy_tab_view_get_page (self->tab_view, widget);
+
+ return hdy_tab_view_get_page_position (self->tab_view, page);
+}
+
+GtkWidget *
+ephy_tab_view_get_nth_page (EphyTabView *self,
+ int index)
+{
+ HdyTabPage *page = hdy_tab_view_get_nth_page (self->tab_view, index);
+
+ return hdy_tab_page_get_child (page);
+}
+
+void
+ephy_tab_view_select_nth_page (EphyTabView *self,
+ int index)
+{
+ HdyTabPage *page = hdy_tab_view_get_nth_page (self->tab_view, index);
+
+ hdy_tab_view_set_selected_page (self->tab_view, page);
+}
+
+gboolean
+ephy_tab_view_select_page (EphyTabView *self,
+ GtkWidget *widget)
+{
+ HdyTabPage *page = hdy_tab_view_get_page (self->tab_view, widget);
+
+ if (page)
+ hdy_tab_view_set_selected_page (self->tab_view, page);
+
+ return !!page;
+}
+
+GtkWidget *
+ephy_tab_view_get_selected_page (EphyTabView *self)
+{
+ HdyTabPage *page = hdy_tab_view_get_selected_page (self->tab_view);
+
+ return hdy_tab_page_get_child (page);
+}
+
+HdyTabView *
+ephy_tab_view_get_tab_view (EphyTabView *self)
+{
+ return self->tab_view;
+}
+
+GList *
+ephy_tab_view_get_pages (EphyTabView *self)
+{
+ GList *list = NULL;
+ int i, n;
+
+ n = hdy_tab_view_get_n_pages (self->tab_view);
+
+ for (i = 0; i < n; i++) {
+ HdyTabPage *page = hdy_tab_view_get_nth_page (self->tab_view, i);
+ GtkWidget *content = hdy_tab_page_get_child (page);
+
+ list = g_list_prepend (list, content);
+ }
+
+ return g_list_reverse (list);
+}
+
+gboolean
+ephy_tab_view_get_is_pinned (EphyTabView *self,
+ GtkWidget *widget)
+{
+ HdyTabPage *page = hdy_tab_view_get_page (self->tab_view, widget);
+
+ return hdy_tab_page_get_pinned (page);
+}
+
+static void
+update_title_cb (HdyTabPage *page)
+{
+ EphyEmbed *embed = EPHY_EMBED (hdy_tab_page_get_child (page));
+ EphyWebView *view = ephy_embed_get_web_view (embed);
+ const char *title = ephy_embed_get_title (embed);
+ const char *address;
+
+ if (!ephy_embed_has_load_pending (embed) &&
+ !hdy_tab_page_get_selected (page) &&
+ hdy_tab_page_get_pinned (page))
+ hdy_tab_page_set_needs_attention (page, TRUE);
+
+ if (title && strlen (title)) {
+ hdy_tab_page_set_title (page, title);
+ return;
+ }
+
+ address = ephy_web_view_get_display_address (view);
+
+ if (ephy_web_view_is_loading (view) &&
+ !ephy_embed_utils_is_no_show_address (address))
+ hdy_tab_page_set_title (page, address);
+}
+
+static void
+update_icon_cb (HdyTabPage *page)
+{
+ EphyEmbed *embed = EPHY_EMBED (hdy_tab_page_get_child (page));
+ EphyWebView *view = ephy_embed_get_web_view (embed);
+ GIcon *icon = G_ICON (ephy_web_view_get_icon (view));
+ g_autoptr (GIcon) placeholder_icon = NULL;
+ const char *uri, *favicon_name;
+
+ if (icon) {
+ hdy_tab_page_set_icon (page, icon);
+ return;
+ }
+
+ uri = webkit_web_view_get_uri (WEBKIT_WEB_VIEW (view));
+ favicon_name = ephy_get_fallback_favicon_name (uri, EPHY_FAVICON_TYPE_NO_MISSING_PLACEHOLDER);
+
+ if (favicon_name)
+ placeholder_icon = g_themed_icon_new (favicon_name);
+
+ hdy_tab_page_set_icon (page, placeholder_icon);
+}
+
+static void
+update_indicator_cb (HdyTabPage *page)
+{
+ EphyEmbed *embed = EPHY_EMBED (hdy_tab_page_get_child (page));
+ EphyWebView *view = ephy_embed_get_web_view (embed);
+ g_autoptr (GIcon) icon = NULL;
+
+ if (webkit_web_view_is_playing_audio (WEBKIT_WEB_VIEW (view))) {
+ if (webkit_web_view_get_is_muted (WEBKIT_WEB_VIEW (view)))
+ icon = G_ICON (g_themed_icon_new ("ephy-audio-muted-symbolic"));
+ else
+ icon = G_ICON (g_themed_icon_new ("ephy-audio-playing-symbolic"));
+ }
+
+ hdy_tab_page_set_indicator_icon (page, icon);
+}
+
+int
+ephy_tab_view_add_tab (EphyTabView *self,
+ EphyEmbed *embed,
+ EphyEmbed *parent,
+ int position,
+ gboolean jump_to)
+{
+ HdyTabPage *page;
+ EphyWebView *view;
+
+ if (parent) {
+ HdyTabPage *parent_page;
+
+ parent_page = hdy_tab_view_get_page (self->tab_view, GTK_WIDGET (parent));
+ page = hdy_tab_view_add_page (self->tab_view, GTK_WIDGET (embed), parent_page);
+ } else if (position < 0) {
+ page = hdy_tab_view_append (self->tab_view, GTK_WIDGET (embed));
+ } else {
+ page = hdy_tab_view_insert (self->tab_view, GTK_WIDGET (embed), position);
+ }
+
+ if (jump_to)
+ hdy_tab_view_set_selected_page (self->tab_view, page);
+
+ view = ephy_embed_get_web_view (embed);
+
+ hdy_tab_page_set_indicator_activatable (page, TRUE);
+
+ g_object_bind_property (view, "is-loading", page, "loading", G_BINDING_SYNC_CREATE);
+
+ g_signal_connect_object (embed, "notify::title",
+ G_CALLBACK (update_title_cb), page,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (view, "notify::display-address",
+ G_CALLBACK (update_title_cb), page,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (view, "notify::icon",
+ G_CALLBACK (update_icon_cb), page,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (view, "notify::uri",
+ G_CALLBACK (update_icon_cb), page,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (view, "notify::is-playing-audio",
+ G_CALLBACK (update_indicator_cb), page,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (view, "notify::is-muted",
+ G_CALLBACK (update_indicator_cb), page,
+ G_CONNECT_SWAPPED);
+
+ update_title_cb (page);
+ update_icon_cb (page);
+ update_indicator_cb (page);
+
+ return hdy_tab_view_get_page_position (self->tab_view, page);
+}
+
+GtkWidget *
+ephy_tab_view_get_current_page (EphyTabView *self)
+{
+ return hdy_tab_page_get_child (get_current_page (self));
+}
+
+static void
+drag_data_received_cb (EphyTabView *self,
+ HdyTabPage *page,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time)
+{
+ GtkWidget *window;
+ EphyEmbed *embed;
+ GdkAtom target;
+ const guchar *data;
+
+ if (g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN,
+ EPHY_PREFS_LOCKDOWN_ARBITRARY_URL))
+ return;
+
+ data = gtk_selection_data_get_data (selection_data);
+ if (gtk_selection_data_get_length (selection_data) <= 0 || data)
+ return;
+
+ embed = EPHY_EMBED (hdy_tab_page_get_child (page));
+ target = gtk_selection_data_get_target (selection_data);
+
+ window = gtk_widget_get_toplevel (GTK_WIDGET (self));
+
+ if (target == gdk_atom_intern (EPHY_DND_URL_TYPE, FALSE)) {
+ /* URL_TYPE has format: url \n title */
+ g_auto (GStrv) split = g_strsplit ((const char *)data, "\n", 2);
+
+ if (split && split[0] && split[0][0] != '\0') {
+ ephy_link_open (EPHY_LINK (window), NULL, NULL, EPHY_LINK_NEW_TAB);
+ ephy_link_open (EPHY_LINK (window), split[0], embed,
+ embed ? 0 : EPHY_LINK_NEW_TAB);
+ }
+ } else if (target == gdk_atom_intern (EPHY_DND_URI_LIST_TYPE, FALSE)) {
+ g_auto (GStrv) uris = gtk_selection_data_get_uris (selection_data);
+ int i;
+
+ if (!uris)
+ return;
+
+ for (i = 0; i < MAX_NUMBER_OF_URLS && uris[i]; i++) {
+ embed = ephy_link_open (EPHY_LINK (window), uris[i], embed,
+ (embed && i == 0) ? 0 : EPHY_LINK_NEW_TAB);
+ }
+ } else {
+ g_autofree char *text =
+ (char *)gtk_selection_data_get_text (selection_data);
+
+ if (text) {
+ g_autofree char *address =
+ ephy_embed_utils_normalize_or_autosearch_address (text);
+
+ ephy_link_open (EPHY_LINK (window), address, embed,
+ embed ? 0 : EPHY_LINK_NEW_TAB);
+ }
+ }
+}
+
+static void
+visibility_policy_changed_cb (EphyTabView *self)
+{
+ EphyEmbedShellMode mode;
+ EphyPrefsUITabsBarVisibilityPolicy policy;
+
+ mode = ephy_embed_shell_get_mode (EPHY_EMBED_SHELL (ephy_shell_get_default ()));
+
+ if (is_desktop_pantheon ())
+ policy = EPHY_PREFS_UI_TABS_BAR_VISIBILITY_POLICY_ALWAYS;
+ else
+ policy = g_settings_get_enum (EPHY_SETTINGS_UI,
+ EPHY_PREFS_UI_TABS_BAR_VISIBILITY_POLICY);
+
+ hdy_tab_bar_set_autohide (self->tab_bar,
+ policy != EPHY_PREFS_UI_TABS_BAR_VISIBILITY_POLICY_ALWAYS);
+ gtk_widget_set_visible (GTK_WIDGET (self->tab_bar),
+ mode != EPHY_EMBED_SHELL_MODE_APPLICATION &&
+ policy != EPHY_PREFS_UI_TABS_BAR_VISIBILITY_POLICY_NEVER);
+}
+
+static void
+expand_changed_cb (EphyTabView *self)
+{
+ gboolean expand = g_settings_get_boolean (EPHY_SETTINGS_UI,
+ EPHY_PREFS_UI_EXPAND_TABS_BAR);
+
+ hdy_tab_bar_set_expand_tabs (self->tab_bar, expand);
+}
+
+static gboolean
+is_layout_reversed (void)
+{
+ GtkSettings *settings;
+ g_autofree char *layout = NULL;
+ g_auto (GStrv) parts = NULL;
+
+ settings = gtk_settings_get_default ();
+ g_object_get (settings, "gtk-decoration-layout", &layout, NULL);
+
+ parts = g_strsplit (layout, ":", 2);
+
+ /* Invalid layout, don't even try */
+ if (g_strv_length (parts) < 2)
+ return FALSE;
+
+ return !!g_strrstr (parts[0], "close");
+}
+
+static void
+notify_decoration_layout_cb (EphyTabView *self)
+{
+ hdy_tab_bar_set_inverted (self->tab_bar, is_layout_reversed ());
+}
+
+void
+ephy_tab_view_set_tab_bar (EphyTabView *self,
+ HdyTabBar *tab_bar)
+{
+ g_autoptr (GtkTargetList) target_list = NULL;
+ GtkSettings *settings;
+ static const GtkTargetEntry url_drag_types [] = {
+ { (char *)EPHY_DND_URI_LIST_TYPE, 0, 0 },
+ { (char *)EPHY_DND_URL_TYPE, 0, 1 },
+ };
+
+ self->tab_bar = tab_bar;
+
+ target_list = gtk_target_list_new (url_drag_types,
+ G_N_ELEMENTS (url_drag_types));
+ gtk_target_list_add_text_targets (target_list, 0);
+
+ hdy_tab_bar_set_extra_drag_dest_targets (self->tab_bar, target_list);
+
+ g_signal_connect_object (tab_bar, "extra-drag-data-received",
+ G_CALLBACK (drag_data_received_cb), self,
+ G_CONNECT_SWAPPED);
+
+ if (is_desktop_pantheon ()) {
+ GtkWidget *button;
+
+ hdy_tab_bar_set_autohide (tab_bar, FALSE);
+ hdy_tab_bar_set_expand_tabs (tab_bar, FALSE);
+
+ button = gtk_button_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_MENU);
+ /* Translators: tooltip for the new tab button */
+ gtk_widget_set_tooltip_text (button, _("Open a new tab"));
+ gtk_actionable_set_action_name (GTK_ACTIONABLE (button), "win.new-tab");
+ gtk_style_context_add_class (gtk_widget_get_style_context (button), "flat");
+ gtk_widget_show (button);
+
+ hdy_tab_bar_set_start_action_widget (tab_bar, button);
+ } else {
+ g_signal_connect_object (EPHY_SETTINGS_UI,
+ "changed::" EPHY_PREFS_UI_TABS_BAR_VISIBILITY_POLICY,
+ G_CALLBACK (visibility_policy_changed_cb), self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (EPHY_SETTINGS_UI,
+ "changed::" EPHY_PREFS_UI_EXPAND_TABS_BAR,
+ G_CALLBACK (expand_changed_cb), self,
+ G_CONNECT_SWAPPED);
+ }
+
+ settings = gtk_settings_get_default ();
+ g_signal_connect_object (settings, "notify::gtk-decoration-layout",
+ G_CALLBACK (notify_decoration_layout_cb), self,
+ G_CONNECT_SWAPPED);
+
+ visibility_policy_changed_cb (self);
+}
diff --git a/src/ephy-tab-view.h b/src/ephy-tab-view.h
new file mode 100644
index 000000000..fb8e0dc57
--- /dev/null
+++ b/src/ephy-tab-view.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 2; indent-pages-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2020 Alexander Mikhaylenko <exalm7659 gmail com>
+ *
+ * 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 "ephy-embed.h"
+
+#include <handy.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_TAB_VIEW (ephy_tab_view_get_type())
+
+G_DECLARE_FINAL_TYPE (EphyTabView, ephy_tab_view, EPHY, TAB_VIEW, GtkBin)
+
+EphyTabView *ephy_tab_view_new (void);
+
+void ephy_tab_view_next (EphyTabView *self);
+
+void ephy_tab_view_pin (EphyTabView *self);
+void ephy_tab_view_unpin (EphyTabView *self);
+
+void ephy_tab_view_close (EphyTabView *self,
+ GtkWidget *widget);
+void ephy_tab_view_close_selected (EphyTabView *self);
+void ephy_tab_view_close_left (EphyTabView *self);
+void ephy_tab_view_close_right (EphyTabView *self);
+void ephy_tab_view_close_other (EphyTabView *self);
+
+void ephy_tab_view_foreach (EphyTabView *self,
+ GtkCallback callback,
+ gpointer user_data);
+
+gint ephy_tab_view_get_n_pages (EphyTabView *self);
+gint ephy_tab_view_get_selected_index (EphyTabView *self);
+gint ephy_tab_view_get_page_index (EphyTabView *self,
+ GtkWidget *widget);
+
+GtkWidget *ephy_tab_view_get_nth_page (EphyTabView *self,
+ gint index);
+void ephy_tab_view_select_nth_page (EphyTabView *self,
+ gint index);
+
+gboolean ephy_tab_view_select_page (EphyTabView *self,
+ GtkWidget *widget);
+
+GtkWidget *ephy_tab_view_get_selected_page (EphyTabView *self);
+
+HdyTabView *ephy_tab_view_get_tab_view (EphyTabView *self);
+
+GList *ephy_tab_view_get_pages (EphyTabView *self);
+
+gboolean ephy_tab_view_get_is_pinned (EphyTabView *self,
+ GtkWidget *widget);
+
+gint ephy_tab_view_add_tab (EphyTabView *self,
+ EphyEmbed *embed,
+ EphyEmbed *parent,
+ int position,
+ gboolean jump_to);
+
+GtkWidget *ephy_tab_view_get_current_page (EphyTabView *self);
+
+void ephy_tab_view_set_tab_bar (EphyTabView *self,
+ HdyTabBar *tab_bar);
+
+G_END_DECLS
diff --git a/src/ephy-window.c b/src/ephy-window.c
index 9b5f3707e..6882bf143 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -45,7 +45,7 @@
#include "ephy-link.h"
#include "ephy-location-entry.h"
#include "ephy-mouse-gesture-controller.h"
-#include "ephy-notebook.h"
+#include "ephy-pages-popover.h"
#include "ephy-pages-view.h"
#include "ephy-permissions-manager.h"
#include "ephy-prefs.h"
@@ -130,10 +130,6 @@ const struct {
{ "toolbar.combined-stop-reload", { NULL } },
/* Tabs */
- { "tab.previous", { "<Primary>Page_Up", "<Primary>KP_9", "<shift><Primary>Tab", NULL } },
- { "tab.next", { "<Primary>Page_Down", "<Primary>KP_3", "<Primary>Tab", NULL } },
- { "tab.move-left", { "<shift><Primary>Page_Up", NULL } },
- { "tab.move-right", { "<shift><Primary>Page_Down", NULL } },
{ "tab.duplicate", { "<shift><Primary>K", NULL } },
{ "tab.close", { "<Primary>W", NULL } },
{ "tab.mute", { "<Primary>M", NULL } },
@@ -154,11 +150,16 @@ struct _EphyWindow {
GtkWidget *main_deck;
EphyFullscreenBox *fullscreen_box;
GtkWidget *window_handle;
+ GtkBox *titlebar_box;
GtkWidget *header_bar;
EphyPagesView *pages_view;
EphyBookmarksManager *bookmarks_manager;
GHashTable *action_labels;
- GtkNotebook *notebook;
+ EphyTabView *tab_view;
+ HdyTabBar *tab_bar;
+ GtkRevealer *tab_bar_revealer;
+ GtkRevealer *pages_menu_revealer;
+ EphyPagesPopover *pages_popover;
GtkWidget *action_bar;
EphyEmbed *active_embed;
EphyWindowChrome chrome;
@@ -216,28 +217,30 @@ enum {
static gint
impl_add_child (EphyEmbedContainer *container,
EphyEmbed *child,
- gint position,
+ EphyEmbed *parent,
+ int position,
gboolean jump_to)
{
EphyWindow *window = EPHY_WINDOW (container);
+ int ret;
- g_assert (!window->is_popup || gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) < 1);
+ g_assert (!window->is_popup || ephy_tab_view_get_n_pages (window->tab_view) < 1);
- return ephy_notebook_add_tab (EPHY_NOTEBOOK (window->notebook),
- child, position, jump_to);
+ ret = ephy_tab_view_add_tab (window->tab_view, child, parent, position, jump_to);
+
+ if (jump_to)
+ ephy_window_update_entry_focus (window, ephy_embed_get_web_view (child));
+
+ return ret;
}
static void
impl_set_active_child (EphyEmbedContainer *container,
EphyEmbed *child)
{
- int page;
- EphyWindow *window;
-
- window = EPHY_WINDOW (container);
+ EphyWindow *window = EPHY_WINDOW (container);
- page = gtk_notebook_page_num (window->notebook, GTK_WIDGET (child));
- gtk_notebook_set_current_page (window->notebook, page);
+ ephy_tab_view_select_page (window->tab_view, GTK_WIDGET (child));
}
static GtkWidget *
@@ -307,12 +310,9 @@ static void
impl_remove_child (EphyEmbedContainer *container,
EphyEmbed *child)
{
- EphyWindow *window;
+ EphyWindow *window = EPHY_WINDOW (container);
- window = EPHY_WINDOW (container);
- g_signal_emit_by_name (window->notebook,
- "tab-close-request",
- child, window);
+ ephy_tab_view_close (window->tab_view, GTK_WIDGET (child));
}
static EphyEmbed *
@@ -326,7 +326,7 @@ impl_get_children (EphyEmbedContainer *container)
{
EphyWindow *window = EPHY_WINDOW (container);
- return gtk_container_get_children (GTK_CONTAINER (window->notebook));
+ return ephy_tab_view_get_pages (window->tab_view);
}
static gboolean
@@ -340,7 +340,7 @@ impl_get_n_children (EphyEmbedContainer *container)
{
EphyWindow *window = EPHY_WINDOW (container);
- return gtk_notebook_get_n_pages (window->notebook);
+ return ephy_tab_view_get_n_pages (window->tab_view);
}
static void
@@ -444,8 +444,8 @@ sync_chromes_visibility (EphyWindow *window)
show_tabsbar = (window->chrome & EPHY_WINDOW_CHROME_TABSBAR);
- ephy_notebook_set_tabs_allowed (EPHY_NOTEBOOK (window->notebook),
- show_tabsbar && !(window->is_popup || window->is_fullscreen));
+ gtk_widget_set_visible (GTK_WIDGET (window->tab_bar_revealer),
+ show_tabsbar && !(window->is_popup));
}
static void
@@ -518,7 +518,6 @@ update_adaptive_mode (EphyWindow *window)
{
EphyHeaderBar *header_bar = EPHY_HEADER_BAR (ephy_window_get_header_bar (window));
EphyActionBar *action_bar = EPHY_ACTION_BAR (window->action_bar);
- EphyNotebook *notebook = EPHY_NOTEBOOK (window->notebook);
gboolean is_narrow, is_mobile_landscape;
EphyAdaptiveMode adaptive_mode;
gint width, height;
@@ -551,7 +550,9 @@ update_adaptive_mode (EphyWindow *window)
EPHY_ADAPTIVE_MODE_NORMAL;
ephy_header_bar_set_adaptive_mode (header_bar, adaptive_mode);
ephy_action_bar_set_adaptive_mode (action_bar, adaptive_mode);
- ephy_notebook_set_adaptive_mode (notebook, adaptive_mode);
+
+ gtk_revealer_set_reveal_child (window->tab_bar_revealer,
+ adaptive_mode == EPHY_ADAPTIVE_MODE_NORMAL);
/* When switching to desktop sizes, drop the tabs view and go back
* to the main view.
@@ -574,7 +575,6 @@ ephy_window_fullscreen (EphyWindow *window)
sync_tab_security (ephy_embed_get_web_view (embed), NULL, window);
update_adaptive_mode (window);
- sync_chromes_visibility (window);
ephy_embed_entering_fullscreen (embed);
}
@@ -585,7 +585,6 @@ ephy_window_unfullscreen (EphyWindow *window)
g_object_notify (G_OBJECT (window), "fullscreen");
update_adaptive_mode (window);
- sync_chromes_visibility (window);
ephy_embed_leaving_fullscreen (window->active_embed);
}
@@ -619,24 +618,33 @@ ephy_window_should_view_receive_key_press_event (EphyWindow *window,
/* Websites are allowed to override most Epiphany accelerators, but not
* window or tab management accelerators. */
if ((event->state & state_mask) == GDK_CONTROL_MASK)
- return keyval != GDK_KEY_n && /* New Window */
- keyval != GDK_KEY_q && /* Quit */
- keyval != GDK_KEY_T && /* Reopen Closed Tab */
- keyval != GDK_KEY_t && /* New Tab */
- keyval != GDK_KEY_w && /* Close Tab */
- keyval != GDK_KEY_Page_Up && /* Previous Tab */
- keyval != GDK_KEY_KP_9 && /* Previous Tab */
- keyval != GDK_KEY_Page_Down && /* Next Tab */
- keyval != GDK_KEY_KP_3 && /* Next Tab */
- keyval != GDK_KEY_Tab && /* Next Tab */
- keyval != GDK_KEY_ISO_Left_Tab; /* Previous Tab (Shift+Tab -> ISO Left Tab) */
+ return keyval != GDK_KEY_n && /* New Window */
+ keyval != GDK_KEY_q && /* Quit */
+ keyval != GDK_KEY_T && /* Reopen Closed Tab */
+ keyval != GDK_KEY_t && /* New Tab */
+ keyval != GDK_KEY_w && /* Close Tab */
+ keyval != GDK_KEY_Page_Up && /* Previous Tab */
+ keyval != GDK_KEY_KP_Page_Up && /* Previous Tab */
+ keyval != GDK_KEY_Page_Down && /* Next Tab */
+ keyval != GDK_KEY_KP_Page_Down && /* Next Tab */
+ keyval != GDK_KEY_Home && /* First Tab */
+ keyval != GDK_KEY_KP_Home && /* First Tab */
+ keyval != GDK_KEY_End && /* Last Tab */
+ keyval != GDK_KEY_KP_End && /* Last Tab */
+ keyval != GDK_KEY_Tab && /* Next Tab */
+ keyval != GDK_KEY_KP_Tab && /* Next Tab */
+ keyval != GDK_KEY_ISO_Left_Tab; /* Previous Tab (Shift+Tab -> ISO Left Tab) */
if ((event->state & state_mask) == (GDK_SHIFT_MASK | GDK_CONTROL_MASK))
- return keyval != GDK_KEY_n && /* New Incognito Window */
- keyval != GDK_KEY_Page_Up && /* Move Tab Left */
- keyval != GDK_KEY_KP_9 && /* Move Tab Left */
- keyval != GDK_KEY_Page_Down && /* Move Tab Right */
- keyval != GDK_KEY_KP_3; /* Move Tab Right */
+ return keyval != GDK_KEY_n && /* New Incognito Window */
+ keyval != GDK_KEY_Page_Up && /* Move Tab Left */
+ keyval != GDK_KEY_KP_Page_Up && /* Move Tab Left */
+ keyval != GDK_KEY_Page_Down && /* Move Tab Right */
+ keyval != GDK_KEY_KP_Page_Down && /* Move Tab Right */
+ keyval != GDK_KEY_Home && /* First Tab */
+ keyval != GDK_KEY_KP_Home && /* First Tab */
+ keyval != GDK_KEY_End && /* Last Tab */
+ keyval != GDK_KEY_KP_End; /* Last Tab */
if ((event->state & state_mask) == GDK_MOD1_MASK)
return keyval != GDK_KEY_Left && /* Back */
@@ -876,22 +884,16 @@ static const GActionEntry window_entries [] = {
{ "content", window_cmd_go_content },
{ "tabs-view", window_cmd_go_tabs_view },
- { "show-tab", window_cmd_show_tab, "u", "uint32 0", window_cmd_change_show_tab_state },
-
/* Toggle actions */
{ "browse-with-caret", NULL, NULL, "false", window_cmd_change_browse_with_caret_state },
{ "fullscreen", NULL, NULL, "false", window_cmd_change_fullscreen_state },
};
static const GActionEntry tab_entries [] = {
- { "previous", window_cmd_tabs_previous },
- { "next", window_cmd_tabs_next },
{ "duplicate", window_cmd_tabs_duplicate },
{ "close", window_cmd_tabs_close },
{ "close-left", window_cmd_tabs_close_left },
{ "close-right", window_cmd_tabs_close_right },
- { "move-left", window_cmd_tabs_move_left },
- { "move-right", window_cmd_tabs_move_right },
{ "close-others", window_cmd_tabs_close_others },
{ "reload-all", window_cmd_tabs_reload_all_tabs },
{ "pin", window_cmd_tabs_pin },
@@ -2586,218 +2588,68 @@ ephy_window_set_active_tab (EphyWindow *window,
}
static void
-tab_accels_item_activate (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
-{
- const char *action_name;
- int tab_number;
-
- action_name = g_action_get_name (G_ACTION (action));
-
- tab_number = atoi (action_name + strlen ("accel-"));
-
- gtk_notebook_set_current_page (EPHY_WINDOW (user_data)->notebook, tab_number);
-}
-
-static void
-tab_accels_update (EphyWindow *window)
+tab_view_setup_menu_cb (HdyTabView *tab_view,
+ HdyTabPage *page,
+ EphyWindow *window)
{
- int n_pages;
- int i = 0;
- GActionGroup *action_group;
- char **actions;
-
- action_group = gtk_widget_get_action_group (GTK_WIDGET (window), "tab");
- actions = g_action_group_list_actions (action_group);
-
- n_pages = gtk_notebook_get_n_pages (window->notebook);
- for (i = 0; actions[i] != NULL; i++) {
- if (strstr (actions[i], "accel-") != NULL) {
- GAction *action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
- actions[i]);
- int tab_number = atoi (actions[i] + strlen ("accel-"));
-
- g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (tab_number < n_pages));
- }
- }
-
- g_strfreev (actions);
-}
-
-static void
-last_tab_accel_activate (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
-{
- EphyWindow *window = EPHY_WINDOW (user_data);
- EphyNotebook *notebook = EPHY_NOTEBOOK (window->notebook);
-
- ephy_notebook_switch_to_last_tab (notebook);
-}
-
-#define TAB_ACCELS_N 10
-
-static void
-setup_tab_accels (EphyWindow *window)
-{
- GActionGroup *action_group;
- GApplication *app;
- guint i;
- GSimpleAction *last_tab_action;
-
- action_group = gtk_widget_get_action_group (GTK_WIDGET (window), "tab");
- app = g_application_get_default ();
-
- for (i = 0; i < TAB_ACCELS_N - 1; i++) {
- GSimpleAction *simple_action;
- char *action_name;
- char *action_name_with_tab;
- char *accel;
-
- action_name = g_strdup_printf ("accel-%u", i);
- action_name_with_tab = g_strconcat ("tab.", action_name, NULL);
- accel = g_strdup_printf ("<alt>%u", (i + 1) % TAB_ACCELS_N);
-
- simple_action = g_simple_action_new (action_name, NULL);
-
- g_action_map_add_action (G_ACTION_MAP (action_group), G_ACTION (simple_action));
- gtk_application_set_accels_for_action (GTK_APPLICATION (app),
- action_name_with_tab,
- (const gchar *[]) {accel, NULL});
-
- g_signal_connect (G_ACTION (simple_action), "activate",
- G_CALLBACK (tab_accels_item_activate), window);
-
- g_object_unref (simple_action);
- g_free (accel);
- g_free (action_name);
- g_free (action_name_with_tab);
- }
-
- last_tab_action = g_simple_action_new ("switch-to-last-tab", NULL);
- g_action_map_add_action (G_ACTION_MAP (action_group), G_ACTION (last_tab_action));
- gtk_application_set_accels_for_action (GTK_APPLICATION (app),
- "tab.switch-to-last-tab",
- (const gchar *[]) {"<alt>0", NULL});
-
- g_signal_connect (G_ACTION (last_tab_action), "activate",
- G_CALLBACK (last_tab_accel_activate), window);
- g_object_unref (last_tab_action);
-}
-
-static gboolean
-show_notebook_popup_menu (GtkNotebook *notebook,
- EphyWindow *window,
- GdkEventButton *event)
-{
- GtkWidget *menu, *tab, *tab_label;
- GMenu *menu_model;
- GtkBuilder *builder;
+ EphyWebView *view;
GActionGroup *action_group;
GAction *action;
+ int n_pages;
+ int n_pinned_pages;
+ int position;
+ gboolean pinned;
+ gboolean audio_playing;
+ gboolean muted;
- builder = gtk_builder_new_from_resource ("/org/gnome/epiphany/gtk/notebook-context-menu.ui");
-
- menu_model = G_MENU (gtk_builder_get_object (builder, "notebook-menu"));
- menu = gtk_menu_new_from_model (G_MENU_MODEL (menu_model));
- gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (window->active_embed), NULL);
-
- action_group = gtk_widget_get_action_group (GTK_WIDGET (window), "tab");
-
- if (event != NULL) {
- EphyWebView *view;
- int n_pages;
- int page_num;
- gboolean pinned;
- gboolean audio_playing;
- gboolean muted;
-
- tab = GTK_WIDGET (window->active_embed);
- n_pages = gtk_notebook_get_n_pages (notebook);
- page_num = gtk_notebook_page_num (notebook, tab);
- pinned = ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), EPHY_EMBED (tab));
+ if (page) {
+ n_pages = hdy_tab_view_get_n_pages (tab_view);
+ n_pinned_pages = hdy_tab_view_get_n_pinned_pages (tab_view);
+ position = hdy_tab_view_get_page_position (tab_view, page);
+ pinned = hdy_tab_page_get_pinned (page);
- view = ephy_embed_get_web_view (EPHY_EMBED (tab));
+ view = ephy_embed_get_web_view (EPHY_EMBED (hdy_tab_page_get_child (page)));
audio_playing = webkit_web_view_is_playing_audio (WEBKIT_WEB_VIEW (view));
muted = webkit_web_view_get_is_muted (WEBKIT_WEB_VIEW (view));
+ }
- /* enable/disable close others/left/right */
- action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
- "close-left");
- g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (page_num > 0) && !pinned);
-
- action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
- "close-right");
- g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (page_num < n_pages - 1) && !pinned);
-
- action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
- "close-others");
- g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (n_pages > 1) && !pinned);
-
- action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
- "reload-all");
- g_simple_action_set_enabled (G_SIMPLE_ACTION (action), n_pages > 1);
-
- action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
- "pin");
- g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !pinned);
-
- action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
- "unpin");
- g_simple_action_set_enabled (G_SIMPLE_ACTION (action), pinned);
-
- action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
- "mute");
- g_simple_action_set_enabled (G_SIMPLE_ACTION (action), audio_playing);
- g_simple_action_set_state (G_SIMPLE_ACTION (action),
- g_variant_new_boolean (muted));
+ action_group = gtk_widget_get_action_group (GTK_WIDGET (window), "tab");
- action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
- "close");
- g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !pinned);
+ /* enable/disable close others/left/right */
+ /* If there's no page, enable all actions so that we don't interfere with hotkeys */
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "close-left");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !page || position > n_pinned_pages);
- gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *)event);
- } else {
- tab = GTK_WIDGET (window->active_embed);
- tab_label = gtk_notebook_get_tab_label (notebook, tab);
-
- /* Not tested, because I don't know how to trigger this code. */
- gtk_menu_popup_at_widget (GTK_MENU (menu),
- tab_label,
- GDK_GRAVITY_SOUTH_WEST,
- GDK_GRAVITY_NORTH_WEST,
- NULL);
- gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
- }
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "close-right");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !page || (position < n_pages - 1 && !pinned));
- g_object_unref (builder);
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "close-others");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !page || (n_pages > n_pinned_pages + 1 && !pinned));
- return TRUE;
-}
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "reload-all");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !page || n_pages > 1);
-static gboolean
-notebook_button_press_cb (GtkNotebook *notebook,
- GdkEventButton *event,
- EphyWindow *window)
-{
- if (GDK_BUTTON_PRESS == event->type && 3 == event->button) {
- return show_notebook_popup_menu (notebook, window, event);
- }
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "pin");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !page || !pinned);
- return FALSE;
-}
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "unpin");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !page || pinned);
-static gboolean
-notebook_popup_menu_cb (GtkNotebook *notebook,
- EphyWindow *window)
-{
- /* Only respond if the notebook is the actual focus */
- if (EPHY_IS_NOTEBOOK (gtk_window_get_focus (GTK_WINDOW (window)))) {
- return show_notebook_popup_menu (notebook, window, NULL);
- }
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "mute");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !page || audio_playing);
+ g_simple_action_set_state (G_SIMPLE_ACTION (action),
+ g_variant_new_boolean (!page || muted));
- return FALSE;
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "close");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !page || !pinned);
}
static gboolean
@@ -2829,7 +2681,7 @@ download_only_load_cb (EphyWebView *view,
if (ephy_web_view_get_document_type (view) == EPHY_WEB_VIEW_DOCUMENT_PDF)
return;
- if (gtk_notebook_get_n_pages (window->notebook) == 1) {
+ if (ephy_tab_view_get_n_pages (window->tab_view) == 1) {
ephy_web_view_load_homepage (view);
return;
}
@@ -2869,14 +2721,19 @@ reader_mode_cb (EphyWebView *view,
}
static void
-notebook_page_added_cb (EphyNotebook *notebook,
- EphyEmbed *embed,
- guint position,
- EphyWindow *window)
+tab_view_page_attached_cb (HdyTabView *tab_view,
+ HdyTabPage *page,
+ gint position,
+ EphyWindow *window)
{
- LOG ("page-added notebook %p embed %p position %u\n", notebook, embed, position);
+ GtkWidget *content = hdy_tab_page_get_child (page);
+ EphyEmbed *embed;
- g_assert (EPHY_IS_EMBED (embed));
+ g_assert (EPHY_IS_EMBED (content));
+
+ embed = EPHY_EMBED (content);
+
+ LOG ("page-attached tab view %p embed %p position %d\n", tab_view, embed, position);
g_signal_connect_object (ephy_embed_get_web_view (embed), "download-only-load",
G_CALLBACK (download_only_load_cb), window, G_CONNECT_AFTER);
@@ -2888,29 +2745,27 @@ notebook_page_added_cb (EphyNotebook *notebook,
window->present_on_insert = FALSE;
g_idle_add ((GSourceFunc)present_on_idle_cb, g_object_ref (window));
}
-
- tab_accels_update (window);
}
static void
-notebook_page_removed_cb (EphyNotebook *notebook,
- EphyEmbed *embed,
- guint position,
- EphyWindow *window)
+tab_view_page_detached_cb (HdyTabView *tab_view,
+ HdyTabPage *page,
+ gint position,
+ EphyWindow *window)
{
- LOG ("page-removed notebook %p embed %p position %u\n", notebook, embed, position);
+ GtkWidget *content = hdy_tab_page_get_child (page);
+
+ LOG ("page-detached tab view %p embed %p position %d\n", tab_view, content, position);
if (window->closing)
return;
- g_assert (EPHY_IS_EMBED (embed));
+ g_assert (EPHY_IS_EMBED (content));
g_signal_handlers_disconnect_by_func
- (ephy_embed_get_web_view (embed), G_CALLBACK (download_only_load_cb), window);
-
- tab_accels_update (window);
+ (ephy_embed_get_web_view (EPHY_EMBED (content)), G_CALLBACK (download_only_load_cb), window);
- if (gtk_notebook_get_n_pages (window->notebook) == 0) {
+ if (ephy_tab_view_get_n_pages (window->tab_view) == 0) {
EphyShell *shell = ephy_shell_get_default ();
GList *windows = gtk_application_get_windows (GTK_APPLICATION (shell));
@@ -2951,7 +2806,7 @@ ephy_window_close_tab (EphyWindow *window,
if (mode != EPHY_EMBED_SHELL_MODE_AUTOMATION)
keep_window_open = g_settings_get_boolean (EPHY_SETTINGS_UI, EPHY_PREFS_UI_KEEP_WINDOW_OPEN);
- if (keep_window_open && gtk_notebook_get_n_pages (window->notebook) == 1) {
+ if (keep_window_open && ephy_tab_view_get_n_pages (window->tab_view) == 1) {
EphyWebView *view = ephy_embed_get_web_view (tab);
if (ephy_web_view_get_is_blank (view) || ephy_web_view_is_overview (view))
@@ -2961,7 +2816,6 @@ ephy_window_close_tab (EphyWindow *window,
}
g_object_set_data (G_OBJECT (tab), "ephy-window-close-tab-closed", GINT_TO_POINTER (TRUE));
- gtk_widget_destroy (GTK_WIDGET (tab));
if (window->last_opened_embed)
g_clear_weak_pointer ((gpointer *)&window->last_opened_embed);
@@ -2972,26 +2826,29 @@ ephy_window_close_tab (EphyWindow *window,
* Beware: window->closing could be true now, after destroying the
* tab, even if it wasn't at the start of this function.
*/
- if (!window->closing && gtk_notebook_get_n_pages (window->notebook) == 0)
+ if (!window->closing && ephy_tab_view_get_n_pages (window->tab_view) == 0)
gtk_widget_destroy (GTK_WIDGET (window));
}
typedef struct {
EphyWindow *window;
EphyEmbed *embed;
+ HdyTabPage *page;
guint id;
} TabHasModifiedFormsData;
static TabHasModifiedFormsData *
tab_has_modified_forms_data_new (EphyWindow *window,
- EphyEmbed *embed)
+ EphyEmbed *embed,
+ HdyTabPage *page)
{
TabHasModifiedFormsData *data = g_new (TabHasModifiedFormsData, 1);
data->window = window;
- data->embed = embed;
+ data->embed = g_object_ref (embed);
+ data->page = page;
data->id = 0;
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&data->window);
- g_object_add_weak_pointer (G_OBJECT (embed), (gpointer *)&data->embed);
+ g_object_add_weak_pointer (G_OBJECT (page), (gpointer *)&data->page);
return data;
}
@@ -2999,7 +2856,8 @@ static void
tab_has_modified_forms_data_free (TabHasModifiedFormsData *data)
{
g_clear_weak_pointer (&data->window);
- g_clear_weak_pointer (&data->embed);
+ g_clear_object (&data->embed);
+ g_clear_weak_pointer (&data->page);
g_clear_handle_id (&data->id, g_source_remove);
g_clear_pointer (&data, g_free);
}
@@ -3021,8 +2879,14 @@ tab_has_modified_forms_cb (EphyWebView *view,
if (data->id != 0 &&
data->window != NULL &&
data->embed != NULL &&
- (!has_modified_forms || confirm_close_with_modified_forms (data->window))) {
- ephy_window_close_tab (data->window, data->embed);
+ data->page != NULL) {
+ HdyTabView *tab_view = ephy_tab_view_get_tab_view (data->window->tab_view);
+
+ if (!has_modified_forms || confirm_close_with_modified_forms (data->window)) {
+ hdy_tab_view_close_page_finish (tab_view, data->page, TRUE);
+ ephy_window_close_tab (data->window, data->embed);
+ } else
+ hdy_tab_view_close_page_finish (tab_view, data->page, FALSE);
}
data->id = 0;
@@ -3039,9 +2903,17 @@ tab_has_modified_forms_timeout_cb (TabHasModifiedFormsData *data)
* ephy_window_close_tab().
*/
data->id = 0;
- if (data->window != NULL && data->embed != NULL)
+ if (data->window != NULL &&
+ data->embed != NULL &&
+ data->page != NULL) {
+ HdyTabView *tab_view = ephy_tab_view_get_tab_view (data->window->tab_view);
+ HdyTabPage *page = data->page;
+
ephy_window_close_tab (data->window, data->embed);
+ hdy_tab_view_close_page_finish (tab_view, page, TRUE);
+ }
+
return G_SOURCE_REMOVE;
}
@@ -3066,15 +2938,21 @@ run_downloads_in_background (EphyWindow *window,
gtk_widget_hide (GTK_WIDGET (window));
}
-static void
-notebook_page_close_request_cb (EphyNotebook *notebook,
- EphyEmbed *embed,
- EphyWindow *window)
+static gboolean
+tab_view_close_page_cb (HdyTabView *tab_view,
+ HdyTabPage *page,
+ EphyWindow *window)
{
- if (gtk_notebook_get_n_pages (window->notebook) == 1) {
+ EphyEmbed *embed = EPHY_EMBED (hdy_tab_page_get_child (page));
+
+ if (hdy_tab_page_get_pinned (page))
+ return GDK_EVENT_PROPAGATE;
+
+ if (ephy_tab_view_get_n_pages (window->tab_view) == 1) {
if (g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN,
EPHY_PREFS_LOCKDOWN_QUIT)) {
- return;
+ hdy_tab_view_close_page_finish (tab_view, page, FALSE);
+ return GDK_EVENT_STOP;
}
if (ephy_embed_shell_get_mode (ephy_embed_shell_get_default ()) == EPHY_EMBED_SHELL_MODE_AUTOMATION) {
@@ -3089,7 +2967,8 @@ notebook_page_close_request_cb (EphyNotebook *notebook,
if (ephy_downloads_manager_has_active_downloads (manager)) {
GList *list = ephy_downloads_manager_get_downloads (manager);
run_downloads_in_background (window, g_list_length (list));
- return;
+ hdy_tab_view_close_page_finish (tab_view, page, FALSE);
+ return GDK_EVENT_STOP;
}
}
}
@@ -3104,23 +2983,23 @@ notebook_page_close_request_cb (EphyNotebook *notebook,
* also be caused by a network process hang!) We'll assume the process has
* been hung if there's no response after one second.
*/
- data = tab_has_modified_forms_data_new (window, embed);
+ data = tab_has_modified_forms_data_new (window, embed, page);
data->id = g_timeout_add_seconds (1, (GSourceFunc)tab_has_modified_forms_timeout_cb, data);
ephy_web_view_has_modified_forms (ephy_embed_get_web_view (embed),
NULL,
(GAsyncReadyCallback)tab_has_modified_forms_cb,
data);
+ return GDK_EVENT_STOP;
} else {
ephy_window_close_tab (window, embed);
}
+
+ return GDK_EVENT_PROPAGATE;
}
-static GtkWidget *
-notebook_create_window_cb (GtkNotebook *notebook,
- GtkWidget *page,
- int x,
- int y,
- EphyWindow *window)
+static HdyTabView *
+tab_view_create_window_cb (HdyTabView *tab_view,
+ EphyWindow *window)
{
EphyWindow *new_window;
@@ -3129,24 +3008,7 @@ notebook_create_window_cb (GtkNotebook *notebook,
new_window->present_on_insert = TRUE;
new_window->present_on_insert_user_time = gtk_get_current_event_time ();
- return ephy_window_get_notebook (new_window);
-}
-
-static EphyEmbed *
-real_get_active_tab (EphyWindow *window,
- int page_num)
-{
- GtkWidget *embed;
-
- if (page_num == -1) {
- page_num = gtk_notebook_get_current_page (window->notebook);
- }
-
- embed = gtk_notebook_get_nth_page (window->notebook, page_num);
-
- g_assert (EPHY_IS_EMBED (embed));
-
- return EPHY_EMBED (embed);
+ return ephy_tab_view_get_tab_view (new_window->tab_view);
}
void
@@ -3169,81 +3031,83 @@ ephy_window_update_entry_focus (EphyWindow *window,
}
static void
-notebook_switch_page_cb (GtkNotebook *notebook,
- GtkWidget *page,
- guint page_num,
- EphyWindow *window)
+tab_view_notify_selected_page_cb (EphyWindow *window)
{
EphyEmbed *embed;
- GActionGroup *group;
- GAction *action;
EphyWebView *view;
-
- LOG ("switch-page notebook %p position %u\n", notebook, page_num);
+ int page_num;
if (window->closing)
return;
+ page_num = ephy_tab_view_get_selected_index (window->tab_view);
+
+ if (page_num < 0)
+ return;
+
+ LOG ("switch-page tab view %p position %d\n", window->tab_view, page_num);
+
/* get the new tab */
- embed = real_get_active_tab (window, page_num);
+
+ embed = EPHY_EMBED (ephy_tab_view_get_nth_page (window->tab_view, page_num));
view = ephy_embed_get_web_view (embed);
/* update new tab */
ephy_window_set_active_tab (window, embed);
- /* update notebook menu */
- group = gtk_widget_get_action_group (GTK_WIDGET (window), "win");
- action = g_action_map_lookup_action (G_ACTION_MAP (group), "show-tab");
- g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_uint32 (page_num));
-
update_reader_mode (window, view);
-
- ephy_window_update_entry_focus (window, view);
}
static void
-notebook_page_reordered_cb (GtkNotebook *notebook,
- GtkWidget *child,
- guint page_num,
- gpointer user_data)
+tab_view_page_reordered_cb (EphyWindow *window)
{
- EphyWindow *window = EPHY_WINDOW (user_data);
-
window->last_opened_embed = NULL;
}
-static GtkNotebook *
-setup_notebook (EphyWindow *window)
+static EphyTabView *
+setup_tab_view (EphyWindow *window)
{
- GtkNotebook *notebook;
-
- notebook = GTK_NOTEBOOK (g_object_new (EPHY_TYPE_NOTEBOOK, NULL));
-
- g_signal_connect_after (notebook, "switch-page",
- G_CALLBACK (notebook_switch_page_cb),
- window);
- g_signal_connect (notebook, "create-window",
- G_CALLBACK (notebook_create_window_cb),
- window);
+ EphyTabView *tab_view = ephy_tab_view_new ();
+ HdyTabView *view = ephy_tab_view_get_tab_view (tab_view);
+ g_autoptr (GtkBuilder) builder = NULL;
- g_signal_connect (notebook, "popup-menu",
- G_CALLBACK (notebook_popup_menu_cb), window);
- g_signal_connect (notebook, "button-press-event",
- G_CALLBACK (notebook_button_press_cb), window);
-
- g_signal_connect (notebook, "page-added",
- G_CALLBACK (notebook_page_added_cb), window);
- g_signal_connect (notebook, "page-removed",
- G_CALLBACK (notebook_page_removed_cb), window);
- g_signal_connect (notebook, "tab-close-request",
- G_CALLBACK (notebook_page_close_request_cb), window);
- g_signal_connect (notebook, "page-reordered",
- G_CALLBACK (notebook_page_reordered_cb), window);
-
- g_signal_connect_swapped (notebook, "open-link",
- G_CALLBACK (ephy_link_open), window);
+ builder = gtk_builder_new_from_resource ("/org/gnome/epiphany/gtk/notebook-context-menu.ui");
- return notebook;
+ hdy_tab_view_set_menu_model (view, G_MENU_MODEL (gtk_builder_get_object (builder, "notebook-menu")));
+ hdy_tab_view_set_shortcut_widget (view, GTK_WIDGET (window));
+
+ g_signal_connect_object (view, "notify::selected-page",
+ G_CALLBACK (tab_view_notify_selected_page_cb),
+ window,
+ G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (view, "create-window",
+ G_CALLBACK (tab_view_create_window_cb),
+ window,
+ 0);
+ g_signal_connect_object (view, "setup-menu",
+ G_CALLBACK (tab_view_setup_menu_cb),
+ window,
+ 0);
+ g_signal_connect_object (view, "close-page",
+ G_CALLBACK (tab_view_close_page_cb),
+ window,
+ 0);
+
+ g_signal_connect_object (view, "page-attached",
+ G_CALLBACK (tab_view_page_attached_cb),
+ window,
+ 0);
+ g_signal_connect_object (view, "page-detached",
+ G_CALLBACK (tab_view_page_detached_cb),
+ window,
+ 0);
+ g_signal_connect_object (view, "page-reordered",
+ G_CALLBACK (tab_view_page_reordered_cb),
+ window,
+ G_CONNECT_SWAPPED);
+
+ return tab_view;
}
static void
@@ -3346,10 +3210,8 @@ ephy_window_state_event (GtkWidget *widget,
ephy_window_unfullscreen (window);
}
- ephy_fullscreen_box_set_fullscreen (window->fullscreen_box,
- fullscreen && window->show_fullscreen_header_bar);
- gtk_widget_set_visible (GTK_WIDGET (window->window_handle),
- !fullscreen || window->show_fullscreen_header_bar);
+ ephy_fullscreen_box_set_fullscreen (window->fullscreen_box, fullscreen &&
window->show_fullscreen_header_bar);
+ gtk_widget_set_visible (GTK_WIDGET (window->titlebar_box), !fullscreen ||
window->show_fullscreen_header_bar);
window->show_fullscreen_header_bar = FALSE;
@@ -3561,6 +3423,50 @@ setup_header_bar (EphyWindow *window)
return header_bar;
}
+static void
+update_pages_menu_revealer (EphyWindow *window)
+{
+ gtk_revealer_set_reveal_child (window->pages_menu_revealer,
+ hdy_tab_bar_get_is_overflowing (window->tab_bar) ||
+ gtk_widget_get_visible (GTK_WIDGET (window->pages_popover)));
+}
+
+static void
+setup_tabs_menu (EphyWindow *window)
+{
+ GtkRevealer *revealer;
+ GtkWidget *menu_button;
+ EphyPagesPopover *popover;
+
+ revealer = GTK_REVEALER (gtk_revealer_new ());
+ gtk_revealer_set_transition_type (revealer,
+ GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT);
+ hdy_tab_bar_set_end_action_widget (window->tab_bar, GTK_WIDGET (revealer));
+ window->pages_menu_revealer = revealer;
+
+ menu_button = gtk_menu_button_new ();
+ gtk_button_set_relief (GTK_BUTTON (menu_button), GTK_RELIEF_NONE);
+ /* Translators: tooltip for the tab switcher menu button */
+ gtk_widget_set_tooltip_text (menu_button, _("View open tabs"));
+ gtk_widget_set_margin_start (menu_button, 1);
+ gtk_container_add (GTK_CONTAINER (revealer), menu_button);
+
+ popover = ephy_pages_popover_new (menu_button);
+ ephy_pages_popover_set_tab_view (popover, window->tab_view);
+ gtk_menu_button_set_popover (GTK_MENU_BUTTON (menu_button),
+ GTK_WIDGET (popover));
+ window->pages_popover = popover;
+
+ g_signal_connect_object (window->tab_bar, "notify::is-overflowing",
+ G_CALLBACK (update_pages_menu_revealer), window,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (window->pages_popover, "notify::visible",
+ G_CALLBACK (update_pages_menu_revealer), window,
+ G_CONNECT_SWAPPED);
+
+ gtk_widget_show_all (GTK_WIDGET (revealer));
+}
+
static EphyLocationController *
setup_location_controller (EphyWindow *window,
EphyHeaderBar *header_bar)
@@ -3826,15 +3732,18 @@ ephy_window_constructed (GObject *object)
ephy_gui_ensure_window_group (GTK_WINDOW (window));
- /* Setup tab accels */
- setup_tab_accels (window);
-
- window->notebook = setup_notebook (window);
+ window->tab_view = setup_tab_view (window);
+ window->tab_bar = hdy_tab_bar_new ();
+ window->tab_bar_revealer = GTK_REVEALER (gtk_revealer_new ());
window->main_deck = hdy_deck_new ();
window->fullscreen_box = ephy_fullscreen_box_new ();
window->pages_view = ephy_pages_view_new ();
- ephy_pages_view_set_notebook (window->pages_view, EPHY_NOTEBOOK (window->notebook));
+ gtk_revealer_set_transition_type (window->tab_bar_revealer, GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN);
+ hdy_tab_bar_set_view (window->tab_bar, ephy_tab_view_get_tab_view (window->tab_view));
+ ephy_pages_view_set_tab_view (window->pages_view, window->tab_view);
+
+ setup_tabs_menu (window);
shell = ephy_shell_get_default ();
mode = ephy_embed_shell_get_mode (EPHY_EMBED_SHELL (shell));
@@ -3850,16 +3759,20 @@ ephy_window_constructed (GObject *object)
window->location_controller = setup_location_controller (window, EPHY_HEADER_BAR (window->header_bar));
window->action_bar = setup_action_bar (window);
box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0));
+ window->titlebar_box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0));
if (g_settings_get_boolean (EPHY_SETTINGS_MAIN, EPHY_PREFS_ASK_FOR_DEFAULT) &&
!is_browser_default () &&
!ephy_profile_dir_is_web_application ())
add_default_browser_question (box);
- gtk_box_pack_start (box, GTK_WIDGET (window->notebook), TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (window->tab_bar_revealer), GTK_WIDGET (window->tab_bar));
+ gtk_box_pack_start (window->titlebar_box, GTK_WIDGET (window->window_handle), FALSE, TRUE, 0);
+ gtk_box_pack_start (window->titlebar_box, GTK_WIDGET (window->tab_bar_revealer), FALSE, TRUE, 0);
+ gtk_box_pack_start (box, GTK_WIDGET (window->tab_view), TRUE, TRUE, 0);
gtk_box_pack_start (box, GTK_WIDGET (window->action_bar), FALSE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (window->fullscreen_box), GTK_WIDGET (box));
- ephy_fullscreen_box_set_titlebar (window->fullscreen_box, GTK_WIDGET (window->window_handle));
+ ephy_fullscreen_box_set_titlebar (window->fullscreen_box, GTK_WIDGET (window->titlebar_box));
gtk_container_add (GTK_CONTAINER (window->main_deck), GTK_WIDGET (window->fullscreen_box));
gtk_container_add (GTK_CONTAINER (window->main_deck), GTK_WIDGET (window->pages_view));
@@ -3867,8 +3780,13 @@ ephy_window_constructed (GObject *object)
gtk_widget_show (GTK_WIDGET (window->main_deck));
gtk_widget_show (GTK_WIDGET (window->pages_view));
gtk_widget_show (GTK_WIDGET (window->fullscreen_box));
+ gtk_widget_show (GTK_WIDGET (window->titlebar_box));
gtk_widget_show (GTK_WIDGET (box));
- gtk_widget_show (GTK_WIDGET (window->notebook));
+ gtk_widget_show (GTK_WIDGET (window->tab_view));
+ gtk_widget_show (GTK_WIDGET (window->tab_bar));
+ gtk_widget_show (GTK_WIDGET (window->tab_bar_revealer));
+
+ ephy_tab_view_set_tab_bar (window->tab_view, window->tab_bar);
hdy_deck_set_visible_child (HDY_DECK (window->main_deck), GTK_WIDGET (window->fullscreen_box));
hdy_deck_set_can_swipe_back (HDY_DECK (window->main_deck), TRUE);
@@ -4016,19 +3934,19 @@ ephy_window_new (void)
}
/**
- * ephy_window_get_notebook:
+ * ephy_window_get_tab_view:
* @window: an #EphyWindow
*
- * Returns the #GtkNotebook used by this window.
+ * Returns the #EphyTabView used by this window.
*
- * Return value: (transfer none): the @window's #GtkNotebook
+ * Return value: (transfer none): the @window's #EphyTabView
**/
-GtkWidget *
-ephy_window_get_notebook (EphyWindow *window)
+EphyTabView *
+ephy_window_get_tab_view (EphyWindow *window)
{
g_assert (EPHY_IS_WINDOW (window));
- return GTK_WIDGET (window->notebook);
+ return window->tab_view;
}
/**
@@ -4347,7 +4265,7 @@ ephy_window_check_modified_forms (EphyWindow *window)
data = g_new0 (ModifiedFormsData, 1);
data->window = window;
data->cancellable = g_cancellable_new ();
- data->embeds_to_check = gtk_notebook_get_n_pages (window->notebook);
+ data->embeds_to_check = ephy_tab_view_get_n_pages (window->tab_view);
tabs = impl_get_children (EPHY_EMBED_CONTAINER (window));
for (l = tabs; l != NULL; l = l->next) {
@@ -4397,7 +4315,7 @@ ephy_window_close (EphyWindow *window)
if (!window->force_close &&
g_settings_get_boolean (EPHY_SETTINGS_MAIN,
EPHY_PREFS_WARN_ON_CLOSE_UNSUBMITTED_DATA) &&
- gtk_notebook_get_n_pages (window->notebook) > 0) {
+ ephy_tab_view_get_n_pages (window->tab_view) > 0) {
ephy_window_check_modified_forms (window);
/* stop window close */
return FALSE;
@@ -4405,7 +4323,7 @@ ephy_window_close (EphyWindow *window)
session = ephy_shell_get_session (ephy_shell_get_default ());
if (ephy_shell_get_n_windows (ephy_shell_get_default ()) > 1 &&
- gtk_notebook_get_n_pages (window->notebook) > 1 &&
+ ephy_tab_view_get_n_pages (window->tab_view) > 1 &&
!ephy_session_is_closing (session) &&
!confirm_close_with_multiple_tabs (window)) {
/* stop window close */
@@ -4450,40 +4368,6 @@ ephy_window_show_fullscreen_header_bar (EphyWindow *window)
window->show_fullscreen_header_bar = TRUE;
}
-int
-ephy_window_get_position_for_new_embed (EphyWindow *window,
- EphyEmbed *embed)
-{
- GtkWidget *notebook = ephy_window_get_notebook (window);
- int position;
-
- if (embed == window->last_opened_embed)
- return window->last_opened_pos++;
-
- position = gtk_notebook_page_num (GTK_NOTEBOOK (notebook), GTK_WIDGET (embed)) + 1;
-
- /* Loop through all pages and skip all pinned tabs */
- do {
- GtkWidget *page;
-
- page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), position);
- if (!page)
- break;
-
- if (!ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), EPHY_EMBED (page)))
- break;
- } while (++position < gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)));
-
- if (window->last_opened_embed)
- g_object_remove_weak_pointer (G_OBJECT (window->last_opened_embed), (gpointer
*)&window->last_opened_embed);
-
- g_object_add_weak_pointer (G_OBJECT (embed), (gpointer *)&window->last_opened_embed);
- window->last_opened_embed = embed;
- window->last_opened_pos = position + 1;
-
- return position;
-}
-
gboolean
ephy_window_is_maximized (EphyWindow *window)
{
diff --git a/src/ephy-window.h b/src/ephy-window.h
index 378593aa1..cdd40fd6f 100644
--- a/src/ephy-window.h
+++ b/src/ephy-window.h
@@ -24,6 +24,7 @@
#include "ephy-embed.h"
#include "ephy-embed-event.h"
#include "ephy-location-controller.h"
+#include "ephy-tab-view.h"
#include "ephy-web-view.h"
#include <handy.h>
@@ -46,7 +47,7 @@ typedef enum
EphyWindow *ephy_window_new (void);
-GtkWidget *ephy_window_get_notebook (EphyWindow *window);
+EphyTabView *ephy_window_get_tab_view (EphyWindow *window);
void ephy_window_open_pages_view (EphyWindow *window);
void ephy_window_close_pages_view (EphyWindow *window);
@@ -84,9 +85,6 @@ void ephy_window_set_default_position (EphyWindow *window,
gint y);
void ephy_window_show_fullscreen_header_bar (EphyWindow *window);
-int ephy_window_get_position_for_new_embed (EphyWindow *window,
- EphyEmbed *embed);
-
void ephy_window_update_entry_focus (EphyWindow *window,
EphyWebView *view);
diff --git a/src/meson.build b/src/meson.build
index 7886d6f14..fa2318567 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -36,7 +36,6 @@ libephymain_sources = [
'ephy-location-controller.c',
'ephy-lockdown.c',
'ephy-mouse-gesture-controller.c',
- 'ephy-notebook.c',
'ephy-page-row.c',
'ephy-pages-button.c',
'ephy-pages-popover.c',
@@ -44,7 +43,7 @@ libephymain_sources = [
'ephy-session.c',
'ephy-shell.c',
'ephy-suggestion-model.c',
- 'ephy-tab-label.c',
+ 'ephy-tab-view.c',
'ephy-web-extension-dialog.c',
'ephy-window.c',
'popup-commands.c',
diff --git a/src/resources/epiphany.gresource.xml b/src/resources/epiphany.gresource.xml
index fe216b966..e85aafef2 100644
--- a/src/resources/epiphany.gresource.xml
+++ b/src/resources/epiphany.gresource.xml
@@ -41,7 +41,6 @@
<file preprocess="xml-stripblanks" compressed="true">gtk/search-engine-row.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/synced-tabs-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/shortcuts-dialog.ui</file>
- <file preprocess="xml-stripblanks" compressed="true">gtk/tab-label.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/webapp-additional-urls-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/web-extensions-dialog.ui</file>
</gresource>
@@ -49,7 +48,6 @@
<file compressed="true" alias="scalable/actions/ephy-download-symbolic.svg"
preprocess="xml-stripblanks">ephy-download-symbolic.svg</file>
<file compressed="true"
alias="scalable/actions/ephy-bookmarks-symbolic.svg">ephy-bookmarks-symbolic.svg</file>
<file compressed="true"
alias="scalable/actions/ephy-bookmark-tag-symbolic.svg">ephy-bookmark-tag-symbolic.svg</file>
- <file compressed="true"
alias="scalable/actions/ephy-missing-favicon-symbolic.svg">ephy-missing-favicon-symbolic.svg</file>
<file compressed="true"
alias="scalable/actions/ephy-reader-mode-symbolic.svg">ephy-reader-mode-symbolic.svg</file>
<file compressed="true"
alias="scalable/status/ephy-audio-muted-symbolic.svg">ephy-audio-muted-symbolic.svg</file>
<file compressed="true"
alias="scalable/status/ephy-audio-playing-symbolic.svg">ephy-audio-playing-symbolic.svg</file>
diff --git a/src/resources/gtk/page-row.ui b/src/resources/gtk/page-row.ui
index 00155a452..f77a0e81b 100644
--- a/src/resources/gtk/page-row.ui
+++ b/src/resources/gtk/page-row.ui
@@ -34,6 +34,7 @@
<object class="GtkSpinner" id="spinner">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="active">True</property>
</object>
<packing>
<property name="position">1</property>
diff --git a/src/resources/gtk/pages-popover.ui b/src/resources/gtk/pages-popover.ui
index d1c84d8a2..9557d511a 100644
--- a/src/resources/gtk/pages-popover.ui
+++ b/src/resources/gtk/pages-popover.ui
@@ -16,7 +16,7 @@
<property name="selection_mode">single</property>
<property name="visible">True</property>
<property name="width_request">300</property>
- <signal name="row-selected" handler="row_selected_cb" swapped="true"/>
+ <signal name="row-activated" handler="row_activated_cb" swapped="true"/>
<style>
<class name="pages-list"/>
</style>
diff --git a/src/resources/themes/_Adwaita-base.scss b/src/resources/themes/_Adwaita-base.scss
index aed7ae204..25a9da4b8 100644
--- a/src/resources/themes/_Adwaita-base.scss
+++ b/src/resources/themes/_Adwaita-base.scss
@@ -70,39 +70,6 @@
animation-iteration-count: 3;
}
-// Pinned tabs
-.main-notebook {
- tab {
- min-width: 16px;
- }
-
- header {
- &.top,
- &.bottom {
- tab {
- border-style: none solid;
- }
- }
-
- &.left,
- &.right {
- tab {
- border-style: solid none;
- }
- }
- }
-}
-
-.tab-attention {
- $_dot_color: if($variant=='light', $selected_bg_color,
- lighten($selected_bg_color,15%));
- background-image: -gtk-gradient(radial,
- center center, 0,
- center center, 0.5,
- to($_dot_color),
- to(transparent));
-}
-
#title-box-container {
color: gtkalpha(themecolor(theme_fg_color), 0.2);
diff --git a/src/resources/themes/_Adwaita-colored-window.scss
b/src/resources/themes/_Adwaita-colored-window.scss
index 2bf349b78..3863f15d4 100644
--- a/src/resources/themes/_Adwaita-colored-window.scss
+++ b/src/resources/themes/_Adwaita-colored-window.scss
@@ -32,6 +32,9 @@ $backdrop_insensitive_color: if($variant == 'light', darken($backdrop_bg_color,
$insensitive_borders_color: mix($borders_color, $bg_color, 80%);
}
+$tab_bg: darken($bg_color, if($variant == 'dark', 6%, 12%));
+$tab_bg_backdrop: darken($backdrop_bg_color, 6%);
+
@import 'drawing';
headerbar {
@@ -70,59 +73,7 @@ actionbar {
}
}
-notebook > header {
- border-color: $borders_color;
- background-color: $dark_fill;
-
- &:backdrop {
- border-color: $backdrop_borders_color;
- background-color: $backdrop_dark_fill;
- }
-
- > tabs > tab {
- color: $insensitive_fg_color;
-
- button.flat {
- &:hover { color: currentColor; }
- &, &:backdrop { color: gtkalpha(currentColor, 0.3); }
- }
-
- &:hover {
- color: mix($insensitive_fg_color, $fg_color, 50%);
- border-color: transparentize($borders_color, 0.7);
- background-color: transparentize($bg_color, 0.8);
- box-shadow: inset 0 -3px $borders_color;
- }
-
- &:backdrop {
- color: mix($backdrop_fg_color, $backdrop_bg_color, 60%);
- border-color: transparent;
- background-color: transparent;
- box-shadow: none;
- }
-
- &:checked {
- color: $fg_color;
- border-color: transparentize($borders_color, 0.5);
- background-color: transparentize($bg_color, 0.5);
- box-shadow: inset 0 -3px $selected_bg_color;
-
- &:hover { background-color: transparentize($bg_color, 0.3); }
- }
-
- &:backdrop:checked {
- color: $backdrop_fg_color;
- border-color: $backdrop_borders_color;
- background-color: $backdrop_bg_color;
- }
- }
-
- > tabs > arrow:active {
- @include button(active);
- }
-}
-
-headerbar, actionbar, notebook > header {
+headerbar, actionbar {
> * {
color: $fg_color;
@@ -176,3 +127,91 @@ headerbar, actionbar, notebook > header {
}
}
}
+
+tabbar {
+ .box {
+ background: darken($tab_bg, 3%);
+ border-bottom: 1px solid $alt_borders_color;
+
+ &:backdrop {
+ background-color: darken($tab_bg_backdrop, 3%);
+ border-color: $backdrop_borders_color;
+ }
+ }
+
+ scrolledwindow.pinned {
+ undershoot {
+ border-color: $alt_borders_color;
+ }
+
+ &:backdrop undershoot {
+ border-color: $backdrop_borders_color;
+ }
+
+ tabbox {
+ &:dir(ltr) {
+ box-shadow: inset -1px 0 $alt_borders_color;
+
+ &:backdrop {
+ box-shadow: inset -1px 0 $backdrop_borders_color;
+ }
+ }
+
+ &:dir(rtl) {
+ box-shadow: inset 1px 0 $alt_borders_color;
+
+ &:backdrop {
+ box-shadow: inset 1px 0 $backdrop_borders_color;
+ }
+ }
+ }
+ }
+
+ tab {
+ border-color: $alt_borders_color;
+ background-color: $tab_bg;
+
+ &:checked {
+ background-color: lighten($tab_bg, 6%);
+
+ &:hover {
+ background-color: lighten($tab_bg, 9%);
+ }
+ }
+
+ &:hover {
+ background-color: lighten($tab_bg, 3%);
+ }
+
+ &:backdrop {
+ border-color: $backdrop_borders_color;
+ background-color: $tab_bg_backdrop;
+
+ &:checked {
+ background-color: $backdrop_bg_color;
+ }
+ }
+
+ .tab-close-button,
+ .tab-indicator.clickable {
+ &:hover {
+ background: gtkalpha($fg_color, .15);
+ }
+
+ &:active {
+ background: gtkalpha(black, .2);
+ }
+ }
+ }
+
+ .start-action,
+ .end-action {
+ background: $tab_bg;
+ border-color: $alt_borders_color;
+
+ &:backdrop {
+ border-color: $backdrop_borders_color;
+ background-color: $tab_bg_backdrop;
+ }
+ }
+}
diff --git a/src/resources/themes/elementary.scss b/src/resources/themes/elementary.scss
index 26459a87c..04ca05682 100644
--- a/src/resources/themes/elementary.scss
+++ b/src/resources/themes/elementary.scss
@@ -56,12 +56,6 @@ $variant: 'light';
}
}
-.main-notebook {
- tab {
- min-width: 30px;
- }
-}
-
// FIXME: this should be in libdazzle
dzlsuggestionpopover > revealer > box {
// Fix background and shadow
diff --git a/src/webextension/api/tabs.c b/src/webextension/api/tabs.c
index 162724508..d54126704 100644
--- a/src/webextension/api/tabs.c
+++ b/src/webextension/api/tabs.c
@@ -46,7 +46,7 @@ tabs_handler_query (EphyWebExtension *self,
g_autoptr (JsonNode) root = NULL;
EphyShell *shell = ephy_shell_get_default ();
GtkWindow *window;
- GtkWidget *notebook;
+ EphyTabView *tab_view;
gboolean current_window = TRUE;
gboolean active = TRUE;
@@ -66,18 +66,18 @@ tabs_handler_query (EphyWebExtension *self,
if (current_window) {
window = gtk_application_get_active_window (GTK_APPLICATION (shell));
- notebook = ephy_window_get_notebook (EPHY_WINDOW (window));
+ tab_view = ephy_window_get_tab_view (EPHY_WINDOW (window));
json_builder_begin_array (builder);
if (active) {
- GtkWidget *page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), gtk_notebook_get_current_page
(GTK_NOTEBOOK (notebook)));
+ GtkWidget *page = ephy_tab_view_get_selected_page (tab_view);
EphyWebView *tmp_webview = ephy_embed_get_web_view (EPHY_EMBED (page));
add_web_view_to_json (builder, tmp_webview);
} else {
- for (int i = 0; i < gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)); i++) {
- GtkWidget *page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i);
+ for (int i = 0; i < ephy_tab_view_get_n_pages (tab_view); i++) {
+ GtkWidget *page = ephy_tab_view_get_nth_page (tab_view, i);
EphyWebView *tmp_webview = ephy_embed_get_web_view (EPHY_EMBED (page));
add_web_view_to_json (builder, tmp_webview);
diff --git a/src/webextension/ephy-web-extension-manager.c b/src/webextension/ephy-web-extension-manager.c
index bfed03f85..fa9136c4b 100644
--- a/src/webextension/ephy-web-extension-manager.c
+++ b/src/webextension/ephy-web-extension-manager.c
@@ -288,9 +288,8 @@ ephy_web_extension_manager_update_location_entry (EphyWebExtensionManager *self,
{
GtkWidget *title_widget;
EphyLocationEntry *lentry;
- GtkWidget *notebook = ephy_window_get_notebook (EPHY_WINDOW (window));
- int current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
- GtkWidget *page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), current_page);
+ EphyTabView *tab_view = ephy_window_get_tab_view (EPHY_WINDOW (window));
+ GtkWidget *page = ephy_tab_view_get_selected_page (tab_view);
EphyWebView *web_view;
if (!page)
@@ -561,17 +560,17 @@ ephy_web_extension_manager_add_web_extension_to_webview (EphyWebExtensionManager
}
static void
-page_added_cb (GtkNotebook *notebook,
- GtkWidget *child,
- guint page_num,
- gpointer user_data)
+page_attached_cb (HdyTabView *tab_view,
+ HdyTabPage *page,
+ gint position,
+ gpointer user_data)
{
EphyWebExtension *web_extension = EPHY_WEB_EXTENSION (user_data);
+ GtkWidget *child = hdy_tab_page_get_child (page);
EphyWebView *web_view = ephy_embed_get_web_view (EPHY_EMBED (child));
- EphyWindow *window = EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (notebook)));
+ EphyWindow *window = EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab_view)));
EphyWebExtensionManager *self = ephy_shell_get_web_extension_manager (ephy_shell_get_default ());
-
ephy_web_extension_manager_add_web_extension_to_webview (self, web_extension, window, web_view);
ephy_web_extension_manager_update_location_entry (self, window);
}
@@ -756,14 +755,15 @@ ephy_web_extension_manager_add_web_extension_to_window (EphyWebExtensionManager
EphyWebExtension *web_extension,
EphyWindow *window)
{
- GtkWidget *notebook = ephy_window_get_notebook (EPHY_WINDOW (window));
+ EphyTabView *tab_view = ephy_window_get_tab_view (EPHY_WINDOW (window));
+ HdyTabView *view = ephy_tab_view_get_tab_view (tab_view);
if (!ephy_web_extension_manager_is_active (self, web_extension))
return;
/* Add page actions and add content script */
- for (int i = 0; i < gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)); i++) {
- GtkWidget *page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i);
+ for (int i = 0; i < ephy_tab_view_get_n_pages (tab_view); i++) {
+ GtkWidget *page = ephy_tab_view_get_nth_page (tab_view, i);
EphyWebView *web_view = ephy_embed_get_web_view (EPHY_EMBED (page));
ephy_web_extension_manager_add_web_extension_to_webview (self, web_extension, window, web_view);
@@ -776,7 +776,7 @@ ephy_web_extension_manager_add_web_extension_to_window (EphyWebExtensionManager
}
ephy_web_extension_manager_update_location_entry (self, window);
- g_signal_connect_object (notebook, "page-added", G_CALLBACK (page_added_cb), web_extension, 0);
+ g_signal_connect_object (view, "page-attached", G_CALLBACK (page_attached_cb), web_extension, 0);
}
static gboolean
@@ -813,14 +813,15 @@ ephy_web_extension_manager_remove_web_extension_from_window (EphyWebExtensionMan
EphyWebExtension *web_extension,
EphyWindow *window)
{
- GtkWidget *notebook = ephy_window_get_notebook (EPHY_WINDOW (window));
+ EphyTabView *tab_view = ephy_window_get_tab_view (EPHY_WINDOW (window));
+ HdyTabView *view = ephy_tab_view_get_tab_view (tab_view);
GtkWidget *browser_action_widget;
if (ephy_web_extension_manager_is_active (self, web_extension))
return;
- for (int i = 0; i < gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)); i++) {
- GtkWidget *page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i);
+ for (int i = 0; i < ephy_tab_view_get_n_pages (tab_view); i++) {
+ GtkWidget *page = ephy_tab_view_get_nth_page (tab_view, i);
EphyWebView *web_view = ephy_embed_get_web_view (EPHY_EMBED (page));
ephy_web_extension_manager_remove_web_extension_from_webview (self, web_extension, window, web_view);
@@ -833,7 +834,7 @@ ephy_web_extension_manager_remove_web_extension_from_window (EphyWebExtensionMan
ephy_web_extension_manager_update_location_entry (self, window);
- g_signal_handlers_disconnect_by_data (notebook, web_extension);
+ g_signal_handlers_disconnect_by_data (view, web_extension);
}
gboolean
diff --git a/src/window-commands.c b/src/window-commands.c
index daa9135dd..3feb7e214 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -46,13 +46,13 @@
#include "ephy-history-dialog.h"
#include "ephy-link.h"
#include "ephy-location-entry.h"
-#include "ephy-notebook.h"
#include "ephy-password-import.h"
#include "ephy-prefs.h"
#include "ephy-session.h"
#include "ephy-settings.h"
#include "ephy-shell.h"
#include "ephy-string.h"
+#include "ephy-tab-view.h"
#include "ephy-view-source-handler.h"
#include "ephy-web-app-utils.h"
#include "ephy-web-extension-dialog.h"
@@ -1180,17 +1180,14 @@ window_cmd_stop (GSimpleAction *action,
static void
check_tab_has_modified_forms_and_reload_cb (EphyWebView *view,
GAsyncResult *result,
- gpointer user_data)
+ EphyEmbed *embed)
{
- EphyWindow *window = EPHY_WINDOW (user_data);
- EphyEmbed *embed;
+ EphyWindow *window = EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view)));
GtkWidget *dialog;
GtkWidget *button;
gboolean has_modified_forms;
int response = GTK_RESPONSE_ACCEPT;
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
-
has_modified_forms = ephy_web_view_has_modified_forms_finish (view, result, NULL);
if (has_modified_forms) {
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
@@ -1220,7 +1217,7 @@ check_tab_has_modified_forms_and_reload_cb (EphyWebView *view,
webkit_web_view_reload (view);
}
- g_object_unref (window);
+ g_object_unref (embed);
}
void
@@ -1231,13 +1228,13 @@ window_cmd_reload (GSimpleAction *action,
EphyWindow *window = EPHY_WINDOW (user_data);
EphyEmbed *embed;
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
+ embed = EPHY_EMBED (ephy_tab_view_get_current_page (ephy_window_get_tab_view (window)));
g_assert (embed != NULL);
ephy_web_view_has_modified_forms (ephy_embed_get_web_view (embed),
NULL,
(GAsyncReadyCallback)check_tab_has_modified_forms_and_reload_cb,
- g_object_ref (window));
+ g_object_ref (embed));
}
void
@@ -2657,80 +2654,21 @@ window_cmd_change_fullscreen_state (GSimpleAction *action,
g_simple_action_set_state (action, g_variant_new_boolean (active));
}
-void
-window_cmd_tabs_previous (GSimpleAction *action,
- GVariant *variant,
- gpointer user_data)
-{
- GtkWidget *nb;
-
- nb = ephy_window_get_notebook (EPHY_WINDOW (user_data));
- g_assert (nb != NULL);
-
- ephy_notebook_prev_page (EPHY_NOTEBOOK (nb));
-}
-
-void
-window_cmd_tabs_next (GSimpleAction *action,
- GVariant *variant,
- gpointer user_data)
-{
- GtkWidget *nb;
-
- nb = ephy_window_get_notebook (EPHY_WINDOW (user_data));
- g_assert (nb != NULL);
-
- ephy_notebook_next_page (EPHY_NOTEBOOK (nb));
-}
-
-void
-window_cmd_tabs_move_left (GSimpleAction *action,
- GVariant *variant,
- gpointer user_data)
-{
- GtkWidget *child;
- GtkNotebook *notebook;
- int page;
-
- notebook = GTK_NOTEBOOK (ephy_window_get_notebook (EPHY_WINDOW (user_data)));
- page = gtk_notebook_get_current_page (notebook);
- if (page < 1)
- return;
-
- child = gtk_notebook_get_nth_page (notebook, page);
- gtk_notebook_reorder_child (notebook, child, page - 1);
-}
-
-void window_cmd_tabs_move_right (GSimpleAction *action,
- GVariant *variant,
- gpointer user_data)
-{
- GtkWidget *child;
- GtkNotebook *notebook;
- int page, n_pages;
-
- notebook = GTK_NOTEBOOK (ephy_window_get_notebook (EPHY_WINDOW (user_data)));
- page = gtk_notebook_get_current_page (notebook);
- n_pages = gtk_notebook_get_n_pages (notebook) - 1;
- if (page > n_pages - 1)
- return;
-
- child = gtk_notebook_get_nth_page (notebook, page);
- gtk_notebook_reorder_child (notebook, child, page + 1);
-}
-
void
window_cmd_tabs_duplicate (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
{
+ EphyTabView *tab_view;
EphyEmbed *embed, *new_embed;
WebKitWebView *view, *new_view;
WebKitWebViewSessionState *session_state;
WebKitBackForwardList *bf_list;
WebKitBackForwardListItem *item;
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (user_data));
+ tab_view = ephy_window_get_tab_view (EPHY_WINDOW (user_data));
+ embed = EPHY_EMBED (ephy_tab_view_get_current_page (tab_view));
+
view = WEBKIT_WEB_VIEW (ephy_embed_get_web_view (embed));
session_state = webkit_web_view_get_session_state (view);
@@ -2758,25 +2696,17 @@ window_cmd_tabs_close (GSimpleAction *action,
gpointer user_data)
{
EphyWindow *window = user_data;
- GtkWidget *notebook;
- EphyEmbed *embed;
- gboolean pinned;
+ EphyTabView *tab_view;
- notebook = ephy_window_get_notebook (window);
+ tab_view = ephy_window_get_tab_view (window);
if (g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN,
EPHY_PREFS_LOCKDOWN_QUIT) &&
- gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) == 1) {
+ ephy_tab_view_get_n_pages (tab_view) <= 1) {
return;
}
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
- g_assert (embed != NULL);
-
- pinned = ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), embed);
-
- if (!pinned)
- g_signal_emit_by_name (notebook, "tab-close-request", embed);
+ ephy_tab_view_close_selected (tab_view);
}
void
@@ -2785,27 +2715,8 @@ window_cmd_tabs_close_left (GSimpleAction *action,
gpointer user_data)
{
EphyWindow *window = user_data;
- GtkWidget *notebook;
- EphyEmbed *embed;
- int current_page_no;
- GSList *pages_to_close = NULL;
-
- notebook = ephy_window_get_notebook (window);
- current_page_no = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
- for (int i = 0; i < current_page_no; i++) {
- embed = EPHY_EMBED (gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i));
-
- if (!ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), embed))
- pages_to_close = g_slist_prepend (pages_to_close, embed);
- }
-
- for (GSList *l = pages_to_close; l != NULL; l = l->next) {
- g_assert (l->data != NULL);
- g_signal_emit_by_name (GTK_NOTEBOOK (notebook), "tab-close-request", l->data);
- }
-
- g_slist_free (pages_to_close);
+ ephy_tab_view_close_left (ephy_window_get_tab_view (window));
}
void
@@ -2814,28 +2725,8 @@ window_cmd_tabs_close_right (GSimpleAction *action,
gpointer user_data)
{
EphyWindow *window = user_data;
- GtkWidget *notebook;
- EphyEmbed *embed;
- int n_pages, current_page_no;
- GSList *pages_to_close = NULL;
- notebook = ephy_window_get_notebook (window);
- n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
- current_page_no = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
-
- for (int i = current_page_no + 1; i < n_pages; i++) {
- embed = EPHY_EMBED (gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i));
-
- if (!ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), embed))
- pages_to_close = g_slist_prepend (pages_to_close, embed);
- }
-
- for (GSList *l = pages_to_close; l != NULL; l = l->next) {
- g_assert (l->data != NULL);
- g_signal_emit_by_name (GTK_NOTEBOOK (notebook), "tab-close-request", l->data);
- }
-
- g_slist_free (pages_to_close);
+ ephy_tab_view_close_right (ephy_window_get_tab_view (window));
}
void
@@ -2844,30 +2735,18 @@ window_cmd_tabs_close_others (GSimpleAction *action,
gpointer user_data)
{
EphyWindow *window = user_data;
- GtkWidget *notebook;
- EphyEmbed *embed;
- int n_pages, current_page;
- GSList *pages_to_close = NULL;
- notebook = ephy_window_get_notebook (window);
- n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
- current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
-
- for (int i = 0; i < n_pages; i++) {
- if (i != current_page) {
- embed = EPHY_EMBED (gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i));
-
- if (!ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), embed))
- pages_to_close = g_slist_prepend (pages_to_close, embed);
- }
- }
+ ephy_tab_view_close_other (ephy_window_get_tab_view (window));
+}
- for (GSList *l = pages_to_close; l != NULL; l = l->next) {
- g_assert (l->data != NULL);
- g_signal_emit_by_name (GTK_NOTEBOOK (notebook), "tab-close-request", l->data);
- }
+static void
+reload_cb (GtkWidget *widget,
+ gpointer user_data)
+{
+ EphyEmbed *embed = EPHY_EMBED (widget);
+ WebKitWebView *view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
- g_slist_free (pages_to_close);
+ webkit_web_view_reload (view);
}
void
@@ -2876,45 +2755,10 @@ window_cmd_tabs_reload_all_tabs (GSimpleAction *action,
gpointer user_data)
{
EphyWindow *window = user_data;
- EphyEmbed *embed;
- WebKitWebView *view;
- GtkWidget *notebook;
- int n_pages;
-
- notebook = ephy_window_get_notebook (window);
- n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
-
- for (int i = 0; i < n_pages; i++) {
- embed = EPHY_EMBED (gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i));
-
- view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
- webkit_web_view_reload (view);
- }
-}
-
-void
-window_cmd_show_tab (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
-{
- EphyWindow *window = EPHY_WINDOW (user_data);
- GtkWidget *notebook;
- guint32 tab_num;
-
- g_assert (g_variant_is_of_type (parameter, G_VARIANT_TYPE_UINT32));
- tab_num = g_variant_get_uint32 (parameter);
-
- notebook = ephy_window_get_notebook (window);
- gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), tab_num);
- g_simple_action_set_state (action, parameter);
-}
-void
-window_cmd_change_show_tab_state (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
-{
- /* This page intentionally left blank. */
+ ephy_tab_view_foreach (ephy_window_get_tab_view (window),
+ reload_cb,
+ NULL);
}
void
@@ -3029,15 +2873,8 @@ window_cmd_tabs_pin (GSimpleAction *action,
gpointer user_data)
{
EphyWindow *window = EPHY_WINDOW (user_data);
- EphyEmbed *embed;
- EphyNotebook *notebook;
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
- g_assert (embed != NULL);
-
- notebook = EPHY_NOTEBOOK (ephy_window_get_notebook (window));
-
- ephy_notebook_tab_set_pinned (notebook, GTK_WIDGET (embed), TRUE);
+ ephy_tab_view_pin (ephy_window_get_tab_view (window));
}
void
@@ -3046,15 +2883,8 @@ window_cmd_tabs_unpin (GSimpleAction *action,
gpointer user_data)
{
EphyWindow *window = EPHY_WINDOW (user_data);
- EphyEmbed *embed;
- EphyNotebook *notebook;
-
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
- g_assert (embed != NULL);
- notebook = EPHY_NOTEBOOK (ephy_window_get_notebook (window));
-
- ephy_notebook_tab_set_pinned (notebook, GTK_WIDGET (embed), FALSE);
+ ephy_tab_view_unpin (ephy_window_get_tab_view (window));
}
void
@@ -3067,13 +2897,16 @@ window_cmd_change_tabs_mute_state (GSimpleAction *action,
EphyWebView *view;
gboolean mute;
- mute = g_variant_get_boolean (state);
-
- embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
+ embed = EPHY_EMBED (ephy_tab_view_get_current_page (ephy_window_get_tab_view (window)));
g_assert (embed != NULL);
view = ephy_embed_get_web_view (embed);
+ if (!webkit_web_view_is_playing_audio (WEBKIT_WEB_VIEW (view)))
+ return;
+
+ mute = !webkit_web_view_get_is_muted (WEBKIT_WEB_VIEW (view));
+
webkit_web_view_set_is_muted (WEBKIT_WEB_VIEW (view), mute);
g_simple_action_set_state (action, g_variant_new_boolean (mute));
diff --git a/src/window-commands.h b/src/window-commands.h
index 25a3b1da3..2c56d9288 100644
--- a/src/window-commands.h
+++ b/src/window-commands.h
@@ -179,18 +179,6 @@ void window_cmd_change_browse_with_caret_state (GSimpleAction *action,
void window_cmd_change_fullscreen_state (GSimpleAction *action,
GVariant *state,
gpointer user_data);
-void window_cmd_tabs_previous (GSimpleAction *action,
- GVariant *state,
- gpointer user_data);
-void window_cmd_tabs_next (GSimpleAction *action,
- GVariant *state,
- gpointer user_data);
-void window_cmd_tabs_move_left (GSimpleAction *action,
- GVariant *state,
- gpointer user_data);
-void window_cmd_tabs_move_right (GSimpleAction *action,
- GVariant *state,
- gpointer user_data);
void window_cmd_tabs_duplicate (GSimpleAction *action,
GVariant *state,
gpointer user_data);
diff --git a/tests/ephy-shell-test.c b/tests/ephy-shell-test.c
index c47035da9..6d3255cad 100644
--- a/tests/ephy-shell-test.c
+++ b/tests/ephy-shell-test.c
@@ -168,19 +168,12 @@ test_ephy_shell_tab_load (void)
gtk_widget_destroy (window);
}
-static int
-get_notebook_page_num (GtkWidget *notebook,
- EphyEmbed *embed)
-{
- return gtk_notebook_page_num (GTK_NOTEBOOK (notebook), GTK_WIDGET (embed));
-}
-
static void
test_ephy_shell_tab_append (void)
{
EphyShell *ephy_shell;
GtkWidget *window;
- GtkWidget *notebook;
+ EphyTabView *tab_view;
EphyEmbed *embed1;
EphyEmbed *embed2;
@@ -190,37 +183,37 @@ test_ephy_shell_tab_append (void)
ephy_shell = ephy_shell_get_default ();
window = GTK_WIDGET (ephy_window_new ());
- notebook = ephy_window_get_notebook (EPHY_WINDOW (window));
+ tab_view = ephy_window_get_tab_view (EPHY_WINDOW (window));
embed1 = ephy_shell_new_tab (ephy_shell, EPHY_WINDOW (window), NULL,
EPHY_NEW_TAB_DONT_SHOW_WINDOW);
- g_assert_cmpint (get_notebook_page_num (notebook, embed1), ==, 0);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed1), ==, 0);
embed2 = ephy_shell_new_tab (ephy_shell, EPHY_WINDOW (window), embed1,
EPHY_NEW_TAB_DONT_SHOW_WINDOW);
- g_assert_cmpint (get_notebook_page_num (notebook, embed1), ==, 0);
- g_assert_cmpint (get_notebook_page_num (notebook, embed2), ==, 1);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed1), ==, 0);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed2), ==, 1);
embed3 = ephy_shell_new_tab (ephy_shell, EPHY_WINDOW (window), embed1,
EPHY_NEW_TAB_DONT_SHOW_WINDOW | EPHY_NEW_TAB_APPEND_AFTER);
- g_assert_cmpint (get_notebook_page_num (notebook, embed1), ==, 0);
- g_assert_cmpint (get_notebook_page_num (notebook, embed3), ==, 1);
- g_assert_cmpint (get_notebook_page_num (notebook, embed2), ==, 2);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed1), ==, 0);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed3), ==, 1);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed2), ==, 2);
embed4 = ephy_shell_new_tab (ephy_shell, EPHY_WINDOW (window), embed1,
EPHY_NEW_TAB_DONT_SHOW_WINDOW | EPHY_NEW_TAB_APPEND_LAST);
- g_assert_cmpint (get_notebook_page_num (notebook, embed1), ==, 0);
- g_assert_cmpint (get_notebook_page_num (notebook, embed3), ==, 1);
- g_assert_cmpint (get_notebook_page_num (notebook, embed2), ==, 2);
- g_assert_cmpint (get_notebook_page_num (notebook, embed4), ==, 3);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed1), ==, 0);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed3), ==, 1);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed2), ==, 2);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed4), ==, 3);
embed5 = ephy_shell_new_tab (ephy_shell, EPHY_WINDOW (window), embed3,
EPHY_NEW_TAB_DONT_SHOW_WINDOW | EPHY_NEW_TAB_APPEND_AFTER);
- g_assert_cmpint (get_notebook_page_num (notebook, embed1), ==, 0);
- g_assert_cmpint (get_notebook_page_num (notebook, embed3), ==, 1);
- g_assert_cmpint (get_notebook_page_num (notebook, embed5), ==, 2);
- g_assert_cmpint (get_notebook_page_num (notebook, embed2), ==, 3);
- g_assert_cmpint (get_notebook_page_num (notebook, embed4), ==, 4);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed1), ==, 0);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed3), ==, 1);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed5), ==, 2);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed2), ==, 3);
+ g_assert_cmpint (ephy_tab_view_get_page_index (tab_view, embed4), ==, 4);
gtk_widget_destroy (window);
}
@@ -231,7 +224,7 @@ test_ephy_shell_tab_from_external (void)
{
EphyShell *ephy_shell;
GtkWidget *window;
- GtkWidget *notebook;
+ EphyTabView *tab_view;
GMainLoop *loop;
EphyEmbed *embed;
@@ -247,7 +240,7 @@ test_ephy_shell_tab_from_external (void)
embed = ephy_shell_new_tab (ephy_shell, NULL, NULL, "about:epiphany",
EPHY_NEW_TAB_DONT_SHOW_WINDOW | EPHY_NEW_TAB_OPEN_PAGE);
window = gtk_widget_get_toplevel (GTK_WIDGET (embed));
- notebook = ephy_window_get_notebook (EPHY_WINDOW (window));
+ tab_view = ephy_window_get_tab_view (EPHY_WINDOW (window));
/* This embed should be used in load-from-external. */
embed2 = ephy_shell_new_tab (ephy_shell, EPHY_WINDOW (window), NULL, NULL,
@@ -268,7 +261,7 @@ test_ephy_shell_tab_from_external (void)
/* This one should fail, because the active embed is not @embed2. */
ephy_test_utils_check_ephy_embed_address (embed2, "ephy-about:overview");
- g_assert_cmpint (gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook)), ==, 0);
+ g_assert_cmpint (ephy_tab_view_get_selected_index (tab_view), ==, 0);
loop = ephy_test_utils_setup_ensure_web_views_are_loaded ();
@@ -281,11 +274,11 @@ test_ephy_shell_tab_from_external (void)
ephy_test_utils_check_ephy_embed_address (embed2, "ephy-about:overview");
ephy_test_utils_check_ephy_embed_address (embed4, "ephy-about:applications");
- gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 1);
+ ephy_tab_view_select_nth_page (tab_view, 1);
/* This should work */
ephy_test_utils_check_ephy_embed_address (embed2, "ephy-about:overview");
- g_assert_cmpint (gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook)), ==, 1);
+ g_assert_cmpint (ephy_tab_view_get_selected_index (tab_view), ==, 1);
loop = ephy_test_utils_setup_wait_until_load_is_committed (ephy_embed_get_web_view (embed2));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]