[epiphany/wip/christopherdavis/tabs-page: 2/3] ephy-window: Use a page instead of popover for mobile tabs



commit c21974067ca3696093acc6efd52c1d20b91aec72
Author: Christopher Davis <brainblasted disroot org>
Date:   Thu Apr 18 21:57:33 2019 -0400

    ephy-window: Use a page instead of popover for mobile tabs
    
    As per https://gitlab.gnome.org/Teams/Design/app-mockups/blob/master/web/web.png, on mobile tabs should 
use
    a separate page from the main view.

 src/ephy-action-bar.c                |  14 --
 src/ephy-pages-view.c                | 293 +++++++++++++++++++++++++++++++++++
 src/ephy-pages-view.h                |  43 +++++
 src/ephy-tab-header-bar.c            |  85 ++++++++++
 src/ephy-tab-header-bar.h            |  35 +++++
 src/ephy-window.c                    |  61 +++++++-
 src/ephy-window.h                    |   1 +
 src/meson.build                      |   2 +
 src/resources/epiphany.gresource.xml |   1 +
 src/resources/gtk/action-bar.ui      |   9 +-
 src/resources/gtk/pages-view.ui      |  21 +++
 src/window-commands.c                |  24 +++
 src/window-commands.h                |   6 +
 13 files changed, 570 insertions(+), 25 deletions(-)
---
diff --git a/src/ephy-action-bar.c b/src/ephy-action-bar.c
index b801f7466..fd4248380 100644
--- a/src/ephy-action-bar.c
+++ b/src/ephy-action-bar.c
@@ -39,7 +39,6 @@ struct _EphyActionBar {
   EphyActionBarStart *action_bar_start;
   EphyActionBarEnd *action_bar_end;
   GtkMenuButton *pages_button;
-  EphyPagesPopover *pages_popover;
 };
 
 G_DEFINE_TYPE (EphyActionBar, ephy_action_bar, GTK_TYPE_REVEALER)
@@ -132,9 +131,6 @@ ephy_action_bar_class_init (EphyActionBarClass *klass)
   gtk_widget_class_bind_template_child (widget_class,
                                         EphyActionBar,
                                         pages_button);
-  gtk_widget_class_bind_template_child (widget_class,
-                                        EphyActionBar,
-                                        pages_popover);
   gtk_widget_class_bind_template_child (widget_class,
                                         EphyActionBar,
                                         action_bar_end);
@@ -154,9 +150,6 @@ ephy_action_bar_init (EphyActionBar *action_bar)
   mode = ephy_embed_shell_get_mode (EPHY_EMBED_SHELL (ephy_shell_get_default ()));
   gtk_widget_set_visible (GTK_WIDGET (action_bar->pages_button),
                           mode != EPHY_EMBED_SHELL_MODE_APPLICATION);
-
-  ephy_pages_popover_set_adaptive_mode (action_bar->pages_popover,
-                                        EPHY_ADAPTIVE_MODE_NARROW);
 }
 
 EphyActionBar *
@@ -179,13 +172,6 @@ ephy_action_bar_get_action_bar_end (EphyActionBar *action_bar)
   return action_bar->action_bar_end;
 }
 
-void
-ephy_action_bar_set_notebook (EphyActionBar *action_bar,
-                              EphyNotebook  *notebook)
-{
-  ephy_pages_popover_set_notebook (action_bar->pages_popover, notebook);
-}
-
 void
 ephy_action_bar_set_adaptive_mode (EphyActionBar    *action_bar,
                                    EphyAdaptiveMode  adaptive_mode)
diff --git a/src/ephy-pages-view.c b/src/ephy-pages-view.c
new file mode 100644
index 000000000..0e3ee2d1f
--- /dev/null
+++ b/src/ephy-pages-view.c
@@ -0,0 +1,293 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright © 2019 Purism SPC
+ *  Copyright © 2019 Adrien Plazas <kekun plazas laposte net>
+ *  Copyright © 2019 Christopher Davis <christopherdavis gnome org>
+ *
+ *  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-pages-view.h"
+
+#define HANDY_USE_UNSTABLE_API
+#include <handy.h>
+#include "ephy-notebook.h"
+#include "ephy-page-row.h"
+#include "ephy-window.h"
+
+struct _EphyPagesView {
+  GtkScrolledWindow parent_instance;
+
+  GtkListBox *list_box;
+
+  GListStore *list_store;
+  EphyNotebook *notebook;
+  EphyAdaptiveMode adaptive_mode;
+};
+
+G_DEFINE_TYPE (EphyPagesView, ephy_pages_view, GTK_TYPE_SCROLLED_WINDOW)
+
+static void
+drop_notebook (EphyPagesView *self)
+{
+  self->notebook = NULL;
+  g_list_store_remove_all (self->list_store);
+}
+
+static void
+release_notebook (EphyPagesView *self)
+{
+  if (self->notebook) {
+    g_object_weak_unref (G_OBJECT (self->notebook), (GWeakNotify)drop_notebook, self);
+    drop_notebook (self);
+  }
+}
+
+static GtkWidget *
+create_row (gpointer item,
+            gpointer user_data)
+{
+  return GTK_WIDGET (g_object_ref (G_OBJECT (item)));
+}
+
+static void
+row_selected_cb (EphyPagesView *self,
+                 GtkListBoxRow *row)
+{
+  gint current_page;
+  gint new_page;
+  EphyWindow *window;
+  GtkWidget *stack;
+  GApplication *application;
+
+  g_assert (EPHY_IS_PAGES_VIEW (self));
+  g_assert (!row || GTK_IS_LIST_BOX_ROW (row));
+
+  application = g_application_get_default ();
+  window = EPHY_WINDOW (gtk_application_get_active_window (GTK_APPLICATION (application)));
+  stack = ephy_window_get_stack (window);
+
+  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;
+
+  gtk_notebook_set_current_page (GTK_NOTEBOOK (self->notebook), new_page);
+  gtk_stack_set_visible_child_name (GTK_STACK (stack), "content");
+}
+
+static void
+row_closed_cb (EphyPagesView *self,
+               EphyPageRow   *row)
+{
+  g_assert (EPHY_IS_PAGES_VIEW (self));
+  g_assert (EPHY_IS_PAGE_ROW (row));
+
+  gtk_notebook_remove_page (GTK_NOTEBOOK (self->notebook),
+                            gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row)));
+}
+
+static void
+current_page_changed_cb (EphyPagesView *self)
+{
+  GtkListBoxRow *current_row, *new_row;
+  gint current_page;
+
+  g_assert (EPHY_IS_PAGES_VIEW (self));
+
+  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)
+{
+  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]),
+                                     self->adaptive_mode);
+    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_cb (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);
+}
+
+static void
+ephy_pages_view_dispose (GObject *object)
+{
+  EphyPagesView *self = EPHY_PAGES_VIEW (object);
+
+  release_notebook (self);
+
+  G_OBJECT_CLASS (ephy_pages_view_parent_class)->dispose (object);
+}
+
+static void
+ephy_pages_view_class_init (EphyPagesViewClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (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);
+  gtk_widget_class_bind_template_callback (widget_class, row_selected_cb);
+}
+
+static void
+list_init (EphyPagesView *self)
+{
+  GtkCssProvider *provider = gtk_css_provider_new ();
+
+  /* This makes the list's background transparent. */
+  gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (provider),
+                                   "list { border-style: none; background-color: transparent; }", -1, NULL);
+  gtk_style_context_add_provider (gtk_widget_get_style_context (GTK_WIDGET (self->list_box)),
+                                  GTK_STYLE_PROVIDER (provider),
+                                  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+  g_object_unref (provider);
+}
+
+static void
+ephy_pages_view_init (EphyPagesView *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  list_init (self);
+
+  self->list_store = g_list_store_new (EPHY_TYPE_PAGE_ROW);
+
+  ephy_pages_view_set_adaptive_mode (self, EPHY_ADAPTIVE_MODE_NORMAL);
+  gtk_list_box_bind_model (self->list_box,
+                           G_LIST_MODEL (self->list_store),
+                           create_row,
+                           NULL,
+                           NULL);
+}
+
+EphyPagesView *
+ephy_pages_view_new (void)
+{
+  return g_object_new (EPHY_TYPE_PAGES_VIEW, NULL);
+}
+
+EphyNotebook *
+ephy_pages_view_get_notebook (EphyPagesView *self)
+{
+  g_assert (EPHY_IS_PAGES_VIEW (self));
+
+  return self->notebook;
+}
+
+void
+ephy_pages_view_set_notebook (EphyPagesView *self,
+                              EphyNotebook  *notebook)
+{
+  GMenu *pages_menu;
+
+  g_assert (EPHY_IS_PAGES_VIEW (self));
+
+  if (self->notebook)
+    release_notebook (self);
+
+  if (!notebook)
+    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_object (pages_menu,
+                           "items-changed",
+                           G_CALLBACK (items_changed_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+  g_signal_connect_object (notebook,
+                           "notify::page",
+                           G_CALLBACK (current_page_changed_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+}
+
+void
+ephy_pages_view_set_adaptive_mode (EphyPagesView    *self,
+                                   EphyAdaptiveMode  adaptive_mode)
+{
+  GListModel *list_model;
+
+  g_assert (EPHY_IS_PAGES_VIEW (self));
+
+  self->adaptive_mode = adaptive_mode;
+
+  list_model = G_LIST_MODEL (self->list_store);
+  for (guint i = 0; i < g_list_model_get_n_items (list_model); i++) {
+    EphyPageRow *row = EPHY_PAGE_ROW (g_list_model_get_item (list_model, i));
+
+    ephy_page_row_set_adaptive_mode (row, self->adaptive_mode);
+  }
+
+  switch (adaptive_mode) {
+  case EPHY_ADAPTIVE_MODE_NORMAL:
+    gtk_widget_set_vexpand (GTK_WIDGET (self), FALSE);
+    /* This should be enough height in normal mode to fit in 900px hight screen. */
+    gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW(self), 700);
+    gtk_list_box_set_header_func (self->list_box, NULL, NULL, NULL);
+
+    break;
+  case EPHY_ADAPTIVE_MODE_NARROW:
+    gtk_widget_set_vexpand (GTK_WIDGET (self), TRUE);
+    gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW (self), 0);
+    gtk_list_box_set_header_func (self->list_box, hdy_list_box_separator_header, NULL, NULL);
+
+    break;
+  }
+}
diff --git a/src/ephy-pages-view.h b/src/ephy-pages-view.h
new file mode 100644
index 000000000..6ccb720a0
--- /dev/null
+++ b/src/ephy-pages-view.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright © 2019 Christopher Davis <christopherdavis gnome org>
+ *
+ *  This file is part of Epiphany.
+ *
+ *  Epiphany is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Epiphany is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Epiphany.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "ephy-adaptive-mode.h"
+#include "ephy-notebook.h"
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_PAGES_VIEW (ephy_pages_view_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyPagesView, ephy_pages_view, EPHY, PAGES_VIEW, GtkScrolledWindow)
+
+EphyPagesView *ephy_pages_view_new               (void);
+
+EphyNotebook  *ephy_pages_view_get_notebook      (EphyPagesView   *view);
+void           ephy_pages_view_set_notebook      (EphyPagesView   *view,
+                                                  EphyNotebook    *notebook);
+
+void           ephy_pages_view_set_adaptive_mode (EphyPagesView   *self,
+                                                  EphyAdaptiveMode adaptive_mode);
+
+G_END_DECLS
diff --git a/src/ephy-tab-header-bar.c b/src/ephy-tab-header-bar.c
new file mode 100644
index 000000000..38d1648b1
--- /dev/null
+++ b/src/ephy-tab-header-bar.c
@@ -0,0 +1,85 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright © 2019 Christopher Davis <christopherdavis gnome org>
+ *
+ *  This file is part of Epiphany.
+ *
+ *  Epiphany is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Epiphany is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Epiphany.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ephy-tab-header-bar.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+struct _EphyTabHeaderBar {
+  GtkHeaderBar parent_instance;
+
+  GtkWidget    *back_button;
+  GtkWidget    *new_tab_button;
+};
+
+G_DEFINE_TYPE (EphyTabHeaderBar, ephy_tab_header_bar, GTK_TYPE_HEADER_BAR)
+
+/**
+ * ephy_tab_header_bar_new:
+ *
+ * Create a new #EphyTabHeaderBar.
+ *
+ * Returns: (transfer full): a newly created #EphyTabHeaderBar
+ */
+GtkWidget *
+ephy_tab_header_bar_new (void)
+{
+  return GTK_WIDGET(g_object_new(EPHY_TYPE_TAB_HEADER_BAR, NULL));
+}
+
+static void
+ephy_tab_header_bar_constructed (GObject *object)
+{
+  GtkWidget *back_button;
+  GtkWidget *new_tab_button;
+  EphyTabHeaderBar *self = EPHY_TAB_HEADER_BAR (object);
+
+  G_OBJECT_CLASS (ephy_tab_header_bar_parent_class)->constructed (object);
+  
+  back_button = GTK_WIDGET (gtk_button_new_from_icon_name ("go-previous-symbolic", GTK_ICON_SIZE_BUTTON));
+  new_tab_button = GTK_WIDGET (gtk_button_new_from_icon_name ("tab-new-symbolic", GTK_ICON_SIZE_BUTTON));
+
+  self->back_button = back_button;
+  self->new_tab_button = new_tab_button;
+  gtk_actionable_set_action_name (GTK_ACTIONABLE (back_button), "win.content");
+  gtk_actionable_set_action_name (GTK_ACTIONABLE (new_tab_button), "win.new-tab");
+
+  gtk_header_bar_pack_start (GTK_HEADER_BAR (self), back_button);
+  gtk_header_bar_pack_end (GTK_HEADER_BAR (self), new_tab_button);
+  
+  gtk_header_bar_set_title (GTK_HEADER_BAR (self), _("Tabs"));
+  gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self), TRUE);
+
+  gtk_widget_show_all (GTK_WIDGET (self));
+}
+
+static void
+ephy_tab_header_bar_class_init (EphyTabHeaderBarClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = ephy_tab_header_bar_constructed;
+}
+
+static void
+ephy_tab_header_bar_init (EphyTabHeaderBar *self)
+{
+}
diff --git a/src/ephy-tab-header-bar.h b/src/ephy-tab-header-bar.h
new file mode 100644
index 000000000..a562a774d
--- /dev/null
+++ b/src/ephy-tab-header-bar.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright © 2019 Christopher Davis <christopherdavis gnome org>
+ *
+ *  This file is part of Epiphany.
+ *
+ *  Epiphany is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Epiphany is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Epiphany.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_TAB_HEADER_BAR (ephy_tab_header_bar_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyTabHeaderBar, ephy_tab_header_bar, EPHY, TAB_HEADER_BAR, GtkHeaderBar)
+
+GtkWidget *ephy_tab_header_bar_new ();
+
+G_END_DECLS
+
+
diff --git a/src/ephy-window.c b/src/ephy-window.c
index e4c137930..4264559bd 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -42,11 +42,13 @@
 #include "ephy-location-entry.h"
 #include "ephy-mouse-gesture-controller.h"
 #include "ephy-notebook.h"
+#include "ephy-pages-view.h"
 #include "ephy-prefs.h"
 #include "ephy-security-popover.h"
 #include "ephy-session.h"
 #include "ephy-settings.h"
 #include "ephy-shell.h"
+#include "ephy-tab-header-bar.h"
 #include "ephy-title-box.h"
 #include "ephy-title-widget.h"
 #include "ephy-type-builtins.h"
@@ -110,6 +112,7 @@ const struct {
   { "win.send-to", { "Send", NULL } },
   { "win.location", { "<Primary>L", "<alt>D", "F6", "Go", "OpenURL", NULL } },
   { "win.home", { "<alt>Home", NULL } },
+  { "win.content", { "Escape", NULL } },
 
   /* Toggle actions */
   { "win.browse-with-caret", { "F7", NULL } },
@@ -144,6 +147,8 @@ struct _EphyWindow {
   DzlApplicationWindow parent_instance;
 
   GtkWidget *header_bar;
+  GtkWidget *main_stack;
+  EphyPagesView *pages_view;
   EphyBookmarksManager *bookmarks_manager;
   GHashTable *action_labels;
   GtkNotebook *notebook;
@@ -831,6 +836,8 @@ static const GActionEntry window_entries [] =
   { "send-to", window_cmd_send_to },
   { "location", window_cmd_go_location },
   { "home", window_cmd_go_home },
+  { "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 },
 
@@ -3308,11 +3315,32 @@ static GtkWidget *
 setup_header_bar (EphyWindow *window)
 {
   GtkWidget *header_bar;
+  GtkWidget *tab_header_bar;
+  GtkWidget *header_stack;
   EphyTitleWidget *title_widget;
 
   header_bar = ephy_header_bar_new (window);
-  dzl_application_window_set_titlebar (DZL_APPLICATION_WINDOW (window), header_bar);
+  tab_header_bar = ephy_tab_header_bar_new ();
+  header_stack = gtk_stack_new ();
+
+  gtk_stack_add_named (GTK_STACK (header_stack), header_bar, "content");
+  gtk_stack_add_named (GTK_STACK (header_stack), tab_header_bar, "tabs");
+
+  g_object_bind_property (G_OBJECT (window->main_stack),
+                          "visible-child-name", G_OBJECT (header_stack),
+                          "visible-child-name", G_BINDING_SYNC_CREATE);
+  g_object_bind_property (G_OBJECT (window->main_stack),
+                          "transition-type", G_OBJECT (header_stack),
+                          "transition-type", G_BINDING_SYNC_CREATE);
+  g_object_bind_property (G_OBJECT (window->main_stack),
+                          "transition-duration", G_OBJECT (header_stack),
+                          "transition-duration", G_BINDING_SYNC_CREATE);
+
+  dzl_application_window_set_titlebar (DZL_APPLICATION_WINDOW (window), header_stack);
   gtk_widget_show (header_bar);
+  gtk_widget_show (header_stack);
+
+  gtk_stack_set_visible_child_name (GTK_STACK (header_stack), "content");
 
   title_widget = ephy_header_bar_get_title_widget (EPHY_HEADER_BAR (header_bar));
   g_signal_connect (title_widget, "lock-clicked",
@@ -3349,9 +3377,6 @@ setup_action_bar (EphyWindow *window)
   gtk_revealer_set_transition_type (GTK_REVEALER (action_bar), GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP);
   gtk_widget_show (action_bar);
 
-  ephy_action_bar_set_notebook (EPHY_ACTION_BAR (action_bar),
-                                EPHY_NOTEBOOK (window->notebook));
-
   return action_bar;
 }
 
@@ -3553,6 +3578,10 @@ ephy_window_constructed (GObject *object)
   setup_tab_accels (window);
 
   window->notebook = setup_notebook (window);
+  window->main_stack = gtk_stack_new ();
+  window->pages_view = ephy_pages_view_new ();
+
+  ephy_pages_view_set_notebook (window->pages_view, EPHY_NOTEBOOK (window->notebook));
 
   /* Setup incognito mode style */
   mode = ephy_embed_shell_get_mode (ephy_embed_shell_get_default ());
@@ -3574,10 +3603,17 @@ ephy_window_constructed (GObject *object)
 
   gtk_box_pack_start (box, GTK_WIDGET (window->notebook), TRUE, TRUE, 0);
   gtk_box_pack_start (box, GTK_WIDGET (window->action_bar), FALSE, TRUE, 0);
-  gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (box));
+  gtk_stack_add_named (GTK_STACK (window->main_stack), GTK_WIDGET (box), "content");
+  gtk_stack_add_named (GTK_STACK (window->main_stack), GTK_WIDGET (window->pages_view), "tabs");
+  gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (window->main_stack));
+  gtk_widget_show_all (GTK_WIDGET (window->pages_view));
+  gtk_widget_show (GTK_WIDGET (window->main_stack));
   gtk_widget_show (GTK_WIDGET (box));
   gtk_widget_show (GTK_WIDGET (window->notebook));
 
+  gtk_stack_set_visible_child_name (GTK_STACK (window->main_stack), "content");
+  gtk_stack_set_transition_type (GTK_STACK (window->main_stack), GTK_STACK_TRANSITION_TYPE_CROSSFADE);
+
   /* other notifiers */
   action_group = gtk_widget_get_action_group (GTK_WIDGET (window), "win");
   action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
@@ -3725,6 +3761,21 @@ ephy_window_get_notebook (EphyWindow *window)
   return GTK_WIDGET (window->notebook);
 }
 
+/**
+ * ephy_window_get_stack:
+ * @window: an #EphyWindow
+ *
+ * Returns the #GtkStack housing the content and tab views
+ *
+ * Return value: (transfer none): the @window's #GtkStack
+ **/
+GtkWidget *
+ephy_window_get_stack (EphyWindow *window)
+{
+  g_assert (EPHY_IS_WINDOW (window));
+
+  return GTK_WIDGET (window->main_stack);
+}
 /**
  * ephy_window_get_find_toolbar:
  * @window: an #EphyWindow
diff --git a/src/ephy-window.h b/src/ephy-window.h
index 1a708ce66..18a75456a 100644
--- a/src/ephy-window.h
+++ b/src/ephy-window.h
@@ -47,6 +47,7 @@ typedef enum
 EphyWindow       *ephy_window_new                 (void);
 
 GtkWidget        *ephy_window_get_notebook        (EphyWindow *window);
+GtkWidget        *ephy_window_get_stack           (EphyWindow *window);
 
 void              ephy_window_load_url            (EphyWindow *window,
                                                    const char *url);
diff --git a/src/meson.build b/src/meson.build
index 899aacd58..f4dc9a88f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -36,10 +36,12 @@ libephymain_sources = [
   'ephy-notebook.c',
   'ephy-page-row.c',
   'ephy-pages-popover.c',
+  'ephy-pages-view.c',
   'ephy-search-engine-dialog.c',
   'ephy-session.c',
   'ephy-shell.c',
   'ephy-suggestion-model.c',
+  'ephy-tab-header-bar.c',
   'ephy-tab-label.c',
   'ephy-window.c',
   'passwords-dialog.c',
diff --git a/src/resources/epiphany.gresource.xml b/src/resources/epiphany.gresource.xml
index 779381af3..6a36df47f 100644
--- a/src/resources/epiphany.gresource.xml
+++ b/src/resources/epiphany.gresource.xml
@@ -26,6 +26,7 @@
     <file preprocess="xml-stripblanks" compressed="true">gtk/page-menu-popover.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/page-row.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/pages-popover.ui</file>
+    <file preprocess="xml-stripblanks" compressed="true">gtk/pages-view.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/passwords-dialog.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/prefs-dialog.ui</file>
     <file preprocess="xml-stripblanks" compressed="true">gtk/prefs-lang-dialog.ui</file>
diff --git a/src/resources/gtk/action-bar.ui b/src/resources/gtk/action-bar.ui
index 80c7de82b..75057d237 100644
--- a/src/resources/gtk/action-bar.ui
+++ b/src/resources/gtk/action-bar.ui
@@ -14,12 +14,12 @@
           </packing>
         </child>
         <child>
-          <object class="GtkMenuButton" id="pages_button">
+          <object class="GtkButton" id="pages_button">
             <property name="visible">True</property>
             <property name="valign">center</property>
-            <!-- Translators: tooltip for the page switcher menu button -->
+            <!-- Translators: tooltip for the page switcher button -->
             <property name="tooltip_text" translatable="yes">View open pages</property>
-            <property name="popover">pages_popover</property>
+            <property name="action_name">win.tabs-view</property>
             <style>
               <class name="image-button"/>
             </style>
@@ -46,7 +46,4 @@
       </object>
     </child>
   </template>
-  <object class="EphyPagesPopover" id="pages_popover">
-    <property name="visible">True</property>
-  </object>
 </interface>
diff --git a/src/resources/gtk/pages-view.ui b/src/resources/gtk/pages-view.ui
new file mode 100644
index 000000000..bbc80b3b9
--- /dev/null
+++ b/src/resources/gtk/pages-view.ui
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.16 -->
+  <template class="EphyPagesView" parent="GtkScrolledWindow">
+    <property name="hscrollbar_policy">never</property>
+    <property name="propagate_natural_height">True</property>
+    <property name="visible">True</property>
+    <child>
+      <object class="GtkListBox" id="list_box">
+        <property name="margin_bottom">12</property>
+        <property name="margin_end">12</property>
+        <property name="margin_start">12</property>
+        <property name="margin_top">12</property>
+        <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"/>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/window-commands.c b/src/window-commands.c
index 6f492c189..639342e7e 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -2292,6 +2292,30 @@ window_cmd_go_home (GSimpleAction *action,
                   EPHY_LINK_HOME_PAGE);
 }
 
+void
+window_cmd_go_content (GSimpleAction *action,
+                       GVariant      *parameter,
+                       gpointer       user_data)
+{
+  GtkWidget *stack;
+  EphyWindow *window = EPHY_WINDOW (user_data);
+
+  stack = ephy_window_get_stack (window);
+  gtk_stack_set_visible_child_name (GTK_STACK (stack), "content");
+}
+
+void
+window_cmd_go_tabs_view (GSimpleAction *action,
+                         GVariant      *parameter,
+                         gpointer       user_data)
+{
+  GtkWidget *stack;
+  EphyWindow *window = EPHY_WINDOW (user_data);
+
+  stack = ephy_window_get_stack (window);
+  gtk_stack_set_visible_child_name (GTK_STACK (stack), "tabs");
+}
+
 void
 window_cmd_change_browse_with_caret_state (GSimpleAction *action,
                                            GVariant      *state,
diff --git a/src/window-commands.h b/src/window-commands.h
index 3f2f6cbff..7cc0f230b 100644
--- a/src/window-commands.h
+++ b/src/window-commands.h
@@ -158,6 +158,12 @@ void window_cmd_go_location                     (GSimpleAction *action,
 void window_cmd_go_home                         (GSimpleAction *action,
                                                  GVariant      *parameter,
                                                  gpointer       user_data);
+void window_cmd_go_content                      (GSimpleAction *action,
+                                                 GVariant      *parameter,
+                                                 gpointer       user_data);
+void window_cmd_go_tabs_view                    (GSimpleAction *action,
+                                                 GVariant      *parameter,
+                                                 gpointer       user_data);
 void window_cmd_change_browse_with_caret_state  (GSimpleAction *action,
                                                  GVariant      *state,
                                                  gpointer       user_data);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]