Remove remnants of iOS WK1 scrolling tree code
[WebKit-https.git] / Source / WebKit / UIProcess / RemoteLayerTree / ios / ScrollingTreeFrameScrollingNodeRemoteIOS.mm
1 /*
2  * Copyright (C) 2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "ScrollingTreeFrameScrollingNodeRemoteIOS.h"
28
29 #if PLATFORM(IOS_FAMILY) && ENABLE(ASYNC_SCROLLING)
30
31 #import "ScrollingTreeScrollingNodeDelegateIOS.h"
32 #import <WebCore/ScrollingStateScrollingNode.h>
33
34 namespace WebKit {
35 using namespace WebCore;
36
37 Ref<ScrollingTreeFrameScrollingNodeRemoteIOS> ScrollingTreeFrameScrollingNodeRemoteIOS::create(ScrollingTree& scrollingTree, ScrollingNodeType nodeType, ScrollingNodeID nodeID)
38 {
39     return adoptRef(*new ScrollingTreeFrameScrollingNodeRemoteIOS(scrollingTree, nodeType, nodeID));
40 }
41
42 ScrollingTreeFrameScrollingNodeRemoteIOS::ScrollingTreeFrameScrollingNodeRemoteIOS(ScrollingTree& scrollingTree, ScrollingNodeType nodeType, ScrollingNodeID nodeID)
43     : ScrollingTreeFrameScrollingNode(scrollingTree, nodeType, nodeID)
44 {
45 }
46
47 ScrollingTreeFrameScrollingNodeRemoteIOS::~ScrollingTreeFrameScrollingNodeRemoteIOS()
48 {
49 }
50
51 void ScrollingTreeFrameScrollingNodeRemoteIOS::commitStateBeforeChildren(const ScrollingStateNode& stateNode)
52 {
53     ScrollingTreeFrameScrollingNode::commitStateBeforeChildren(stateNode);
54     
55     const auto& scrollingStateNode = downcast<ScrollingStateFrameScrollingNode>(stateNode);
56
57     if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::CounterScrollingLayer))
58         m_counterScrollingLayer = scrollingStateNode.counterScrollingLayer();
59
60     if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::HeaderLayer))
61         m_headerLayer = scrollingStateNode.headerLayer();
62
63     if (scrollingStateNode.hasChangedProperty(ScrollingStateFrameScrollingNode::FooterLayer))
64         m_footerLayer = scrollingStateNode.footerLayer();
65
66     if (stateNode.hasChangedProperty(ScrollingStateScrollingNode::ScrollContainerLayer)) {
67         if (scrollContainerLayer())
68             m_scrollingNodeDelegate = std::make_unique<ScrollingTreeScrollingNodeDelegateIOS>(*this);
69         else
70             m_scrollingNodeDelegate = nullptr;
71     }
72
73     if (m_scrollingNodeDelegate)
74         m_scrollingNodeDelegate->commitStateBeforeChildren(downcast<ScrollingStateScrollingNode>(stateNode));
75 }
76
77 void ScrollingTreeFrameScrollingNodeRemoteIOS::commitStateAfterChildren(const ScrollingStateNode& stateNode)
78 {
79     ScrollingTreeFrameScrollingNode::commitStateAfterChildren(stateNode);
80
81     const auto& scrollingStateNode = downcast<ScrollingStateFrameScrollingNode>(stateNode);
82
83     // Update the scroll position after child nodes have been updated, because they need to have updated their constraints before any scrolling happens.
84     if (scrollingStateNode.hasChangedProperty(ScrollingStateScrollingNode::RequestedScrollPosition))
85         setScrollPosition(scrollingStateNode.requestedScrollPosition());
86
87     if (m_scrollingNodeDelegate)
88         m_scrollingNodeDelegate->commitStateAfterChildren(downcast<ScrollingStateScrollingNode>(stateNode));
89 }
90
91 FloatPoint ScrollingTreeFrameScrollingNodeRemoteIOS::minimumScrollPosition() const
92 {
93     FloatPoint position = ScrollableArea::scrollPositionFromOffset(FloatPoint(), toFloatSize(scrollOrigin()));
94     
95     if (isRootNode() && scrollingTree().scrollPinningBehavior() == PinToBottom)
96         position.setY(maximumScrollPosition().y());
97
98     return position;
99 }
100
101 FloatPoint ScrollingTreeFrameScrollingNodeRemoteIOS::maximumScrollPosition() const
102 {
103     FloatPoint position = ScrollableArea::scrollPositionFromOffset(FloatPoint(totalContentsSizeForRubberBand() - scrollableAreaSize()), toFloatSize(scrollOrigin()));
104     position = position.expandedTo(FloatPoint());
105
106     if (isRootNode() && scrollingTree().scrollPinningBehavior() == PinToTop)
107         position.setY(minimumScrollPosition().y());
108
109     return position;
110 }
111
112 FloatPoint ScrollingTreeFrameScrollingNodeRemoteIOS::scrollPosition() const
113 {
114     if (m_scrollingNodeDelegate)
115         return m_scrollingNodeDelegate->scrollPosition();
116
117     return -scrolledContentsLayer().position;
118 }
119
120 void ScrollingTreeFrameScrollingNodeRemoteIOS::setScrollPosition(const FloatPoint& position, ScrollPositionClamp clamp)
121 {
122     auto scrollPosition = position;
123     if (clamp == ScrollPositionClamp::ToContentEdges)
124         scrollPosition = clampScrollPosition(scrollPosition);
125
126     FloatRect newLayoutViewport = layoutViewportForScrollPosition(scrollPosition, frameScaleFactor());
127     setLayoutViewport(newLayoutViewport);
128     auto layoutViewportOrigin = newLayoutViewport.location();
129
130     setScrollLayerPosition(scrollPosition, layoutViewport());
131     scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition, layoutViewportOrigin);
132 }
133
134 void ScrollingTreeFrameScrollingNodeRemoteIOS::setScrollLayerPosition(const FloatPoint& scrollPosition, const FloatRect& layoutViewport)
135 {
136     if (m_scrollingNodeDelegate) {
137         m_scrollingNodeDelegate->setScrollLayerPosition(scrollPosition);
138         return;
139     }
140
141     [scrolledContentsLayer() setPosition:-scrollPosition];
142     updateChildNodesAfterScroll(scrollPosition);
143 }
144
145 void ScrollingTreeFrameScrollingNodeRemoteIOS::updateChildNodesAfterScroll(const FloatPoint& scrollPosition)
146 {
147     ScrollBehaviorForFixedElements behaviorForFixed = scrollBehaviorForFixedElements();
148     FloatRect viewportRect(scrollPosition, scrollableAreaSize());
149     FloatPoint scrollPositionForFixedChildren = FrameView::scrollPositionForFixedPosition(enclosingLayoutRect(viewportRect), LayoutSize(totalContentsSize()), LayoutPoint(scrollPosition), scrollOrigin(), frameScaleFactor(), fixedElementsLayoutRelativeToFrame(), behaviorForFixed, headerHeight(), footerHeight());
150
151     [m_counterScrollingLayer setPosition:scrollPositionForFixedChildren];
152
153     if (m_headerLayer || m_footerLayer) {
154         // Generally the banners should have the same horizontal-position computation as a fixed element. However,
155         // the banners are not affected by the frameScaleFactor(), so if there is currently a non-1 frameScaleFactor()
156         // then we should recompute scrollPositionForFixedChildren for the banner with a scale factor of 1.
157         float horizontalScrollOffsetForBanner = scrollPositionForFixedChildren.x();
158         if (frameScaleFactor() != 1)
159             horizontalScrollOffsetForBanner = FrameView::scrollPositionForFixedPosition(enclosingLayoutRect(viewportRect), LayoutSize(totalContentsSize()), LayoutPoint(scrollPosition), scrollOrigin(), 1, fixedElementsLayoutRelativeToFrame(), behaviorForFixed, headerHeight(), footerHeight()).x();
160
161         if (m_headerLayer)
162             [m_headerLayer setPosition:FloatPoint(horizontalScrollOffsetForBanner, 0)];
163
164         if (m_footerLayer)
165             [m_footerLayer setPosition:FloatPoint(horizontalScrollOffsetForBanner, totalContentsSize().height() - footerHeight())];
166     }
167     
168     if (!m_children)
169         return;
170
171
172     FloatRect fixedPositionRect;
173     if (!parent())
174         fixedPositionRect = scrollingTree().fixedPositionRect();
175     else
176         fixedPositionRect = FloatRect(scrollPosition, scrollableAreaSize());
177
178     for (auto& child : *m_children)
179         child->updateLayersAfterAncestorChange(*this, fixedPositionRect, FloatSize());
180 }
181
182 void ScrollingTreeFrameScrollingNodeRemoteIOS::updateLayersAfterDelegatedScroll(const FloatPoint& scrollPosition)
183 {
184     if (m_scrollingNodeDelegate) {
185         m_scrollingNodeDelegate->updateChildNodesAfterScroll(scrollPosition);
186         return;
187     }
188
189     updateChildNodesAfterScroll(scrollPosition);
190 }
191
192 void ScrollingTreeFrameScrollingNodeRemoteIOS::updateLayersAfterViewportChange(const FloatRect& fixedPositionRect, double /*scale*/)
193 {
194     // Note: we never currently have a m_counterScrollingLayer (which is used for background-attachment:fixed) on iOS.
195     [m_counterScrollingLayer setPosition:fixedPositionRect.location()];
196
197     if (!m_children)
198         return;
199
200     for (auto& child : *m_children)
201         child->updateLayersAfterAncestorChange(*this, fixedPositionRect, FloatSize());
202 }
203
204 void ScrollingTreeFrameScrollingNodeRemoteIOS::updateLayersAfterAncestorChange(const ScrollingTreeNode& changedNode, const FloatRect& fixedPositionRect, const FloatSize& cumulativeDelta)
205 {
206     if (m_scrollingNodeDelegate) {
207         m_scrollingNodeDelegate->updateLayersAfterAncestorChange(changedNode, fixedPositionRect, cumulativeDelta);
208         return;
209     }
210
211     if (!m_children)
212         return;
213
214     FloatRect currFrameFixedPositionRect(scrollPosition(), scrollableAreaSize()); // FIXME: use up-to-date layout viewport.
215     for (auto& child : *m_children)
216         child->updateLayersAfterAncestorChange(changedNode, currFrameFixedPositionRect, { });
217 }
218
219 }
220 #endif