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 12:45:57 +0900
changeset 686635 cb048d1f6c10f4718fb32cad8d81ffacb136ed48
parent 686177 b3d0e7e94d930c2cf636e490ab0a0a8b5f29f567
child 737413 60a1a06bc50e2000d6179a6cfd2bdf890e20ed40
push id86230
push userhikezoe@mozilla.com
push dateThu, 26 Oct 2017 03:50:39 +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 grand parent.
     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();