[evolution] Move menu bar handling to utils



commit aa1814e414e19e451d3f2e72139afe835b5e494a
Author: Cédric Bellegarde <cedric bellegarde adishatz org>
Date:   Mon May 30 21:39:26 2022 +0200

    Move menu bar handling to utils

 .../evolution-util/evolution-util-docs.sgml.in     |   1 +
 src/e-util/CMakeLists.txt                          |   2 +
 src/e-util/e-menu-bar.c                            | 284 +++++++++++++++++++++
 src/e-util/e-menu-bar.h                            |  60 +++++
 src/e-util/e-util.h                                |   1 +
 src/shell/e-shell-window-private.c                 | 119 +--------
 src/shell/e-shell-window-private.h                 |   5 +-
 src/shell/e-shell-window.c                         |   7 +-
 8 files changed, 357 insertions(+), 122 deletions(-)
---
diff --git a/docs/reference/evolution-util/evolution-util-docs.sgml.in 
b/docs/reference/evolution-util/evolution-util-docs.sgml.in
index 5b9898aedd..1f13919787 100644
--- a/docs/reference/evolution-util/evolution-util-docs.sgml.in
+++ b/docs/reference/evolution-util/evolution-util-docs.sgml.in
@@ -284,6 +284,7 @@
     <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-bar.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 1b8a3dd1da..bf79e18567 100644
--- a/src/e-util/CMakeLists.txt
+++ b/src/e-util/CMakeLists.txt
@@ -173,6 +173,7 @@ set(SOURCES
        e-markdown-utils.c
        e-marshal.c
        e-headerbar-button.c
+       e-menu-bar.c
        e-misc-utils.c
        e-mktemp.c
        e-month-widget.c
@@ -450,6 +451,7 @@ set(HEADERS
        e-markdown-editor.h
        e-markdown-utils.h
        e-headerbar-button.h
+       e-menu-bar.h
        e-misc-utils.h
        e-mktemp.h
        e-month-widget.h
diff --git a/src/e-util/e-menu-bar.c b/src/e-util/e-menu-bar.c
new file mode 100644
index 0000000000..d679aadf87
--- /dev/null
+++ b/src/e-util/e-menu-bar.c
@@ -0,0 +1,284 @@
+/* -*- 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
+ */
+
+#include "evolution-config.h"
+
+#include "e-menu-bar.h"
+
+struct _EMenuBarPrivate {
+       GtkWidget *inner_menu_bar;
+
+       guint visible : 1;
+       gulong delayed_show_id;
+       gulong delayed_hide_id;
+};
+
+G_DEFINE_TYPE_WITH_CODE (EMenuBar, e_menu_bar, G_TYPE_OBJECT,
+       G_ADD_PRIVATE (EMenuBar))
+
+
+enum {
+       PROP_0,
+       PROP_VISIBLE
+};
+
+static void
+menu_bar_visible_settings_changed_cb (GSettings *settings,
+                                     const gchar *key,
+                                     gpointer data)
+{
+       g_return_if_fail (E_IS_MENU_BAR (data));
+
+       e_menu_bar_set_visible (
+               E_MENU_BAR (data),
+               g_settings_get_boolean (settings, key));
+}
+
+static void
+menu_bar_dispose (GObject *menu_bar)
+{
+       EMenuBar *self = E_MENU_BAR (menu_bar);
+
+       if (self->priv->delayed_show_id) {
+               g_source_remove (self->priv->delayed_show_id);
+               self->priv->delayed_show_id = 0;
+       }
+
+       if (self->priv->delayed_hide_id) {
+               g_source_remove (self->priv->delayed_hide_id);
+               self->priv->delayed_hide_id = 0;
+       }
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_menu_bar_parent_class)->dispose (menu_bar);
+}
+
+static void
+menu_bar_set_property (GObject *object,
+                      guint property_id,
+                      const GValue *value,
+                      GParamSpec *pspec)
+{
+       EMenuBar *menubar = E_MENU_BAR (object);
+
+       switch (property_id) {
+               case PROP_VISIBLE:
+                       e_menu_bar_set_visible (
+                               menubar,
+                               g_value_get_boolean (value));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+menu_bar_get_property (GObject *object,
+                      guint property_id,
+                      GValue *value,
+                      GParamSpec *pspec)
+{
+       EMenuBar *menubar = E_MENU_BAR (object);
+
+       switch (property_id) {
+               case PROP_VISIBLE:
+                       g_value_set_boolean (
+                               value, e_menu_bar_get_visible (menubar));
+                       return;
+       }
+
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_menu_bar_class_init (EMenuBarClass *klass)
+{
+       GObjectClass *object_class;
+
+       object_class = G_OBJECT_CLASS (klass);
+       object_class->dispose = menu_bar_dispose;
+       object_class->set_property = menu_bar_set_property;
+       object_class->get_property = menu_bar_get_property;
+
+       g_object_class_install_property (
+               object_class,
+               PROP_VISIBLE,
+               g_param_spec_boolean (
+                       "visible",
+                       "Visible",
+                       "Inner menubar visible",
+                       FALSE,
+                       G_PARAM_READWRITE));
+}
+
+static void
+e_menu_bar_init (EMenuBar *self)
+{
+       self->priv = e_menu_bar_get_instance_private (self);
+}
+
+static gboolean
+delayed_show_cb (gpointer user_data)
+{
+       EMenuBar *self = user_data;
+
+       self->priv->delayed_show_id = 0;
+
+       if (!self->priv->visible) {
+               gtk_widget_set_visible (GTK_WIDGET (self->priv->inner_menu_bar), TRUE);
+       }
+
+       return FALSE;
+}
+
+static gboolean
+delayed_hide_cb (gpointer user_data)
+{
+       EMenuBar *self = user_data;
+       GtkWidget *widget = GTK_WIDGET (self->priv->inner_menu_bar);
+
+       self->priv->delayed_hide_id = 0;
+
+       if (!self->priv->visible &&
+           !self->priv->delayed_show_id) {
+               if (gtk_widget_get_visible (widget) &&
+                   !gtk_menu_shell_get_selected_item (GTK_MENU_SHELL (self->priv->inner_menu_bar)))
+                       gtk_widget_set_visible (widget, FALSE);
+       }
+
+       return FALSE;
+}
+
+static void
+e_menu_bar_window_event_after_cb (GtkWindow *window,
+                                 GdkEvent *event,
+                                 EMenuBar *self)
+{
+       g_return_if_fail (event != NULL);
+
+       if (event->type != GDK_KEY_PRESS &&
+           event->type != GDK_KEY_RELEASE &&
+           event->type != GDK_BUTTON_RELEASE &&
+           event->type != GDK_FOCUS_CHANGE)
+               return;
+
+       if (event->type == GDK_KEY_PRESS) {
+               GdkEventKey *key_event;
+
+               key_event = (GdkEventKey *) event;
+
+               if ((key_event->keyval == GDK_KEY_Alt_L || key_event->keyval == GDK_KEY_Alt_R) &&
+                   !(key_event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK |
+                                         GDK_SUPER_MASK | GDK_HYPER_MASK |
+                                         GDK_META_MASK))) {
+                       if (self->priv->delayed_hide_id) {
+                               g_source_remove (self->priv->delayed_hide_id);
+                               self->priv->delayed_hide_id = 0;
+                       }
+
+                       if (self->priv->delayed_show_id) {
+                               g_source_remove (self->priv->delayed_show_id);
+                               self->priv->delayed_show_id = 0;
+
+                               delayed_show_cb (self);
+                       } else {
+                               /* To not flash when using Alt+Tab or
+                                  similar system-wide shortcuts */
+                               self->priv->delayed_show_id =
+                                       g_timeout_add (250, delayed_show_cb, self);
+                       }
+               }
+       } else if (event->type != GDK_BUTTON_RELEASE || !(event->button.state & GDK_MOD1_MASK)) {
+               if (self->priv->delayed_show_id) {
+                       g_source_remove (self->priv->delayed_show_id);
+                       self->priv->delayed_show_id = 0;
+               }
+
+               if (gtk_widget_get_visible (GTK_WIDGET (self->priv->inner_menu_bar)) &&
+                   !self->priv->delayed_hide_id) {
+                       self->priv->delayed_hide_id =
+                               g_timeout_add (500, delayed_hide_cb, self);
+               }
+       }
+}
+
+/**
+ * e_menu_bar_new:
+ * @inner_menu_bar: #GtkMenuBar to handle
+ * @window: monitor #GtkWindow for &lt;Alt&gt; key event
+ *
+ * Creates a new #EMenuBar showing @inner_menu_bar on demand
+ *
+ * Returns: (transfer full): a new #EMenuBar
+ *
+ * Since: 3.46
+ **/
+GtkWidget *
+e_menu_bar_new (GtkMenuBar *inner_menu_bar,
+               GtkWindow *window)
+{
+       GtkWidget *menu_bar;
+       GSettings *settings;
+
+       g_return_val_if_fail (GTK_IS_MENU_BAR (inner_menu_bar), NULL);
+       g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+       menu_bar = g_object_new (E_TYPE_MENU_BAR, NULL);
+       E_MENU_BAR (menu_bar)->priv->inner_menu_bar = GTK_WIDGET (inner_menu_bar);
+
+       settings = e_util_ref_settings ("org.gnome.evolution.shell");
+       g_signal_connect (
+               settings, "changed::menubar-visible",
+               G_CALLBACK (menu_bar_visible_settings_changed_cb),
+               menu_bar);
+       e_menu_bar_set_visible (
+               E_MENU_BAR (menu_bar),
+               g_settings_get_boolean (settings, "menubar-visible"));
+       g_object_unref (settings);
+
+       g_signal_connect_object (window, "event-after",
+               G_CALLBACK (e_menu_bar_window_event_after_cb), menu_bar, G_CONNECT_AFTER);
+
+       return menu_bar;
+}
+
+/**
+ * e_menu_bar_get_visible:
+ * @self: a #EMenuBar
+ *
+ * Determines whether the inner menu bar is visible.
+ *
+ * Returns: %TRUE if the inner menu bar is visible
+ *
+ * Since: 3.46
+ **/
+gboolean
+e_menu_bar_get_visible (EMenuBar *self)
+{
+       g_return_val_if_fail (E_IS_MENU_BAR (self), FALSE);
+
+       return self->priv->visible;
+}
+
+/**
+ * e_menu_bar_set_visible:
+ * @self: a #EMenuBar
+ * @visible: whether the inner menu bar should be shown or not
+ *
+ * Sets the visibility state of the inner menu bar.
+ *
+ * Since: 3.46
+ **/
+void
+e_menu_bar_set_visible (EMenuBar *menu_bar,
+                       gboolean visible)
+{
+       g_return_if_fail (E_IS_MENU_BAR (menu_bar));
+
+       menu_bar->priv->visible = visible;
+       gtk_widget_set_visible (GTK_WIDGET (menu_bar->priv->inner_menu_bar), visible);
+}
diff --git a/src/e-util/e-menu-bar.h b/src/e-util/e-menu-bar.h
new file mode 100644
index 0000000000..c293f876f5
--- /dev/null
+++ b/src/e-util/e-menu-bar.h
@@ -0,0 +1,60 @@
+/* -*- 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_MENUBAR_H
+#define E_MENUBAR_H
+
+#include <gtk/gtk.h>
+#include <e-util/e-util.h>
+
+#define E_TYPE_MENU_BAR \
+       (e_menu_bar_get_type ())
+#define E_MENU_BAR(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_MENU_BAR, EMenuBar))
+#define E_MENU_BAR_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_MENU_BAR, EMenuBarClass))
+#define E_IS_MENU_BAR(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_MENU_BAR))
+#define E_IS_MENU_BAR_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_MENU_BAR))
+#define E_MENU_BAR_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_MENU_BAR, EMenuBarClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMenuBar EMenuBar;
+typedef struct _EMenuBarClass EMenuBarClass;
+typedef struct _EMenuBarPrivate EMenuBarPrivate;
+
+struct _EMenuBar {
+       GObject parent;
+       EMenuBarPrivate *priv;
+};
+
+struct _EMenuBarClass {
+       GObjectClass parent_class;
+};
+
+GType          e_menu_bar_get_type     (void);
+GtkWidget *    e_menu_bar_new          (GtkMenuBar *widget,
+                                        GtkWindow *window);
+gboolean       e_menu_bar_get_visible  (EMenuBar *menu_bar);
+void           e_menu_bar_set_visible  (EMenuBar *menu_bar,
+                                        gboolean visible);
+
+G_END_DECLS
+
+#endif /* E_MENUBAR_H */
diff --git a/src/e-util/e-util.h b/src/e-util/e-util.h
index 4ba1469e37..673293d9c3 100644
--- a/src/e-util/e-util.h
+++ b/src/e-util/e-util.h
@@ -156,6 +156,7 @@
 #include <e-util/e-markdown-editor.h>
 #include <e-util/e-markdown-utils.h>
 #include <e-util/e-headerbar-button.h>
+#include <e-util/e-menu-bar.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/shell/e-shell-window-private.c b/src/shell/e-shell-window-private.c
index 2545814b0b..7dce9252e6 100644
--- a/src/shell/e-shell-window-private.c
+++ b/src/shell/e-shell-window-private.c
@@ -269,107 +269,6 @@ e_shell_window_private_init (EShellWindow *shell_window)
                G_CALLBACK (shell_window_connect_proxy_cb), shell_window);
 }
 
-static gboolean
-delayed_menubar_show_cb (gpointer user_data)
-{
-       EShellWindow *shell_window = user_data;
-
-       g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE);
-
-       shell_window->priv->delayed_menubar_show_id = 0;
-
-       if (!e_shell_window_get_menubar_visible (shell_window)) {
-               GtkWidget *main_menu;
-
-               main_menu = e_shell_window_get_managed_widget (shell_window, "/main-menu");
-
-               gtk_widget_show (main_menu);
-       }
-
-       return FALSE;
-}
-
-static gboolean
-delayed_menubar_hide_cb (gpointer user_data)
-{
-       EShellWindow *shell_window = user_data;
-
-       g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE);
-
-       shell_window->priv->delayed_menubar_hide_id = 0;
-
-       if (!e_shell_window_get_menubar_visible (shell_window) &&
-           !shell_window->priv->delayed_menubar_show_id) {
-               GtkWidget *main_menu;
-
-               main_menu = e_shell_window_get_managed_widget (shell_window, "/main-menu");
-
-               if (gtk_widget_get_visible (main_menu) &&
-                   !gtk_menu_shell_get_selected_item (GTK_MENU_SHELL (main_menu)))
-                       gtk_widget_hide (main_menu);
-       }
-
-       return FALSE;
-}
-
-static void
-e_shell_window_event_after_cb (EShellWindow *shell_window,
-                              GdkEvent *event)
-{
-       GtkWidget *main_menu;
-
-       g_return_if_fail (event != NULL);
-
-       if (event->type != GDK_KEY_PRESS &&
-           event->type != GDK_KEY_RELEASE &&
-           event->type != GDK_BUTTON_RELEASE &&
-           event->type != GDK_FOCUS_CHANGE)
-               return;
-
-       g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
-
-       if (e_shell_window_get_menubar_visible (shell_window))
-               return;
-
-       main_menu = e_shell_window_get_managed_widget (shell_window, "/main-menu");
-
-       if (event->type == GDK_KEY_PRESS) {
-               GdkEventKey *key_event;
-
-               key_event = (GdkEventKey *) event;
-
-               if ((key_event->keyval == GDK_KEY_Alt_L || key_event->keyval == GDK_KEY_Alt_R) &&
-                   !(key_event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK 
| GDK_META_MASK))) {
-                       if (shell_window->priv->delayed_menubar_hide_id) {
-                               g_source_remove (shell_window->priv->delayed_menubar_hide_id);
-                               shell_window->priv->delayed_menubar_hide_id = 0;
-                       }
-
-                       if (shell_window->priv->delayed_menubar_show_id) {
-                               g_source_remove (shell_window->priv->delayed_menubar_show_id);
-                               shell_window->priv->delayed_menubar_show_id = 0;
-
-                               delayed_menubar_show_cb (shell_window);
-                       } else {
-                               /* To not flash when using Alt+Tab or similar system-wide shortcuts */
-                               shell_window->priv->delayed_menubar_show_id =
-                                       e_named_timeout_add (250, delayed_menubar_show_cb, shell_window);
-                       }
-               }
-       } else if (event->type != GDK_BUTTON_RELEASE || !(event->button.state & GDK_MOD1_MASK)) {
-               if (shell_window->priv->delayed_menubar_show_id) {
-                       g_source_remove (shell_window->priv->delayed_menubar_show_id);
-                       shell_window->priv->delayed_menubar_show_id = 0;
-               }
-
-               if (gtk_widget_get_visible (main_menu) &&
-                   !shell_window->priv->delayed_menubar_hide_id) {
-                       shell_window->priv->delayed_menubar_hide_id =
-                               e_named_timeout_add (500, delayed_menubar_hide_cb, shell_window);
-               }
-       }
-}
-
 static gboolean
 e_shell_window_key_press_event_cb (GtkWidget *widget,
                                   GdkEventKey *event)
@@ -470,8 +369,10 @@ e_shell_window_private_constructed (EShellWindow *shell_window)
        box = GTK_BOX (widget);
 
        widget = shell_window_construct_menubar (shell_window);
-       if (widget != NULL)
+       if (widget != NULL) {
+               shell_window->priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), window);
                gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
+       }
 
        widget = shell_window_construct_toolbar (shell_window);
        if (widget != NULL)
@@ -684,9 +585,6 @@ e_shell_window_private_constructed (EShellWindow *shell_window)
 
        g_object_unref (settings);
 
-       g_signal_connect (shell_window, "event-after",
-               G_CALLBACK (e_shell_window_event_after_cb), NULL);
-
        g_signal_connect (shell_window, "key-press-event",
                G_CALLBACK (e_shell_window_key_press_event_cb), NULL);
 
@@ -716,16 +614,6 @@ e_shell_window_private_dispose (EShellWindow *shell_window)
 {
        EShellWindowPrivate *priv = shell_window->priv;
 
-       if (priv->delayed_menubar_show_id) {
-               g_source_remove (priv->delayed_menubar_show_id);
-               priv->delayed_menubar_show_id = 0;
-       }
-
-       if (priv->delayed_menubar_hide_id) {
-               g_source_remove (priv->delayed_menubar_hide_id);
-               priv->delayed_menubar_hide_id = 0;
-       }
-
        /* Need to disconnect handlers before we unref the shell. */
        if (priv->signal_handler_ids != NULL) {
                GArray *array = priv->signal_handler_ids;
@@ -759,6 +647,7 @@ e_shell_window_private_dispose (EShellWindow *shell_window)
        g_clear_object (&priv->switcher);
        g_clear_object (&priv->tooltip_label);
        g_clear_object (&priv->status_notebook);
+       g_clear_object (&priv->menu_bar);
 
        priv->destroyed = TRUE;
 }
diff --git a/src/shell/e-shell-window-private.h b/src/shell/e-shell-window-private.h
index de80f8e767..6fecfef838 100644
--- a/src/shell/e-shell-window-private.h
+++ b/src/shell/e-shell-window-private.h
@@ -82,6 +82,7 @@ struct _EShellWindowPrivate {
        GtkWidget *tooltip_label;
        GtkWidget *status_notebook;
        GtkWidget *headerbar;
+       GtkWidget *menu_bar;
 
        /* Shell signal handlers. */
        GArray *signal_handler_ids;
@@ -90,16 +91,12 @@ struct _EShellWindowPrivate {
 
        guint destroyed        : 1;  /* XXX Do we still need this? */
        guint safe_mode : 1;
-       guint menubar_visible : 1;
        guint sidebar_visible : 1;
        guint switcher_visible : 1;
        guint taskbar_visible : 1;
        guint toolbar_visible : 1;
        guint is_main_instance : 1;
 
-       gulong delayed_menubar_show_id;
-       gulong delayed_menubar_hide_id;
-
        GSList *postponed_alerts; /* EAlert * */
 };
 
diff --git a/src/shell/e-shell-window.c b/src/shell/e-shell-window.c
index 6fe7672ad0..a7b302a081 100644
--- a/src/shell/e-shell-window.c
+++ b/src/shell/e-shell-window.c
@@ -1564,7 +1564,8 @@ e_shell_window_get_menubar_visible (EShellWindow *shell_window)
 {
        g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE);
 
-       return shell_window->priv->menubar_visible;
+       return shell_window->priv->menu_bar &&
+               e_menu_bar_get_visible (E_MENU_BAR (shell_window->priv->menu_bar));
 }
 
 /**
@@ -1584,10 +1585,10 @@ e_shell_window_set_menubar_visible (EShellWindow *shell_window,
 
        g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
 
-       if (shell_window->priv->menubar_visible == menubar_visible)
+       if (e_menu_bar_get_visible (E_MENU_BAR (shell_window->priv->menu_bar)) == menubar_visible)
                return;
 
-       shell_window->priv->menubar_visible = menubar_visible;
+       e_menu_bar_set_visible (E_MENU_BAR (shell_window->priv->menu_bar), menubar_visible);
 
        settings = e_util_ref_settings ("org.gnome.evolution.shell");
        if (!menubar_visible &&


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