[gtk/wip/otte/boxes: 7/20] widget: Add GtkWidgetClass:root and :unroot functions



commit 6b3983be57a596f42caa58ffd440c43d480ab784
Author: Benjamin Otte <otte redhat com>
Date:   Sun Jul 29 03:31:36 2018 +0200

    widget: Add GtkWidgetClass:root and :unroot functions
    
    They get added whenever a widget gets added into a hierarchy with a root
    widget.

 gtk/gtkwidget.c        | 71 ++++++++++++++++++++++++++++++++++++++++++++++----
 gtk/gtkwidget.h        |  5 ++++
 gtk/gtkwidgetprivate.h |  5 ++++
 3 files changed, 76 insertions(+), 5 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 4002e2ba12..23ac98c154 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -602,6 +602,8 @@ static void             gtk_widget_real_move_focus              (GtkWidget
                                                                  GtkDirectionType  direction);
 static gboolean                gtk_widget_real_keynav_failed           (GtkWidget        *widget,
                                                                 GtkDirectionType  direction);
+static void             gtk_widget_root                         (GtkWidget        *widget);
+static void             gtk_widget_unroot                       (GtkWidget        *widget);
 #ifdef G_ENABLE_CONSISTENCY_CHECKS
 static void             gtk_widget_verify_invariants            (GtkWidget        *widget);
 static void             gtk_widget_push_verify_invariants       (GtkWidget        *widget);
@@ -853,6 +855,18 @@ gtk_widget_real_grab_notify (GtkWidget *widget,
     }
 }
 
+static void
+gtk_widget_real_root (GtkWidget *widget)
+{
+  gtk_widget_forall (widget, (GtkCallback) gtk_widget_root, NULL);
+}
+
+static void
+gtk_widget_real_unroot (GtkWidget *widget)
+{
+  gtk_widget_forall (widget, (GtkCallback) gtk_widget_unroot, NULL);
+}
+
 static void
 gtk_widget_class_init (GtkWidgetClass *klass)
 {
@@ -899,6 +913,8 @@ gtk_widget_class_init (GtkWidgetClass *klass)
   klass->unmap = gtk_widget_real_unmap;
   klass->realize = gtk_widget_real_realize;
   klass->unrealize = gtk_widget_real_unrealize;
+  klass->root = gtk_widget_real_root;
+  klass->unroot = gtk_widget_real_unroot;
   klass->size_allocate = gtk_widget_real_size_allocate;
   klass->get_request_mode = gtk_widget_real_get_request_mode;
   klass->measure = gtk_widget_real_measure;
@@ -2868,6 +2884,9 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
   gtk_css_node_set_visible (priv->cssnode, priv->visible);
   /* need to set correct type here, and only class has the correct type here */
   gtk_css_node_set_widget_type (priv->cssnode, G_TYPE_FROM_CLASS (g_class));
+
+  if (g_type_is_a (G_TYPE_FROM_CLASS (g_class), GTK_TYPE_ROOT))
+    priv->root = (GtkRoot *) widget;
 }
 
 
@@ -2995,6 +3014,42 @@ gtk_widget_new (GType        type,
   return widget;
 }
 
+static void
+gtk_widget_root (GtkWidget *widget)
+{
+  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+  /* roots are rooted by default */
+  if (GTK_IS_ROOT (widget))
+    return;
+
+  g_assert (priv->root == NULL);
+  g_assert (!priv->realized);
+  g_assert (priv->parent);
+  g_assert (priv->parent->priv->root);
+
+  priv->root = priv->parent->priv->root;
+
+  GTK_WIDGET_GET_CLASS (widget)->root (widget);
+}
+
+static void
+gtk_widget_unroot (GtkWidget *widget)
+{
+  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+  /* roots are rooted by default and cannot be unrooted */
+  if (GTK_IS_ROOT (widget))
+    return;
+
+  g_assert (priv->root);
+  g_assert (!priv->realized);
+
+  GTK_WIDGET_GET_CLASS (widget)->unroot (widget);
+
+  priv->root = NULL;
+}
+
 /**
  * gtk_widget_unparent:
  * @widget: a #GtkWidget
@@ -3046,6 +3101,9 @@ gtk_widget_unparent (GtkWidget *widget)
   if (_gtk_widget_get_realized (widget))
     gtk_widget_unrealize (widget);
 
+  if (priv->root)
+    gtk_widget_unroot (widget);
+
   /* If we are unanchoring the child, we save around the toplevel
    * to emit hierarchy changed
    */
@@ -3103,10 +3161,9 @@ gtk_widget_unparent (GtkWidget *widget)
     gtk_list_list_model_item_removed (old_parent->priv->children_observer, old_prev_sibling);
 
   if (toplevel)
-    {
-      _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
-      g_object_unref (toplevel);
-    }
+    _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
+
+  g_clear_object (&toplevel);
 
   /* Now that the parent pointer is nullified and the hierarchy-changed
    * already passed, go ahead and unset the parent window, if we are unparenting
@@ -6591,7 +6648,11 @@ gtk_widget_reposition_after (GtkWidget *widget,
     }
 
   if (priv->parent->priv->anchored && prev_parent == NULL)
-    _gtk_widget_propagate_hierarchy_changed (widget, NULL);
+    {
+      _gtk_widget_propagate_hierarchy_changed (widget, NULL);
+    }
+  if (parent->priv->root && priv->root == NULL)
+    gtk_widget_root (widget);
 
   if (prev_parent == NULL)
     g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_PARENT]);
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 9b89f70246..7afc676351 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -152,6 +152,9 @@ struct _GtkWidget
  *   widget is destroyed, which means that gtk_widget_unrealize() has
  *   been called or the widget has been unmapped (that is, it is going
  *   to be hidden).
+ * @root: Called when the widget gets added to a #GtkRoot widget.
+ * @unroot: Called when the widget is about to be removed from its
+ *   #GtkRoot widget.
  * @size_allocate: Signal emitted to get the widget allocation.
  * @state_flags_changed: Signal emitted when the widget state changes,
  *   see gtk_widget_get_state_flags().
@@ -247,6 +250,8 @@ struct _GtkWidgetClass
   void (* unmap)               (GtkWidget        *widget);
   void (* realize)             (GtkWidget        *widget);
   void (* unrealize)           (GtkWidget        *widget);
+  void (* root)                (GtkWidget        *widget);
+  void (* unroot)              (GtkWidget        *widget);
   void (* size_allocate)       (GtkWidget           *widget,
                                 int                  width,
                                 int                  height,
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index cdfe98b9be..acc8eca031 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -124,6 +124,11 @@ struct _GtkWidgetPrivate
    */
   gchar *name;
 
+  /* The root this widget belongs to or %NULL if widget is not
+   * rooted or is a #GtkRoot itself.
+   */
+  GtkRoot *root;
+
   /* The list of attached windows to this widget.
    * We keep a list in order to call reset_style to all of them,
    * recursively.


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