From d30d56452cbd8d1c495c902018df17dee14875c8 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Fri, 17 Aug 2012 18:09:35 -0400 Subject: [PATCH] GtkWidget: Add gtk_widget_insert_action_group() This allows adding a GActionGroup with a given name at an arbitrary point in the widget tree. This patch also adds an internal _get_action_muxer() API. Calling this will create a GActionMuxer associated with the widget. The parent of the muxer will be the muxer of the widget's conceptual parent. For non-menus, that is the normal parent. For menus, it is the attach widget. In this way, we end up with a hierarchy of GActionMuxer that largely reflects the hierarchy of GtkWidget, but only in places that the action context has been requested. These muxers are the ones on which the inserted actions groups are installed. A following patch will add a user of this API. --- docs/reference/gtk/gtk3-sections.txt | 1 + gtk/gtk.symbols | 1 + gtk/gtkmenu.c | 4 ++ gtk/gtkwidget.c | 67 ++++++++++++++++++++++++++++ gtk/gtkwidget.h | 4 ++ gtk/gtkwidgetprivate.h | 4 ++ 6 files changed, 81 insertions(+) diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt index 0d16ef420a..8bdcb890db 100644 --- a/docs/reference/gtk/gtk3-sections.txt +++ b/docs/reference/gtk/gtk3-sections.txt @@ -5291,6 +5291,7 @@ gtk_widget_get_mapped gtk_widget_get_requisition gtk_widget_device_is_shadowed gtk_widget_get_modifier_mask +gtk_widget_insert_action_group gtk_widget_get_path diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index f0bffa4c69..1441671857 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -3828,6 +3828,7 @@ gtk_widget_unmap gtk_widget_unparent gtk_widget_unrealize gtk_widget_unset_state_flags +gtk_widget_insert_action_group #ifdef GDK_WINDOWING_WIN32 gtk_win32_embed_widget_get_type #endif diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 9f0bfee818..6667ed5f6d 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -1220,6 +1220,8 @@ gtk_menu_attach_to_widget (GtkMenu *menu, /* Attach the widget to the toplevel window. */ gtk_window_set_attached_to (GTK_WINDOW (menu->priv->toplevel), attach_widget); + _gtk_widget_update_parent_muxer (GTK_WIDGET (menu)); + /* Fallback title for menu comes from attach widget */ gtk_menu_update_title (menu); @@ -1294,6 +1296,8 @@ gtk_menu_detach (GtkMenu *menu) g_slice_free (GtkMenuAttachData, data); + _gtk_widget_update_parent_muxer (GTK_WIDGET (menu)); + /* Fallback title for menu comes from attach widget */ gtk_menu_update_title (menu); diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 628ff17c74..ebcea83755 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -390,6 +390,9 @@ struct _GtkWidgetPrivate /* The widget's requested sizes */ SizeRequestCache requests; + /* actions attached to this or any parent widget */ + GActionMuxer *muxer; + /* The widget's window or its parent window if it does * not have a window. (Which will be indicated by the * GTK_NO_WINDOW flag being set). @@ -3899,6 +3902,8 @@ gtk_widget_unparent (GtkWidget *widget) if (priv->context) gtk_style_context_set_parent (priv->context, NULL); + _gtk_widget_update_parent_muxer (widget); + g_signal_emit (widget, widget_signals[PARENT_SET], 0, old_parent); if (toplevel) { @@ -7968,6 +7973,8 @@ gtk_widget_set_parent (GtkWidget *widget, gtk_style_context_set_parent (priv->context, gtk_widget_get_style_context (parent)); + _gtk_widget_update_parent_muxer (widget); + g_signal_emit (widget, widget_signals[PARENT_SET], 0, NULL); if (priv->parent->priv->anchored) _gtk_widget_propagate_hierarchy_changed (widget, NULL); @@ -10268,6 +10275,8 @@ gtk_widget_dispose (GObject *object) priv->in_destruction = FALSE; } + g_clear_object (&priv->muxer); + G_OBJECT_CLASS (gtk_widget_parent_class)->dispose (object); } @@ -14072,3 +14081,61 @@ _gtk_widget_set_style (GtkWidget *widget, { widget->priv->style = style; } + +void +_gtk_widget_update_parent_muxer (GtkWidget *widget) +{ + GtkWidget *parent; + GActionMuxer *parent_muxer; + + if (widget->priv->muxer == NULL) + return; + + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = gtk_widget_get_parent (widget); + + parent_muxer = parent ? _gtk_widget_get_action_muxer (parent) : NULL; + + g_action_muxer_set_parent (widget->priv->muxer, parent_muxer); +} + +GActionMuxer * +_gtk_widget_get_action_muxer (GtkWidget *widget) +{ + if (widget->priv->muxer == NULL) + { + widget->priv->muxer = g_action_muxer_new (); + _gtk_widget_update_parent_muxer (widget); + } + + return widget->priv->muxer; +} + +/** + * gtk_widget_insert_action_group: + * @widget: a #GtkWidget + * @name: the prefix for actions in @group + * @group: a #GActionGroup + * + * Inserts @group into @widget. Children of @widget that implement + * #GtkActionable can then be associated with actions in @group by + * setting their 'action-name' to @prefix.. + * + * Since: 3.6 + */ +void +gtk_widget_insert_action_group (GtkWidget *widget, + const gchar *name, + GActionGroup *group) +{ + GActionMuxer *muxer; + + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (name != NULL); + + muxer = _gtk_widget_get_action_muxer (widget); + + g_action_muxer_insert (muxer, name, group); +} diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index 576d7e91b9..c178478117 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -886,6 +886,10 @@ GDK_AVAILABLE_IN_3_4 GdkModifierType gtk_widget_get_modifier_mask (GtkWidget *widget, GdkModifierIntent intent); +GDK_AVAILABLE_IN_3_6 +void gtk_widget_insert_action_group (GtkWidget *widget, + const gchar *name, + GActionGroup *group); G_END_DECLS diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index c59ed3902f..c7c0cfee64 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -27,6 +27,7 @@ #include "gtkcsstypesprivate.h" #include "gtkwidget.h" +#include "gactionmuxer.h" G_BEGIN_DECLS @@ -178,6 +179,9 @@ void _gtk_widget_invalidate_style_context (GtkWidget *widget GtkCssChange change); void _gtk_widget_style_context_invalidated (GtkWidget *widget); +void _gtk_widget_update_parent_muxer (GtkWidget *widget); +GActionMuxer * _gtk_widget_get_action_muxer (GtkWidget *widget); + G_END_DECLS #endif /* __GTK_WIDGET_PRIVATE_H__ */