+ (*sGtkWidgetPathIterSetObjectName)(path, -1, aName);
+
+@@ -130,95 +356,168 @@ CreateCSSNode(const char* aName, GtkStyl
+ }
+
+ static GtkStyleContext*
+-GetChildNodeStyle(WidgetNodeType aStyleType,
+- WidgetNodeType aWidgetType,
+- const gchar* aStyleClass,
+- WidgetNodeType aParentNodeType)
++CreateChildCSSNode(const char* aName, WidgetNodeType aParentNodeType)
+ {
+- GtkStyleContext* style;
+-
+- if (gtk_check_version(3, 20, 0) != nullptr) {
+- style = gtk_widget_get_style_context(sWidgetStorage[aWidgetType]);
+-
+- gtk_style_context_save(style);
+- MOZ_ASSERT(!sStyleContextNeedsRestore);
+- sStyleContextNeedsRestore = true;
+-
+- gtk_style_context_add_class(style, aStyleClass);
+- }
+- else {
+- style = sStyleStorage[aStyleType];
+- if (!style) {
+- style = CreateCSSNode(aStyleClass, GetStyleInternal(aParentNodeType));
+- MOZ_ASSERT(!sStyleContextNeedsRestore);
+- sStyleStorage[aStyleType] = style;
+- }
+- }
++ return CreateCSSNode(aName, GetCssNodeStyleInternal(aParentNodeType));
++}
+
++static GtkStyleContext*
++GetWidgetStyleWithClass(WidgetNodeType aWidgetType, const gchar* aStyleClass)
++{
++ GtkStyleContext* style = gtk_widget_get_style_context(GetWidget(aWidgetType));
++ gtk_style_context_save(style);
++ MOZ_ASSERT(!sStyleContextNeedsRestore);
++ sStyleContextNeedsRestore = true;
++ gtk_style_context_add_class(style, aStyleClass);
+ return style;
+ }
+
++/* GetCssNodeStyleInternal is used by Gtk >= 3.20 */
+ static GtkStyleContext*
+-GetStyleInternal(WidgetNodeType aNodeType)
++GetCssNodeStyleInternal(WidgetNodeType aNodeType)
+ {
++ GtkStyleContext* style = sStyleStorage[aNodeType];
++ if (style)
++ return style;
++
+ switch (aNodeType) {
+- case MOZ_GTK_SCROLLBAR_HORIZONTAL:
+- /* Root CSS node / widget for scrollbars */
++ case MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL:
++ style = CreateChildCSSNode("contents",
++ MOZ_GTK_SCROLLBAR_HORIZONTAL);
+ break;
+ case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_SCROLLBAR_HORIZONTAL,
+- GTK_STYLE_CLASS_TROUGH,
+- MOZ_GTK_SCROLLBAR_HORIZONTAL);
+-
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
++ MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL);
++ break;
+ case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_SCROLLBAR_HORIZONTAL,
+- GTK_STYLE_CLASS_SLIDER,
+- MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL);
+-
+- case MOZ_GTK_SCROLLBAR_VERTICAL:
+- /* Root CSS node / widget for scrollbars */
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER,
++ MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL);
++ break;
++ case MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL:
++ style = CreateChildCSSNode("contents",
++ MOZ_GTK_SCROLLBAR_VERTICAL);
+ break;
+ case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_SCROLLBAR_VERTICAL,
+- GTK_STYLE_CLASS_TROUGH,
+- MOZ_GTK_SCROLLBAR_VERTICAL);
+-
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
++ MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL);
++ break;
+ case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_SCROLLBAR_VERTICAL,
+- GTK_STYLE_CLASS_SLIDER,
+- MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL);
+-
+- case MOZ_GTK_RADIOBUTTON_CONTAINER:
+- /* Root CSS node / widget for checkboxes */
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER,
++ MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL);
+ break;
+ case MOZ_GTK_RADIOBUTTON:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_RADIOBUTTON_CONTAINER,
+- GTK_STYLE_CLASS_RADIO,
+- MOZ_GTK_RADIOBUTTON_CONTAINER);
+- case MOZ_GTK_CHECKBUTTON_CONTAINER:
+- /* Root CSS node / widget for radiobuttons */
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_RADIO,
++ MOZ_GTK_RADIOBUTTON_CONTAINER);
+ break;
+ case MOZ_GTK_CHECKBUTTON:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_CHECKBUTTON_CONTAINER,
+- GTK_STYLE_CLASS_CHECK,
+- MOZ_GTK_CHECKBUTTON_CONTAINER);
+- default:
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK,
++ MOZ_GTK_CHECKBUTTON_CONTAINER);
++ break;
++ case MOZ_GTK_PROGRESS_TROUGH:
++ /* Progress bar background (trough) */
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
++ MOZ_GTK_PROGRESSBAR);
++ break;
++ case MOZ_GTK_PROGRESS_CHUNK:
++ style = CreateChildCSSNode("progress",
++ MOZ_GTK_PROGRESS_TROUGH);
+ break;
++ case MOZ_GTK_TOOLTIP:
++ // We create this from the path because GtkTooltipWindow is not public.
++ style = CreateCSSNode("tooltip", nullptr, GTK_TYPE_TOOLTIP);
++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND);
++ break;
++ case MOZ_GTK_GRIPPER:
++ // TODO - create from CSS node
++ return GetWidgetStyleWithClass(MOZ_GTK_GRIPPER,
++ GTK_STYLE_CLASS_GRIP);
++ case MOZ_GTK_INFO_BAR:
++ // TODO - create from CSS node
++ return GetWidgetStyleWithClass(MOZ_GTK_INFO_BAR,
++ GTK_STYLE_CLASS_INFO);
++ case MOZ_GTK_SPINBUTTON_ENTRY:
++ // TODO - create from CSS node
++ return GetWidgetStyleWithClass(MOZ_GTK_SPINBUTTON,
++ GTK_STYLE_CLASS_ENTRY);
++ case MOZ_GTK_SCROLLED_WINDOW:
++ // TODO - create from CSS node
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLED_WINDOW,
++ GTK_STYLE_CLASS_FRAME);
++ case MOZ_GTK_TEXT_VIEW:
++ // TODO - create from CSS node
++ return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW,
++ GTK_STYLE_CLASS_VIEW);
++ default:
++ // TODO - create style from style path
++ GtkWidget* widget = GetWidget(aNodeType);
++ return gtk_widget_get_style_context(widget);
+ }
+
+- GtkWidget* widget = GetWidget(aNodeType);
+- if (widget) {
+- return gtk_widget_get_style_context(widget);
+- }
++ MOZ_ASSERT(style, "missing style context for node type");
++ sStyleStorage[aNodeType] = style;
++ return style;
++}
+
+- MOZ_ASSERT_UNREACHABLE("missing style context for node type");
+- return nullptr;
++/* GetWidgetStyleInternal is used by Gtk < 3.20 */
++static GtkStyleContext*
++GetWidgetStyleInternal(WidgetNodeType aNodeType)
++{
++ switch (aNodeType) {
++ case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL:
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_HORIZONTAL,
++ GTK_STYLE_CLASS_TROUGH);
++ case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_HORIZONTAL,
++ GTK_STYLE_CLASS_SLIDER);
++ case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL:
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_VERTICAL,
++ GTK_STYLE_CLASS_TROUGH);
++ case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_VERTICAL,
++ GTK_STYLE_CLASS_SLIDER);
++ case MOZ_GTK_RADIOBUTTON:
++ return GetWidgetStyleWithClass(MOZ_GTK_RADIOBUTTON_CONTAINER,
++ GTK_STYLE_CLASS_RADIO);
++ case MOZ_GTK_CHECKBUTTON:
++ return GetWidgetStyleWithClass(MOZ_GTK_CHECKBUTTON_CONTAINER,
++ GTK_STYLE_CLASS_CHECK);
++ case MOZ_GTK_PROGRESS_TROUGH:
++ return GetWidgetStyleWithClass(MOZ_GTK_PROGRESSBAR,
++ GTK_STYLE_CLASS_TROUGH);
++ case MOZ_GTK_TOOLTIP: {
++ GtkStyleContext* style = sStyleStorage[aNodeType];
++ if (style)
++ return style;
++
++ // The tooltip style class is added first in CreateTooltipWidget() so
++ // that gtk_widget_path_append_for_widget() in CreateStyleForWidget()
++ // will find it.
++ GtkWidget* tooltipWindow = CreateTooltipWidget();
++ style = CreateStyleForWidget(tooltipWindow, nullptr);
++ gtk_widget_destroy(tooltipWindow); // Release GtkWindow self-reference.
++ sStyleStorage[aNodeType] = style;
++ return style;
++ }
++ case MOZ_GTK_GRIPPER:
++ return GetWidgetStyleWithClass(MOZ_GTK_GRIPPER,
++ GTK_STYLE_CLASS_GRIP);
++ case MOZ_GTK_INFO_BAR:
++ return GetWidgetStyleWithClass(MOZ_GTK_INFO_BAR,
++ GTK_STYLE_CLASS_INFO);
++ case MOZ_GTK_SPINBUTTON_ENTRY:
++ return GetWidgetStyleWithClass(MOZ_GTK_SPINBUTTON,
++ GTK_STYLE_CLASS_ENTRY);
++ case MOZ_GTK_SCROLLED_WINDOW:
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLED_WINDOW,
++ GTK_STYLE_CLASS_FRAME);
++ case MOZ_GTK_TEXT_VIEW:
++ return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW,
++ GTK_STYLE_CLASS_VIEW);
++ default:
++ GtkWidget* widget = GetWidget(aNodeType);
++ MOZ_ASSERT(widget);
++ return gtk_widget_get_style_context(widget);
++ }
+ }
+
+ void
+@@ -245,13 +544,39 @@ ResetWidgetCache(void)
+
+ GtkStyleContext*
+ ClaimStyleContext(WidgetNodeType aNodeType, GtkTextDirection aDirection,
+- StyleFlags aFlags)
++ GtkStateFlags aStateFlags, StyleFlags aFlags)
+ {
+- GtkStyleContext* style = GetStyleInternal(aNodeType);
++ MOZ_ASSERT(!sStyleContextNeedsRestore);
++ GtkStyleContext* style;
++ if (gtk_check_version(3, 20, 0) != nullptr) {
++ style = GetWidgetStyleInternal(aNodeType);
++ } else {
++ style = GetCssNodeStyleInternal(aNodeType);
++ }
+ #ifdef DEBUG
+ MOZ_ASSERT(!sCurrentStyleContext);
+ sCurrentStyleContext = style;