(Async scrolling) Handle 'position:fixed' inside 'position:sticky' correctly.
[WebKit-https.git] / Source / WebCore / page / scrolling / cocoa / ScrollingTreeStickyNode.mm
index 06cc451..60e173e 100644 (file)
@@ -66,7 +66,7 @@ void ScrollingTreeStickyNode::commitStateBeforeChildren(const ScrollingStateNode
         m_constraints = stickyStateNode.viewportConstraints();
 }
 
-void ScrollingTreeStickyNode::applyLayerPositions()
+FloatPoint ScrollingTreeStickyNode::computeLayerPosition() const
 {
     auto computeLayerPositionForScrollingNode = [&](ScrollingTreeNode& scrollingNode) {
         FloatRect constrainingRect;
@@ -80,41 +80,42 @@ void ScrollingTreeStickyNode::applyLayerPositions()
         return m_constraints.layerPositionForConstrainingRect(constrainingRect);
     };
 
-    auto computeLayerPosition = [&] {
-        for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
-            if (is<ScrollingTreePositionedNode>(*ancestor)) {
-                auto& positioningAncestor = downcast<ScrollingTreePositionedNode>(*ancestor);
-
-                // FIXME: Do we need to do anything for ScrollPositioningBehavior::Stationary?
-                if (positioningAncestor.scrollPositioningBehavior() == ScrollPositioningBehavior::Moves) {
-                    if (positioningAncestor.relatedOverflowScrollingNodes().isEmpty())
-                        break;
-                    auto overflowNode = scrollingTree().nodeForID(positioningAncestor.relatedOverflowScrollingNodes()[0]);
-                    if (!overflowNode)
-                        break;
-
-                    auto position = computeLayerPositionForScrollingNode(*overflowNode);
-
-                    if (positioningAncestor.layer() == m_layer) {
-                        // We'll also do the adjustment the positioning node would do.
-                        position -= positioningAncestor.scrollDeltaSinceLastCommit();
-                    }
-                    
-                    return position;
+    for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
+        if (is<ScrollingTreePositionedNode>(*ancestor)) {
+            auto& positioningAncestor = downcast<ScrollingTreePositionedNode>(*ancestor);
+
+            // FIXME: Do we need to do anything for ScrollPositioningBehavior::Stationary?
+            if (positioningAncestor.scrollPositioningBehavior() == ScrollPositioningBehavior::Moves) {
+                if (positioningAncestor.relatedOverflowScrollingNodes().isEmpty())
+                    break;
+                auto overflowNode = scrollingTree().nodeForID(positioningAncestor.relatedOverflowScrollingNodes()[0]);
+                if (!overflowNode)
+                    break;
+
+                auto position = computeLayerPositionForScrollingNode(*overflowNode);
+
+                if (positioningAncestor.layer() == m_layer) {
+                    // We'll also do the adjustment the positioning node would do.
+                    position -= positioningAncestor.scrollDeltaSinceLastCommit();
                 }
-            }
-            if (is<ScrollingTreeScrollingNode>(*ancestor))
-                return computeLayerPositionForScrollingNode(*ancestor);
 
-            if (is<ScrollingTreeFixedNode>(*ancestor) || is<ScrollingTreeStickyNode>(*ancestor)) {
-                // FIXME: Do we need scrolling tree nodes at all for nested cases?
-                return m_constraints.layerPositionAtLastLayout();
+                return position;
             }
         }
-        ASSERT_NOT_REACHED();
-        return m_constraints.layerPositionAtLastLayout();
-    };
+        if (is<ScrollingTreeScrollingNode>(*ancestor))
+            return computeLayerPositionForScrollingNode(*ancestor);
+
+        if (is<ScrollingTreeFixedNode>(*ancestor) || is<ScrollingTreeStickyNode>(*ancestor)) {
+            // FIXME: Do we need scrolling tree nodes at all for nested cases?
+            return m_constraints.layerPositionAtLastLayout();
+        }
+    }
+    ASSERT_NOT_REACHED();
+    return m_constraints.layerPositionAtLastLayout();
+}
 
+void ScrollingTreeStickyNode::applyLayerPositions()
+{
     auto layerPosition = computeLayerPosition();
 
     LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeStickyNode " << scrollingNodeID() << " constrainingRectAtLastLayout " << m_constraints.constrainingRectAtLastLayout() << " last layer pos " << m_constraints.layerPositionAtLastLayout() << " layerPosition " << layerPosition);
@@ -122,6 +123,12 @@ void ScrollingTreeStickyNode::applyLayerPositions()
     [m_layer _web_setLayerTopLeftPosition:layerPosition - m_constraints.alignmentOffset()];
 }
 
+FloatSize ScrollingTreeStickyNode::scrollDeltaSinceLastCommit() const
+{
+    auto layerPosition = computeLayerPosition();
+    return layerPosition - m_constraints.layerPositionAtLastLayout();
+}
+
 void ScrollingTreeStickyNode::dumpProperties(TextStream& ts, ScrollingStateTreeAsTextBehavior behavior) const
 {
     ts << "sticky node";