bug 1315668 CreateStyleForWidget: store classes on context instead of path r?stransky
CreateStyleForWidget() then provides the same behavior with
g_style_context_save() as contexts from widget root style nodes.
MozReview-Commit-ID: 6lRCp3XOoRr
--- a/widget/gtk/WidgetStyleCache.cpp
+++ b/widget/gtk/WidgetStyleCache.cpp
@@ -692,51 +692,73 @@ GetWidget(WidgetNodeType aWidgetType)
sWidgetStorage[aWidgetType] = widget;
}
return widget;
}
GtkStyleContext*
CreateStyleForWidget(GtkWidget* aWidget, GtkStyleContext* aParentStyle)
{
- GtkWidgetPath* path = aParentStyle ?
- gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) :
- gtk_widget_path_new();
+ static auto sGtkWidgetClassGetCSSName =
+ reinterpret_cast<const char* (*)(GtkWidgetClass*)>
+ (dlsym(RTLD_DEFAULT, "gtk_widget_class_get_css_name"));
+
+ GtkWidgetClass *widgetClass = GTK_WIDGET_GET_CLASS(aWidget);
+ const gchar* name = sGtkWidgetClassGetCSSName ?
+ sGtkWidgetClassGetCSSName(widgetClass) : nullptr;
+
+ GtkStyleContext *context =
+ CreateCSSNode(name, aParentStyle, G_TYPE_FROM_CLASS(widgetClass));
- // Work around https://bugzilla.gnome.org/show_bug.cgi?id=767312
- // which exists in GTK+ 3.20.
- gtk_widget_get_style_context(aWidget);
+ // Classes are stored on the style context instead of the path so that any
+ // future gtk_style_context_save() will inherit classes on the head CSS
+ // node, in the same way as happens when called on a style context owned by
+ // a widget.
+ //
+ // Classes can be stored on a GtkCssNodeDeclaration and/or the path.
+ // gtk_style_context_save() reuses the GtkCssNodeDeclaration, and appends a
+ // new object to the path, without copying the classes from the old path
+ // head. The new head picks up classes from the GtkCssNodeDeclaration, but
+ // not the path. GtkWidgets store their classes on the
+ // GtkCssNodeDeclaration, so make sure to add classes there.
+ //
+ // Picking up classes from the style context also means that
+ // https://bugzilla.gnome.org/show_bug.cgi?id=767312, which can stop
+ // gtk_widget_path_append_for_widget() from finding classes in GTK 3.20,
+ // is not a problem.
+ GtkStyleContext* widgetStyle = gtk_widget_get_style_context(aWidget);
+ GList* classes = gtk_style_context_list_classes(widgetStyle);
+ for (GList* link = classes; link; link = link->next) {
+ gtk_style_context_add_class(context, static_cast<gchar*>(link->data));
+ }
+ g_list_free(classes);
- gtk_widget_path_append_for_widget(path, aWidget);
// Release any floating reference on aWidget.
g_object_ref_sink(aWidget);
g_object_unref(aWidget);
- GtkStyleContext *context = gtk_style_context_new();
- gtk_style_context_set_path(context, path);
- gtk_style_context_set_parent(context, aParentStyle);
- gtk_widget_path_unref(path);
-
return context;
}
GtkStyleContext*
CreateCSSNode(const char* aName, GtkStyleContext* aParentStyle, GType aType)
{
static auto sGtkWidgetPathIterSetObjectName =
reinterpret_cast<void (*)(GtkWidgetPath *, gint, const char *)>
(dlsym(RTLD_DEFAULT, "gtk_widget_path_iter_set_object_name"));
GtkWidgetPath* path = aParentStyle ?
gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) :
gtk_widget_path_new();
gtk_widget_path_append_type(path, aType);
- (*sGtkWidgetPathIterSetObjectName)(path, -1, aName);
+ if (sGtkWidgetPathIterSetObjectName) {
+ (*sGtkWidgetPathIterSetObjectName)(path, -1, aName);
+ }
GtkStyleContext *context = gtk_style_context_new();
gtk_style_context_set_path(context, path);
gtk_style_context_set_parent(context, aParentStyle);
gtk_widget_path_unref(path);
return context;
}
--- a/widget/gtk/WidgetStyleCache.h
+++ b/widget/gtk/WidgetStyleCache.h
@@ -23,17 +23,16 @@ GetWidget(WidgetNodeType aNodeType);
/*
* Return a new style context based on aWidget, as a child of aParentStyle.
* If aWidget still has a floating reference, then it is sunk and released.
*/
GtkStyleContext*
CreateStyleForWidget(GtkWidget* aWidget, GtkStyleContext* aParentStyle);
-// CreateCSSNode is implemented for gtk >= 3.20 only.
GtkStyleContext*
CreateCSSNode(const char* aName,
GtkStyleContext* aParentStyle,
GType aType = G_TYPE_NONE);
// Callers must call ReleaseStyleContext() on the returned context.
GtkStyleContext*
ClaimStyleContext(WidgetNodeType aNodeType,
--- a/widget/gtk/mozgtk/mozgtk.c
+++ b/widget/gtk/mozgtk/mozgtk.c
@@ -558,16 +558,17 @@ STUB(gtk_style_context_get_direction)
STUB(gtk_style_context_get_margin)
STUB(gtk_style_context_get_padding)
STUB(gtk_style_context_get_path)
STUB(gtk_style_context_get_property)
STUB(gtk_style_context_get_state)
STUB(gtk_style_context_get_style)
STUB(gtk_style_context_has_class)
STUB(gtk_style_context_invalidate)
+STUB(gtk_style_context_list_classes)
STUB(gtk_style_context_new)
STUB(gtk_style_context_remove_class)
STUB(gtk_style_context_remove_region)
STUB(gtk_style_context_restore)
STUB(gtk_style_context_save)
STUB(gtk_style_context_set_direction)
STUB(gtk_style_context_set_path)
STUB(gtk_style_context_set_parent)