[gtk/widget-class-actions: 1/6] Allow registering actions per-class



commit 425dd943b25e3e89682a9f6e48633f11f8f825bd
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jun 14 12:12:10 2019 +0000

    Allow registering actions per-class
    
    Add a facility to register and install actions.
    To register them, call gtk_widget_class_install_action
    in class_init. To install them, call
    gtk_widget_add_class_actions in init. This adds
    one or more action groups to the widgets action
    muxer. There's also some convenience api to
    notify about action state changes.

 docs/reference/gtk/gtk4-sections.txt |  19 ++-
 gtk/gtkwidget.c                      | 224 ++++++++++++++++++++++++++++
 gtk/gtkwidget.h                      |  79 ++++++++++
 gtk/gtkwidgetactiongroup.c           | 276 +++++++++++++++++++++++++++++++++++
 gtk/gtkwidgetactiongroupprivate.h    |  53 +++++++
 gtk/meson.build                      |   1 +
 6 files changed, 647 insertions(+), 5 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 4d072641da..8d27a99c27 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -4549,11 +4549,6 @@ gtk_widget_get_opacity
 gtk_widget_set_opacity
 gtk_widget_get_overflow
 gtk_widget_set_overflow
-gtk_widget_insert_action_group
-gtk_widget_list_action_prefixes
-gtk_widget_get_action_group
-gtk_widget_activate_action
-gtk_widget_activate_default
 gtk_widget_measure
 gtk_widget_snapshot_child
 gtk_widget_get_next_sibling
@@ -4630,6 +4625,20 @@ gtk_widget_class_set_connect_func
 gtk_widget_observe_children
 gtk_widget_observe_controllers
 
+<SUBSECTION Actions>
+gtk_widget_insert_action_group
+gtk_widget_list_action_prefixes
+gtk_widget_get_action_group
+gtk_widget_activate_action
+gtk_widget_activate_default
+GtkWidgetActionActivate
+GtkWidgetActionQuery
+GtkWidgetActionChange
+gtk_widget_class_install_action
+gtk_widget_add_class_actions
+gtk_widget_notify_class_action_enabled
+gtk_widget_notify_class_action_state
+
 <SUBSECTION Standard>
 GTK_WIDGET
 GTK_IS_WIDGET
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 0bc88b06b2..2dd4ce13ec 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -70,6 +70,7 @@
 #include "gtkversion.h"
 #include "gtkwidgetpaintableprivate.h"
 #include "gtkwidgetpathprivate.h"
+#include "gtkwidgetactiongroupprivate.h"
 #include "gtkwindowgroup.h"
 #include "gtkwindowprivate.h"
 #include "gtknativeprivate.h"
@@ -501,6 +502,7 @@ struct _GtkWidgetClassPrivate
   AtkRole accessible_role;
   const char *css_name;
   GType layout_manager_type;
+  GPtrArray *actions;
 };
 
 enum {
@@ -13479,3 +13481,225 @@ gtk_widget_should_layout (GtkWidget *widget)
   return TRUE;
 }
 
+static gboolean
+default_query (GtkWidget           *widget,
+               const char          *action_name,
+               gboolean            *enabled,
+               const GVariantType **parameter_type,
+               const GVariantType **state_type,
+               GVariant           **state_hint,
+               GVariant           **state)
+{
+  if (enabled)
+    *enabled = TRUE;
+  if (parameter_type)
+    *parameter_type = NULL;
+  if (state_type)
+    *state_type = NULL;
+  if (state_hint)
+    *state_hint = NULL;
+  if (state)
+    *state = NULL;
+  return TRUE;
+}
+
+static void
+default_change (GtkWidget  *widget,
+                const char *action_name,
+                GVariant   *parameter)
+{
+  g_warning ("%sClass action %s has no state", G_OBJECT_TYPE_NAME (widget), action_name);
+}
+
+/**
+ * gtk_widget_class_install_action:
+ * @widget_class: a #GtkWidgetClass
+ * @prefixed_name: a prefixed action name, such as "clipboard.paste"
+ * @activate: callback to use when the action is activated
+ * @query: (allow-none): callback to use when the action properties
+       are queried, or %NULL for always-enabled stateless actions
+ * @change: (allow-none): callback to use when the action state is
+ *     changed, or %NULL for stateless actions
+ *
+ * This should be called at class initialization time to specify
+ * actions to be added for all instances of this class.
+ *
+ * Actions installed in this way can be simple or stateful.
+ * See the #GAction documentation for more information.
+ *
+ * Note that any class that installs actions must call
+ * gtk_widget_add_class_actions() in the widget’s instance initializer.
+ */
+void
+gtk_widget_class_install_action (GtkWidgetClass          *widget_class,
+                                 const char              *prefixed_name,
+                                 GtkWidgetActionActivate  activate,
+                                 GtkWidgetActionQuery     query,
+                                 GtkWidgetActionChange    change)
+{
+  GtkWidgetClassPrivate *priv = widget_class->priv;
+  GtkWidgetAction *action;
+  int i;
+  char *p;
+  char *prefix;
+  char *name;
+
+  g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
+
+  p = strchr (prefixed_name, '.');
+  if (p == 0)
+    {
+      g_warning ("Action name %s does not contain a '.'", prefixed_name);
+      return;
+    }
+  prefix = g_strndup (prefixed_name, p - prefixed_name);
+  name = g_strdup (p + 1);
+
+  if (priv->actions == NULL)
+    priv->actions = g_ptr_array_new ();
+
+  for (i = 0; i < priv->actions->len; i++)
+    {
+      action = g_ptr_array_index (priv->actions, i);
+
+      if (strcmp (action->prefix, prefix) == 0 &&
+          strcmp (action->name, name) == 0)
+        {
+          g_warning ("Duplicate action name %s.%s", prefix, name);
+          g_free (prefix);
+          g_free (name);
+          return;
+        }
+    }
+
+  action = g_new0 (GtkWidgetAction, 1);
+  action->prefix = prefix;
+  action->name = name;
+  action->activate = activate;
+  action->query = query ? query : default_query;
+  action->change = change ? change : default_change;
+
+  GTK_NOTE(ACTIONS,
+           g_message ("%sClass: Adding %s.%s action\n",
+                      g_type_name (G_TYPE_FROM_CLASS (widget_class)),
+                      prefix, name));
+
+  g_ptr_array_add (priv->actions, action);
+}
+
+/**
+ * gtk_widget_add_class_actions:
+ * @widget: a #GtkWidget
+ *
+ * Creates and adds any actions that are associated with the widget's class.
+ *
+ * This function must be called in the instance initializer for any
+ * class which installs actions with gtk_widget_class_install_action()
+ * at class initialization time.
+ */
+void
+gtk_widget_add_class_actions (GtkWidget *widget)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS (widget);
+  GtkWidgetClassPrivate *priv = widget_class->priv;
+  int i;
+  GHashTable *prefixes;
+  GHashTableIter iter;
+  const char *prefix;
+
+  if (priv->actions == NULL)
+    {
+      g_warning ("No class actions registered for %s", G_OBJECT_TYPE_NAME (widget));
+      return;
+    }
+
+  prefixes = g_hash_table_new (g_str_hash, g_str_equal);
+
+  for (i = 0; i < priv->actions->len; i++)
+    {
+      GtkWidgetAction *action = g_ptr_array_index (priv->actions, i);
+      g_hash_table_add (prefixes, action->prefix);
+    }
+
+  g_hash_table_iter_init (&iter, prefixes);
+  while (g_hash_table_iter_next (&iter, (gpointer *)&prefix, NULL))
+    {
+      GActionGroup *group;
+
+      group = gtk_widget_action_group_new (widget, prefix, priv->actions);
+      gtk_widget_insert_action_group (widget, prefix, group);
+      g_object_unref (group);
+    }
+
+  g_hash_table_unref (prefixes);
+}
+
+/**
+ * gtk_widget_notify_class_action_enabled:
+ * @widget: a #GtkWidget
+ * @prefixed_name: a prefixed action name, such as "clipboard.paste"
+ *
+ * Convenience API to notify when an action installed
+ * with gtk_widget_class_install_action() changes its
+ * enabled state. It must be called after the change
+ * has taken place (we expect the @query callback to
+ * already return the new state).
+ *
+ * This function is a more convenient alternative
+ * to calling g_action_group_action_enabled_changed()
+ * directly.
+ */
+void
+gtk_widget_notify_class_action_enabled (GtkWidget  *widget,
+                                        const char *prefixed_name)
+{
+  GtkActionMuxer *muxer;
+  GActionGroup *group;
+  gboolean enabled;
+  const char *name;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  muxer = _gtk_widget_get_action_muxer (widget, FALSE);
+  group = gtk_action_muxer_find (muxer, prefixed_name, &name);
+
+  g_return_if_fail (gtk_widget_action_group_get_widget (GTK_WIDGET_ACTION_GROUP (group)) == widget);
+
+  enabled = g_action_group_get_action_enabled (group, name);
+  g_action_group_action_enabled_changed (group, name, enabled);
+}
+
+/**
+ * gtk_widget_notify_class_action_state:
+ * @widget: a #GtkWidget
+ * @prefixed_name: a prefixed action name, such as "clipboard.paste"
+ *
+ * Convenience API to notify when an action installed
+ * with gtk_widget_class_install_action() changes its
+ * state. It must be called after the change has taken
+ * place (we expect the @query callback to already
+ * return the new state).
+ *
+ * This function is a more convenient alternative
+ * to calling g_action_group_action_state_changed()
+ * directly.
+ */
+void
+gtk_widget_notify_class_action_state (GtkWidget  *widget,
+                                      const char *prefixed_name)
+{
+  GtkActionMuxer *muxer;
+  GActionGroup *group;
+  GVariant *state;
+  const char *name;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  muxer = _gtk_widget_get_action_muxer (widget, FALSE);
+  group = gtk_action_muxer_find (muxer, prefixed_name, &name);
+
+  g_return_if_fail (gtk_widget_action_group_get_widget (GTK_WIDGET_ACTION_GROUP (group)) == widget);
+
+  state = g_action_group_get_action_state (group, name);
+  g_action_group_action_state_changed (group, name, state);
+}
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index bb2766078b..add11a318e 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -1030,6 +1030,85 @@ GDK_AVAILABLE_IN_ALL
 gboolean                gtk_widget_should_layout        (GtkWidget   *widget);
 
 
+/**
+ * GtkWidgetActionActivate:
+ * @widget: the widget to which the action belongs
+ * @action_name: the (unprefixed) action name
+ * @parameter: parameter for activation
+ *
+ * The type of the callback functions used for activating
+ * actions installed with gtk_widget_class_install_action().
+ *
+ * The @parameter must match the @parameter_type of the action.
+ */
+typedef void     (* GtkWidgetActionActivate)   (GtkWidget           *widget,
+                                                const char          *action_name,
+                                                GVariant            *parameter);
+/**
+ * GtkWidgetActionQuery:
+ * @widget: the widget to which the action belongs
+ * @action_name: the (unprefixed) action name
+ * @enabled: (out) (optional): return location for the enabled state
+ * @parameter_type: (out) (optional): return location for the parameter type
+ * @state_type: (out) (optional): return location for the state type
+ * @state_hint: (out) (optional): return location for the state hint
+ * @state: (out) (optional): return location for the state
+ *
+ * The type of the callback functions used to query
+ * the properties of actions installed with gtk_widget_class_install_action().
+ *
+ * See the #GAction documentation for more details about the
+ * meaning of these properties.
+ *
+ * Returns: %TRUE if the action was found
+ */
+typedef gboolean (* GtkWidgetActionQuery)      (GtkWidget           *widget,
+                                                const char          *action_name,
+                                                gboolean            *enabled,
+                                                const GVariantType **parameter_type,
+                                                const GVariantType **state_type,
+                                                GVariant           **state_hint,
+                                                GVariant           **state);
+
+/**
+ * GtkWidgetActionChange:
+ * @widget: the widget to which the action belongs
+ * @action_name: the (unprefixed) action name
+ * @state: the new state
+ *
+ * The type of the callback functions used to change the
+ * state of actions installed with gtk_widget_class_install_action().
+ *
+ * The @state must match the @state_type of the action.
+ *
+ * Note that you can change the enabledness and state
+ * of widget actions by other means, as long as you
+ * emit the required #GActionGroup notification signals,
+ * which can be done with GtkWidget convenience API.
+ * This callback is used when the action state is
+ * changed via the #GActionGroup API.
+ */
+typedef void     (*GtkWidgetActionChange)      (GtkWidget           *widget,
+                                                const char          *action_name,
+                                                GVariant            *state);
+
+GDK_AVAILABLE_IN_ALL
+void                    gtk_widget_class_install_action (GtkWidgetClass            *widget_class,
+                                                         const char                *prefixed_name,
+                                                         GtkWidgetActionActivate    activate,
+                                                         GtkWidgetActionQuery       query,
+                                                         GtkWidgetActionChange      change);
+
+GDK_AVAILABLE_IN_ALL
+void                    gtk_widget_add_class_actions (GtkWidget *widget);
+GDK_AVAILABLE_IN_ALL
+void                    gtk_widget_notify_class_action_enabled (GtkWidget  *widget,
+                                                                const char *prefixed_name);
+GDK_AVAILABLE_IN_ALL
+void                    gtk_widget_notify_class_action_state (GtkWidget  *widget,
+                                                              const char *prefixed_name);
+
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkWidget, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkRequisition, gtk_requisition_free)
 
diff --git a/gtk/gtkwidgetactiongroup.c b/gtk/gtkwidgetactiongroup.c
new file mode 100644
index 0000000000..0273682dbe
--- /dev/null
+++ b/gtk/gtkwidgetactiongroup.c
@@ -0,0 +1,276 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkwidgetactiongroupprivate.h"
+
+
+enum {
+  PROP_WIDGET = 1,
+  PROP_PREFIX,
+  PROP_ACTIONS
+};
+
+struct _GtkWidgetActionGroup {
+  GObject parent;
+
+  GtkWidget *widget;
+  char *prefix;
+
+  GPtrArray *actions;
+};
+
+typedef struct {
+  GObjectClass parent_class;
+} GtkWidgetActionGroupClass;
+
+static void gtk_widget_action_group_iface_init (GActionGroupInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkWidgetActionGroup, gtk_widget_action_group, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, gtk_widget_action_group_iface_init))
+
+static char **
+gtk_widget_action_group_list_actions (GActionGroup *action_group)
+{
+  GtkWidgetActionGroup *group = GTK_WIDGET_ACTION_GROUP (action_group);
+  GPtrArray *actions;
+  int i;
+
+  actions = g_ptr_array_new ();
+ 
+  for (i = 0; i < group->actions->len; i++)
+    {
+      GtkWidgetAction *action = g_ptr_array_index (group->actions, i);
+
+      if (strcmp (group->prefix, action->prefix) == 0)
+        g_ptr_array_add (actions, g_strdup (action->name));
+    }
+
+  g_ptr_array_add (actions, NULL);
+
+  return (char **)g_ptr_array_free (actions, FALSE);
+}
+
+static gboolean
+gtk_widget_action_group_query_action (GActionGroup        *action_group,
+                                      const gchar         *action_name,
+                                      gboolean            *enabled,
+                                      const GVariantType **parameter_type,
+                                      const GVariantType **state_type,
+                                      GVariant           **state_hint,
+                                      GVariant           **state)
+{
+  GtkWidgetActionGroup *group = GTK_WIDGET_ACTION_GROUP (action_group);
+  int i;
+
+  for (i = 0; i < group->actions->len; i++)
+    {
+      GtkWidgetAction *action = g_ptr_array_index (group->actions, i);
+
+      if (strcmp (action->prefix, group->prefix) == 0 &&
+          strcmp (action->name, action_name) == 0)
+        {
+          return action->query (group->widget,
+                                action->name,
+                                enabled,
+                                parameter_type,
+                                state_type,
+                                state_hint,
+                                state);
+        }
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_widget_action_group_change_action_state (GActionGroup *action_group,
+                                             const gchar  *action_name,
+                                             GVariant     *value)
+{
+  GtkWidgetActionGroup *group = GTK_WIDGET_ACTION_GROUP (action_group);
+  int i;
+
+  for (i = 0; i < group->actions->len; i++)
+    {
+      GtkWidgetAction *action = g_ptr_array_index (group->actions, i);
+
+      if (strcmp (action->prefix, group->prefix) == 0 &&
+          strcmp (action->name, action_name) == 0)
+        {
+          if (action->change)
+            action->change (group->widget, action->name, value);
+
+          break;
+        }
+    }
+}
+
+static void
+gtk_widget_action_group_activate_action (GActionGroup *action_group,
+                                         const  char  *action_name,
+                                         GVariant     *parameter)
+{
+  GtkWidgetActionGroup *group = GTK_WIDGET_ACTION_GROUP (action_group);
+  int i;
+
+  for (i = 0; i < group->actions->len; i++)
+    {
+      GtkWidgetAction *action = g_ptr_array_index (group->actions, i);
+
+      if (strcmp (action->prefix, group->prefix) == 0 &&
+          strcmp (action->name, action_name) == 0)
+        {
+          action->activate (group->widget, action->name, parameter);
+          break;
+        }
+    }
+}
+
+static void
+gtk_widget_action_group_iface_init (GActionGroupInterface *iface)
+{
+  iface->list_actions = gtk_widget_action_group_list_actions;
+  iface->query_action = gtk_widget_action_group_query_action;
+  iface->change_action_state = gtk_widget_action_group_change_action_state;
+  iface->activate_action = gtk_widget_action_group_activate_action;
+}
+
+static void
+gtk_widget_action_group_init (GtkWidgetActionGroup *group)
+{
+}
+
+static void
+gtk_widget_action_group_set_property (GObject      *object,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  GtkWidgetActionGroup *group = GTK_WIDGET_ACTION_GROUP (object);
+
+  switch (prop_id)
+    {
+    case PROP_WIDGET:
+      group->widget = g_value_get_object (value);
+      break;
+
+    case PROP_PREFIX:
+      group->prefix = g_value_dup_string (value);
+      break;
+
+    case PROP_ACTIONS:
+      group->actions = g_value_dup_boxed (value);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+gtk_widget_action_group_get_property (GObject    *object,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  GtkWidgetActionGroup *group = GTK_WIDGET_ACTION_GROUP (object);
+
+  switch (prop_id)
+    {
+    case PROP_WIDGET:
+      g_value_set_object (value, group->widget);
+      break;
+
+    case PROP_PREFIX:
+      g_value_set_string (value, group->prefix);
+      break;
+
+    case PROP_ACTIONS:
+      g_value_set_boxed (value, group->actions);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+static void
+gtk_widget_action_group_finalize (GObject *object)
+{
+  GtkWidgetActionGroup *group = GTK_WIDGET_ACTION_GROUP (object);
+
+  g_free (group->prefix);
+  g_ptr_array_unref (group->actions);
+
+  G_OBJECT_CLASS (gtk_widget_action_group_parent_class)->finalize (object);
+}
+
+static void
+gtk_widget_action_group_class_init (GtkWidgetActionGroupClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->set_property = gtk_widget_action_group_set_property;
+  object_class->get_property = gtk_widget_action_group_get_property;
+  object_class->finalize = gtk_widget_action_group_finalize;
+
+  g_object_class_install_property (object_class, PROP_WIDGET,
+      g_param_spec_object ("widget",
+                           "The widget",
+                           "The widget to which this action group belongs",
+                           GTK_TYPE_WIDGET,
+                           G_PARAM_READWRITE |
+                           G_PARAM_CONSTRUCT_ONLY |
+                           G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (object_class, PROP_PREFIX,
+      g_param_spec_string ("prefix",
+                           "The prefix",
+                           "The prefix for actions in this group",
+                           NULL,
+                           G_PARAM_READWRITE |
+                           G_PARAM_CONSTRUCT_ONLY |
+                           G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (object_class, PROP_ACTIONS,
+      g_param_spec_boxed ("actions",
+                          "The actions",
+                          "The actions",
+                          G_TYPE_PTR_ARRAY,
+                          G_PARAM_READWRITE |
+                          G_PARAM_CONSTRUCT_ONLY |
+                          G_PARAM_STATIC_STRINGS));
+}
+
+GActionGroup *
+gtk_widget_action_group_new (GtkWidget  *widget,
+                             const char *prefix,
+                             GPtrArray  *actions)
+{
+  return (GActionGroup *)g_object_new (GTK_TYPE_WIDGET_ACTION_GROUP,
+                                       "widget", widget,
+                                       "prefix", prefix,
+                                       "actions", actions,
+                                       NULL);
+}
+
+GtkWidget *
+gtk_widget_action_group_get_widget (GtkWidgetActionGroup *group)
+{
+  return group->widget;
+}
diff --git a/gtk/gtkwidgetactiongroupprivate.h b/gtk/gtkwidgetactiongroupprivate.h
new file mode 100644
index 0000000000..3b1c7c5b55
--- /dev/null
+++ b/gtk/gtkwidgetactiongroupprivate.h
@@ -0,0 +1,53 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * Authors:
+ * - Matthias Clasen <mclasen redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_WIDGET_ACTION_GROUP_PRIVATE_H__
+#define __GTK_WIDGET_ACTION_GROUP_PRIVATE_H__
+
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_WIDGET_ACTION_GROUP           (gtk_widget_action_group_get_type ())
+#define GTK_WIDGET_ACTION_GROUP(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GTK_TYPE_WIDGET_ACTION_GROUP, GtkWidgetActionGroup))
+#define GTK_IS_WIDGET_ACTION_GROUP(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GTK_TYPE_WIDGET_ACTION_GROUP))
+
+typedef struct _GtkWidgetActionGroup GtkWidgetActionGroup;
+
+typedef struct {
+  char *prefix;
+  char *name;
+
+  GtkWidgetActionActivate activate;
+  GtkWidgetActionQuery    query;
+  GtkWidgetActionChange   change;
+} GtkWidgetAction;
+
+
+GType           gtk_widget_action_group_get_type (void) G_GNUC_CONST;
+
+GActionGroup *  gtk_widget_action_group_new      (GtkWidget  *widget,
+                                                  const char *prefix,
+                                                  GPtrArray  *actions);
+GtkWidget *     gtk_widget_action_group_get_widget (GtkWidgetActionGroup *group);
+
+G_END_DECLS
+
+#endif /* __GTK_WIDGET_ACTION_GROUP_PRIVATE_H__ */
diff --git a/gtk/meson.build b/gtk/meson.build
index c5bd9b154f..77b4465660 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -394,6 +394,7 @@ gtk_public_sources = files([
   'gtkviewport.c',
   'gtkvolumebutton.c',
   'gtkwidget.c',
+  'gtkwidgetactiongroup.c',
   'gtkwidgetfocus.c',
   'gtkwidgetpaintable.c',
   'gtkwidgetpath.c',


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