Propagate rooting and unrooting widgets to layout managers

Layout managers may need to get access to data attached to the root of a
scene graph.
This commit is contained in:
Emmanuele Bassi 2019-06-10 14:43:14 +01:00
parent e07098da03
commit e7b2c530c5
4 changed files with 61 additions and 0 deletions

View File

@ -91,6 +91,7 @@
typedef struct {
GtkWidget *widget;
GtkRoot *root;
/* HashTable<Widget, LayoutChild> */
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);
}
}
/**

View File

@ -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];
};

View File

@ -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

View File

@ -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);