Bug 1409166 - Check whether the target animating frame is scrolled out of each scrollable ancestor. r?mattwoodrow,birtles draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Thu, 26 Oct 2017 18:09:32 +0900
changeset 686708 b457bd569d8357ceb3d4e4fabb348a9406a62c32
parent 686177 b3d0e7e94d930c2cf636e490ab0a0a8b5f29f567
child 737442 f703343a5e0cf06f43e7f29e23569508df8b91a1
push id86262
push userhikezoe@mozilla.com
push dateThu, 26 Oct 2017 09:10:06 +0000
reviewersmattwoodrow, birtles
bugs1409166
milestone58.0a1
Bug 1409166 - Check whether the target animating frame is scrolled out of each scrollable ancestor. r?mattwoodrow,birtles Before this patch, we had been checking each scrollable ancestor is scrolled out of its scrollable ancestor. So if the target animating frame is at the bottom of its scrollable parent and if half of the scrollable parent is scrolled out of its ancestor, the animating frame was considered as 'in-view'. MozReview-Commit-ID: BDueuF3cT4I
dom/animation/test/chrome/test_restyles.html
layout/generic/nsFrame.cpp
--- a/dom/animation/test/chrome/test_restyles.html
+++ b/dom/animation/test/chrome/test_restyles.html
@@ -317,17 +317,20 @@ waitForAllPaints(function() {
       return;
     }
 
     var grandParent = addDiv(null,
       { style: 'overflow-y: scroll; height: 20px;' });
     var parentElement = addDiv(null,
       { style: 'overflow-y: scroll; height: 100px;' });
     var div = addDiv(null,
-      { style: 'animation: background-color 100s; position: relative; top: 100px;' });
+      { style: 'animation: background-color 100s; ' +
+               'position: relative; ' +
+               'top: 60px;' }); // This element is in-view in the parent, but
+                                // out of view in the grandparent.
     grandParent.appendChild(parentElement);
     parentElement.appendChild(div);
     var animation = div.getAnimations()[0];
 
     await animation.ready;
     var markers = await observeStyling(5);
 
     is(markers.length, 0,
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -10773,32 +10773,33 @@ nsIFrame::GetPseudoElement(CSSPseudoElem
   if (aType == CSSPseudoElementType::after) {
     return nsLayoutUtils::GetAfterPseudo(mContent);
   }
 
   return nullptr;
 }
 
 static bool
-IsFrameScrolledOutOfView(nsIFrame *aFrame)
+IsFrameScrolledOutOfView(nsIFrame* aTarget,
+                         const nsRect& aTargetRect,
+                         nsIFrame* aParent)
 {
   nsIScrollableFrame* scrollableFrame =
-    nsLayoutUtils::GetNearestScrollableFrame(aFrame,
+    nsLayoutUtils::GetNearestScrollableFrame(aParent,
       nsLayoutUtils::SCROLLABLE_SAME_DOC |
       nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
   if (!scrollableFrame) {
     return false;
   }
 
   nsIFrame *scrollableParent = do_QueryFrame(scrollableFrame);
-  nsRect rect = aFrame->GetVisualOverflowRectRelativeToSelf();
 
   nsRect transformedRect =
-    nsLayoutUtils::TransformFrameRectToAncestor(aFrame,
-                                                rect,
+    nsLayoutUtils::TransformFrameRectToAncestor(aTarget,
+                                                aTargetRect,
                                                 scrollableParent);
 
   nsRect scrollableRect = scrollableParent->GetVisualOverflowRect();
   if (transformedRect.IsEmpty()) {
     // If the transformed rect is empty it represents a line or a point that we
     // should check is outside the the scrollable rect.
     if (transformedRect.x > scrollableRect.XMost() ||
         transformedRect.y > scrollableRect.YMost() ||
@@ -10810,23 +10811,24 @@ IsFrameScrolledOutOfView(nsIFrame *aFram
     return true;
   }
 
   nsIFrame* parent = scrollableParent->GetParent();
   if (!parent) {
     return false;
   }
 
-  return IsFrameScrolledOutOfView(parent);
+  return IsFrameScrolledOutOfView(aTarget, aTargetRect, parent);
 }
 
 bool
 nsIFrame::IsScrolledOutOfView()
 {
-  return IsFrameScrolledOutOfView(this);
+  nsRect rect = GetVisualOverflowRectRelativeToSelf();
+  return IsFrameScrolledOutOfView(this, rect, this);
 }
 
 gfx::Matrix
 nsIFrame::ComputeWidgetTransform()
 {
   const nsStyleUIReset* uiReset = StyleUIReset();
   if (!uiReset->mSpecifiedWindowTransform) {
     return gfx::Matrix();