[gtk/wip/chergert/action-parent] widget: add gtk_widget_set_action_parent()




commit 6cedc6508f3c40887a1219a157a9dfbdc0cf3d53
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.

 gtk/gtkwidget.c        | 63 ++++++++++++++++++++++++++++++++++++++++++++++++--
 gtk/gtkwidget.h        |  3 +++
 gtk/gtkwidgetprivate.h |  1 +
 3 files changed, 65 insertions(+), 2 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index afe7e9224e..0b97edc6d0 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,53 @@ gtk_widget_set_active_state (GtkWidget *widget,
         gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_ACTIVE);
     }
 }
+
+/**
+ * gtk_widget_set_action_parent:
+ * @widget: a #Gtkwidget
+ * @action_parent: (nullable): a #GtkWidget or %NULL
+ *
+ * Sets the action parent for @widget meaning that actions that are not
+ * attached to @widget will be resolved through @action_parent instead
+ * of the widgets parent.
+ *
+ * Setting an action parent can be particularly 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 || 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]