diff --git a/gtk/gtklayoutmanager.c b/gtk/gtklayoutmanager.c index c41a604b99..1aa7724d49 100644 --- a/gtk/gtklayoutmanager.c +++ b/gtk/gtklayoutmanager.c @@ -91,6 +91,7 @@ typedef struct { GtkWidget *widget; + GtkRoot *root; /* HashTable */ GHashTable *layout_children; @@ -98,6 +99,16 @@ typedef struct { G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkLayoutManager, gtk_layout_manager, G_TYPE_OBJECT) +static void +gtk_layout_manager_real_root (GtkLayoutManager *manager) +{ +} + +static void +gtk_layout_manager_real_unroot (GtkLayoutManager *manager) +{ +} + static GtkSizeRequestMode gtk_layout_manager_real_get_request_mode (GtkLayoutManager *manager, GtkWidget *widget) @@ -195,6 +206,8 @@ gtk_layout_manager_class_init (GtkLayoutManagerClass *klass) klass->measure = gtk_layout_manager_real_measure; klass->allocate = gtk_layout_manager_real_allocate; klass->create_layout_child = gtk_layout_manager_real_create_layout_child; + klass->root = gtk_layout_manager_real_root; + klass->unroot = gtk_layout_manager_real_unroot; } static void @@ -226,6 +239,38 @@ gtk_layout_manager_set_widget (GtkLayoutManager *layout_manager, } priv->widget = widget; + + if (widget != NULL) + gtk_layout_manager_set_root (layout_manager, gtk_widget_get_root (widget)); +} + +/*< private > + * gtk_layout_manager_set_root: + * @layout_manager: a #GtkLayoutManager + * @root: (nullable): a #GtkWidget implementing #GtkRoot + * + * Sets a back pointer from @root to @layout_manager. + * + * This function is called by #GtkWidget when getting rooted and unrooted, + * and will call #GtkLayoutManagerClass.root() or #GtkLayoutManagerClass.unroot() + * depending on whether @root is a #GtkWidget or %NULL. + */ +void +gtk_layout_manager_set_root (GtkLayoutManager *layout_manager, + GtkRoot *root) +{ + GtkLayoutManagerPrivate *priv = gtk_layout_manager_get_instance_private (layout_manager); + GtkRoot *old_root = priv->root; + + priv->root = root; + + if (old_root != root) + { + if (priv->root != NULL) + GTK_LAYOUT_MANAGER_GET_CLASS (layout_manager)->root (layout_manager); + else + GTK_LAYOUT_MANAGER_GET_CLASS (layout_manager)->unroot (layout_manager); + } } /** diff --git a/gtk/gtklayoutmanager.h b/gtk/gtklayoutmanager.h index 06659ee70e..3066dc5660 100644 --- a/gtk/gtklayoutmanager.h +++ b/gtk/gtklayoutmanager.h @@ -42,6 +42,10 @@ G_DECLARE_DERIVABLE_TYPE (GtkLayoutManager, gtk_layout_manager, GTK, LAYOUT_MANA * @layout_child_type: the type of #GtkLayoutChild used by this layout manager * @create_layout_child: a virtual function, used to create a #GtkLayoutChild * meta object for the layout properties + * @root: a virtual function, called when the widget using the layout + * manager is attached to a #GtkRoot + * @unroot: a virtual function, called when the widget using the layout + * manager is detached from a #GtkRoot * * The `GtkLayoutManagerClass` structure contains only private data, and * should only be accessed through the provided API, or when subclassing @@ -77,6 +81,9 @@ struct _GtkLayoutManagerClass GtkWidget *widget, GtkWidget *for_child); + void (* root) (GtkLayoutManager *manager); + void (* unroot) (GtkLayoutManager *manager); + /*< private >*/ gpointer _padding[16]; }; diff --git a/gtk/gtklayoutmanagerprivate.h b/gtk/gtklayoutmanagerprivate.h index 14eb30e161..5cdbf2e440 100644 --- a/gtk/gtklayoutmanagerprivate.h +++ b/gtk/gtklayoutmanagerprivate.h @@ -10,4 +10,7 @@ void gtk_layout_manager_set_widget (GtkLayoutManager *manager, void gtk_layout_manager_remove_layout_child (GtkLayoutManager *manager, GtkWidget *widget); +void gtk_layout_manager_set_root (GtkLayoutManager *manager, + GtkRoot *root); + G_END_DECLS diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 0c653a90f8..6713213940 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -2893,6 +2893,9 @@ gtk_widget_root (GtkWidget *widget) _gtk_widget_update_parent_muxer (widget); + if (priv->layout_manager) + gtk_layout_manager_set_root (priv->layout_manager, priv->root); + GTK_WIDGET_GET_CLASS (widget)->root (widget); if (!GTK_IS_ROOT (widget)) @@ -2920,6 +2923,9 @@ gtk_widget_unroot (GtkWidget *widget) if (priv->context) gtk_style_context_set_display (priv->context, gdk_display_get_default ()); + if (priv->layout_manager) + gtk_layout_manager_set_root (priv->layout_manager, NULL); + if (g_object_get_qdata (G_OBJECT (widget), quark_pango_context)) g_object_set_qdata (G_OBJECT (widget), quark_pango_context, NULL);