[libdazzle] shorcuts: add DzlShortcutTooltip



commit 4f6d63b41890ae6cf6fb321cf8b43dc7022e6365
Author: Christian Hergert <chergert redhat com>
Date:   Tue Oct 2 17:32:03 2018 -0700

    shorcuts: add DzlShortcutTooltip
    
    This is a helper to show tooltips that include shortcuts that are defined
    in the keytheme (and therefore may change during application use).

 src/dazzle.h                         |   1 +
 src/shortcuts/dzl-shortcut-manager.c |  59 +++++
 src/shortcuts/dzl-shortcut-private.h |   4 +
 src/shortcuts/dzl-shortcut-tooltip.c | 419 +++++++++++++++++++++++++++++++++++
 src/shortcuts/dzl-shortcut-tooltip.h |  53 +++++
 src/shortcuts/meson.build            |   2 +
 tests/meson.build                    |   8 +-
 tests/test-shortcut-tooltip.c        |  88 ++++++++
 8 files changed, 633 insertions(+), 1 deletion(-)
---
diff --git a/src/dazzle.h b/src/dazzle.h
index c4cf7a6..a076507 100644
--- a/src/dazzle.h
+++ b/src/dazzle.h
@@ -110,6 +110,7 @@ G_BEGIN_DECLS
 #include "shortcuts/dzl-shortcut-simple-label.h"
 #include "shortcuts/dzl-shortcut-theme-editor.h"
 #include "shortcuts/dzl-shortcut-theme.h"
+#include "shortcuts/dzl-shortcut-tooltip.h"
 #include "shortcuts/dzl-shortcuts-group.h"
 #include "shortcuts/dzl-shortcuts-section.h"
 #include "shortcuts/dzl-shortcuts-shortcut.h"
diff --git a/src/shortcuts/dzl-shortcut-manager.c b/src/shortcuts/dzl-shortcut-manager.c
index 797af46..94815ea 100644
--- a/src/shortcuts/dzl-shortcut-manager.c
+++ b/src/shortcuts/dzl-shortcut-manager.c
@@ -82,6 +82,12 @@ typedef struct
    */
   GNode *root;
 
+  /*
+   * GHashTable to match command/action to a nodedata, useful to generate
+   * a tooltip-text string for a given widget.
+   */
+  GHashTable *command_id_to_node_data;
+
   /*
    * We keep track of the search paths for loading themes here. Each element is
    * a string containing the path to the file-system resource. If the path
@@ -302,6 +308,8 @@ dzl_shortcut_manager_finalize (GObject *object)
   DzlShortcutManager *self = (DzlShortcutManager *)object;
   DzlShortcutManagerPrivate *priv = dzl_shortcut_manager_get_instance_private (self);
 
+  g_clear_pointer (&priv->command_id_to_node_data, g_hash_table_unref);
+
   if (priv->root != NULL)
     {
       g_node_traverse (priv->root, G_IN_ORDER, G_TRAVERSE_ALL, -1, free_node_data, NULL);
@@ -449,6 +457,7 @@ dzl_shortcut_manager_init (DzlShortcutManager *self)
 {
   DzlShortcutManagerPrivate *priv = dzl_shortcut_manager_get_instance_private (self);
 
+  priv->command_id_to_node_data = g_hash_table_new (g_str_hash, g_str_equal);
   priv->seen_entries = g_hash_table_new (shortcut_entry_hash, NULL);
   priv->themes = g_ptr_array_new_with_free_func (destroy_theme);
   priv->root = g_node_new (NULL);
@@ -1331,6 +1340,7 @@ dzl_shortcut_manager_add_command (DzlShortcutManager *self,
                                   const gchar        *title,
                                   const gchar        *subtitle)
 {
+  DzlShortcutManagerPrivate *priv;
   DzlShortcutNodeData *data;
   GNode *parent;
 
@@ -1341,6 +1351,8 @@ dzl_shortcut_manager_add_command (DzlShortcutManager *self,
   if (self == NULL)
     self = dzl_shortcut_manager_get_default ();
 
+  priv = dzl_shortcut_manager_get_instance_private (self);
+
   section = g_intern_string (section);
   group = g_intern_string (group);
   title = g_intern_string (title);
@@ -1359,6 +1371,10 @@ dzl_shortcut_manager_add_command (DzlShortcutManager *self,
 
   g_node_append_data (parent, data);
 
+  g_print ("Inserting %s %p\n", data->name, data);
+
+  g_hash_table_insert (priv->command_id_to_node_data, (gpointer)data->name, data);
+
   g_signal_emit (self, signals [CHANGED], 0);
 }
 
@@ -1649,3 +1665,46 @@ dzl_shortcut_manager_merge (DzlShortcutManager *self,
 
   DZL_EXIT;
 }
+
+/**
+ * _dzl_shortcut_manager_get_command_info:
+ * @self: a #DzlShortcutManager
+ * @command_id: the command-id
+ * @title: (out) (optional): a location for the title
+ * @subtitle: (out) (optional): a location for the subtitle
+ *
+ * Gets command information about command-id
+ *
+ * Returns: %TRUE if the command-id was found and out parameters were set.
+ *
+ * Since: 3.32
+ */
+gboolean
+_dzl_shortcut_manager_get_command_info (DzlShortcutManager  *self,
+                                        const gchar         *command_id,
+                                        const gchar        **title,
+                                        const gchar        **subtitle)
+{
+  DzlShortcutManagerPrivate *priv;
+  DzlShortcutNodeData *node;
+
+  if (self == NULL)
+    self = dzl_shortcut_manager_get_default ();
+
+  g_return_val_if_fail (DZL_IS_SHORTCUT_MANAGER (self), FALSE);
+
+  priv = dzl_shortcut_manager_get_instance_private (self);
+
+  if ((node = g_hash_table_lookup (priv->command_id_to_node_data, command_id)))
+    {
+      if (title != NULL)
+        *title = node->title;
+
+      if (subtitle != NULL)
+        *subtitle = node->subtitle;
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
diff --git a/src/shortcuts/dzl-shortcut-private.h b/src/shortcuts/dzl-shortcut-private.h
index e4a8895..63a3453 100644
--- a/src/shortcuts/dzl-shortcut-private.h
+++ b/src/shortcuts/dzl-shortcut-private.h
@@ -150,6 +150,10 @@ gboolean               _dzl_shortcut_chord_table_iter_next          (DzlShortcut
                                                                      const DzlShortcutChord    **chord,
                                                                      gpointer                   *value);
 void                   _dzl_shortcut_chord_table_iter_steal         (DzlShortcutChordTableIter  *iter);
+gboolean               _dzl_shortcut_manager_get_command_info       (DzlShortcutManager         *self,
+                                                                     const gchar                *command_id,
+                                                                     const gchar               **title,
+                                                                     const gchar               **subtitle);
 
 static inline gboolean
 DZL_IS_SHORTCUT_CLOSURE_CHAIN (DzlShortcutClosureChain *self)
diff --git a/src/shortcuts/dzl-shortcut-tooltip.c b/src/shortcuts/dzl-shortcut-tooltip.c
new file mode 100644
index 0000000..96df3d4
--- /dev/null
+++ b/src/shortcuts/dzl-shortcut-tooltip.c
@@ -0,0 +1,419 @@
+/* dzl-shortcut-tooltip.c
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "dzl-shortcut-tooltip"
+
+#include "shortcuts/dzl-shortcut-controller.h"
+#include "shortcuts/dzl-shortcut-private.h"
+#include "shortcuts/dzl-shortcut-simple-label.h"
+#include "shortcuts/dzl-shortcut-theme.h"
+#include "shortcuts/dzl-shortcut-tooltip.h"
+#include "util/dzl-macros.h"
+
+/**
+ * SECTION:dzl-shortcut-tooltip
+ * @title: DzlShortcutTooltip
+ * @short_description: display fancy tooltips containing shortcuts
+ *
+ * This class is used to display a fancy shortcut on a tooltip along with
+ * information about the shortcut.
+ *
+ * The shortcut must be registered with Dazzle using the DzlShortcutManager
+ * and have a registered command-id.
+ *
+ * The display text for the shortcut will match that shown in the shortcuts
+ * window help.
+ *
+ * Since: 3.32
+ */
+
+struct _DzlShortcutTooltip
+{
+  GObject parent_instance;
+
+  /* Interned string with the command-id to update the shortcut
+   * based on the current key-theme.
+   */
+  const gchar *command_id;
+
+  /* If the title is set manually, we do not need to discover it
+   * from the registered shortcuts.
+   */
+  gchar *title;
+
+  /* The widget that we are watching the ::query-tooltip for. */
+  GtkWidget *widget;
+
+  /* The signal connection id for ::query() on @widget */
+  gulong query_handler;
+
+  /* Our signal connection id for ::destroy() on @widget */
+  gulong destroy_handler;
+};
+
+G_DEFINE_TYPE (DzlShortcutTooltip, dzl_shortcut_tooltip, G_TYPE_OBJECT)
+
+enum {
+  PROP_0,
+  PROP_COMMAND_ID,
+  PROP_TITLE,
+  PROP_WIDGET,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static gboolean
+dzl_shortcut_tooltip_query_cb (DzlShortcutTooltip *self,
+                               gint                x,
+                               gint                y,
+                               gboolean            keyboard_mode,
+                               GtkTooltip         *tooltip,
+                               GtkWidget          *widget)
+{
+  DzlShortcutController *controller;
+  const DzlShortcutChord *chord;
+  DzlShortcutManager *manager;
+  DzlShortcutTheme *theme;
+  const gchar *title = NULL;
+  const gchar *subtitle = NULL;
+
+  g_assert (DZL_IS_SHORTCUT_TOOLTIP (self));
+  g_assert (GTK_IS_TOOLTIP (tooltip));
+  g_assert (GTK_IS_WIDGET (widget));
+  g_assert (widget == self->widget);
+
+  if (self->command_id == NULL ||
+      !(controller = dzl_shortcut_controller_try_find (widget)) ||
+      !(manager = dzl_shortcut_controller_get_manager (controller)) ||
+      !(theme = dzl_shortcut_manager_get_theme (manager)))
+    return FALSE;
+
+  /* If we find a matching chord for the command-id, display it to the user */
+  if ((chord = dzl_shortcut_theme_get_chord_for_command (theme, self->command_id)) &&
+      (self->title != NULL ||
+       _dzl_shortcut_manager_get_command_info (manager, self->command_id, &title, &subtitle)))
+    {
+      g_autofree gchar *accel = dzl_shortcut_chord_to_string (chord);
+      DzlShortcutSimpleLabel *label;
+
+      label = DZL_SHORTCUT_SIMPLE_LABEL (dzl_shortcut_simple_label_new ());
+      dzl_shortcut_simple_label_set_command (label, self->command_id);
+      dzl_shortcut_simple_label_set_accel (label, accel);
+
+      if (self->title != NULL)
+        dzl_shortcut_simple_label_set_title (label, self->title);
+      else
+        dzl_shortcut_simple_label_set_title (label, title);
+
+      gtk_widget_show (GTK_WIDGET (label));
+
+      gtk_tooltip_set_custom (tooltip, GTK_WIDGET (label));
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/**
+ * dzl_shortcut_tooltip_new:
+ *
+ * Create a new #DzlShortcutTooltip.
+ *
+ * Returns: (transfer full): a newly created #DzlShortcutTooltip
+ *
+ * Since: 3.32
+ */
+DzlShortcutTooltip *
+dzl_shortcut_tooltip_new (void)
+{
+  return g_object_new (DZL_TYPE_SHORTCUT_TOOLTIP, NULL);
+}
+
+static void
+dzl_shortcut_tooltip_finalize (GObject *object)
+{
+  DzlShortcutTooltip *self = (DzlShortcutTooltip *)object;
+
+  if (self->widget != NULL && self->query_handler != 0)
+    {
+      dzl_clear_signal_handler (self->widget, &self->query_handler);
+      dzl_clear_signal_handler (self->widget, &self->destroy_handler);
+    }
+
+  self->widget = NULL;
+
+  G_OBJECT_CLASS (dzl_shortcut_tooltip_parent_class)->finalize (object);
+}
+
+static void
+dzl_shortcut_tooltip_get_property (GObject    *object,
+                                   guint       prop_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  DzlShortcutTooltip *self = DZL_SHORTCUT_TOOLTIP (object);
+
+  switch (prop_id)
+    {
+    case PROP_WIDGET:
+      g_value_set_object (value, dzl_shortcut_tooltip_get_widget (self));
+      break;
+
+    case PROP_COMMAND_ID:
+      g_value_set_static_string (value, self->command_id);
+      break;
+
+    case PROP_TITLE:
+      g_value_set_string (value, dzl_shortcut_tooltip_get_title (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+dzl_shortcut_tooltip_set_property (GObject      *object,
+                                   guint         prop_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  DzlShortcutTooltip *self = DZL_SHORTCUT_TOOLTIP (object);
+
+  switch (prop_id)
+    {
+    case PROP_WIDGET:
+      dzl_shortcut_tooltip_set_widget (self, g_value_get_object (value));
+      break;
+
+    case PROP_COMMAND_ID:
+      dzl_shortcut_tooltip_set_command_id (self, g_value_get_string (value));
+      break;
+
+    case PROP_TITLE:
+      dzl_shortcut_tooltip_set_title (self, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+dzl_shortcut_tooltip_class_init (DzlShortcutTooltipClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = dzl_shortcut_tooltip_finalize;
+  object_class->get_property = dzl_shortcut_tooltip_get_property;
+  object_class->set_property = dzl_shortcut_tooltip_set_property;
+
+  properties [PROP_COMMAND_ID] =
+    g_param_spec_string ("command-id",
+                         "Command Id",
+                         "The shortcut command-id to track for shortcut changes",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * DzlShortcutTooltip:title:
+   *
+   * The "title" property contains an alternate title for the tooltip
+   * instead of discovering the title from the shortcut manager.
+   *
+   * Since: 3.32
+   */
+  properties [PROP_TITLE] =
+    g_param_spec_string ("title",
+                         "title",
+                         "Title for the tooltip",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_WIDGET] =
+    g_param_spec_object ("widget",
+                         "Widget",
+                         "The widget to monitor for query-tooltip",
+                         GTK_TYPE_WIDGET,
+                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+dzl_shortcut_tooltip_init (DzlShortcutTooltip *self)
+{
+}
+
+/**
+ * dzl_shortcut_tooltip_get_title:
+ *
+ * Gets the #DzlShortcutTooltip:title property, if set.
+ *
+ * Returns: (nullable): a string containing the title, or %NULL
+ *
+ * Since: 3.32
+ */
+const gchar *
+dzl_shortcut_tooltip_get_title (DzlShortcutTooltip *self)
+{
+  g_return_val_if_fail (DZL_IS_SHORTCUT_TOOLTIP (self), NULL);
+
+  return self->title;
+}
+
+/**
+ * dzl_shortcut_tooltip_set_title:
+ * @self: a #DzlShortcutTooltip
+ * @title: (nullable): a title for the tooltip, or %NULL
+ *
+ * Sets the #DzlShortcutTooltip:title property, which can be used to
+ * override the default title for the tooltip as discovered from the
+ * shortcut manager.
+ *
+ * Since: 3.32
+ */
+void
+dzl_shortcut_tooltip_set_title (DzlShortcutTooltip *self,
+                                const gchar        *title)
+{
+  g_return_if_fail (DZL_IS_SHORTCUT_TOOLTIP (self));
+
+  if (!dzl_str_equal0 (title, self->title))
+    {
+      g_free (self->title);
+      self->title = g_strdup (title);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
+    }
+}
+
+/**
+ * dzl_shortcut_tooltip_get_command_id:
+ * @self: a #DzlShortcutTooltip
+ *
+ * Gets the #DzlShortcutTooltip:command-id property.
+ *
+ * Returns: (nullable): a string containing the command id
+ *
+ * Since: 3.32
+ */
+const gchar *
+dzl_shortcut_tooltip_get_command_id (DzlShortcutTooltip *self)
+{
+  g_return_val_if_fail (DZL_IS_SHORTCUT_TOOLTIP (self), NULL);
+
+  return self->command_id;
+}
+
+/**
+ * dzl_shortcut_tooltip_set_command_id:
+ * @self: a #DzlShortcutTooltip
+ * @command_id: the command-id of the shortcut registered
+ *
+ * This sets the #DzlShortcutTooltip:command-id property which denotes which
+ * shortcut registered with libdazzle to display when a tooltip request is
+ * received.
+ *
+ * Since: 3.32
+ */
+void
+dzl_shortcut_tooltip_set_command_id (DzlShortcutTooltip *self,
+                                     const gchar        *command_id)
+{
+  g_return_if_fail (DZL_IS_SHORTCUT_TOOLTIP (self));
+
+  command_id = g_intern_string (command_id);
+
+  if (command_id != self->command_id)
+    {
+      self->command_id = command_id;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_COMMAND_ID]);
+    }
+}
+
+/**
+ * dzl_shortcut_tooltip_get_widget:
+ *
+ * Gets the #GtkWidget that the shortcut-tooltip is wrapping.
+ *
+ * Returns: (nullable) (transfer none): a #GtkWidget or %NULL if unset
+ *
+ * Since: 3.32
+ */
+GtkWidget *
+dzl_shortcut_tooltip_get_widget (DzlShortcutTooltip *self)
+{
+  g_return_val_if_fail (DZL_IS_SHORTCUT_TOOLTIP (self), NULL);
+
+  return self->widget;
+}
+
+/**
+ * dzl_shortcut_tooltip_set_widget:
+ * @self: a #DzlShortcutTooltip
+ * @widget: (nullable): a #GtkWidget or %NULL
+ *
+ * Sets the widget to connect to the #GtkWidget::query-tooltip signal.
+ *
+ * If configured, the widget will be displayed with an appropriate tooltip
+ * message matching the shortcut from #DzlShortcutTooltip:command-id.
+ *
+ * Since: 3.32
+ */
+void
+dzl_shortcut_tooltip_set_widget (DzlShortcutTooltip *self,
+                                 GtkWidget          *widget)
+{
+  g_return_if_fail (DZL_IS_SHORTCUT_TOOLTIP (self));
+
+  if (widget != self->widget)
+    {
+      if (self->widget != NULL)
+        {
+          gtk_widget_set_has_tooltip (self->widget, FALSE);
+          dzl_clear_signal_handler (self->widget, &self->query_handler);
+          dzl_clear_signal_handler (self->widget, &self->destroy_handler);
+          self->widget = NULL;
+        }
+
+      if (widget != NULL)
+        {
+          self->widget = widget;
+          gtk_widget_set_has_tooltip (self->widget, TRUE);
+          self->query_handler =
+            g_signal_connect_object (self->widget,
+                                     "query-tooltip",
+                                     G_CALLBACK (dzl_shortcut_tooltip_query_cb),
+                                     self,
+                                     G_CONNECT_SWAPPED);
+          self->destroy_handler =
+            g_signal_connect (self->widget,
+                              "destroy",
+                              G_CALLBACK (gtk_widget_destroyed),
+                              &self->widget);
+        }
+
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_WIDGET]);
+    }
+}
diff --git a/src/shortcuts/dzl-shortcut-tooltip.h b/src/shortcuts/dzl-shortcut-tooltip.h
new file mode 100644
index 0000000..0ca5e2c
--- /dev/null
+++ b/src/shortcuts/dzl-shortcut-tooltip.h
@@ -0,0 +1,53 @@
+/* dzl-shortcut-tooltip.h
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "dzl-version-macros.h"
+
+G_BEGIN_DECLS
+
+#define DZL_TYPE_SHORTCUT_TOOLTIP (dzl_shortcut_tooltip_get_type())
+
+DZL_AVAILABLE_IN_3_32
+G_DECLARE_FINAL_TYPE (DzlShortcutTooltip, dzl_shortcut_tooltip, DZL, SHORTCUT_TOOLTIP, GObject)
+
+DZL_AVAILABLE_IN_3_32
+DzlShortcutTooltip *dzl_shortcut_tooltip_new            (void);
+DZL_AVAILABLE_IN_3_32
+GtkWidget          *dzl_shortcut_tooltip_get_widget     (DzlShortcutTooltip *self);
+DZL_AVAILABLE_IN_3_32
+void                dzl_shortcut_tooltip_set_widget     (DzlShortcutTooltip *self,
+                                                         GtkWidget          *widget);
+DZL_AVAILABLE_IN_3_32
+const gchar        *dzl_shortcut_tooltip_get_command_id (DzlShortcutTooltip *self);
+DZL_AVAILABLE_IN_3_32
+void                dzl_shortcut_tooltip_set_command_id (DzlShortcutTooltip *self,
+                                                         const gchar        *command_id);
+DZL_AVAILABLE_IN_3_32
+const gchar        *dzl_shortcut_tooltip_get_title      (DzlShortcutTooltip *self);
+DZL_AVAILABLE_IN_3_32
+void                dzl_shortcut_tooltip_set_title      (DzlShortcutTooltip *self,
+                                                         const gchar        *title);
+
+
+G_END_DECLS
diff --git a/src/shortcuts/meson.build b/src/shortcuts/meson.build
index 0df7fbb..888d892 100644
--- a/src/shortcuts/meson.build
+++ b/src/shortcuts/meson.build
@@ -10,6 +10,7 @@ shortcuts_headers = [
   'dzl-shortcut-simple-label.h',
   'dzl-shortcut-theme-editor.h',
   'dzl-shortcut-theme.h',
+  'dzl-shortcut-tooltip.h',
   'dzl-shortcuts-group.h',
   'dzl-shortcuts-section.h',
   'dzl-shortcuts-shortcut.h',
@@ -30,6 +31,7 @@ shortcuts_sources = [
   'dzl-shortcut-theme-load.c',
   'dzl-shortcut-theme-save.c',
   'dzl-shortcut-theme.c',
+  'dzl-shortcut-tooltip.c',
   'dzl-shortcuts-group.c',
   'dzl-shortcuts-section.c',
   'dzl-shortcuts-shortcut.c',
diff --git a/tests/meson.build b/tests/meson.build
index 7bdab0a..35d509f 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -391,4 +391,10 @@ test_model_filter = executable('test-model-filter', 'test-model-filter.c',
 )
 test('test-model-filter', test_model_filter, env: test_env)
 
-endif
+test_shortcut_tooltip = executable('test-shortcut-tooltip', 'test-shortcut-tooltip.c',
+        c_args: test_cflags,
+     link_args: test_link_args,
+  dependencies: libdazzle_deps + [libdazzle_dep],
+)
+
+endif
\ No newline at end of file
diff --git a/tests/test-shortcut-tooltip.c b/tests/test-shortcut-tooltip.c
new file mode 100644
index 0000000..c507123
--- /dev/null
+++ b/tests/test-shortcut-tooltip.c
@@ -0,0 +1,88 @@
+/* test-shortcut-tooltip.c
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <dazzle.h>
+
+static const DzlShortcutEntry entries[] = {
+  {
+    "org.gnome.dazzle.test.fullscreen",
+    DZL_SHORTCUT_PHASE_CAPTURE,
+    "F11",
+    "Window",
+    "Management",
+    "Fullscreen window",
+    NULL
+  }
+};
+
+static void
+button_clicked_cb (GtkButton          *button,
+                   DzlShortcutTooltip *tooltip)
+{
+  static guint count;
+
+  count++;
+
+  dzl_shortcut_tooltip_set_title (tooltip, count % 2 ? "Unfullscreen window" : "Fullscreen window");
+}
+
+gint
+main (gint argc,
+      gchar *argv[])
+{
+  GtkWindow *window;
+  GtkWidget *button;
+  g_autoptr(DzlShortcutTooltip) tooltip = NULL;
+  DzlShortcutController *controller;
+
+  gtk_init (&argc, &argv);
+
+  dzl_shortcut_manager_add_shortcut_entries (NULL, entries, G_N_ELEMENTS (entries), NULL);
+
+  window = g_object_new (GTK_TYPE_WINDOW,
+                         "title", "Shorcut tooltip test",
+                         NULL);
+  button = g_object_new (GTK_TYPE_BUTTON,
+                         "visible", TRUE,
+                         "label", "Test Button",
+                         NULL);
+  controller = dzl_shortcut_controller_find (button);
+  dzl_shortcut_controller_add_command_action (controller,
+                                              "org.gnome.dazzle.test.fullscreen",
+                                              "F11",
+                                              DZL_SHORTCUT_PHASE_CAPTURE,
+                                              "win.fullscren");
+
+  gtk_container_add (GTK_CONTAINER (window), button);
+
+  tooltip = dzl_shortcut_tooltip_new ();
+
+  dzl_shortcut_tooltip_set_widget (tooltip, button);
+  dzl_shortcut_tooltip_set_command_id (tooltip, "org.gnome.dazzle.test.fullscreen");
+
+  g_signal_connect (button, "clicked", G_CALLBACK (button_clicked_cb), tooltip);
+
+  g_signal_connect (window, "delete-event", gtk_main_quit, NULL);
+  gtk_window_present (GTK_WINDOW (window));
+
+  gtk_main ();
+
+  return 0;
+}


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