Bug 964885 - Implement stacking context behavior of CSS will-change. r=dbaron
authorBenoit Girard <b56girard@gmail.com>
Wed, 05 Feb 2014 23:50:22 -0500
changeset 169601 8f1c76b3a93103432cc567546814928db4090817
parent 169600 cc7d6d3ebc7effb3f9313e75b1a3e245ce2bc56f
child 169602 ad1d8b7022f7c4e0d7850ac70f9ddfa49132d523
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersdbaron
bugs964885
milestone30.0a1
Bug 964885 - Implement stacking context behavior of CSS will-change. r=dbaron
layout/generic/nsFrame.cpp
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleConsts.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2175,16 +2175,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
     || child->IsTransformed()
     || disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL
     || nsSVGIntegrationUtils::UsingEffectsForFrame(child);
 
   bool isPositioned = disp->IsPositioned(child);
   bool isStackingContext =
     (isPositioned && (disp->mPosition == NS_STYLE_POSITION_STICKY ||
                       pos->mZIndex.GetUnit() == eStyleUnit_Integer)) ||
+     (disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) ||
      isVisuallyAtomic || (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT);
 
   if (isVisuallyAtomic || isPositioned || (!isSVG && disp->IsFloating(child)) ||
       ((disp->mClipFlags & NS_STYLE_CLIP_RECT) &&
        IsSVGContentWithCSSClip(child)) ||
       (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
     // If you change this, also change IsPseudoStackingContextFromStyle()
     pseudoStackingContext = true;
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -2384,17 +2384,18 @@ CSS_PROP_POSITION(
     VARIANT_HKLP | VARIANT_CALC,
     kWidthKTable,
     offsetof(nsStylePosition, mMinWidth),
     eStyleAnimType_Coord)
 CSS_PROP_DISPLAY(
     mix-blend-mode,
     mix_blend_mode,
     MixBlendMode,
-    CSS_PROPERTY_PARSE_VALUE,
+    CSS_PROPERTY_PARSE_VALUE |
+        CSS_PROPERTY_CREATES_STACKING_CONTEXT,
     "layout.css.mix-blend-mode.enabled",
     VARIANT_HK,
     kBlendModeKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_DISPLAY(
     opacity,
     opacity,
@@ -2754,17 +2755,19 @@ CSS_PROP_VISIBILITY(
     VARIANT_HK,
     kPointerEventsKTable,
     offsetof(nsStyleVisibility, mPointerEvents),
     eStyleAnimType_EnumU8)
 CSS_PROP_DISPLAY(
     position,
     position,
     Position,
-    CSS_PROPERTY_PARSE_VALUE,
+    CSS_PROPERTY_PARSE_VALUE |
+        // For position: sticky
+        CSS_PROPERTY_CREATES_STACKING_CONTEXT,
     "",
     VARIANT_HK,
     kPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_QUOTES(
     quotes,
     quotes,
@@ -2969,17 +2972,18 @@ CSS_PROP_TEXT(
     kTextTransformKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_DISPLAY(
     transform,
     transform,
     Transform,
     CSS_PROPERTY_PARSE_FUNCTION |
-        CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH,
+        CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH |
+        CSS_PROPERTY_CREATES_STACKING_CONTEXT,
     "",
     0,
     nullptr,
     offsetof(nsStyleDisplay, mSpecifiedTransform),
     eStyleAnimType_Custom)
 CSS_PROP_DISPLAY(
     transform-origin,
     transform_origin,
@@ -3003,27 +3007,29 @@ CSS_PROP_DISPLAY(
     0,
     kBackgroundPositionKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_DISPLAY(
     perspective,
     perspective,
     Perspective,
-    CSS_PROPERTY_PARSE_VALUE,
+    CSS_PROPERTY_PARSE_VALUE |
+        CSS_PROPERTY_CREATES_STACKING_CONTEXT,
     "",
     VARIANT_NONE | VARIANT_INHERIT | VARIANT_LENGTH | VARIANT_POSITIVE_DIMENSION,
     nullptr,
     offsetof(nsStyleDisplay, mChildPerspective),
     eStyleAnimType_Coord)
 CSS_PROP_DISPLAY(
     transform-style,
     transform_style,
     TransformStyle,
-    CSS_PROPERTY_PARSE_VALUE,
+    CSS_PROPERTY_PARSE_VALUE |
+        CSS_PROPERTY_CREATES_STACKING_CONTEXT,
     "",
     VARIANT_HK,
     kTransformStyleKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_DISPLAY(
     backface-visibility,
     backface_visibility,
@@ -3284,17 +3290,18 @@ CSS_PROP_VISIBILITY(
     VARIANT_HK,
     kWritingModeKTable,
     offsetof(nsStyleVisibility, mWritingMode),
     eStyleAnimType_EnumU8)
 CSS_PROP_POSITION(
     z-index,
     z_index,
     ZIndex,
-    CSS_PROPERTY_PARSE_VALUE,
+    CSS_PROPERTY_PARSE_VALUE |
+        CSS_PROPERTY_CREATES_STACKING_CONTEXT,
     "",
     VARIANT_AHI,
     nullptr,
     offsetof(nsStylePosition, mZIndex),
     eStyleAnimType_Coord)
 CSS_PROP_XUL(
     -moz-box-align,
     box_align,
@@ -3432,17 +3439,18 @@ CSS_PROP_FONT(
     eStyleAnimType_None)
 #endif // !defined(CSS_PROP_LIST_EXCLUDE_INTERNAL)
 #endif // !defined(CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND)
 
 CSS_PROP_SVGRESET(
     clip-path,
     clip_path,
     ClipPath,
-    CSS_PROPERTY_PARSE_VALUE,
+    CSS_PROPERTY_PARSE_VALUE |
+        CSS_PROPERTY_CREATES_STACKING_CONTEXT,
     "",
     VARIANT_HUO,
     nullptr,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_SVG(
     clip-rule,
     clip_rule,
@@ -3512,17 +3520,18 @@ CSS_PROP_SVG(
     VARIANT_HK,
     kFillRuleKTable,
     offsetof(nsStyleSVG, mFillRule),
     eStyleAnimType_EnumU8)
 CSS_PROP_SVGRESET(
     filter,
     filter,
     Filter,
-    CSS_PROPERTY_PARSE_FUNCTION,
+    CSS_PROPERTY_PARSE_FUNCTION |
+        CSS_PROPERTY_CREATES_STACKING_CONTEXT,
     "",
     0,
     nullptr,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_Custom)
 CSS_PROP_SVGRESET(
     flood-color,
     flood_color,
@@ -3598,17 +3607,18 @@ CSS_PROP_SVG(
     VARIANT_HUO,
     nullptr,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_SVGRESET(
     mask,
     mask,
     Mask,
-    CSS_PROPERTY_PARSE_VALUE,
+    CSS_PROPERTY_PARSE_VALUE |
+        CSS_PROPERTY_CREATES_STACKING_CONTEXT,
     "",
     VARIANT_HUO,
     nullptr,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_SVGRESET(
     mask-type,
     mask_type,
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -186,16 +186,19 @@ static_assert((CSS_PROPERTY_PARSE_PROPER
 
 // This property is allowed in an @page rule.
 #define CSS_PROPERTY_APPLIES_TO_PAGE_RULE         (1<<19)
 
 // This property's getComputedStyle implementation requires layout to be
 // flushed.
 #define CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH     (1<<20)
 
+// This property requires a stacking context.
+#define CSS_PROPERTY_CREATES_STACKING_CONTEXT     (1<<21)
+
 /**
  * Types of animatable values.
  */
 enum nsStyleAnimType {
   // requires a custom implementation in
   // nsStyleAnimation::ExtractComputedValue
   eStyleAnimType_Custom,
 
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -5472,26 +5472,34 @@ nsRuleNode::ComputeDisplayData(void* aSt
     display->mWillChange.Clear();
     display->mWillChangeBitField = 0;
     for (const nsCSSValueList* item = willChangeValue->GetListValue();
          item; item = item->mNext)
     {
       if (item->mValue.UnitHasStringValue()) {
         nsAutoString buffer;
         item->mValue.GetStringValue(buffer);
+        display->mWillChange.AppendElement(buffer);
+
         if (buffer.EqualsLiteral("transform")) {
           display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_TRANSFORM;
         }
         if (buffer.EqualsLiteral("opacity")) {
           display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_OPACITY;
         }
         if (buffer.EqualsLiteral("scroll-position")) {
           display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_SCROLL;
         }
-        display->mWillChange.AppendElement(buffer);
+
+        nsCSSProperty prop =
+          nsCSSProps::LookupProperty(buffer, nsCSSProps::eEnabled);
+        if (nsCSSProps::PropHasFlags(prop,
+                                     CSS_PROPERTY_CREATES_STACKING_CONTEXT)) {
+          display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_STACKING_CONTEXT;
+        }
       }
     }
     break;
   }
 
   case eCSSUnit_Inherit:
     display->mWillChange = parentDisplay->mWillChange;
     display->mWillChangeBitField = parentDisplay->mWillChangeBitField;
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -207,19 +207,20 @@ static inline mozilla::css::Side operato
 #define NS_COLOR_MOZ_HYPERLINKTEXT              -4
 #define NS_COLOR_MOZ_VISITEDHYPERLINKTEXT       -5
 #define NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT        -6
 // Only valid as paints in SVG glyphs
 #define NS_COLOR_CONTEXT_FILL                   -7
 #define NS_COLOR_CONTEXT_STROKE                 -8
 
 // See nsStyleDisplay
-#define NS_STYLE_WILL_CHANGE_TRANSFORM          (1<<0)
-#define NS_STYLE_WILL_CHANGE_SCROLL             (1<<1)
-#define NS_STYLE_WILL_CHANGE_OPACITY            (1<<2)
+#define NS_STYLE_WILL_CHANGE_STACKING_CONTEXT   (1<<0)
+#define NS_STYLE_WILL_CHANGE_TRANSFORM          (1<<1)
+#define NS_STYLE_WILL_CHANGE_SCROLL             (1<<2)
+#define NS_STYLE_WILL_CHANGE_OPACITY            (1<<3)
 
 // See nsStyleDisplay
 #define NS_STYLE_ANIMATION_DIRECTION_NORMAL       0
 #define NS_STYLE_ANIMATION_DIRECTION_REVERSE      1
 #define NS_STYLE_ANIMATION_DIRECTION_ALTERNATE    2
 #define NS_STYLE_ANIMATION_DIRECTION_ALTERNATE_REVERSE    3
 
 // See nsStyleDisplay
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2462,17 +2462,23 @@ nsChangeHint nsStyleDisplay::CalcDiffere
     if (mChildPerspective != aOther.mChildPerspective ||
         mTransformStyle != aOther.mTransformStyle)
       NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint);
 
     if (mBackfaceVisibility != aOther.mBackfaceVisibility)
       NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
   }
 
-  if (mWillChangeBitField != aOther.mWillChangeBitField) {
+  uint8_t willChangeBitsChanged =
+    mWillChangeBitField ^ aOther.mWillChangeBitField;
+  if (willChangeBitsChanged & NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) {
+    NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
+  }
+  if (willChangeBitsChanged & ~uint8_t(NS_STYLE_WILL_CHANGE_STACKING_CONTEXT)) {
+    // FIXME (Bug 974125): Don't reconstruct the frame
     NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
   }
 
   // Note:  Our current behavior for handling changes to the
   // transition-duration, transition-delay, and transition-timing-function
   // properties is to do nothing.  In other words, the transition
   // property that matters is what it is when the transition begins, and
   // we don't stop a transition later because the transition property
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1796,20 +1796,22 @@ struct nsStyleDisplay {
   bool mBreakBefore;    // [reset]
   bool mBreakAfter;     // [reset]
   uint8_t mOverflowX;           // [reset] see nsStyleConsts.h
   uint8_t mOverflowY;           // [reset] see nsStyleConsts.h
   uint8_t mResize;              // [reset] see nsStyleConsts.h
   uint8_t mClipFlags;           // [reset] see nsStyleConsts.h
   uint8_t mOrient;              // [reset] see nsStyleConsts.h
   uint8_t mMixBlendMode;        // [reset] see nsStyleConsts.h
-  uint8_t mWillChangeBitField;  // [reset] see nsStyleConsts.h. Stores a bitfield
-                                // representation of the property that
-                                // are frequently queried. This should match
-                                // mWillChange
+  uint8_t mWillChangeBitField;  // [reset] see nsStyleConsts.h. Stores a
+                                // bitfield representation of the properties
+                                // that are frequently queried. This should
+                                // match mWillChange. Also tracks if any of the
+                                // properties in the will-change list require
+                                // a stacking context.
   nsAutoTArray<nsString, 1> mWillChange;
 
   uint8_t mTouchAction;         // [reset] see nsStyleConsts.h
 
   // mSpecifiedTransform is the list of transform functions as
   // specified, or null to indicate there is no transform.  (inherit or
   // initial are replaced by an actual list of transform functions, or
   // null, as appropriate.)