Bug 1277818 - exports CreateCSSNode() and divides pre/post 3.20 styles construction, r=karlt
authorMartin Stransky <stransky@redhat.com>
Tue, 07 Jun 2016 02:49:00 +0200
changeset 300902 da10d713f676de4f10c3195564a8b48578108203
parent 300901 afd3d8815462223c07690301f03f5b22e61bd400
child 300903 48b1777f5fe3b70d2c328da74c3b4986b8308e1e
push id19599
push usercbook@mozilla.com
push dateWed, 08 Jun 2016 10:16:21 +0000
treeherderfx-team@81f4cc3f6f4c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1277818
milestone50.0a1
Bug 1277818 - exports CreateCSSNode() and divides pre/post 3.20 styles construction, r=karlt
widget/gtk/WidgetStyleCache.cpp
widget/gtk/WidgetStyleCache.h
--- a/widget/gtk/WidgetStyleCache.cpp
+++ b/widget/gtk/WidgetStyleCache.cpp
@@ -17,17 +17,17 @@
 static GtkWidget* sWidgetStorage[MOZ_GTK_WIDGET_NODE_COUNT];
 static GtkStyleContext* sStyleStorage[MOZ_GTK_WIDGET_NODE_COUNT];
 
 static bool sStyleContextNeedsRestore;
 #ifdef DEBUG
 static GtkStyleContext* sCurrentStyleContext;
 #endif
 static GtkStyleContext*
-GetStyleInternal(WidgetNodeType aNodeType);
+GetCssNodeStyleInternal(WidgetNodeType aNodeType);
 
 static GtkWidget*
 CreateWindowWidget()
 {
   GtkWidget *widget = gtk_window_new(GTK_WINDOW_POPUP);
   gtk_widget_realize(widget);
   gtk_widget_set_name(widget, "MozillaGtkWidget");
   return widget;
@@ -145,146 +145,146 @@ GetWidget(WidgetNodeType aWidgetType)
   GtkWidget* widget = sWidgetStorage[aWidgetType];
   if (!widget) {
     widget = CreateWidget(aWidgetType);
     sWidgetStorage[aWidgetType] = widget;
   }
   return widget;
 }
 
-static GtkStyleContext*
-CreateCSSNode(const char* aName, GtkStyleContext *aParentStyle)
+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 =
-    gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle));
+  GtkWidgetPath* path = aParentStyle ?
+    gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) :
+    gtk_widget_path_new();
 
-  gtk_widget_path_append_type(path, G_TYPE_NONE);
+  gtk_widget_path_append_type(path, aType);
 
   (*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;
 }
 
 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 style;
+  return CreateCSSNode(aName, GetCssNodeStyleInternal(aParentNodeType));
 }
 
+/* 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 */
-      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_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_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_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);
-
-    case MOZ_GTK_PROGRESSBAR:
-      /* Root CSS node / widget for progress bars */
+      style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK,
+                                 MOZ_GTK_CHECKBUTTON_CONTAINER);
       break;
     case MOZ_GTK_PROGRESS_TROUGH:
       /* Progress bar background (trough) */
-      return GetChildNodeStyle(aNodeType,
-                               MOZ_GTK_PROGRESSBAR,
-                               GTK_STYLE_CLASS_TROUGH,
-                               MOZ_GTK_PROGRESSBAR);
+      style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
+                                 MOZ_GTK_PROGRESSBAR);
+      break;
     case MOZ_GTK_PROGRESS_CHUNK:
-      /* Actual progress bar indicator for Gtk3.20+ only. */
-      return GetChildNodeStyle(MOZ_GTK_PROGRESS_CHUNK,
-                               MOZ_GTK_PROGRESSBAR,
-                               "progress",
-                               MOZ_GTK_PROGRESS_TROUGH);
+      style = CreateChildCSSNode("progress",
+                                 MOZ_GTK_PROGRESS_TROUGH);
+      break;
     default:
-      break;
+      // 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);
+  if (style) {
+    sStyleStorage[aNodeType] = style;
+    return style;
   }
 
   MOZ_ASSERT_UNREACHABLE("missing style context for node type");
   return nullptr;
 }
 
+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;
+}
+
+/* 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);
+    default:
+      GtkWidget* widget = GetWidget(aNodeType);
+      MOZ_ASSERT(widget);
+      return gtk_widget_get_style_context(widget);
+  }
+}
+
 void
 ResetWidgetCache(void)
 {
   MOZ_ASSERT(!sStyleContextNeedsRestore);
 #ifdef DEBUG
   MOZ_ASSERT(!sCurrentStyleContext);
 #endif
 
@@ -302,17 +302,22 @@ ResetWidgetCache(void)
   mozilla::PodArrayZero(sWidgetStorage);
 }
 
 GtkStyleContext*
 ClaimStyleContext(WidgetNodeType aNodeType, GtkTextDirection aDirection,
                   GtkStateFlags aStateFlags, StyleFlags aFlags)
 {
   MOZ_ASSERT(!sStyleContextNeedsRestore);
-  GtkStyleContext* style = GetStyleInternal(aNodeType);
+  GtkStyleContext* style;
+  if (gtk_check_version(3, 20, 0) != nullptr) {
+    style = GetWidgetStyleInternal(aNodeType);
+  } else {
+    style = GetCssNodeStyleInternal(aNodeType);
+  }
 #ifdef DEBUG
   MOZ_ASSERT(!sCurrentStyleContext);
   sCurrentStyleContext = style;
 #endif
   GtkStateFlags oldState = gtk_style_context_get_state(style);
   GtkTextDirection oldDirection = gtk_style_context_get_direction(style);
   if (oldState != aStateFlags || oldDirection != aDirection) {
     // From GTK 3.8, set_state() will overwrite the direction, so set
--- a/widget/gtk/WidgetStyleCache.h
+++ b/widget/gtk/WidgetStyleCache.h
@@ -16,16 +16,22 @@ typedef unsigned StyleFlags;
 enum : StyleFlags {
   NO_STYLE_FLAGS,
   WHATEVER_MIGHT_BE_NEEDED = 1U << 0,
 };
 
 GtkWidget*
 GetWidget(WidgetNodeType aNodeType);
 
+// 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,
                   GtkTextDirection aDirection = GTK_TEXT_DIR_LTR,
                   GtkStateFlags aStateFlags = GTK_STATE_FLAG_NORMAL,
                   StyleFlags aFlags = NO_STYLE_FLAGS);
 void
 ReleaseStyleContext(GtkStyleContext* style);