[libpanel] widget: give access to muxed page actions from frame
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libpanel] widget: give access to muxed page actions from frame
- Date: Wed, 27 Jul 2022 19:18:29 +0000 (UTC)
commit d863e9dae6aebc8a30e6c82ffc9cd91872464e0f
Author: Christian Hergert <chergert redhat com>
Date: Wed Jul 27 11:54:48 2022 -0700
widget: give access to muxed page actions from frame
This requires that applications use panel_widget_insert_action_group()
so that the actions are muxed into a group that can be extracted and
connected to the frame hosting the PanelWidget.
src/meson.build | 1 +
src/panel-action-muxer-private.h | 42 +++
src/panel-action-muxer.c | 602 +++++++++++++++++++++++++++++++++++++++
src/panel-frame.c | 5 +
src/panel-widget-private.h | 5 +-
src/panel-widget.c | 34 +++
src/panel-widget.h | 4 +
7 files changed, 691 insertions(+), 2 deletions(-)
---
diff --git a/src/meson.build b/src/meson.build
index 524233a..b63244a 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -18,6 +18,7 @@ panel_version_h = configure_file(
configuration: version_data)
libpanel_sources = [
+ 'panel-action-muxer.c',
'panel-binding-group.c',
'panel-dock.c',
'panel-dock-child.c',
diff --git a/src/panel-action-muxer-private.h b/src/panel-action-muxer-private.h
new file mode 100644
index 0000000..e694756
--- /dev/null
+++ b/src/panel-action-muxer-private.h
@@ -0,0 +1,42 @@
+/* panel-action-muxer-private.h
+ *
+ * Copyright 2022 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-Panelntifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define PANEL_TYPE_ACTION_MUXER (panel_action_muxer_get_type())
+
+G_DECLARE_FINAL_TYPE (PanelActionMuxer, panel_action_muxer, PANEL, ACTION_MUXER, GObject)
+
+PanelActionMuxer *panel_action_muxer_new (void);
+void panel_action_muxer_insert_action_group (PanelActionMuxer *self,
+ const char *prefix,
+ GActionGroup *action_group);
+void panel_action_muxer_remove_action_group (PanelActionMuxer *self,
+ const char *prefix);
+char **panel_action_muxer_list_groups (PanelActionMuxer *self);
+GActionGroup *panel_action_muxer_get_action_group (PanelActionMuxer *self,
+ const char *prefix);
+void panel_action_muxer_clear (PanelActionMuxer *self);
+
+G_END_DECLS
diff --git a/src/panel-action-muxer.c b/src/panel-action-muxer.c
new file mode 100644
index 0000000..382e61f
--- /dev/null
+++ b/src/panel-action-muxer.c
@@ -0,0 +1,602 @@
+/* panel-action-muxer.c
+ *
+ * Copyright 2022 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-Panelntifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include "panel-action-muxer-private.h"
+
+struct _PanelActionMuxer
+{
+ GObject parent_instance;
+ GPtrArray *action_groups;
+ guint n_recurse;
+};
+
+typedef struct
+{
+ PanelActionMuxer *backptr;
+ char *prefix;
+ GActionGroup *action_group;
+ GSignalGroup *action_group_signals;
+} PrefixedActionGroup;
+
+static void action_group_iface_init (GActionGroupInterface *iface);
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (PanelActionMuxer, panel_action_muxer, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, action_group_iface_init))
+
+static void
+prefixed_action_group_finalize (gpointer data)
+{
+ PrefixedActionGroup *pag = data;
+
+ g_assert (pag->backptr == NULL);
+
+ g_clear_object (&pag->action_group_signals);
+ g_clear_object (&pag->action_group);
+ g_clear_pointer (&pag->prefix, g_free);
+}
+
+static void
+prefixed_action_group_unref (PrefixedActionGroup *pag)
+{
+ g_rc_box_release_full (pag, prefixed_action_group_finalize);
+}
+
+static void
+prefixed_action_group_drop (PrefixedActionGroup *pag)
+{
+ g_signal_group_set_target (pag->action_group_signals, NULL);
+ pag->backptr = NULL;
+ prefixed_action_group_unref (pag);
+}
+
+static PrefixedActionGroup *
+prefixed_action_group_ref (PrefixedActionGroup *pag)
+{
+ return g_rc_box_acquire (pag);
+}
+
+static void
+panel_action_muxer_dispose (GObject *object)
+{
+ PanelActionMuxer *self = (PanelActionMuxer *)object;
+
+ if (self->action_groups->len > 0)
+ g_ptr_array_remove_range (self->action_groups, 0, self->action_groups->len);
+
+ G_OBJECT_CLASS (panel_action_muxer_parent_class)->finalize (object);
+}
+
+static void
+panel_action_muxer_finalize (GObject *object)
+{
+ PanelActionMuxer *self = (PanelActionMuxer *)object;
+
+ g_clear_pointer (&self->action_groups, g_ptr_array_unref);
+
+ G_OBJECT_CLASS (panel_action_muxer_parent_class)->finalize (object);
+}
+
+static void
+panel_action_muxer_class_init (PanelActionMuxerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = panel_action_muxer_dispose;
+ object_class->finalize = panel_action_muxer_finalize;
+}
+
+static void
+panel_action_muxer_init (PanelActionMuxer *self)
+{
+ self->action_groups = g_ptr_array_new_with_free_func ((GDestroyNotify)prefixed_action_group_drop);
+}
+
+PanelActionMuxer *
+panel_action_muxer_new (void)
+{
+ return g_object_new (PANEL_TYPE_ACTION_MUXER, NULL);
+}
+
+/**
+ * panel_action_muxer_list_groups:
+ * @self: a #PanelActionMuxer
+ *
+ * Gets a list of group names in the muxer.
+ *
+ * Returns: (transfer full) (array zero-terminated=1) (element-type utf8):
+ * an array containing the names of groups within the muxer
+ */
+char **
+panel_action_muxer_list_groups (PanelActionMuxer *self)
+{
+ GArray *ar;
+
+ g_return_val_if_fail (PANEL_IS_ACTION_MUXER (self), NULL);
+
+ ar = g_array_new (TRUE, FALSE, sizeof (char *));
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+ char *prefix = g_strdup (pag->prefix);
+
+ g_assert (prefix != NULL);
+ g_assert (g_str_has_suffix (prefix, "."));
+
+ *strrchr (prefix, '.') = 0;
+
+ g_array_append_val (ar, prefix);
+ }
+
+ return (char **)g_array_free (ar, FALSE);
+}
+
+static void
+panel_action_muxer_action_group_action_added_cb (GActionGroup *action_group,
+ const char *action_name,
+ PrefixedActionGroup *pag)
+{
+ g_autofree char *full_name = NULL;
+
+ g_assert (G_IS_ACTION_GROUP (action_group));
+ g_assert (action_name != NULL);
+ g_assert (pag != NULL);
+ g_assert (pag->backptr != NULL);
+ g_assert (PANEL_IS_ACTION_MUXER (pag->backptr));
+
+ full_name = g_strconcat (pag->prefix, action_name, NULL);
+ g_action_group_action_added (G_ACTION_GROUP (pag->backptr), full_name);
+}
+
+static void
+panel_action_muxer_action_group_action_removed_cb (GActionGroup *action_group,
+ const char *action_name,
+ PrefixedActionGroup *pag)
+{
+ g_autofree char *full_name = NULL;
+
+ g_assert (G_IS_ACTION_GROUP (action_group));
+ g_assert (action_name != NULL);
+ g_assert (pag != NULL);
+ g_assert (pag->backptr != NULL);
+ g_assert (PANEL_IS_ACTION_MUXER (pag->backptr));
+
+ full_name = g_strconcat (pag->prefix, action_name, NULL);
+ g_action_group_action_removed (G_ACTION_GROUP (pag->backptr), full_name);
+}
+
+static void
+panel_action_muxer_action_group_action_enabled_changed_cb (GActionGroup *action_group,
+ const char *action_name,
+ gboolean enabled,
+ PrefixedActionGroup *pag)
+{
+ g_autofree char *full_name = NULL;
+
+ g_assert (G_IS_ACTION_GROUP (action_group));
+ g_assert (action_name != NULL);
+ g_assert (pag != NULL);
+ g_assert (pag->backptr != NULL);
+ g_assert (PANEL_IS_ACTION_MUXER (pag->backptr));
+
+ full_name = g_strconcat (pag->prefix, action_name, NULL);
+ g_action_group_action_enabled_changed (G_ACTION_GROUP (pag->backptr), full_name, enabled);
+}
+
+static void
+panel_action_muxer_action_group_action_state_changed_cb (GActionGroup *action_group,
+ const char *action_name,
+ GVariant *value,
+ PrefixedActionGroup *pag)
+{
+ g_autofree char *full_name = NULL;
+
+ g_assert (G_IS_ACTION_GROUP (action_group));
+ g_assert (action_name != NULL);
+ g_assert (pag != NULL);
+ g_assert (pag->backptr != NULL);
+ g_assert (PANEL_IS_ACTION_MUXER (pag->backptr));
+
+ full_name = g_strconcat (pag->prefix, action_name, NULL);
+ g_action_group_action_state_changed (G_ACTION_GROUP (pag->backptr), full_name, value);
+}
+
+void
+panel_action_muxer_insert_action_group (PanelActionMuxer *self,
+ const char *prefix,
+ GActionGroup *action_group)
+{
+ g_autofree char *prefix_dot = NULL;
+
+ g_return_if_fail (PANEL_IS_ACTION_MUXER (self));
+ g_return_if_fail (self->n_recurse == 0);
+ g_return_if_fail (prefix != NULL);
+ g_return_if_fail (!action_group || G_IS_ACTION_GROUP (action_group));
+
+ /* Protect against recursion via signal emission. We don't want anything to
+ * mess with our GArray while we are actively processing actions. To do so is
+ * invalid API use.
+ */
+ self->n_recurse++;
+
+ /* Precalculate with a dot suffix so we can simplify lookups */
+ prefix_dot = g_strconcat (prefix, ".", NULL);
+
+ /* Find our matching action group by prefix, and then notify it has been
+ * removed from our known actions.
+ */
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+ g_auto(GStrv) action_names = NULL;
+
+ g_assert (pag->prefix != NULL);
+ g_assert (G_IS_ACTION_GROUP (pag->action_group));
+
+ if (g_strcmp0 (pag->prefix, prefix_dot) != 0)
+ continue;
+
+ /* Clear signal group first, since it has weak pointers */
+ g_signal_group_set_target (pag->action_group_signals, NULL);
+
+ /* Retrieve list of all the action names so we can drop references */
+ action_names = g_action_group_list_actions (pag->action_group);
+
+ /* Remove this entry from our knowledge, clear pag because it now
+ * points to potentially invalid memory.
+ */
+ pag = NULL;
+ g_ptr_array_remove_index_fast (self->action_groups, i);
+
+ /* Notify any actiongroup listeners of removed actions */
+ for (guint j = 0; action_names[j]; j++)
+ {
+ g_autofree char *action_name = g_strconcat (prefix_dot, action_names[j], NULL);
+ g_action_group_action_removed (G_ACTION_GROUP (self), action_name);
+ }
+
+ break;
+ }
+
+ /* If we got a new action group to replace it, setup tracking of the
+ * action group and then notify of all the current actions.
+ */
+ if (action_group != NULL)
+ {
+ g_auto(GStrv) action_names = g_action_group_list_actions (action_group);
+ PrefixedActionGroup *new_pag = g_rc_box_new0 (PrefixedActionGroup);
+
+ new_pag->backptr = self;
+ new_pag->prefix = g_strdup (prefix_dot);
+ new_pag->action_group = g_object_ref (action_group);
+ new_pag->action_group_signals = g_signal_group_new (G_TYPE_ACTION_GROUP);
+ g_ptr_array_add (self->action_groups, new_pag);
+
+ g_signal_group_connect_data (new_pag->action_group_signals,
+ "action-added",
+ G_CALLBACK (panel_action_muxer_action_group_action_added_cb),
+ prefixed_action_group_ref (new_pag),
+ (GClosureNotify)prefixed_action_group_unref,
+ 0);
+ g_signal_group_connect_data (new_pag->action_group_signals,
+ "action-removed",
+ G_CALLBACK (panel_action_muxer_action_group_action_removed_cb),
+ prefixed_action_group_ref (new_pag),
+ (GClosureNotify)prefixed_action_group_unref,
+ 0);
+ g_signal_group_connect_data (new_pag->action_group_signals,
+ "action-enabled-changed",
+ G_CALLBACK (panel_action_muxer_action_group_action_enabled_changed_cb),
+ prefixed_action_group_ref (new_pag),
+ (GClosureNotify)prefixed_action_group_unref,
+ 0);
+ g_signal_group_connect_data (new_pag->action_group_signals,
+ "action-state-changed",
+ G_CALLBACK (panel_action_muxer_action_group_action_state_changed_cb),
+ prefixed_action_group_ref (new_pag),
+ (GClosureNotify)prefixed_action_group_unref,
+ 0);
+
+ g_signal_group_set_target (new_pag->action_group_signals, action_group);
+
+ for (guint j = 0; action_names[j]; j++)
+ {
+ g_autofree char *action_name = g_strconcat (prefix_dot, action_names[j], NULL);
+ g_action_group_action_added (G_ACTION_GROUP (self), action_name);
+ }
+ }
+
+ self->n_recurse--;
+}
+
+void
+panel_action_muxer_remove_action_group (PanelActionMuxer *self,
+ const char *prefix)
+{
+ g_return_if_fail (PANEL_IS_ACTION_MUXER (self));
+ g_return_if_fail (prefix != NULL);
+
+ panel_action_muxer_insert_action_group (self, prefix, NULL);
+}
+
+/**
+ * panel_action_muxer_get_action_group:
+ * @self: a #PanelActionMuxer
+ * @prefix: the name of the inserted action group
+ *
+ * Locates the #GActionGroup inserted as @prefix.
+ *
+ * If no group was found matching @group, %NULL is returned.
+ *
+ * Returns: (transfer none) (nullable): a #GActionGroup matching @prefix if
+ * found, otherwise %NULL.
+ */
+GActionGroup *
+panel_action_muxer_get_action_group (PanelActionMuxer *self,
+ const char *prefix)
+{
+ g_autofree char *prefix_dot = NULL;
+
+ g_return_val_if_fail (PANEL_IS_ACTION_MUXER (self), NULL);
+ g_return_val_if_fail (prefix!= NULL, NULL);
+
+ prefix_dot = g_strconcat (prefix, ".", NULL);
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+
+ if (g_strcmp0 (pag->prefix, prefix_dot) == 0)
+ return pag->action_group;
+ }
+
+ return NULL;
+}
+
+static gboolean
+panel_action_muxer_has_action (GActionGroup *group,
+ const char *action_name)
+{
+ PanelActionMuxer *self = PANEL_ACTION_MUXER (group);
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+
+ if (g_str_has_prefix (action_name, pag->prefix))
+ {
+ const char *short_name = action_name + strlen (pag->prefix);
+
+ if (g_action_group_has_action (pag->action_group, short_name))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static char **
+panel_action_muxer_list_actions (GActionGroup *group)
+{
+ PanelActionMuxer *self = PANEL_ACTION_MUXER (group);
+ GArray *ar = g_array_new (TRUE, FALSE, sizeof (char *));
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+ g_auto(GStrv) action_names = g_action_group_list_actions (pag->action_group);
+
+ for (guint j = 0; action_names[j]; j++)
+ {
+ char *full_action_name = g_strconcat (pag->prefix, action_names[j], NULL);
+ g_array_append_val (ar, full_action_name);
+ }
+ }
+
+ return (char **)g_array_free (ar, FALSE);
+}
+
+static gboolean
+panel_action_muxer_get_action_enabled (GActionGroup *group,
+ const char *action_name)
+{
+ PanelActionMuxer *self = PANEL_ACTION_MUXER (group);
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+
+ if (g_str_has_prefix (action_name, pag->prefix))
+ {
+ const char *short_name = action_name + strlen (pag->prefix);
+
+ if (g_action_group_has_action (pag->action_group, short_name))
+ return g_action_group_get_action_enabled (pag->action_group, short_name);
+ }
+ }
+
+ return FALSE;
+}
+
+static GVariant *
+panel_action_muxer_get_action_state (GActionGroup *group,
+ const char *action_name)
+{
+ PanelActionMuxer *self = PANEL_ACTION_MUXER (group);
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+
+ if (g_str_has_prefix (action_name, pag->prefix))
+ {
+ const char *short_name = action_name + strlen (pag->prefix);
+
+ if (g_action_group_has_action (pag->action_group, short_name))
+ return g_action_group_get_action_state (pag->action_group, short_name);
+ }
+ }
+
+ return NULL;
+}
+
+static GVariant *
+panel_action_muxer_get_action_state_hint (GActionGroup *group,
+ const char *action_name)
+{
+ PanelActionMuxer *self = PANEL_ACTION_MUXER (group);
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+
+ if (g_str_has_prefix (action_name, pag->prefix))
+ {
+ const char *short_name = action_name + strlen (pag->prefix);
+
+ if (g_action_group_has_action (pag->action_group, short_name))
+ return g_action_group_get_action_state_hint (pag->action_group, short_name);
+ }
+ }
+
+ return NULL;
+}
+
+static void
+panel_action_muxer_change_action_state (GActionGroup *group,
+ const char *action_name,
+ GVariant *value)
+{
+ PanelActionMuxer *self = PANEL_ACTION_MUXER (group);
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+
+ if (g_str_has_prefix (action_name, pag->prefix))
+ {
+ const char *short_name = action_name + strlen (pag->prefix);
+
+ if (g_action_group_has_action (pag->action_group, short_name))
+ {
+ g_action_group_change_action_state (pag->action_group, short_name, value);
+ break;
+ }
+ }
+ }
+}
+
+static const GVariantType *
+panel_action_muxer_get_action_state_type (GActionGroup *group,
+ const char *action_name)
+{
+ PanelActionMuxer *self = PANEL_ACTION_MUXER (group);
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+
+ if (g_str_has_prefix (action_name, pag->prefix))
+ {
+ const char *short_name = action_name + strlen (pag->prefix);
+
+ if (g_action_group_has_action (pag->action_group, short_name))
+ return g_action_group_get_action_state_type (pag->action_group, short_name);
+ }
+ }
+
+ return NULL;
+}
+
+static void
+panel_action_muxer_activate_action (GActionGroup *group,
+ const char *action_name,
+ GVariant *parameter)
+{
+ PanelActionMuxer *self = PANEL_ACTION_MUXER (group);
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+
+ if (g_str_has_prefix (action_name, pag->prefix))
+ {
+ const char *short_name = action_name + strlen (pag->prefix);
+
+ if (g_action_group_has_action (pag->action_group, short_name))
+ {
+ g_action_group_activate_action (pag->action_group, short_name, parameter);
+ break;
+ }
+ }
+ }
+}
+
+static const GVariantType *
+panel_action_muxer_get_action_parameter_type (GActionGroup *group,
+ const char *action_name)
+{
+ PanelActionMuxer *self = PANEL_ACTION_MUXER (group);
+
+ for (guint i = 0; i < self->action_groups->len; i++)
+ {
+ const PrefixedActionGroup *pag = g_ptr_array_index (self->action_groups, i);
+
+ if (g_str_has_prefix (action_name, pag->prefix))
+ {
+ const char *short_name = action_name + strlen (pag->prefix);
+
+ if (g_action_group_has_action (pag->action_group, short_name))
+ return g_action_group_get_action_parameter_type (pag->action_group, short_name);
+ }
+ }
+
+ return NULL;
+}
+
+static void
+action_group_iface_init (GActionGroupInterface *iface)
+{
+ iface->has_action = panel_action_muxer_has_action;
+ iface->list_actions = panel_action_muxer_list_actions;
+ iface->get_action_parameter_type = panel_action_muxer_get_action_parameter_type;
+ iface->get_action_enabled = panel_action_muxer_get_action_enabled;
+ iface->get_action_state = panel_action_muxer_get_action_state;
+ iface->get_action_state_hint = panel_action_muxer_get_action_state_hint;
+ iface->get_action_state_type = panel_action_muxer_get_action_state_type;
+ iface->change_action_state = panel_action_muxer_change_action_state;
+ iface->activate_action = panel_action_muxer_activate_action;
+}
+
+void
+panel_action_muxer_clear (PanelActionMuxer *self)
+{
+ g_auto(GStrv) action_groups = NULL;
+
+ g_return_if_fail (PANEL_IS_ACTION_MUXER (self));
+
+ if ((action_groups = panel_action_muxer_list_actions (G_ACTION_GROUP (self))))
+ {
+ for (guint i = 0; action_groups[i]; i++)
+ panel_action_muxer_remove_action_group (self, action_groups[i]);
+ }
+}
diff --git a/src/panel-frame.c b/src/panel-frame.c
index 8fe701b..dfc283d 100644
--- a/src/panel-frame.c
+++ b/src/panel-frame.c
@@ -232,6 +232,7 @@ panel_frame_update_actions (PanelFrame *self)
{
PanelFramePrivate *priv = panel_frame_get_instance_private (self);
PanelWidget *visible_child;
+ GActionGroup *action_group = NULL;
GtkWidget *grid;
g_assert (PANEL_IS_FRAME (self));
@@ -239,6 +240,10 @@ panel_frame_update_actions (PanelFrame *self)
grid = gtk_widget_get_ancestor (GTK_WIDGET (self), PANEL_TYPE_GRID);
visible_child = panel_frame_get_visible_child (self);
+ if (visible_child != NULL)
+ action_group = _panel_widget_get_action_group (visible_child);
+ gtk_widget_insert_action_group (GTK_WIDGET (self), "page", action_group);
+
gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.move-right", grid && visible_child);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.move-left", grid && visible_child);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.move-down", grid && visible_child);
diff --git a/src/panel-widget-private.h b/src/panel-widget-private.h
index 5ecda34..4e58138 100644
--- a/src/panel-widget-private.h
+++ b/src/panel-widget-private.h
@@ -24,7 +24,8 @@
G_BEGIN_DECLS
-gboolean _panel_widget_can_save (PanelWidget *self);
-void _panel_widget_emit_presented (PanelWidget *self);
+gboolean _panel_widget_can_save (PanelWidget *self);
+void _panel_widget_emit_presented (PanelWidget *self);
+GActionGroup *_panel_widget_get_action_group (PanelWidget *self);
G_END_DECLS
diff --git a/src/panel-widget.c b/src/panel-widget.c
index 75b1c55..c7e7b50 100644
--- a/src/panel-widget.c
+++ b/src/panel-widget.c
@@ -20,6 +20,7 @@
#include "config.h"
+#include "panel-action-muxer-private.h"
#include "panel-dock-private.h"
#include "panel-dock-child-private.h"
#include "panel-frame-private.h"
@@ -34,6 +35,7 @@ typedef struct
GIcon *icon;
GMenuModel *menu_model;
PanelSaveDelegate *save_delegate;
+ PanelActionMuxer *action_muxer;
GtkWidget *maximize_frame;
GtkWidget *maximize_dock_child;
@@ -162,6 +164,12 @@ panel_widget_dispose (GObject *object)
PanelWidget *self = (PanelWidget *)object;
PanelWidgetPrivate *priv = panel_widget_get_instance_private (self);
+ if (priv->action_muxer != NULL)
+ {
+ panel_action_muxer_clear (priv->action_muxer);
+ g_clear_object (&priv->action_muxer);
+ }
+
g_clear_pointer (&priv->icon_name, g_free);
g_clear_pointer (&priv->title, g_free);
g_clear_pointer (&priv->child, gtk_widget_unparent);
@@ -1285,3 +1293,29 @@ _panel_widget_emit_presented (PanelWidget *self)
g_signal_emit (self, signals [PRESENTED], 0);
}
+
+GActionGroup *
+_panel_widget_get_action_group (PanelWidget *self)
+{
+ PanelWidgetPrivate *priv = panel_widget_get_instance_private (self);
+
+ if (priv->action_muxer == NULL)
+ priv->action_muxer = panel_action_muxer_new ();
+
+ return G_ACTION_GROUP (priv->action_muxer);
+}
+
+void
+panel_widget_insert_action_group (PanelWidget *self,
+ const char *prefix,
+ GActionGroup *group)
+{
+ GActionGroup *muxer;
+
+ g_return_if_fail (PANEL_IS_WIDGET (self));
+ g_return_if_fail (prefix != NULL);
+
+ muxer = _panel_widget_get_action_group (self);
+
+ panel_action_muxer_insert_action_group (PANEL_ACTION_MUXER (muxer), prefix, group);
+}
diff --git a/src/panel-widget.h b/src/panel-widget.h
index 8f8065d..2e9efed 100644
--- a/src/panel-widget.h
+++ b/src/panel-widget.h
@@ -133,5 +133,9 @@ void panel_widget_set_save_delegate (PanelWidget *self,
PanelSaveDelegate *save_delegate);
PANEL_AVAILABLE_IN_ALL
void panel_widget_close (PanelWidget *self);
+PANEL_AVAILABLE_IN_ALL
+void panel_widget_insert_action_group (PanelWidget *self,
+ const char *prefix,
+ GActionGroup *group);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]