[evolution] EShell: Use a header bar as title bar



commit 38a531c503b54c3d457baff1c2ebab46848f11cc
Author: Cédric Bellegarde <cedric bellegarde adishatz org>
Date:   Mon Jun 13 17:21:23 2022 +0200

    EShell: Use a header bar as title bar
    
    - Move common actions from toolbar to headerbar
    - Add EHeaderBarButton to mimic and replace EMenuToolButton
    - Add EShellHeaderBar for "New button" handling

 data/ui/evolution-calendars.ui                     |   6 +-
 data/ui/evolution-mail-reader.ui                   |  21 +-
 .../evolution-shell/evolution-shell-docs.sgml.in   |   5 +
 .../evolution-util/evolution-util-docs.sgml.in     |   3 +-
 src/e-util/CMakeLists.txt                          |   6 +-
 src/e-util/e-headerbar-button.c                    | 484 +++++++++++++++++++++
 src/e-util/e-headerbar-button.h                    |  68 +++
 src/e-util/e-menu-tool-action.c                    |  57 ---
 src/e-util/e-menu-tool-action.h                    |  73 ----
 src/e-util/e-menu-tool-button.c                    | 276 ------------
 src/e-util/e-menu-tool-button.h                    |  78 ----
 src/e-util/e-util.h                                |   3 +-
 src/mail/e-mail-reader.c                           | 176 ++++++--
 src/mail/e-mail-reader.h                           |   3 +
 src/modules/calendar/e-cal-shell-view-private.c    |  37 ++
 src/modules/calendar/e-cal-shell-view-private.h    |   1 +
 src/modules/mail/e-mail-shell-view-private.c       | 113 +++--
 src/modules/mail/e-mail-shell-view-private.h       |   5 +-
 src/shell/CMakeLists.txt                           |   2 +
 src/shell/e-shell-headerbar.c                      | 310 +++++++++++++
 src/shell/e-shell-headerbar.h                      |  59 +++
 src/shell/e-shell-window-private.c                 |  54 ++-
 src/shell/e-shell-window-private.h                 |   5 +-
 src/shell/e-shell-window.c                         |  92 +---
 24 files changed, 1214 insertions(+), 723 deletions(-)
---
diff --git a/data/ui/evolution-calendars.ui b/data/ui/evolution-calendars.ui
index fa68e3b84d..7aa1ca3159 100644
--- a/data/ui/evolution-calendars.ui
+++ b/data/ui/evolution-calendars.ui
@@ -1,4 +1,4 @@
-<ui evolution-ui-version="1.0">
+<ui evolution-ui-version="1.1">
   <menubar name='main-menu'>
     <menu action='file-menu'>
       <placeholder name='file-actions'>
@@ -59,10 +59,6 @@
     <toolitem action='calendar-print'/>
     <toolitem action='delete-selection'/>
     <separator/>
-    <toolitem action='calendar-go-back'/>
-    <toolitem action='calendar-go-today'/>
-    <toolitem action='calendar-go-forward'/>
-    <separator/>
     <toolitem action='calendar-jump-to'/>
     <separator/>
     <toolitem action='calendar-view-day'/>
diff --git a/data/ui/evolution-mail-reader.ui b/data/ui/evolution-mail-reader.ui
index 07659a37f9..f135d7c355 100644
--- a/data/ui/evolution-mail-reader.ui
+++ b/data/ui/evolution-mail-reader.ui
@@ -1,4 +1,4 @@
-<ui evolution-ui-version="1.1">
+<ui evolution-ui-version="1.2">
   <accelerator action='mail-smart-backward'/>
   <accelerator action='mail-smart-forward'/>
 
@@ -137,25 +137,6 @@
   </menubar>
   <toolbar name='main-toolbar'>
     <placeholder name='mail-toolbar-common'>
-      <toolitem action='mail-reply-sender'/>
-      <toolitem action='mail-reply-group'>
-        <menu action='mail-reply-group-menu'>
-          <menuitem action='mail-reply-all'/>
-          <menuitem action='mail-reply-list'/>
-          <menu action='mail-reply-template'/>
-          <menuitem action='mail-reply-alternative'/>
-        </menu>
-      </toolitem>
-      <toolitem action='mail-forward'>
-        <menu action='mail-forward-as-menu'>
-          <menuitem action='mail-forward-attached-full'/>
-          <menuitem action='mail-forward-inline-full'/>
-          <menuitem action='mail-forward-quoted-full'/>
-          <separator/>
-          <menuitem action='mail-redirect'/>
-        </menu>
-      </toolitem>
-      <separator/>
       <toolitem action='mail-print'/>
       <toolitem action='mail-delete'/>
       <toolitem action='mail-mark-junk'/>
diff --git a/docs/reference/evolution-shell/evolution-shell-docs.sgml.in 
b/docs/reference/evolution-shell/evolution-shell-docs.sgml.in
index cd7e054639..760c105bac 100644
--- a/docs/reference/evolution-shell/evolution-shell-docs.sgml.in
+++ b/docs/reference/evolution-shell/evolution-shell-docs.sgml.in
@@ -24,6 +24,7 @@
     <xi:include href="xml/e-shell-taskbar.xml"/>
     <xi:include href="xml/e-shell-searchbar.xml"/>
     <xi:include href="xml/e-shell-switcher.xml"/>
+    <xi:include href="xml/e-shell-headerbar.xml"/>
     <xi:include href="xml/e-shell-utils.xml"/>
   </chapter>
 
@@ -41,6 +42,10 @@
     <title>Index</title>
     <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
   </index>
+  <index id="api-index-3-46" role="3.46">
+    <title>Index of new symbols in 3.46</title>
+    <xi:include href="xml/api-index-3.46.xml"><xi:fallback /></xi:include>
+  </index>
   <index id="api-index-3-42" role="3.42">
     <title>Index of new symbols in 3.42</title>
     <xi:include href="xml/api-index-3.42.xml"><xi:fallback /></xi:include>
diff --git a/docs/reference/evolution-util/evolution-util-docs.sgml.in 
b/docs/reference/evolution-util/evolution-util-docs.sgml.in
index 9b6386d0f2..5b9898aedd 100644
--- a/docs/reference/evolution-util/evolution-util-docs.sgml.in
+++ b/docs/reference/evolution-util/evolution-util-docs.sgml.in
@@ -277,14 +277,13 @@
     <xi:include href="xml/e-ellipsized-combo-box-text.xml"/>
     <xi:include href="xml/e-file-utils.xml"/>
     <xi:include href="xml/e-focus-tracker.xml"/>
+    <xi:include href="xml/e-headerbar-button.xml"/>
     <xi:include href="xml/e-image-chooser.xml"/>
     <xi:include href="xml/e-import-assistant.xml"/>
     <xi:include href="xml/e-interval-chooser.xml"/>
     <xi:include href="xml/e-mail-identity-combo-box.xml"/>
     <xi:include href="xml/e-map.xml"/>
     <xi:include href="xml/e-markdown-editor.xml"/>
-    <xi:include href="xml/e-menu-tool-action.xml"/>
-    <xi:include href="xml/e-menu-tool-button.xml"/>
     <xi:include href="xml/e-mktemp.xml"/>
     <xi:include href="xml/e-month-widget.xml"/>
     <xi:include href="xml/e-name-selector-dialog.xml"/>
diff --git a/src/e-util/CMakeLists.txt b/src/e-util/CMakeLists.txt
index 46588be512..1b8a3dd1da 100644
--- a/src/e-util/CMakeLists.txt
+++ b/src/e-util/CMakeLists.txt
@@ -172,8 +172,7 @@ set(SOURCES
        e-markdown-editor.c
        e-markdown-utils.c
        e-marshal.c
-       e-menu-tool-action.c
-       e-menu-tool-button.c
+       e-headerbar-button.c
        e-misc-utils.c
        e-mktemp.c
        e-month-widget.c
@@ -450,8 +449,7 @@ set(HEADERS
        e-map.h
        e-markdown-editor.h
        e-markdown-utils.h
-       e-menu-tool-action.h
-       e-menu-tool-button.h
+       e-headerbar-button.h
        e-misc-utils.h
        e-mktemp.h
        e-month-widget.h
diff --git a/src/e-util/e-headerbar-button.c b/src/e-util/e-headerbar-button.c
new file mode 100644
index 0000000000..c443af1c93
--- /dev/null
+++ b/src/e-util/e-headerbar-button.c
@@ -0,0 +1,484 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * SPDX-FileCopyrightText: (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * SPDX-FileCopyrightText: (C) 2022 Cédric Bellegarde <cedric bellegarde adishatz org>
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+/* EHeaderBarButton is a collection of buttons (one main button and additionnal actions)
+ * with an optional dropdown menu.
+ *
+ * You can use e_header_bar_button_new() to get a new #EHeaderBarButton. If you do not provide
+ * an action, prefered action will be used. See e_header_bar_button_take_menu().
+ */
+
+#include "evolution-config.h"
+
+#include "e-headerbar-button.h"
+#include "e-misc-utils.h"
+
+#include <glib/gi18n.h>
+
+struct _EHeaderBarButtonPrivate {
+       GtkWidget *button;
+       GtkWidget *dropdown_button;
+
+       GtkAction *action;
+       gchar *label;
+       gchar *prefer_item;
+};
+
+enum {
+       PROP_0,
+       PROP_PREFER_ITEM,
+       PROP_LABEL,
+       PROP_ACTION
+};
+
+G_DEFINE_TYPE_WITH_CODE (EHeaderBarButton, e_header_bar_button, GTK_TYPE_BOX,
+       G_ADD_PRIVATE (EHeaderBarButton))
+
+static GtkAction *
+header_bar_button_get_prefer_action (EHeaderBarButton *header_bar_button)
+{
+       GtkMenu *menu;
+       GList *children;
+       GtkAction *action = NULL;
+       GList *link;
+       const gchar *prefer_item;
+
+       if (header_bar_button->priv->dropdown_button == NULL)
+               return NULL;
+
+       menu = gtk_menu_button_get_popup ( GTK_MENU_BUTTON (header_bar_button->priv->dropdown_button));
+       g_return_val_if_fail (menu != NULL, NULL);
+
+       children = gtk_container_get_children (GTK_CONTAINER (menu));
+       g_return_val_if_fail (children != NULL, NULL);
+
+       prefer_item = header_bar_button->priv->prefer_item;
+
+       for (link = children; link != NULL; link = g_list_next (link)) {
+               GtkWidget *child;
+               const gchar *name;
+
+               child = GTK_WIDGET (link->data);
+
+               if (!GTK_IS_MENU_ITEM (child))
+                       continue;
+
+               action = gtk_activatable_get_related_action (
+                       GTK_ACTIVATABLE (child));
+
+               if (action == NULL)
+                       continue;
+
+               name = gtk_action_get_name (action);
+
+               if (prefer_item == NULL ||
+                               *prefer_item == '\0' ||
+                               g_strcmp0 (name, prefer_item) == 0) {
+                       break;
+               }
+       }
+
+       g_list_free (children);
+
+       return action;
+}
+
+static void
+header_bar_button_update_button_for_action (GtkButton *button,
+                                           GtkAction *action)
+{
+       GtkWidget *image;
+       GtkStyleContext *style_context;
+       const gchar *tooltip;
+       const gchar *icon_name;
+
+       g_return_if_fail (button != NULL);
+       g_return_if_fail (action != NULL);
+
+       tooltip = gtk_action_get_tooltip (action);
+       gtk_widget_set_tooltip_text (GTK_WIDGET (button), tooltip);
+
+       icon_name = gtk_action_get_icon_name (action);
+       if (icon_name == NULL) {
+               GIcon *icon = gtk_action_get_gicon (action);
+               image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_BUTTON);
+       } else {
+               image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
+       }
+       gtk_widget_set_margin_end (image, 2);
+       gtk_button_set_image (GTK_BUTTON (button), image);
+       gtk_widget_show (image);
+
+       /* Force text button class to fix some themes */
+       style_context = gtk_widget_get_style_context (GTK_WIDGET (button));
+       gtk_style_context_add_class (style_context, "text-button");
+}
+
+static void
+header_bar_button_update_button (EHeaderBarButton *header_bar_button)
+{
+       GtkAction *action;
+
+       if (header_bar_button->priv->action == NULL)
+               action = header_bar_button_get_prefer_action (header_bar_button);
+       else
+               action = header_bar_button->priv->action;
+
+       if (action != NULL) {
+               header_bar_button_update_button_for_action (
+                       GTK_BUTTON (header_bar_button->priv->button),
+                       action);
+       }
+}
+
+static void
+header_bar_button_clicked (EHeaderBarButton *header_bar_button)
+{
+       GtkAction *action;
+
+       if (header_bar_button->priv->action == NULL)
+               action = header_bar_button_get_prefer_action (header_bar_button);
+       else
+               action = header_bar_button->priv->action;
+
+       if (action != NULL)
+               gtk_action_activate (action);
+}
+
+static void
+header_bar_button_set_prefer_item (EHeaderBarButton *self,
+                                  const gchar *prefer_item)
+{
+       g_return_if_fail (E_IS_HEADER_BAR_BUTTON (self));
+
+       if (g_strcmp0 (self->priv->prefer_item, prefer_item) == 0)
+               return;
+
+       g_free (self->priv->prefer_item);
+
+       self->priv->prefer_item = g_strdup (prefer_item);
+       header_bar_button_update_button (self);
+}
+
+static void
+header_bar_button_set_property (GObject *object,
+                               guint property_id,
+                               const GValue *value,
+                               GParamSpec *pspec)
+{
+       EHeaderBarButton *header_bar_button = E_HEADER_BAR_BUTTON (object);
+
+       switch (property_id) {
+               case PROP_PREFER_ITEM:
+                       header_bar_button_set_prefer_item (
+                               header_bar_button,
+                               g_value_get_string (value));
+                       return;
+               case PROP_LABEL:
+                       if (header_bar_button->priv->label == NULL)
+                               header_bar_button->priv->label = g_value_dup_string (value);
+                       return;
+               case PROP_ACTION:
+                       header_bar_button->priv->action = g_value_get_object (value);
+                       if (header_bar_button->priv->action != NULL)
+                               g_object_ref (header_bar_button->priv->action);
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+header_bar_button_get_property (GObject *object,
+                               guint property_id,
+                               GValue *value,
+                               GParamSpec *pspec)
+{
+       EHeaderBarButton *header_bar_button = E_HEADER_BAR_BUTTON (object);
+
+       switch (property_id) {
+               case PROP_PREFER_ITEM:
+                       g_value_set_string (
+                               value, header_bar_button->priv->prefer_item);
+                       return;
+               case PROP_LABEL:
+                       g_value_set_string (value, header_bar_button->priv->label);
+                       return;
+               case PROP_ACTION:
+                       g_value_set_object (value, header_bar_button->priv->action);
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+header_bar_button_constructed (GObject *object)
+{
+       EHeaderBarButton *header_bar_button = E_HEADER_BAR_BUTTON (object);
+       GtkStyleContext *style_context;
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_header_bar_button_parent_class)->constructed (object);
+
+       if (GTK_IS_TOGGLE_ACTION (header_bar_button->priv->action)) {
+               header_bar_button->priv->button = gtk_toggle_button_new_with_label (
+                       header_bar_button->priv->label);
+       } else {
+               header_bar_button->priv->button = gtk_button_new_with_label (
+                       header_bar_button->priv->label);
+       }
+       gtk_widget_show (header_bar_button->priv->button);
+
+       gtk_box_pack_start (
+               GTK_BOX (header_bar_button), header_bar_button->priv->button,
+               FALSE, FALSE, 0);
+
+       if (header_bar_button->priv->action != NULL) {
+               header_bar_button_update_button_for_action (
+                       GTK_BUTTON (header_bar_button->priv->button),
+                       header_bar_button->priv->action);
+
+               e_binding_bind_property (
+                       header_bar_button->priv->action, "sensitive",
+                       header_bar_button, "sensitive",
+                       G_BINDING_SYNC_CREATE);
+
+               if (GTK_IS_TOGGLE_ACTION (header_bar_button->priv->action))
+                       e_binding_bind_property (
+                               header_bar_button->priv->action, "active",
+                               header_bar_button->priv->button, "active",
+                               G_BINDING_SYNC_CREATE);
+       }
+
+       /* TODO: GTK4 port: do not use linked buttons
+        * https://developer.gnome.org/hig/patterns/containers/header-bars.html#button-grouping */
+       style_context = gtk_widget_get_style_context (GTK_WIDGET (header_bar_button));
+       gtk_style_context_add_class (style_context, "linked");
+
+       g_signal_connect_swapped (
+               header_bar_button->priv->button, "clicked",
+               G_CALLBACK (header_bar_button_clicked), header_bar_button);
+}
+
+static void
+header_bar_button_finalize (GObject *object)
+{
+       EHeaderBarButton *header_bar_button = E_HEADER_BAR_BUTTON (object);
+
+       g_free (header_bar_button->priv->prefer_item);
+       g_free (header_bar_button->priv->label);
+
+       if (header_bar_button->priv->action != NULL)
+               g_object_unref (header_bar_button->priv->action);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_header_bar_button_parent_class)->finalize (object);
+}
+
+static void
+e_header_bar_button_class_init (EHeaderBarButtonClass *class)
+{
+       GObjectClass *object_class;
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->set_property = header_bar_button_set_property;
+       object_class->get_property = header_bar_button_get_property;
+       object_class->constructed = header_bar_button_constructed;
+       object_class->finalize = header_bar_button_finalize;
+
+       g_object_class_install_property (
+               object_class,
+               PROP_PREFER_ITEM,
+               g_param_spec_string (
+                       "prefer-item",
+                       "Prefer Item",
+                       "Name of an item to show instead of the first",
+                       NULL,
+                       G_PARAM_READWRITE));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_LABEL,
+               g_param_spec_string (
+                       "label",
+                       "Label",
+                       "Button label",
+                       NULL,
+                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_ACTION,
+               g_param_spec_object (
+                       "action",
+                       "Action",
+                       "Button action",
+                       GTK_TYPE_ACTION,
+                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+e_header_bar_button_init (EHeaderBarButton *self)
+{
+       self->priv = e_header_bar_button_get_instance_private (self);
+
+       self->priv->dropdown_button = NULL;
+       self->priv->prefer_item = NULL;
+       self->priv->label = NULL;
+}
+
+/**
+ * e_header_bar_button_new:
+ * @action: An action overriding menu default action
+ *
+ * Creates a new #EHeaderBarButton labeled with @label.
+ * If action is %NULL, button will use default preferred menu action if available,
+ * see e_header_bar_button_take_menu().
+ *
+ * Returns: (transfer full): a new #EHeaderBarButton
+ *
+ * Since: 3.46
+ **/
+GtkWidget*
+e_header_bar_button_new (const gchar *label,
+                        GtkAction *action)
+{
+       return g_object_new (E_TYPE_HEADER_BAR_BUTTON,
+               "label", label,
+               "action", action, NULL);
+}
+
+/**
+ * e_header_bar_button_add_action:
+ * @header_bar_button: #EHeaderBarButton
+ * @label: The text you want the #GtkButton to hold.
+ * @action: #GtkButton related action
+ *
+ * Adds a new button with a related action.
+ *
+ * Since: 3.46
+ **/
+void
+e_header_bar_button_add_action (EHeaderBarButton *header_bar_button,
+                               const gchar *label,
+                               GtkAction *action)
+{
+       GtkWidget *button;
+
+       g_return_if_fail (E_IS_HEADER_BAR_BUTTON (header_bar_button));
+       g_return_if_fail (GTK_IS_ACTION (action));
+
+       if (GTK_IS_TOGGLE_ACTION (action))
+               button = gtk_toggle_button_new_with_label (label);
+       else
+               button = gtk_button_new_with_label (label);
+
+       gtk_widget_show (button);
+       gtk_box_pack_start (GTK_BOX (header_bar_button), button, FALSE, FALSE, 0);
+
+       e_binding_bind_property (
+               action, "sensitive",
+               button, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
+       if (GTK_IS_TOGGLE_ACTION (action))
+               e_binding_bind_property (
+                       action, "active",
+                       button, "active",
+                       G_BINDING_SYNC_CREATE);
+
+       g_signal_connect_swapped (
+               button, "clicked",
+               G_CALLBACK (gtk_action_activate), action);
+
+       header_bar_button_update_button_for_action (GTK_BUTTON (button), action);
+}
+
+/**
+ * e_header_bar_button_take_menu:
+ * @header_bar_button: #EHeaderBarButton
+ * @menu: (transfer full) (nullable): A #GtkMenu, or %NULL to unset and disable the dropdown button.
+ *
+ * Sets the #GtkMenu that will be popped up when the @menu_button is clicked, or
+ * %NULL to dissociate any existing menu and disable the dropdown button.
+ *
+ * If current #EHeaderBarButton action is %NULL, clicking the button will fire
+ * the preferred item, if set, or the first menu item otherwise.
+ *
+ * Since: 3.46
+ **/
+void
+e_header_bar_button_take_menu (EHeaderBarButton *header_bar_button,
+                              GtkWidget *menu)
+{
+       g_return_if_fail (E_IS_HEADER_BAR_BUTTON (header_bar_button));
+
+       if (!GTK_IS_MENU (menu)) {
+               if (header_bar_button->priv->dropdown_button != NULL)
+                       gtk_widget_hide (header_bar_button->priv->dropdown_button);
+               return;
+       }
+
+       if (header_bar_button->priv->dropdown_button == NULL) {
+               header_bar_button->priv->dropdown_button = gtk_menu_button_new ();
+               gtk_box_pack_end (
+                       GTK_BOX (header_bar_button), header_bar_button->priv->dropdown_button,
+                       FALSE, FALSE, 0);
+       }
+
+       gtk_menu_button_set_popup (GTK_MENU_BUTTON (header_bar_button->priv->dropdown_button), menu);
+
+       header_bar_button_update_button (header_bar_button);
+
+       gtk_widget_show (header_bar_button->priv->dropdown_button);
+}
+
+/**
+ * e_header_bar_button_css_add_class:
+ * @header_bar_button: #EHeaderBarButton
+ * @class_name: a CSS class name
+ *
+ * Adds a CSS class to #EHeaderBarButton main button
+ *
+ * Since: 3.46
+ **/
+void e_header_bar_button_css_add_class (EHeaderBarButton *header_bar_button,
+                                       const gchar *class_name)
+{
+       GtkStyleContext *style_context;
+
+       g_return_if_fail (E_IS_HEADER_BAR_BUTTON (header_bar_button));
+
+       style_context = gtk_widget_get_style_context (header_bar_button->priv->button);
+       gtk_style_context_add_class (style_context, class_name);
+}
+
+/**
+ * e_header_bar_button_add_accelerator:
+ * @header_bar_button: #EHeaderBarButton to activate
+ * @accel_group: Accel group for this widget, added to its toplevel.
+ * @accel_key: GDK keyval of the accelerator
+ * @accel_mods: Modifier key combination of the accelerator.
+ * @accel_flags: Flag accelerators, e.g. GTK_ACCEL_VISIBLE
+ *
+ * Installs an accelerator for main action
+ *
+ * Since: 3.46
+ **/
+void e_header_bar_button_add_accelerator (EHeaderBarButton *header_bar_button,
+                                         GtkAccelGroup* accel_group,
+                                         guint accel_key,
+                                         GdkModifierType accel_mods,
+                                         GtkAccelFlags accel_flags)
+{
+       g_return_if_fail (E_IS_HEADER_BAR_BUTTON (header_bar_button));
+
+       gtk_widget_add_accelerator (
+               GTK_WIDGET (header_bar_button->priv->button), "clicked",
+               accel_group, accel_key, accel_mods, accel_flags);
+}
diff --git a/src/e-util/e-headerbar-button.h b/src/e-util/e-headerbar-button.h
new file mode 100644
index 0000000000..44dcae44d0
--- /dev/null
+++ b/src/e-util/e-headerbar-button.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * SPDX-FileCopyrightText: (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * SPDX-FileCopyrightText: (C) 2022 Cédric Bellegarde <cedric bellegarde adishatz org>
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION)
+#error "Only <e-util/e-util.h> should be included directly."
+#endif
+
+#ifndef E_HEADER_BAR_BUTTON_H
+#define E_HEADER_BAR_BUTTON_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_HEADER_BAR_BUTTON \
+       (e_header_bar_button_get_type ())
+#define E_HEADER_BAR_BUTTON(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_HEADER_BAR_BUTTON, EHeaderBarButton))
+#define E_HEADER_BAR_BUTTON_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_HEADER_BAR_BUTTON, EHeaderBarButtonClass))
+#define E_IS_HEADER_BAR_BUTTON(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_HEADER_BAR_BUTTON))
+#define E_IS_HEADER_BAR_BUTTON_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_HEADER_BAR_BUTTON))
+#define E_HEADER_BAR_BUTTON_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_HEADER_BAR_BUTTON, EHeaderBarButtonClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EHeaderBarButton EHeaderBarButton;
+typedef struct _EHeaderBarButtonClass EHeaderBarButtonClass;
+typedef struct _EHeaderBarButtonPrivate EHeaderBarButtonPrivate;
+
+struct _EHeaderBarButton {
+       GtkBox parent;
+       EHeaderBarButtonPrivate *priv;
+};
+
+struct _EHeaderBarButtonClass {
+       GtkBoxClass parent_class;
+};
+
+GType          e_header_bar_button_get_type            (void) G_GNUC_CONST;
+GtkWidget*     e_header_bar_button_new                 (const gchar *label,
+                                                        GtkAction *action);
+void           e_header_bar_button_add_action          (EHeaderBarButton *header_bar_button,
+                                                        const gchar *label,
+                                                        GtkAction *action);
+void           e_header_bar_button_take_menu           (EHeaderBarButton *header_bar_button,
+                                                        GtkWidget *menu);
+void           e_header_bar_button_css_add_class       (EHeaderBarButton *header_bar_button,
+                                                        const gchar *class);
+void           e_header_bar_button_add_accelerator     (EHeaderBarButton* header_bar_button,
+                                                        GtkAccelGroup* accel_group,
+                                                        guint accel_key,
+                                                        GdkModifierType accel_mods,
+                                                        GtkAccelFlags accel_flags);
+G_END_DECLS
+
+#endif /* E_HEADER_BAR_BUTTON_H */
diff --git a/src/e-util/e-util.h b/src/e-util/e-util.h
index d580d14382..4ba1469e37 100644
--- a/src/e-util/e-util.h
+++ b/src/e-util/e-util.h
@@ -155,8 +155,7 @@
 #include <e-util/e-map.h>
 #include <e-util/e-markdown-editor.h>
 #include <e-util/e-markdown-utils.h>
-#include <e-util/e-menu-tool-action.h>
-#include <e-util/e-menu-tool-button.h>
+#include <e-util/e-headerbar-button.h>
 #include <e-util/e-misc-utils.h>
 #include <e-util/e-mktemp.h>
 #include <e-util/e-month-widget.h>
diff --git a/src/mail/e-mail-reader.c b/src/mail/e-mail-reader.c
index f387d5afd8..5b696e8dd3 100644
--- a/src/mail/e-mail-reader.c
+++ b/src/mail/e-mail-reader.c
@@ -29,6 +29,7 @@
 #include <X11/XF86keysym.h>
 #endif
 
+#include <shell/e-shell-headerbar.h>
 #include <shell/e-shell-utils.h>
 
 #include <libemail-engine/libemail-engine.h>
@@ -2636,6 +2637,13 @@ static GtkActionEntry mail_reader_entries[] = {
          N_("Flag the selected messages for follow-up"),
          G_CALLBACK (action_mail_flag_for_followup_cb) },
 
+       { "mail-forward",
+         "mail-forward",
+         N_("_Forward"),
+         "<Control>f",
+         N_("Forward the selected message to someone"),
+         G_CALLBACK (action_mail_forward_cb) },
+
        { "mail-forward-attached",
          NULL,
          N_("_Attached"),
@@ -2904,6 +2912,13 @@ static GtkActionEntry mail_reader_entries[] = {
          N_("Choose reply options for the selected message"),
          G_CALLBACK (action_mail_reply_alternative_cb) },
 
+       { "mail-reply-group",
+         "mail-reply-all",
+         N_("Group Reply"),
+         "<Control>g",
+         N_("Reply to the mailing list, or to all recipients"),
+         G_CALLBACK (action_mail_reply_group_cb) },
+
        { "mail-reply-list",
          NULL,
          N_("Reply to _List"),
@@ -5158,7 +5173,6 @@ e_mail_reader_init (EMailReader *reader,
                     gboolean init_actions,
                     gboolean connect_signals)
 {
-       EMenuToolAction *menu_tool_action;
        GtkActionGroup *action_group;
        GtkWidget *message_list;
        GtkAction *action;
@@ -5190,44 +5204,6 @@ e_mail_reader_init (EMailReader *reader,
        action_group = e_mail_reader_get_action_group (
                reader, E_MAIL_READER_ACTION_GROUP_STANDARD);
 
-       /* The "mail-forward" action is special: it uses a GtkMenuToolButton
-        * for its toolbar item type.  So we have to create it separately. */
-
-       menu_tool_action = e_menu_tool_action_new (
-               "mail-forward", _("_Forward"),
-               _("Forward the selected message to someone"));
-
-       gtk_action_set_icon_name (
-               GTK_ACTION (menu_tool_action), "mail-forward");
-
-       g_signal_connect (
-               menu_tool_action, "activate",
-               G_CALLBACK (action_mail_forward_cb), reader);
-
-       gtk_action_group_add_action_with_accel (
-               action_group, GTK_ACTION (menu_tool_action), "<Control>f");
-
-       /* Likewise the "mail-reply-group" action. */
-
-       menu_tool_action = e_menu_tool_action_new (
-               /* For Translators: "Group Reply" will reply either to a mailing list
-                * (if possible and if that configuration option is enabled), or else
-                * it will reply to all. The word "Group" was chosen because it covers
-                * either of those, without too strongly implying one or the other. */
-               "mail-reply-group", _("Group Reply"),
-               _("Reply to the mailing list, or to all recipients"));
-
-       gtk_action_set_icon_name (
-               GTK_ACTION (menu_tool_action), "mail-reply-all");
-
-       g_signal_connect (
-               menu_tool_action, "activate",
-               G_CALLBACK (action_mail_reply_group_cb), reader);
-
-       gtk_action_group_add_action_with_accel (
-               action_group, GTK_ACTION (menu_tool_action), "<Control>g");
-
-       /* Add the other actions the normal way. */
        gtk_action_group_add_actions (
                action_group, mail_reader_entries,
                G_N_ELEMENTS (mail_reader_entries), reader);
@@ -5285,11 +5261,9 @@ e_mail_reader_init (EMailReader *reader,
 
        action_name = "mail-forward";
        action = e_mail_reader_get_action (reader, action_name);
-       gtk_action_set_is_important (action, TRUE);
 
        action_name = "mail-reply-group";
        action = e_mail_reader_get_action (reader, action_name);
-       gtk_action_set_is_important (action, TRUE);
 
        action_name = "mail-next";
        action = e_mail_reader_get_action (reader, action_name);
@@ -5301,11 +5275,9 @@ e_mail_reader_init (EMailReader *reader,
 
        action_name = "mail-reply-all";
        action = e_mail_reader_get_action (reader, action_name);
-       gtk_action_set_is_important (action, TRUE);
 
        action_name = "mail-reply-sender";
        action = e_mail_reader_get_action (reader, action_name);
-       gtk_action_set_is_important (action, TRUE);
        gtk_action_set_short_label (action, _("Reply"));
 
        action_name = "add-to-address-book";
@@ -6307,3 +6279,121 @@ e_mail_reader_remove_ui (EMailReader *reader)
 
        iface->remove_ui (reader);
 }
+
+/**
+ * e_mail_reader_create_reply_menu:
+ * @reader: A #EMailReader
+ *
+ * Get reply menu
+ *
+ * Returns: (transfer full): A new #GtkMenu
+ *
+ * Since: 3.46
+ **/
+GtkWidget *
+e_mail_reader_create_reply_menu (EMailReader *reader)
+{
+       GtkWindow *window;
+       GtkWidget *menu;
+       GtkAction *action;
+       GtkAccelGroup *accel_group;
+       GtkUIManager *ui_manager;
+
+       menu = gtk_menu_new ();
+
+       window = e_mail_reader_get_window (reader);
+       g_return_val_if_fail (window != NULL, menu);
+
+       if (E_IS_SHELL_WINDOW (window))
+               ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window));
+       else if (E_IS_MAIL_BROWSER (window))
+               ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window));
+       else
+               return menu;
+
+       accel_group = gtk_ui_manager_get_accel_group (ui_manager);
+
+       action = e_mail_reader_get_action (reader, "mail-reply-all");
+       gtk_action_set_accel_group (action, accel_group);
+       gtk_menu_shell_append (
+               GTK_MENU_SHELL (menu),
+               gtk_action_create_menu_item (action));
+
+       action = e_mail_reader_get_action (reader, "mail-reply-list");
+       gtk_action_set_accel_group (action, accel_group);
+       gtk_menu_shell_append (
+               GTK_MENU_SHELL (menu),
+               gtk_action_create_menu_item (action));
+
+       action = e_mail_reader_get_action (reader, "mail-reply-alternative");
+       gtk_action_set_accel_group (action, accel_group);
+       gtk_menu_shell_append (
+               GTK_MENU_SHELL (menu),
+               gtk_action_create_menu_item (action));
+
+       gtk_widget_show_all (menu);
+
+       return menu;
+}
+
+/**
+ * e_mail_reader_create_forward_menu:
+ * @reader: A #EMailReader
+ *
+ * Get forward menu
+ *
+ * Returns: (transfer full): A new #GtkMenu
+ *
+ * Since: 3.46
+ **/
+GtkWidget *
+e_mail_reader_create_forward_menu (EMailReader *reader)
+{
+       GtkWindow *window;
+       GtkWidget *menu;
+       GtkAction *action;
+       GtkAccelGroup *accel_group;
+       GtkUIManager *ui_manager;
+
+       menu = gtk_menu_new ();
+
+       window = e_mail_reader_get_window (reader);
+       g_return_val_if_fail (window != NULL, menu);
+
+       if (E_IS_SHELL_WINDOW (window))
+               ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window));
+       else if (E_IS_MAIL_BROWSER (window))
+               ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window));
+       else
+               return menu;
+
+       accel_group = gtk_ui_manager_get_accel_group (ui_manager);
+
+       action = e_mail_reader_get_action (reader, "mail-forward-attached-full");
+       gtk_action_set_accel_group (action, accel_group);
+       gtk_menu_shell_append (
+               GTK_MENU_SHELL (menu),
+               gtk_action_create_menu_item (action));
+
+       action = e_mail_reader_get_action (reader, "mail-forward-inline-full");
+       gtk_action_set_accel_group (action, accel_group);
+       gtk_menu_shell_append (
+               GTK_MENU_SHELL (menu),
+               gtk_action_create_menu_item (action));
+
+       action = e_mail_reader_get_action (reader, "mail-forward-quoted-full");
+       gtk_action_set_accel_group (action, accel_group);
+       gtk_menu_shell_append (
+               GTK_MENU_SHELL (menu),
+               gtk_action_create_menu_item (action));
+
+       action = e_mail_reader_get_action (reader, "mail-redirect");
+       gtk_action_set_accel_group (action, accel_group);
+       gtk_menu_shell_append (
+               GTK_MENU_SHELL (menu),
+               gtk_action_create_menu_item (action));
+
+       gtk_widget_show_all (menu);
+
+       return menu;
+}
diff --git a/src/mail/e-mail-reader.h b/src/mail/e-mail-reader.h
index ce0ced4927..41ce3946c8 100644
--- a/src/mail/e-mail-reader.h
+++ b/src/mail/e-mail-reader.h
@@ -214,6 +214,9 @@ void                e_mail_reader_composer_created  (EMailReader *reader,
                                                 CamelMimeMessage *message);
 void           e_mail_reader_reload            (EMailReader *reader);
 void           e_mail_reader_remove_ui         (EMailReader *reader);
+GtkWidget *    e_mail_reader_create_reply_menu (EMailReader *reader);
+GtkWidget *    e_mail_reader_create_forward_menu
+                                               (EMailReader *reader);
 
 G_END_DECLS
 
diff --git a/src/modules/calendar/e-cal-shell-view-private.c b/src/modules/calendar/e-cal-shell-view-private.c
index da0142958e..f01e288253 100644
--- a/src/modules/calendar/e-cal-shell-view-private.c
+++ b/src/modules/calendar/e-cal-shell-view-private.c
@@ -309,6 +309,37 @@ cal_shell_view_taskpad_settings_changed_cb (GSettings *settings,
        }
 }
 
+static void
+cal_shell_view_update_header_bar (ECalShellView *cal_shell_view)
+{
+       EShellWindow *shell_window;
+       EShellView *shell_view;
+       EShellHeaderBar *shell_headerbar;
+       GtkWidget *widget;
+       GtkAction *action;
+
+       shell_view = E_SHELL_VIEW (cal_shell_view);
+       shell_window = e_shell_view_get_shell_window (shell_view);
+       shell_headerbar = E_SHELL_HEADER_BAR (gtk_window_get_titlebar (GTK_WINDOW (shell_window)));
+
+       e_shell_header_bar_clear (shell_headerbar, "e-cal-shell-view");
+       if (!e_shell_view_is_active (shell_view))
+               return;
+
+       action = ACTION (CALENDAR_GO_BACK);
+       widget = e_header_bar_button_new (NULL, action);
+       gtk_widget_set_name (widget, "e-cal-shell-view-buttons");
+       gtk_widget_show (widget);
+
+       action = ACTION (CALENDAR_GO_TODAY);
+       e_header_bar_button_add_action (E_HEADER_BAR_BUTTON (widget), NULL, action);
+
+       action = ACTION (CALENDAR_GO_FORWARD);
+       e_header_bar_button_add_action (E_HEADER_BAR_BUTTON (widget), NULL, action);
+
+       e_shell_header_bar_pack_end (shell_headerbar, widget);
+}
+
 void
 e_cal_shell_view_private_init (ECalShellView *cal_shell_view)
 {
@@ -399,6 +430,12 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view)
        priv->client_cache = e_shell_get_client_cache (shell);
        g_object_ref (priv->client_cache);
 
+       g_signal_connect_object (
+               cal_shell_view, "toggled",
+               G_CALLBACK (cal_shell_view_update_header_bar),
+               NULL,
+               G_CONNECT_AFTER);
+
        handler_id = g_signal_connect (
                priv->client_cache, "backend-error",
                G_CALLBACK (cal_shell_view_backend_error_cb),
diff --git a/src/modules/calendar/e-cal-shell-view-private.h b/src/modules/calendar/e-cal-shell-view-private.h
index fa8ab91178..8385370217 100644
--- a/src/modules/calendar/e-cal-shell-view-private.h
+++ b/src/modules/calendar/e-cal-shell-view-private.h
@@ -28,6 +28,7 @@
 
 #include <libecal/libecal.h>
 
+#include <shell/e-shell-headerbar.h>
 #include <shell/e-shell-utils.h>
 
 #include <calendar/gui/calendar-config.h>
diff --git a/src/modules/mail/e-mail-shell-view-private.c b/src/modules/mail/e-mail-shell-view-private.c
index ad161670c8..86fd1c70db 100644
--- a/src/modules/mail/e-mail-shell-view-private.c
+++ b/src/modules/mail/e-mail-shell-view-private.c
@@ -1465,40 +1465,28 @@ create_send_receive_submenu (EMailShellView *mail_shell_view)
 void
 e_mail_shell_view_update_send_receive_menus (EMailShellView *mail_shell_view)
 {
-       EMailShellViewPrivate *priv;
+       EMailShellContent *mail_shell_content;
        EShellWindow *shell_window;
        EShellView *shell_view;
+       EMailView *mail_view;
+       EShellHeaderBar *shell_headerbar;
        GtkWidget *widget;
+       GtkAction *action;
+       const gchar *action_name;
        const gchar *widget_path;
 
        g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view));
 
-       priv = E_MAIL_SHELL_VIEW_GET_PRIVATE (mail_shell_view);
-
        shell_view = E_SHELL_VIEW (mail_shell_view);
        shell_window = e_shell_view_get_shell_window (shell_view);
+       shell_headerbar = E_SHELL_HEADER_BAR (gtk_window_get_titlebar (GTK_WINDOW (shell_window)));
 
-       if (!e_shell_view_is_active (shell_view)) {
-               if (priv->send_receive_tool_item) {
-                       GtkWidget *toolbar;
-
-                       toolbar = e_shell_window_get_managed_widget (
-                               shell_window, "/main-toolbar");
-                       g_return_if_fail (toolbar != NULL);
-
-                       gtk_container_remove (
-                               GTK_CONTAINER (toolbar),
-                               GTK_WIDGET (priv->send_receive_tool_item));
-                       gtk_container_remove (
-                               GTK_CONTAINER (toolbar),
-                               GTK_WIDGET (priv->send_receive_tool_separator));
-
-                       priv->send_receive_tool_item = NULL;
-                       priv->send_receive_tool_separator = NULL;
-               }
-
+       e_shell_header_bar_clear (shell_headerbar, "e-mail-shell-view");
+       if (!e_shell_view_is_active (shell_view))
                return;
-       }
+
+       mail_shell_content = mail_shell_view->priv->mail_shell_content;
+       mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
 
        widget_path =
                "/main-menu/file-menu"
@@ -1509,46 +1497,45 @@ e_mail_shell_view_update_send_receive_menus (EMailShellView *mail_shell_view)
                        GTK_MENU_ITEM (widget),
                        create_send_receive_submenu (mail_shell_view));
 
-       if (!priv->send_receive_tool_item) {
-               GtkWidget *toolbar;
-               GtkToolItem *tool_item;
-               gint index;
-
-               toolbar = e_shell_window_get_managed_widget (
-                       shell_window, "/main-toolbar");
-               g_return_if_fail (toolbar != NULL);
-
-               widget_path =
-                       "/main-toolbar/toolbar-actions/mail-send-receiver";
-               widget = e_shell_window_get_managed_widget (
-                       shell_window, widget_path);
-               g_return_if_fail (widget != NULL);
-
-               index = gtk_toolbar_get_item_index (
-                       GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (widget));
-
-               tool_item = gtk_separator_tool_item_new ();
-               gtk_toolbar_insert (GTK_TOOLBAR (toolbar), tool_item, index);
-               gtk_widget_show (GTK_WIDGET (tool_item));
-               priv->send_receive_tool_separator = tool_item;
-
-               tool_item = GTK_TOOL_ITEM (
-                       e_menu_tool_button_new (_("Send / Receive")));
-               gtk_tool_item_set_is_important (tool_item, TRUE);
-               gtk_toolbar_insert (GTK_TOOLBAR (toolbar), tool_item, index);
-               gtk_widget_show (GTK_WIDGET (tool_item));
-               priv->send_receive_tool_item = tool_item;
-
-               e_binding_bind_property (
-                       ACTION (MAIL_SEND_RECEIVE), "sensitive",
-                       tool_item, "sensitive",
-                       G_BINDING_SYNC_CREATE);
-       }
-
-       if (priv->send_receive_tool_item)
-               gtk_menu_tool_button_set_menu (
-                       GTK_MENU_TOOL_BUTTON (priv->send_receive_tool_item),
-                       create_send_receive_submenu (mail_shell_view));
+       widget = e_header_bar_button_new (_("Send / Receive"), ACTION (MAIL_SEND_RECEIVE));
+       gtk_widget_set_name (widget, "e-mail-shell-view-send-receive");
+       e_header_bar_button_take_menu (
+               E_HEADER_BAR_BUTTON (widget),
+               create_send_receive_submenu (mail_shell_view));
+       gtk_widget_show (widget);
+
+       e_shell_header_bar_pack_start (shell_headerbar, widget);
+
+       action_name = "mail-forward";
+       action = e_mail_reader_get_action (E_MAIL_READER (mail_view), action_name);
+       widget = e_header_bar_button_new (_("Forward"), action);
+       gtk_widget_set_name (widget, "e-mail-shell-view-forward");
+       e_header_bar_button_take_menu (
+               E_HEADER_BAR_BUTTON (widget),
+               e_mail_reader_create_forward_menu (E_MAIL_READER (mail_view)));
+       gtk_widget_show (widget);
+
+       e_shell_header_bar_pack_end (shell_headerbar, widget);
+
+       action_name = "mail-reply-group";
+       action = e_mail_reader_get_action (E_MAIL_READER (mail_view), action_name);
+       widget = e_header_bar_button_new (_("Group Reply"), action);
+       gtk_widget_set_name (widget, "e-mail-shell-view-reply-group");
+       gtk_widget_show (widget);
+
+       e_header_bar_button_take_menu (
+               E_HEADER_BAR_BUTTON (widget),
+               e_mail_reader_create_reply_menu (E_MAIL_READER (mail_view)));
+
+       e_shell_header_bar_pack_end (shell_headerbar, widget);
+
+       action_name = "mail-reply-sender";
+       action = e_mail_reader_get_action (E_MAIL_READER (mail_view), action_name);
+       widget = e_header_bar_button_new (_("Reply"), action);
+       gtk_widget_set_name (widget, "e-mail-shell-view-reply-sender");
+       gtk_widget_show (widget);
+
+       e_shell_header_bar_pack_end (shell_headerbar, widget);
 }
 
 static void
diff --git a/src/modules/mail/e-mail-shell-view-private.h b/src/modules/mail/e-mail-shell-view-private.h
index 512003654a..6a7a44bd4b 100644
--- a/src/modules/mail/e-mail-shell-view-private.h
+++ b/src/modules/mail/e-mail-shell-view-private.h
@@ -26,6 +26,8 @@
 #include <glib/gi18n.h>
 #include <camel/camel-search-private.h>  /* for camel_search_word */
 
+#include "shell/e-shell-headerbar.h"
+
 #include <mail/e-mail-folder-create-dialog.h>
 #include <mail/e-mail-reader.h>
 #include <mail/e-mail-reader-utils.h>
@@ -133,9 +135,6 @@ struct _EMailShellViewPrivate {
        CamelVeeFolder *search_account_current;
        GCancellable *search_account_cancel;
 
-       GtkToolItem *send_receive_tool_item;
-       GtkToolItem *send_receive_tool_separator;
-
        gboolean vfolder_allow_expunge;
        gboolean ignore_folder_popup_selection_done;
 
diff --git a/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt
index 9a3307ce0b..101a85dcc8 100644
--- a/src/shell/CMakeLists.txt
+++ b/src/shell/CMakeLists.txt
@@ -19,6 +19,7 @@ set(SOURCES
        e-shell-backend.c
        e-shell-content.c
        e-shell-enumtypes.c
+       e-shell-headerbar.c
        e-shell-searchbar.c
        e-shell-sidebar.c
        e-shell-switcher.c
@@ -40,6 +41,7 @@ set(HEADERS
        e-shell-backend.h
        e-shell-common.h
        e-shell-content.h
+       e-shell-headerbar.h
        e-shell-searchbar.h
        e-shell-sidebar.h
        e-shell-switcher.h
diff --git a/src/shell/e-shell-headerbar.c b/src/shell/e-shell-headerbar.c
new file mode 100644
index 0000000000..feedce68b4
--- /dev/null
+++ b/src/shell/e-shell-headerbar.c
@@ -0,0 +1,310 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * SPDX-FileCopyrightText: (C) 2022 Cédric Bellegarde <cedric bellegarde adishatz org>
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "evolution-config.h"
+
+#include "e-shell-headerbar.h"
+#include "e-shell-window-private.h"
+
+#include <glib/gi18n.h>
+
+struct _EShellHeaderBarPrivate {
+       GWeakRef shell_window;
+
+       GtkWidget *new_button;
+       GtkWidget *start_buttons;
+       GtkWidget *end_buttons;
+
+       gulong prefered_item_notify_id;
+};
+
+enum {
+       PROP_0,
+       PROP_SHELL_WINDOW
+};
+
+G_DEFINE_TYPE_WITH_CODE (EShellHeaderBar, e_shell_header_bar, GTK_TYPE_HEADER_BAR,
+       G_ADD_PRIVATE (EShellHeaderBar))
+
+static void
+shell_header_bar_clear_box (GtkWidget *widget,
+                           const gchar *name)
+{
+       GList *children, *iter;
+       const gchar *widget_name;
+
+       children = gtk_container_get_children (GTK_CONTAINER (widget));
+
+       for (iter = children; iter != NULL; iter = g_list_next (iter)) {
+               widget_name = gtk_widget_get_name (iter->data);
+               if (widget_name != NULL && g_str_has_prefix (widget_name, name))
+                       gtk_widget_destroy (iter->data);
+       }
+
+       g_list_free (children);
+}
+
+static EShellWindow *
+shell_header_bar_dup_shell_window (EShellHeaderBar *headerbar)
+{
+       g_return_val_if_fail (E_IS_SHELL_HEADER_BAR (headerbar), NULL);
+
+       return g_weak_ref_get (&headerbar->priv->shell_window);
+}
+
+static void
+shell_header_bar_set_shell_window (EShellHeaderBar *headerbar,
+                                  EShellWindow *shell_window)
+{
+       EShellWindow *priv_shell_window = shell_header_bar_dup_shell_window (headerbar);
+
+       /* This should be always NULL, but for a sake of completeness
+          and no memory leak do unref it here. Also do *not* use
+          g_clear_object(), because the non-NULL is tested below. */
+       if (priv_shell_window)
+               g_object_unref (priv_shell_window);
+
+       g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
+       g_return_if_fail (priv_shell_window == NULL);
+
+       g_weak_ref_set (
+               &headerbar->priv->shell_window,
+               G_OBJECT (shell_window));
+}
+
+static void
+shell_header_bar_update_new_menu (EShellWindow *shell_window,
+                                 GParamSpec *pspec,
+                                 gpointer user_data)
+{
+       EShellHeaderBar *headerbar = user_data;
+       GtkWidget *menu;
+
+       /* Update the "New" menu button submenu. */
+       menu = e_shell_window_create_new_menu (shell_window);
+       e_header_bar_button_take_menu (E_HEADER_BAR_BUTTON (headerbar->priv->new_button), menu);
+}
+
+
+static void
+shell_header_bar_set_property (GObject *object,
+                              guint property_id,
+                              const GValue *value,
+                              GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_SHELL_WINDOW:
+                       shell_header_bar_set_shell_window (
+                               E_SHELL_HEADER_BAR (object),
+                               g_value_get_object (value));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+shell_header_bar_get_property (GObject *object,
+                              guint property_id,
+                              GValue *value,
+                              GParamSpec *pspec)
+{
+       switch (property_id) {
+               case PROP_SHELL_WINDOW:
+                       g_value_take_object (
+                               value, shell_header_bar_dup_shell_window (
+                               E_SHELL_HEADER_BAR (object)));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+shell_header_bar_constructed (GObject *object)
+{
+       EShellHeaderBar *headerbar = E_SHELL_HEADER_BAR (object);
+       EShellWindow *shell_window = shell_header_bar_dup_shell_window (headerbar);
+       GtkUIManager *ui_manager = e_shell_window_get_ui_manager (shell_window);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_shell_header_bar_parent_class)->constructed (object);
+
+       g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
+
+       e_header_bar_button_add_accelerator (
+               E_HEADER_BAR_BUTTON (headerbar->priv->new_button),
+               gtk_ui_manager_get_accel_group (ui_manager),
+               GDK_KEY_N, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+
+       headerbar->priv->prefered_item_notify_id = e_signal_connect_notify (
+               shell_window, "notify::active-view",
+               G_CALLBACK (shell_header_bar_update_new_menu), headerbar);
+
+       g_object_unref (shell_window);
+}
+
+static void
+shell_header_bar_dispose (GObject *object)
+{
+       EShellHeaderBar *headerbar = E_SHELL_HEADER_BAR (object);
+
+       if (headerbar->priv->new_button != NULL) {
+               EShellWindow *shell_window = shell_header_bar_dup_shell_window (headerbar);
+
+               if (shell_window) {
+                       g_signal_handler_disconnect (
+                               shell_window,
+                               headerbar->priv->prefered_item_notify_id);
+                       g_object_unref (headerbar->priv->new_button);
+
+                       g_object_unref (shell_window);
+               }
+
+               headerbar->priv->new_button = NULL;
+               headerbar->priv->prefered_item_notify_id = 0;
+       }
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_shell_header_bar_parent_class)->dispose (object);
+}
+
+static void
+e_shell_header_bar_class_init (EShellHeaderBarClass *klass)
+{
+       GObjectClass *object_class;
+
+       object_class = G_OBJECT_CLASS (klass);
+       object_class->set_property = shell_header_bar_set_property;
+       object_class->get_property = shell_header_bar_get_property;
+       object_class->dispose = shell_header_bar_dispose;
+       object_class->constructed = shell_header_bar_constructed;
+
+       /**
+        * EShellHeaderbar:shell-window
+        *
+        * The #EShellWindow to which the headerbar belongs.
+        **/
+       g_object_class_install_property (
+               object_class,
+               PROP_SHELL_WINDOW,
+               g_param_spec_object (
+                       "shell-window",
+                       "Shell Window",
+                       "The window to which the headerbar belongs",
+                       E_TYPE_SHELL_WINDOW,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT_ONLY |
+                       G_PARAM_EXPLICIT_NOTIFY |
+                       G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_shell_header_bar_init (EShellHeaderBar *self)
+{
+       GtkWidget *new_button;
+
+       self->priv = e_shell_header_bar_get_instance_private (self);
+       gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (self), TRUE);
+
+       new_button = e_header_bar_button_new (C_("toolbar-button", "New"), NULL);
+       gtk_header_bar_pack_start (GTK_HEADER_BAR (self), new_button);
+       gtk_widget_show (new_button);
+       self->priv->new_button = g_object_ref (new_button);
+
+       self->priv->start_buttons = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
+       gtk_header_bar_pack_start (GTK_HEADER_BAR (self), self->priv->start_buttons);
+       gtk_widget_show (self->priv->start_buttons);
+
+       self->priv->end_buttons = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
+       gtk_header_bar_pack_end (GTK_HEADER_BAR (self), self->priv->end_buttons);
+       gtk_widget_show (self->priv->end_buttons);
+}
+
+/**
+ * e_shell_header_bar_new:
+ * @shel_window: The #EShellWindow to which the headerbar belongs
+ *
+ * Creates a new #EShellHeaderBar
+ *
+ * Returns: (transfer full): a new #EShellHeaderBar
+ *
+ * Since: 3.46
+ **/
+GtkWidget *
+e_shell_header_bar_new (EShellWindow *shell_window)
+{
+       return g_object_new (E_TYPE_SHELL_HEADER_BAR, "shell-window", shell_window, NULL);
+}
+
+/**
+ * e_shell_header_bar_get_new_button:
+ * @headerbar: a #EShellHeaderBar
+ *
+ * Returns: (transfer none): the 'New' button widget, which is #EHeaderBarButton
+ *
+ * Since: 3.46
+ **/
+GtkWidget *
+e_shell_header_bar_get_new_button (EShellHeaderBar *headerbar)
+{
+       g_return_val_if_fail (E_IS_SHELL_HEADER_BAR (headerbar), NULL);
+
+       return headerbar->priv->new_button;
+}
+
+/**
+ * e_shell_header_bar_pack_start:
+ * @headerbar: an #EShellHeaderBar
+ * @widget: widget to pack
+ *
+ * Adds child to bar, packed with reference to the start of the bar.
+ *
+ * Since: 3.46
+ **/
+void
+e_shell_header_bar_pack_start (EShellHeaderBar *headerbar,
+                              GtkWidget *widget)
+{
+       g_return_if_fail (E_IS_SHELL_HEADER_BAR (headerbar));
+
+       gtk_box_pack_start (GTK_BOX (headerbar->priv->start_buttons), widget, FALSE, FALSE, 0);
+}
+
+/**
+ * e_shell_header_bar_pack_end:
+ * @headerbar: an #EShellHeaderBar
+ * @widget: widget to pack
+ *
+ * Adds child to bar, packed with reference to the end of the bar.
+ *
+ * Since: 3.46
+ **/
+void e_shell_header_bar_pack_end (EShellHeaderBar *headerbar,
+                                 GtkWidget *widget)
+{
+       g_return_if_fail (E_IS_SHELL_HEADER_BAR (headerbar));
+
+       gtk_box_pack_end (GTK_BOX (headerbar->priv->end_buttons), widget, FALSE, FALSE, 0);
+}
+
+/**
+ * e_shell_header_bar_clear:
+ * @headerbar: an #EShellHeaderBar
+ * @name: widget name starts with
+ *
+ * Removes all widgets from the header bar where widget name starts with @name
+ *
+ * Since: 3.46
+ **/
+void e_shell_header_bar_clear (EShellHeaderBar *headerbar,
+                              const gchar *name)
+{
+       g_return_if_fail (E_IS_SHELL_HEADER_BAR (headerbar));
+
+       shell_header_bar_clear_box (headerbar->priv->start_buttons, name);
+       shell_header_bar_clear_box (headerbar->priv->end_buttons, name);
+}
diff --git a/src/shell/e-shell-headerbar.h b/src/shell/e-shell-headerbar.h
new file mode 100644
index 0000000000..2aaabf009b
--- /dev/null
+++ b/src/shell/e-shell-headerbar.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * SPDX-FileCopyrightText: (C) 2022 Cédric Bellegarde <cedric bellegarde adishatz org>
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef E_SHELL_HEADER_BAR_H
+#define E_SHELL_HEADER_BAR_H
+
+#include <gtk/gtk.h>
+
+#include <e-util/e-util.h>
+#include <shell/e-shell-window.h>
+
+#define E_TYPE_SHELL_HEADER_BAR \
+       (e_shell_header_bar_get_type ())
+#define E_SHELL_HEADER_BAR(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_SHELL_HEADER_BAR, EShellHeaderBar))
+#define E_SHELL_HEADER_BAR_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_SHELL_HEADER_BAR, EShellHeaderBarClass))
+#define E_IS_SHELL_HEADER_BAR(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_SHELL_HEADER_BAR))
+#define E_IS_SHELL_HEADER_BAR_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_SHELL_HEADER_BAR))
+#define E_SHELL_HEADER_BAR_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_SHELL_HEADER_BAR, EShellHeaderBarClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EShellHeaderBar EShellHeaderBar;
+typedef struct _EShellHeaderBarClass EShellHeaderBarClass;
+typedef struct _EShellHeaderBarPrivate EShellHeaderBarPrivate;
+
+struct _EShellHeaderBar {
+       GtkHeaderBar parent;
+       EShellHeaderBarPrivate *priv;
+};
+
+struct _EShellHeaderBarClass {
+       GtkHeaderBarClass parent_class;
+};
+
+GType                  e_shell_header_bar_get_type                     (void);
+GtkWidget *            e_shell_header_bar_new                          (EShellWindow *shell_window);
+GtkWidget *            e_shell_header_bar_get_new_button               (EShellHeaderBar *headerbar);
+void                   e_shell_header_bar_pack_start                   (EShellHeaderBar *headerbar,
+                                                                        GtkWidget *widget);
+void                   e_shell_header_bar_pack_end                     (EShellHeaderBar *headerbar,
+                                                                        GtkWidget *widget);
+void                   e_shell_header_bar_clear                        (EShellHeaderBar *headerbar,
+                                                                        const gchar *name);
+G_END_DECLS
+
+#endif /* E_SHELL_HEADER_BAR_H */
diff --git a/src/shell/e-shell-window-private.c b/src/shell/e-shell-window-private.c
index 8eb50413f9..2545814b0b 100644
--- a/src/shell/e-shell-window-private.c
+++ b/src/shell/e-shell-window-private.c
@@ -203,6 +203,30 @@ shell_window_construct_taskbar (EShellWindow *shell_window)
        return class->construct_taskbar (shell_window);
 }
 
+static gboolean
+shell_window_active_view_to_prefer_item (GBinding *binding,
+                                         const GValue *source_value,
+                                         GValue *target_value,
+                                         gpointer user_data)
+{
+       GObject *source_object;
+       EShell *shell;
+       EShellBackend *shell_backend;
+       const gchar *active_view;
+       const gchar *prefer_item;
+
+       active_view = g_value_get_string (source_value);
+
+       source_object = g_binding_get_source (binding);
+       shell = e_shell_window_get_shell (E_SHELL_WINDOW (source_object));
+       shell_backend = e_shell_get_backend_by_name (shell, active_view);
+       prefer_item = e_shell_backend_get_prefer_new_item (shell_backend);
+
+       g_value_set_string (target_value, prefer_item);
+
+       return TRUE;
+}
+
 void
 e_shell_window_private_init (EShellWindow *shell_window)
 {
@@ -435,6 +459,10 @@ e_shell_window_private_constructed (EShellWindow *shell_window)
 
        /* Construct window widgets. */
 
+       priv->headerbar = e_shell_header_bar_new (shell_window);
+       gtk_window_set_titlebar (window, priv->headerbar);
+       gtk_widget_show (priv->headerbar);
+
        widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
        gtk_container_add (GTK_CONTAINER (shell_window), widget);
        gtk_widget_show (widget);
@@ -661,6 +689,26 @@ e_shell_window_private_constructed (EShellWindow *shell_window)
 
        g_signal_connect (shell_window, "key-press-event",
                G_CALLBACK (e_shell_window_key_press_event_cb), NULL);
+
+       /* XXX The ECalShellBackend has a hack where it forces the
+        *     EMenuButton to update its button image by forcing
+        *     a "notify::active-view" signal emission on the window.
+        *     This will trigger the property binding, which will set
+        *     EMenuButton's "prefer-item" property, which will
+        *     invoke header_bar_update_new_menu(), which
+        *     will cause EMenuButton to update its button image.
+        *
+        *     It's a bit of a Rube Goldberg machine and should be
+        *     reworked, but it's just serving one (now documented)
+        *     corner case and works for now. */
+       e_binding_bind_property_full (
+               shell_window, "active-view",
+               e_shell_header_bar_get_new_button (E_SHELL_HEADER_BAR (priv->headerbar)),
+               "prefer-item",
+               G_BINDING_SYNC_CREATE,
+               shell_window_active_view_to_prefer_item,
+               (GBindingTransformFunc) NULL,
+               NULL, (GDestroyNotify) NULL);
 }
 
 void
@@ -810,7 +858,6 @@ e_shell_window_update_title (EShellWindow *shell_window)
        EShellView *shell_view;
        const gchar *view_title;
        const gchar *view_name;
-       gchar *window_title;
 
        g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
 
@@ -818,8 +865,5 @@ e_shell_window_update_title (EShellWindow *shell_window)
        shell_view = e_shell_window_get_shell_view (shell_window, view_name);
        view_title = e_shell_view_get_title (shell_view);
 
-       /* Translators: This is used for the main window title. */
-       window_title = g_strdup_printf (_("%s — Evolution"), view_title);
-       gtk_window_set_title (GTK_WINDOW (shell_window), window_title);
-       g_free (window_title);
+       gtk_window_set_title (GTK_WINDOW (shell_window), view_title);
 }
diff --git a/src/shell/e-shell-window-private.h b/src/shell/e-shell-window-private.h
index ae10390521..de80f8e767 100644
--- a/src/shell/e-shell-window-private.h
+++ b/src/shell/e-shell-window-private.h
@@ -30,6 +30,7 @@
 
 #include "shell/e-shell.h"
 #include "shell/e-shell-content.h"
+#include "shell/e-shell-headerbar.h"
 #include "shell/e-shell-view.h"
 #include "shell/e-shell-searchbar.h"
 #include "shell/e-shell-switcher.h"
@@ -80,9 +81,7 @@ struct _EShellWindowPrivate {
        GtkWidget *switcher;
        GtkWidget *tooltip_label;
        GtkWidget *status_notebook;
-
-       /* Miscellaneous */
-       GtkWidget *menubar_box;
+       GtkWidget *headerbar;
 
        /* Shell signal handlers. */
        GArray *signal_handler_ids;
diff --git a/src/shell/e-shell-window.c b/src/shell/e-shell-window.c
index e7be30feee..6fe7672ad0 100644
--- a/src/shell/e-shell-window.c
+++ b/src/shell/e-shell-window.c
@@ -108,42 +108,6 @@ shell_window_menubar_update_new_menu (EShellWindow *shell_window)
        gtk_widget_show (widget);
 }
 
-static void
-shell_window_toolbar_update_new_menu (GtkMenuToolButton *menu_tool_button,
-                                      GParamSpec *pspec,
-                                      EShellWindow *shell_window)
-{
-       GtkWidget *menu;
-
-       /* Update the "New" menu tool button submenu. */
-       menu = e_shell_window_create_new_menu (shell_window);
-       gtk_menu_tool_button_set_menu (menu_tool_button, menu);
-}
-
-static gboolean
-shell_window_active_view_to_prefer_item (GBinding *binding,
-                                         const GValue *source_value,
-                                         GValue *target_value,
-                                         gpointer user_data)
-{
-       GObject *source_object;
-       EShell *shell;
-       EShellBackend *shell_backend;
-       const gchar *active_view;
-       const gchar *prefer_item;
-
-       active_view = g_value_get_string (source_value);
-
-       source_object = g_binding_get_source (binding);
-       shell = e_shell_window_get_shell (E_SHELL_WINDOW (source_object));
-       shell_backend = e_shell_get_backend_by_name (shell, active_view);
-       prefer_item = e_shell_backend_get_prefer_new_item (shell_backend);
-
-       g_value_set_string (target_value, prefer_item);
-
-       return TRUE;
-}
-
 static void
 shell_window_set_notebook_page (EShellWindow *shell_window,
                                 GParamSpec *pspec,
@@ -473,12 +437,8 @@ shell_window_construct_menubar (EShellWindow *shell_window)
 static GtkWidget *
 shell_window_construct_toolbar (EShellWindow *shell_window)
 {
-       GtkUIManager *ui_manager;
        GtkWidget *toolbar;
        GtkWidget *box;
-       GtkToolItem *item;
-
-       ui_manager = e_shell_window_get_ui_manager (shell_window);
 
        box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
        gtk_widget_show (box);
@@ -490,69 +450,23 @@ shell_window_construct_toolbar (EShellWindow *shell_window)
 
        toolbar = e_shell_window_get_managed_widget (
                shell_window, "/main-toolbar");
+       gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
 
        gtk_style_context_add_class (
                gtk_widget_get_style_context (toolbar),
                GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
 
-       /* XXX Having this separator in the UI definition doesn't work
-        *     because GtkUIManager is unaware of the "New" button, so
-        *     it makes the separator invisible.  One possibility is to
-        *     define a GtkAction subclass for which create_tool_item()
-        *     return an EMenuToolButton.  Then both this separator
-        *     and the "New" button could be added to the UI definition.
-        *     Tempting, but the "New" button and its dynamically
-        *     generated menu is already a complex beast, and I'm not
-        *     convinced having it proxy some new type of GtkAction
-        *     is worth the extra effort. */
-       item = gtk_separator_tool_item_new ();
-       gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, 0);
-       gtk_widget_show (GTK_WIDGET (item));
-
-       /* Translators: a 'New' toolbar button caption which is context sensitive and
-          runs one of the actions under File->New menu */
-       item = e_menu_tool_button_new (C_("toolbar-button", "New"));
-       gtk_tool_item_set_is_important (GTK_TOOL_ITEM (item), TRUE);
-       gtk_widget_add_accelerator (
-               GTK_WIDGET (item), "clicked",
-               gtk_ui_manager_get_accel_group (ui_manager),
-               GDK_KEY_N, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
-       gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, 0);
-       gtk_widget_show (GTK_WIDGET (item));
-
-       /* XXX The ECalShellBackend has a hack where it forces the
-        *     EMenuToolButton to update its button image by forcing
-        *     a "notify::active-view" signal emission on the window.
-        *     This will trigger the property binding, which will set
-        *     EMenuToolButton's "prefer-item" property, which will
-        *     invoke shell_window_toolbar_update_new_menu(), which
-        *     will cause EMenuToolButton to update its button image.
-        *
-        *     It's a bit of a Rube Goldberg machine and should be
-        *     reworked, but it's just serving one (now documented)
-        *     corner case and works for now. */
-       e_binding_bind_property_full (
-               shell_window, "active-view",
-               item, "prefer-item",
-               G_BINDING_SYNC_CREATE,
-               shell_window_active_view_to_prefer_item,
-               (GBindingTransformFunc) NULL,
-               NULL, (GDestroyNotify) NULL);
-
-       g_signal_connect (
-               item, "notify::prefer-item",
-               G_CALLBACK (shell_window_toolbar_update_new_menu),
-               shell_window);
-
        gtk_box_pack_start (GTK_BOX (box), toolbar, TRUE, TRUE, 0);
 
        toolbar = e_shell_window_get_managed_widget (
                shell_window, "/search-toolbar");
        gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE);
+       gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
 
        toolbar = e_shell_window_get_managed_widget (
                shell_window, "/close-toolbar");
        gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE);
+       gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
 
        return box;
 }


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