Bug 1227327 - Invalidate table parts and MathML frames when background-position changes on them. r?dbaron draft
authorMarkus Stange <mstange@themasta.com>
Thu, 28 Apr 2016 13:01:22 -0400
changeset 362640 b70ed0e4686941b492da5f9f205d5e0243287d67
parent 358327 77cead2cd20300623eea2416bc9bce4d5021df09
child 362641 2a7fa025fd406c35dcdb2575cad262f45de0bb8f
child 362973 2e04882a2b3fc5dd57db642635224763b3f454d3
child 363446 2c625b10bdd5718c7393b366d0d447a416ccccdd
push id17003
push usermstange@themasta.com
push dateMon, 02 May 2016 20:51:40 +0000
reviewersdbaron
bugs1227327
milestone49.0a1
Bug 1227327 - Invalidate table parts and MathML frames when background-position changes on them. r?dbaron Theoretically we should do the same for nsTreeBodyFrame, but that frame type is harder to detect and I'm not sure it's worth adding code to support updating background-position on XUL trees. MozReview-Commit-ID: 8HPT53MX6bO
layout/base/RestyleManager.cpp
layout/base/nsChangeHint.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -881,16 +881,29 @@ RestyleManager::ProcessRestyledFrames(ns
         // backgrounds (and those of table parts inside of it) are
         // painted as part of the table's nsDisplayTableBorderBackground
         // display item, or part of its own display item.  That requires
         // invalidation, so change UpdateOpacityLayer to RepaintFrame.
         hint &= ~nsChangeHint_UpdateOpacityLayer;
         hint |= nsChangeHint_RepaintFrame;
       }
 
+      if (hint & nsChangeHint_UpdateBackgroundPosition) {
+        // For most frame types, DLBI can detect background position changes,
+        // so we only need to schedule a paint.
+        hint |= nsChangeHint_SchedulePaint;
+        if (frame->IsFrameOfType(nsIFrame::eTablePart) ||
+            frame->IsFrameOfType(nsIFrame::eMathML)) {
+          // Table parts and MathML frames don't build display items for their
+          // backgrounds, so DLBI can't detect background-position changes for
+          // these frames. Repaint the whole frame.
+          hint |= nsChangeHint_RepaintFrame;
+        }
+      }
+
       if (hint & (nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView |
                   nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateTransformLayer |
                   nsChangeHint_ChildrenOnlyTransform | nsChangeHint_SchedulePaint)) {
         ApplyRenderingChangeToTree(mPresContext, frame, hint);
       }
       if ((hint & nsChangeHint_RecomputePosition) && !didReflowThisFrame) {
         ActiveLayerTracker::NotifyOffsetRestyle(frame);
         // It is possible for this to fall back to a reflow
--- a/layout/base/nsChangeHint.h
+++ b/layout/base/nsChangeHint.h
@@ -189,16 +189,25 @@ enum nsChangeHint {
    *
    * Used as extra data for handling UpdateOpacityLayer hints.
    *
    * Note that we do not send this hint if the non-1 value was 0.99 or
    * greater, since in that case we send a RepaintFrame hint instead.
    */
   nsChangeHint_UpdateUsesOpacity = 1 << 25,
 
+  /**
+   * Indicates that the 'background-position' property changed.
+   * Regular frames can invalidate these changes using DLBI, but
+   * for some frame types we need to repaint the whole frame because
+   * the frame does not build individual background image display items
+   * for each background layer.
+   */
+  nsChangeHint_UpdateBackgroundPosition = 1 << 26,
+
   // IMPORTANT NOTE: When adding new hints, consider whether you need to
   // add them to NS_HintsNotHandledForDescendantsIn() below.  Please also
   // add them to RestyleManager::ChangeHintToString.
 };
 
 // Redefine these operators to return nothing. This will catch any use
 // of these operators on hints. We should not be using these operators
 // on nsChangeHints
@@ -298,33 +307,35 @@ inline nsChangeHint operator^=(nsChangeH
           nsChangeHint_ChildrenOnlyTransform | \
           nsChangeHint_RecomputePosition | \
           nsChangeHint_UpdateContainingBlock | \
           nsChangeHint_BorderStyleNoneChange | \
           nsChangeHint_NeedReflow | \
           nsChangeHint_ReflowChangesSizeOrPosition | \
           nsChangeHint_ClearAncestorIntrinsics | \
           nsChangeHint_UpdateComputedBSize | \
-          nsChangeHint_UpdateUsesOpacity)
+          nsChangeHint_UpdateUsesOpacity | \
+          nsChangeHint_UpdateBackgroundPosition)
 
 inline nsChangeHint NS_HintsNotHandledForDescendantsIn(nsChangeHint aChangeHint) {
   nsChangeHint result = nsChangeHint(aChangeHint & (
     nsChangeHint_UpdateTransformLayer |
     nsChangeHint_UpdateEffects |
     nsChangeHint_InvalidateRenderingObservers |
     nsChangeHint_UpdateOpacityLayer |
     nsChangeHint_UpdateOverflow |
     nsChangeHint_UpdatePostTransformOverflow |
     nsChangeHint_UpdateParentOverflow |
     nsChangeHint_ChildrenOnlyTransform |
     nsChangeHint_RecomputePosition |
     nsChangeHint_UpdateContainingBlock |
     nsChangeHint_BorderStyleNoneChange |
     nsChangeHint_UpdateComputedBSize |
-    nsChangeHint_UpdateUsesOpacity));
+    nsChangeHint_UpdateUsesOpacity | \
+    nsChangeHint_UpdateBackgroundPosition));
 
   if (!NS_IsHintSubset(nsChangeHint_NeedDirtyReflow, aChangeHint)) {
     if (NS_IsHintSubset(nsChangeHint_NeedReflow, aChangeHint)) {
       // If NeedDirtyReflow is *not* set, then NeedReflow is a
       // non-inherited hint.
       NS_UpdateHint(result, nsChangeHint_NeedReflow);
     }
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2633,17 +2633,17 @@ nsStyleImageLayers::Layer::CalcDifferenc
              mSize != aOther.mSize ||
              mImage != aOther.mImage ||
              mMaskMode != aOther.mMaskMode ||
              mComposite != aOther.mComposite) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
   if (mPosition != aOther.mPosition) {
-    hint |= nsChangeHint_SchedulePaint;
+    hint |= nsChangeHint_UpdateBackgroundPosition;
   }
 
   return hint;
 }
 
 // --------------------
 // nsStyleBackground
 //
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -796,17 +796,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz);
   }
   void Destroy(nsPresContext* aContext);
 
   nsChangeHint CalcDifference(const nsStyleBackground& aOther) const;
   static nsChangeHint MaxDifference() {
      return nsChangeHint_UpdateEffects |
            nsChangeHint_RepaintFrame |
-           nsChangeHint_SchedulePaint |
+           nsChangeHint_UpdateBackgroundPosition |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
     // handled for descendants at all.
     return nsChangeHint(0);
   }