Bug 1237454 - Add VisibilityChange change hint. r?emilio draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Fri, 09 Feb 2018 10:43:10 +0900
changeset 752904 871aceb3fbc9688e3089b467144ac3ad24fd2673
parent 752848 35dfa0882568c06f2d81b6749179815cd4f82886
child 752905 598fb5eda6c8b224826d326da3c99df6051065f9
push id98428
push userbmo:hikezoe@mozilla.com
push dateFri, 09 Feb 2018 10:01:48 +0000
reviewersemilio
bugs1237454
milestone60.0a1
Bug 1237454 - Add VisibilityChange change hint. r?emilio This new change hint doesn't influence layout so that it can be regarded as nsChangeHint_Hints_CanIgnoreIfNotVisible. Note that if visibility changed from collapse or to collapse, we set NS_STYLE_HINT_REFLOW separetely. MozReview-Commit-ID: AirDWeBYVKG
dom/animation/test/mozilla/file_restyles.html
layout/base/RestyleManager.cpp
layout/base/nsChangeHint.h
layout/style/nsStyleStruct.cpp
--- a/dom/animation/test/mozilla/file_restyles.html
+++ b/dom/animation/test/mozilla/file_restyles.html
@@ -653,17 +653,17 @@ waitForAllPaints(() => {
     is(markers.length, 5,
        'Animations running on the main-thread which were in nested scrolled ' +
        'out elements should update restyle soon after the element moved ' +
        'in view by scrolling');
 
     await ensureElementRemoval(grandParent);
   });
 
-  add_task_if_omta_enabled(async function no_restyling_compositor_animations_in_visiblily_hidden_element() {
+  add_task_if_omta_enabled(async function no_restyling_compositor_animations_in_visibility_hidden_element() {
     var div = addDiv(null,
      { style: 'animation: opacity 100s; visibility: hidden' });
     var animation = div.getAnimations()[0];
 
     await animation.ready;
     ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
 
     var markers = await observeStyling(5);
@@ -722,17 +722,17 @@ waitForAllPaints(() => {
     is(markers.length, 1,
        'Animations running on the main-thread which was in scrolled out ' +
        'elements should update restyling soon after the element moved in ' +
        'view by resizing');
 
     await ensureElementRemoval(parentElement);
   });
 
-  add_task(async function no_restyling_main_thread_animations_in_visiblily_hidden_element() {
+  add_task(async function no_restyling_main_thread_animations_in_visibility_hidden_element() {
     var div = addDiv(null,
      { style: 'animation: background-color 100s; visibility: hidden' });
     var animation = div.getAnimations()[0];
 
     await animation.ready;
     var markers = await observeStyling(5);
 
     todo_is(markers.length, 0,
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -433,37 +433,39 @@ RestyleManager::ChangeHintToString(nsCha
     "UpdateSubtreeOverflow", "UpdatePostTransformOverflow",
     "UpdateParentOverflow",
     "ChildrenOnlyTransform", "RecomputePosition", "UpdateContainingBlock",
     "BorderStyleNoneChange", "UpdateTextPath", "SchedulePaint",
     "NeutralChange", "InvalidateRenderingObservers",
     "ReflowChangesSizeOrPosition", "UpdateComputedBSize",
     "UpdateUsesOpacity", "UpdateBackgroundPosition",
     "AddOrRemoveTransform", "CSSOverflowChange",
-    "UpdateWidgetProperties", "UpdateTableCellSpans"
+    "UpdateWidgetProperties", "UpdateTableCellSpans",
+    "VisibilityChange"
   };
-  static_assert(nsChangeHint_AllHints == (1u << ArrayLength(names)) - 1,
+  static_assert(nsChangeHint_AllHints ==
+                  static_cast<uint32_t>((1ull << ArrayLength(names)) - 1),
                 "Name list doesn't match change hints.");
-  uint32_t hint = aHint & ((1u << ArrayLength(names)) - 1);
-  uint32_t rest = aHint & ~((1u << ArrayLength(names)) - 1);
+  uint32_t hint = aHint & static_cast<uint32_t>((1ull << ArrayLength(names)) - 1);
+  uint32_t rest = aHint & ~static_cast<uint32_t>((1ull << ArrayLength(names)) - 1);
   if ((hint & NS_STYLE_HINT_REFLOW) == NS_STYLE_HINT_REFLOW) {
     result.AppendLiteral("NS_STYLE_HINT_REFLOW");
     hint = hint & ~NS_STYLE_HINT_REFLOW;
     any = true;
   } else if ((hint & nsChangeHint_AllReflowHints) == nsChangeHint_AllReflowHints) {
     result.AppendLiteral("nsChangeHint_AllReflowHints");
     hint = hint & ~nsChangeHint_AllReflowHints;
     any = true;
   } else if ((hint & NS_STYLE_HINT_VISUAL) == NS_STYLE_HINT_VISUAL) {
     result.AppendLiteral("NS_STYLE_HINT_VISUAL");
     hint = hint & ~NS_STYLE_HINT_VISUAL;
     any = true;
   }
   for (uint32_t i = 0; i < ArrayLength(names); i++) {
-    if (hint & (1 << i)) {
+    if (hint & (1u << i)) {
       if (any) {
         result.AppendLiteral(" | ");
       }
       result.AppendPrintf("nsChangeHint_%s", names[i]);
       any = true;
     }
   }
   if (rest) {
--- a/layout/base/nsChangeHint.h
+++ b/layout/base/nsChangeHint.h
@@ -240,32 +240,40 @@ enum nsChangeHint : uint32_t {
   nsChangeHint_UpdateWidgetProperties = 1 << 29,
 
   /**
    *  Indicates that there has been a colspan or rowspan attribute change
    *  on the cells of a table.
    */
   nsChangeHint_UpdateTableCellSpans = 1 << 30,
 
+  /**
+   * Indicates that the visiblity property changed.
+   * This change hint is used for skip restyling for animations on
+   * visibility:hidden elements in the case where the elements have no visible
+   * descendants.
+   */
+  nsChangeHint_VisibilityChange = 1u << 31,
+
   // IMPORTANT NOTE: When adding a new hint, you will need to add it to
   // one of:
   //
   //   * nsChangeHint_Hints_NeverHandledForDescendants
   //   * nsChangeHint_Hints_AlwaysHandledForDescendants
   //   * nsChangeHint_Hints_SometimesHandledForDescendants
   //
   // and you also may need to handle it in NS_HintsNotHandledForDescendantsIn.
   //
   // Please also add it to RestyleManager::ChangeHintToString and
   // modify nsChangeHint_AllHints below accordingly.
 
   /**
    * Dummy hint value for all hints. It exists for compile time check.
    */
-  nsChangeHint_AllHints = (1u << 31) - 1,
+  nsChangeHint_AllHints = uint32_t((1ull << 32) - 1),
 };
 
 // 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
 inline void operator<(nsChangeHint s1, nsChangeHint s2) {}
 inline void operator>(nsChangeHint s1, nsChangeHint s2) {}
 inline void operator!=(nsChangeHint s1, nsChangeHint s2) {}
@@ -337,17 +345,18 @@ inline nsChangeHint operator^=(nsChangeH
   nsChangeHint_NeedDirtyReflow |                           \
   nsChangeHint_NeutralChange |                             \
   nsChangeHint_ReconstructFrame |                          \
   nsChangeHint_RepaintFrame |                              \
   nsChangeHint_SchedulePaint |                             \
   nsChangeHint_SyncFrameView |                             \
   nsChangeHint_UpdateCursor |                              \
   nsChangeHint_UpdateSubtreeOverflow |                     \
-  nsChangeHint_UpdateTextPath                              \
+  nsChangeHint_UpdateTextPath |                            \
+  nsChangeHint_VisibilityChange                            \
 )
 
 // The change hints that are never handled for descendants.
 #define nsChangeHint_Hints_NeverHandledForDescendants (    \
   nsChangeHint_BorderStyleNoneChange |                     \
   nsChangeHint_ChildrenOnlyTransform |                     \
   nsChangeHint_CSSOverflowChange |                         \
   nsChangeHint_InvalidateRenderingObservers |              \
@@ -451,17 +460,18 @@ static_assert(!(nsChangeHint_Hints_Alway
 
 #define nsChangeHint_Hints_CanIgnoreIfNotVisible           \
   nsChangeHint(NS_STYLE_HINT_VISUAL |                      \
                nsChangeHint_NeutralChange |                \
                nsChangeHint_UpdateOpacityLayer |           \
                nsChangeHint_AddOrRemoveTransform |         \
                nsChangeHint_UpdatePostTransformOverflow  | \
                nsChangeHint_UpdateTransformLayer |         \
-               nsChangeHint_UpdateUsesOpacity)
+               nsChangeHint_UpdateUsesOpacity |            \
+               nsChangeHint_VisibilityChange)
 
 // NB: Once we drop support for the old style system, this logic should be
 // inlined in the Servo style system to eliminate the FFI call.
 inline nsChangeHint NS_HintsNotHandledForDescendantsIn(nsChangeHint aChangeHint) {
   nsChangeHint result =
     aChangeHint & nsChangeHint_Hints_NeverHandledForDescendants;
 
   if (!NS_IsHintSubset(nsChangeHint_NeedDirtyReflow, aChangeHint)) {
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -4106,16 +4106,20 @@ nsStyleVisibility::CalcDifference(const 
     // classes (e.g. table rows/cells) copy their value from an ancestor.
     hint |= nsChangeHint_ReconstructFrame;
   } else {
     if ((mImageOrientation != aNewData.mImageOrientation)) {
       hint |= nsChangeHint_AllReflowHints |
               nsChangeHint_RepaintFrame;
     }
     if (mVisible != aNewData.mVisible) {
+      if (mVisible == NS_STYLE_VISIBILITY_VISIBLE ||
+          aNewData.mVisible == NS_STYLE_VISIBILITY_VISIBLE) {
+        hint |= nsChangeHint_VisibilityChange;
+      }
       if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
           (NS_STYLE_VISIBILITY_COLLAPSE == aNewData.mVisible)) {
         hint |= NS_STYLE_HINT_REFLOW;
       } else {
         hint |= NS_STYLE_HINT_VISUAL;
       }
     }
     if (mTextOrientation != aNewData.mTextOrientation) {