Fixed elements bounce when rubber-banding at the bottom of the page
[WebKit-https.git] / Source / WebCore / page / scrolling / ScrollingStateFrameScrollingNode.cpp
1 /*
2  * Copyright (C) 2014, 2016 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 #include "config.h"
27 #include "ScrollingStateFrameScrollingNode.h"
28
29 #if ENABLE(ASYNC_SCROLLING) || USE(COORDINATED_GRAPHICS)
30
31 #include "ScrollingStateTree.h"
32 #include "TextStream.h"
33
34 namespace WebCore {
35
36 Ref<ScrollingStateFrameScrollingNode> ScrollingStateFrameScrollingNode::create(ScrollingStateTree& stateTree, ScrollingNodeID nodeID)
37 {
38     return adoptRef(*new ScrollingStateFrameScrollingNode(stateTree, nodeID));
39 }
40
41 ScrollingStateFrameScrollingNode::ScrollingStateFrameScrollingNode(ScrollingStateTree& stateTree, ScrollingNodeID nodeID)
42     : ScrollingStateScrollingNode(stateTree, FrameScrollingNode, nodeID)
43 {
44 }
45
46 ScrollingStateFrameScrollingNode::ScrollingStateFrameScrollingNode(const ScrollingStateFrameScrollingNode& stateNode, ScrollingStateTree& adoptiveTree)
47     : ScrollingStateScrollingNode(stateNode, adoptiveTree)
48 #if PLATFORM(MAC)
49     , m_verticalScrollerImp(stateNode.verticalScrollerImp())
50     , m_horizontalScrollerImp(stateNode.horizontalScrollerImp())
51 #endif
52     , m_eventTrackingRegions(stateNode.eventTrackingRegions())
53     , m_requestedScrollPosition(stateNode.requestedScrollPosition())
54     , m_layoutViewport(stateNode.layoutViewport())
55     , m_minLayoutViewportOrigin(stateNode.minLayoutViewportOrigin())
56     , m_maxLayoutViewportOrigin(stateNode.maxLayoutViewportOrigin())
57     , m_frameScaleFactor(stateNode.frameScaleFactor())
58     , m_topContentInset(stateNode.topContentInset())
59     , m_headerHeight(stateNode.headerHeight())
60     , m_footerHeight(stateNode.footerHeight())
61     , m_synchronousScrollingReasons(stateNode.synchronousScrollingReasons())
62     , m_behaviorForFixed(stateNode.scrollBehaviorForFixedElements())
63     , m_requestedScrollPositionRepresentsProgrammaticScroll(stateNode.requestedScrollPositionRepresentsProgrammaticScroll())
64     , m_fixedElementsLayoutRelativeToFrame(stateNode.fixedElementsLayoutRelativeToFrame())
65     , m_visualViewportEnabled(stateNode.visualViewportEnabled())
66 {
67     if (hasChangedProperty(ScrolledContentsLayer))
68         setScrolledContentsLayer(stateNode.scrolledContentsLayer().toRepresentation(adoptiveTree.preferredLayerRepresentation()));
69
70     if (hasChangedProperty(CounterScrollingLayer))
71         setCounterScrollingLayer(stateNode.counterScrollingLayer().toRepresentation(adoptiveTree.preferredLayerRepresentation()));
72
73     if (hasChangedProperty(InsetClipLayer))
74         setInsetClipLayer(stateNode.insetClipLayer().toRepresentation(adoptiveTree.preferredLayerRepresentation()));
75
76     if (hasChangedProperty(ContentShadowLayer))
77         setContentShadowLayer(stateNode.contentShadowLayer().toRepresentation(adoptiveTree.preferredLayerRepresentation()));
78
79     if (hasChangedProperty(HeaderLayer))
80         setHeaderLayer(stateNode.headerLayer().toRepresentation(adoptiveTree.preferredLayerRepresentation()));
81
82     if (hasChangedProperty(FooterLayer))
83         setFooterLayer(stateNode.footerLayer().toRepresentation(adoptiveTree.preferredLayerRepresentation()));
84 }
85
86 ScrollingStateFrameScrollingNode::~ScrollingStateFrameScrollingNode()
87 {
88 }
89
90 Ref<ScrollingStateNode> ScrollingStateFrameScrollingNode::clone(ScrollingStateTree& adoptiveTree)
91 {
92     return adoptRef(*new ScrollingStateFrameScrollingNode(*this, adoptiveTree));
93 }
94
95 void ScrollingStateFrameScrollingNode::setFrameScaleFactor(float scaleFactor)
96 {
97     if (m_frameScaleFactor == scaleFactor)
98         return;
99
100     m_frameScaleFactor = scaleFactor;
101
102     setPropertyChanged(FrameScaleFactor);
103 }
104
105 void ScrollingStateFrameScrollingNode::setEventTrackingRegions(const EventTrackingRegions& eventTrackingRegions)
106 {
107     if (m_eventTrackingRegions == eventTrackingRegions)
108         return;
109
110     m_eventTrackingRegions = eventTrackingRegions;
111     setPropertyChanged(EventTrackingRegion);
112 }
113
114 void ScrollingStateFrameScrollingNode::setSynchronousScrollingReasons(SynchronousScrollingReasons reasons)
115 {
116     if (m_synchronousScrollingReasons == reasons)
117         return;
118
119     m_synchronousScrollingReasons = reasons;
120     setPropertyChanged(ReasonsForSynchronousScrolling);
121 }
122
123 void ScrollingStateFrameScrollingNode::setScrollBehaviorForFixedElements(ScrollBehaviorForFixedElements behaviorForFixed)
124 {
125     if (m_behaviorForFixed == behaviorForFixed)
126         return;
127
128     m_behaviorForFixed = behaviorForFixed;
129     setPropertyChanged(BehaviorForFixedElements);
130 }
131
132 void ScrollingStateFrameScrollingNode::setLayoutViewport(const FloatRect& r)
133 {
134     if (m_layoutViewport == r)
135         return;
136
137     m_layoutViewport = r;
138     setPropertyChanged(LayoutViewport);
139 }
140
141 void ScrollingStateFrameScrollingNode::setMinLayoutViewportOrigin(const FloatPoint& p)
142 {
143     if (m_minLayoutViewportOrigin == p)
144         return;
145
146     m_minLayoutViewportOrigin = p;
147     setPropertyChanged(MinLayoutViewportOrigin);
148 }
149
150 void ScrollingStateFrameScrollingNode::setMaxLayoutViewportOrigin(const FloatPoint& p)
151 {
152     if (m_maxLayoutViewportOrigin == p)
153         return;
154
155     m_maxLayoutViewportOrigin = p;
156     setPropertyChanged(MaxLayoutViewportOrigin);
157 }
158
159 void ScrollingStateFrameScrollingNode::setHeaderHeight(int headerHeight)
160 {
161     if (m_headerHeight == headerHeight)
162         return;
163
164     m_headerHeight = headerHeight;
165     setPropertyChanged(HeaderHeight);
166 }
167
168 void ScrollingStateFrameScrollingNode::setFooterHeight(int footerHeight)
169 {
170     if (m_footerHeight == footerHeight)
171         return;
172
173     m_footerHeight = footerHeight;
174     setPropertyChanged(FooterHeight);
175 }
176
177 void ScrollingStateFrameScrollingNode::setTopContentInset(float topContentInset)
178 {
179     if (m_topContentInset == topContentInset)
180         return;
181
182     m_topContentInset = topContentInset;
183     setPropertyChanged(TopContentInset);
184 }
185
186 void ScrollingStateFrameScrollingNode::setScrolledContentsLayer(const LayerRepresentation& layerRepresentation)
187 {
188     if (layerRepresentation == m_scrolledContentsLayer)
189         return;
190     
191     m_scrolledContentsLayer = layerRepresentation;
192     setPropertyChanged(ScrolledContentsLayer);
193 }
194
195 void ScrollingStateFrameScrollingNode::setCounterScrollingLayer(const LayerRepresentation& layerRepresentation)
196 {
197     if (layerRepresentation == m_counterScrollingLayer)
198         return;
199     
200     m_counterScrollingLayer = layerRepresentation;
201     setPropertyChanged(CounterScrollingLayer);
202 }
203
204 void ScrollingStateFrameScrollingNode::setInsetClipLayer(const LayerRepresentation& layerRepresentation)
205 {
206     if (layerRepresentation == m_insetClipLayer)
207         return;
208     
209     m_insetClipLayer = layerRepresentation;
210     setPropertyChanged(InsetClipLayer);
211 }
212
213 void ScrollingStateFrameScrollingNode::setContentShadowLayer(const LayerRepresentation& layerRepresentation)
214 {
215     if (layerRepresentation == m_contentShadowLayer)
216         return;
217     
218     m_contentShadowLayer = layerRepresentation;
219     setPropertyChanged(ContentShadowLayer);
220 }
221
222 void ScrollingStateFrameScrollingNode::setHeaderLayer(const LayerRepresentation& layerRepresentation)
223 {
224     if (layerRepresentation == m_headerLayer)
225         return;
226     
227     m_headerLayer = layerRepresentation;
228     setPropertyChanged(HeaderLayer);
229 }
230
231 void ScrollingStateFrameScrollingNode::setFooterLayer(const LayerRepresentation& layerRepresentation)
232 {
233     if (layerRepresentation == m_footerLayer)
234         return;
235     
236     m_footerLayer = layerRepresentation;
237     setPropertyChanged(FooterLayer);
238 }
239
240 void ScrollingStateFrameScrollingNode::setFixedElementsLayoutRelativeToFrame(bool fixedElementsLayoutRelativeToFrame)
241 {
242     if (fixedElementsLayoutRelativeToFrame == m_fixedElementsLayoutRelativeToFrame)
243         return;
244     
245     m_fixedElementsLayoutRelativeToFrame = fixedElementsLayoutRelativeToFrame;
246     setPropertyChanged(FixedElementsLayoutRelativeToFrame);
247 }
248
249 // Only needed while visual viewports are runtime-switchable.
250 void ScrollingStateFrameScrollingNode::setVisualViewportEnabled(bool visualViewportEnabled)
251 {
252     if (visualViewportEnabled == m_visualViewportEnabled)
253         return;
254     
255     m_visualViewportEnabled = visualViewportEnabled;
256     setPropertyChanged(VisualViewportEnabled);
257 }
258
259 #if !PLATFORM(MAC)
260 void ScrollingStateFrameScrollingNode::setScrollerImpsFromScrollbars(Scrollbar*, Scrollbar*)
261 {
262 }
263 #endif
264
265 void ScrollingStateFrameScrollingNode::dumpProperties(TextStream& ts, int indent, ScrollingStateTreeAsTextBehavior behavior) const
266 {
267     ts << "(Frame scrolling node" << "\n";
268     
269     ScrollingStateScrollingNode::dumpProperties(ts, indent, behavior);
270     
271     if (m_frameScaleFactor != 1) {
272         writeIndent(ts, indent + 1);
273         ts << "(frame scale factor " << m_frameScaleFactor << ")\n";
274     }
275     
276     if (m_visualViewportEnabled) {
277         writeIndent(ts, indent + 1);
278         ts << "(layout viewport " << m_layoutViewport << ")\n";
279         writeIndent(ts, indent + 1);
280         ts << "(min layout viewport origin " << m_minLayoutViewportOrigin << ")\n";
281         writeIndent(ts, indent + 1);
282         ts << "(max layout viewport origin " << m_maxLayoutViewportOrigin << ")\n";
283     }
284     
285     if (m_behaviorForFixed == StickToViewportBounds) {
286         writeIndent(ts, indent + 1);
287         ts << "(fixed behavior: stick to viewport)\n";
288     }
289
290     if (!m_eventTrackingRegions.asynchronousDispatchRegion.isEmpty()) {
291         ++indent;
292         writeIndent(ts, indent);
293         ts << "(asynchronous event dispatch region";
294         ++indent;
295         for (auto rect : m_eventTrackingRegions.asynchronousDispatchRegion.rects()) {
296             ts << "\n";
297             writeIndent(ts, indent);
298             ts << rect;
299         }
300         ts << ")\n";
301         indent -= 2;
302     }
303     if (!m_eventTrackingRegions.eventSpecificSynchronousDispatchRegions.isEmpty()) {
304         for (const auto& synchronousEventRegion : m_eventTrackingRegions.eventSpecificSynchronousDispatchRegions) {
305             ++indent;
306             writeIndent(ts, indent);
307             ts << "(synchronous event dispatch region for event " << synchronousEventRegion.key;
308             ++indent;
309             for (auto rect : synchronousEventRegion.value.rects()) {
310                 ts << "\n";
311                 writeIndent(ts, indent);
312                 ts << rect;
313             }
314             ts << ")\n";
315             indent -= 2;
316         }
317     }
318
319     if (m_synchronousScrollingReasons) {
320         writeIndent(ts, indent + 1);
321         ts << "(Scrolling on main thread because: " << ScrollingCoordinator::synchronousScrollingReasonsAsText(m_synchronousScrollingReasons) << ")\n";
322     }
323     
324     // FIXME: dump more properties.
325 }
326
327 } // namespace WebCore
328
329 #endif // ENABLE(ASYNC_SCROLLING) || USE(COORDINATED_GRAPHICS)