bug 1301194 be more careful to only invalidate style context when state changes r=stransky+263117
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 08 Sep 2016 10:12:55 +1200
changeset 357851 ba1e87c0e0a6fc531a396273050e039fd0eabb2d
parent 357850 f0f15b7c6aa77a0c5750918aa0a1cb3dc82185bc
child 357852 ba9818c399546dbbe0eaaeccc4dbd7615b10d102
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstransky
bugs1301194, 263117
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1301194 be more careful to only invalidate style context when state changes r=stransky+263117 Previously oldState differed from aStateFlags just because it contained direction flags. MozReview-Commit-ID: DuGpHdt9EuX
widget/gtk/WidgetStyleCache.cpp
--- a/widget/gtk/WidgetStyleCache.cpp
+++ b/widget/gtk/WidgetStyleCache.cpp
@@ -4,16 +4,24 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <dlfcn.h>
 #include <gtk/gtk.h>
 #include "WidgetStyleCache.h"
 #include "gtkdrawing.h"
 
+#define STATE_FLAG_DIR_LTR (1U << 7)
+#define STATE_FLAG_DIR_RTL (1U << 8)
+#if GTK_CHECK_VERSION(3,8,0)
+static_assert(GTK_STATE_FLAG_DIR_LTR == STATE_FLAG_DIR_LTR &&
+              GTK_STATE_FLAG_DIR_RTL == STATE_FLAG_DIR_RTL,
+              "incorrect direction state flags");
+#endif
+
 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*
@@ -819,35 +827,59 @@ ClaimStyleContext(WidgetNodeType aNodeTy
     style = GetWidgetStyleInternal(aNodeType);
   } else {
     style = GetCssNodeStyleInternal(aNodeType);
   }
 #ifdef DEBUG
   MOZ_ASSERT(!sCurrentStyleContext);
   sCurrentStyleContext = style;
 #endif
+  bool stateChanged = false;
+  bool stateHasDirection = gtk_get_minor_version() >= 8;
   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
-    // direction after state.
-    gtk_style_context_set_state(style, aStateFlags);
-    gtk_style_context_set_direction(style, aDirection);
-
-    // This invalidate is necessary for unsaved style contexts from GtkWidgets
-    // in pre-3.18 GTK, because automatic invalidation of such contexts
-    // was delayed until a resize event runs.
-    //
-    // https://bugzilla.mozilla.org/show_bug.cgi?id=1272194#c7
-    //
-    // Avoid calling invalidate on saved contexts to avoid performing
-    // build_properties() (in 3.16 stylecontext.c) unnecessarily early.
-    if (!sStyleContextNeedsRestore) {
-      gtk_style_context_invalidate(style);
+  MOZ_ASSERT(!(aStateFlags & (STATE_FLAG_DIR_LTR|STATE_FLAG_DIR_RTL)));
+  unsigned newState = aStateFlags;
+  if (stateHasDirection) {
+    switch (aDirection) {
+      case GTK_TEXT_DIR_LTR:
+        newState |= STATE_FLAG_DIR_LTR;
+        break;
+      case GTK_TEXT_DIR_RTL:
+        newState |= STATE_FLAG_DIR_RTL;
+        break;
+      default:
+        MOZ_FALLTHROUGH_ASSERT("Bad GtkTextDirection");
+      case GTK_TEXT_DIR_NONE:
+        // GtkWidget uses a default direction if neither is explicitly
+        // specified, but here DIR_NONE is interpreted as meaning the
+        // direction is not important, so don't change the direction
+        // unnecessarily.
+        newState |= oldState & (STATE_FLAG_DIR_LTR|STATE_FLAG_DIR_RTL);
     }
+  } else if (aDirection != GTK_TEXT_DIR_NONE) {
+    GtkTextDirection oldDirection = gtk_style_context_get_direction(style);
+    if (aDirection != oldDirection) {
+      gtk_style_context_set_direction(style, aDirection);
+      stateChanged = true;
+    }
+  }
+  if (oldState != newState) {
+    gtk_style_context_set_state(style, static_cast<GtkStateFlags>(newState));
+    stateChanged = true;
+  }
+  // This invalidate is necessary for unsaved style contexts from GtkWidgets
+  // in pre-3.18 GTK, because automatic invalidation of such contexts
+  // was delayed until a resize event runs.
+  //
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=1272194#c7
+  //
+  // Avoid calling invalidate on saved contexts to avoid performing
+  // build_properties() (in 3.16 stylecontext.c) unnecessarily early.
+  if (stateChanged && !sStyleContextNeedsRestore) {
+    gtk_style_context_invalidate(style);
   }
   return style;
 }
 
 void
 ReleaseStyleContext(GtkStyleContext* aStyleContext)
 {
   if (sStyleContextNeedsRestore) {