[gtk/wip/chergert/action-parent: 1/4] widget: add gtk_widget_set_action_parent()
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/action-parent: 1/4] widget: add gtk_widget_set_action_parent()
- Date: Mon, 2 May 2022 23:46:51 +0000 (UTC)
commit 25937d238656800c0876a7acf55b51552b417c51
Author: Christian Hergert <chergert redhat com>
Date: Mon May 2 14:36:26 2022 -0700
widget: add gtk_widget_set_action_parent()
This adds a new function to the 4.8 ABI that allows setting an action
parent for a widget. The action parent affects the action muxing so that
instead of using the widgets direct ancestor, an alternate widget's
action muxer may be used.
You may not set an action parent for a widget that is a direct descendant
of your widget as that would cause cycles in action resolution.
You might find this API useful for situations where you want menus in
headerbars to route through action muxers for the current document as
well as toolbars or sidebars.
Fixes #4860
gtk/gtkwidget.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++--
gtk/gtkwidget.h | 3 +++
gtk/gtkwidgetprivate.h | 1 +
3 files changed, 68 insertions(+), 2 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index afe7e9224e..ca5ee20ed3 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -7390,6 +7390,8 @@ gtk_widget_dispose (GObject *object)
GSList *sizegroups;
GtkATContext *at_context;
+ g_clear_object (&priv->action_parent);
+
if (priv->muxer != NULL)
g_object_run_dispose (G_OBJECT (priv->muxer));
@@ -10808,13 +10810,20 @@ void
_gtk_widget_update_parent_muxer (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+ GtkActionMuxer *parent_muxer;
GtkWidget *child;
if (priv->muxer == NULL)
return;
- gtk_action_muxer_set_parent (priv->muxer,
- gtk_widget_get_parent_muxer (widget, FALSE));
+ if (priv->action_parent != NULL &&
+ !gtk_widget_is_ancestor (priv->action_parent, widget))
+ parent_muxer = _gtk_widget_get_action_muxer (priv->action_parent, FALSE);
+ else
+ parent_muxer = gtk_widget_get_parent_muxer (widget, FALSE);
+
+ gtk_action_muxer_set_parent (priv->muxer, parent_muxer);
+
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
@@ -12934,3 +12943,56 @@ gtk_widget_set_active_state (GtkWidget *widget,
gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_ACTIVE);
}
}
+
+/**
+ * gtk_widget_set_action_parent:
+ * @widget: a [class@Gtk.Widget]
+ * @action_parent: (nullable): a [class@Gtk.Widget]
+ *
+ * Sets the action parent for @widget.
+ *
+ * Actions will resolve through @action_parent for @widget and all of
+ * it's descendants unless otherwise specified with
+ * [method@Gtk.Widget.set_action_parent].
+ *
+ * Setting an action parent can be useful when you want actions within
+ * a menu or toolbar to resolve through a document widget.
+ *
+ * To unset an action parent, use `NULL` for @action_parent and the widget
+ * will resume using the parent widget as the action parent.
+ *
+ * Since: 4.8
+ */
+void
+gtk_widget_set_action_parent (GtkWidget *widget,
+ GtkWidget *action_parent)
+{
+ GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+ GtkActionMuxer *muxer;
+ GtkActionMuxer *parent_muxer;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (action_parent != widget);
+ g_return_if_fail (!action_parent || GTK_IS_WIDGET (action_parent));
+ g_return_if_fail (!action_parent || !gtk_widget_is_ancestor (action_parent, widget));
+
+ muxer = _gtk_widget_get_action_muxer (widget, FALSE);
+
+ if (action_parent == NULL)
+ {
+ if (muxer != NULL)
+ {
+ parent_muxer = gtk_widget_get_parent_muxer (widget, FALSE);
+ gtk_action_muxer_set_parent (muxer, parent_muxer);
+ }
+ }
+ else
+ {
+ if (muxer == NULL)
+ muxer = _gtk_widget_get_action_muxer (widget, TRUE);
+ parent_muxer = _gtk_widget_get_action_muxer (action_parent, TRUE);
+ gtk_action_muxer_set_parent (muxer, parent_muxer);
+ }
+
+ g_set_object (&priv->action_parent, action_parent);
+}
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 0788fcdd81..1a9793f296 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -924,6 +924,9 @@ char ** gtk_widget_get_css_classes (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_set_css_classes (GtkWidget *widget,
const char **classes);
+GDK_AVAILABLE_IN_4_8
+void gtk_widget_set_action_parent (GtkWidget *widget,
+ GtkWidget *action_parent);
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index e1e336e6e6..b8f17c8f23 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -185,6 +185,7 @@ struct _GtkWidgetPrivate
GtkListListModel *children_observer;
GtkListListModel *controller_observer;
GtkActionMuxer *muxer;
+ GtkWidget *action_parent;
GtkWidget *focus_child;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]