bug 1301194 be more careful to only invalidate style context when state changes r?stransky draft
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 08 Sep 2016 10:12:55 +1200
changeset 411294 2ed5d24007c9995a0e3dc5e8cffe4be1ff415efb
parent 410870 91c2b9d5c1354ca79e5b174591dbb03b32b15bbf
child 411295 53da5c41e263c08d5abe52be8cf1002f5f47f507
push id28878
push userktomlinson@mozilla.com
push dateWed, 07 Sep 2016 22:16:10 +0000
reviewersstransky
bugs1301194
milestone51.0a1
bug 1301194 be more careful to only invalidate style context when state changes r?stransky 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) {