ce94901ec3fd4fccfc47b39c51c8420447eeef15
[WebKit-https.git] / Source / WebCore / page / scrolling / AsyncScrollingCoordinator.cpp
1 /*
2  * Copyright (C) 2014 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
28 #if ENABLE(ASYNC_SCROLLING)
29 #include "AsyncScrollingCoordinator.h"
30
31 #include "EditorClient.h"
32 #include "Frame.h"
33 #include "FrameView.h"
34 #include "GraphicsLayer.h"
35 #include "MainFrame.h"
36 #include "Page.h"
37 #include "ScrollingConstraints.h"
38 #include "ScrollingStateFixedNode.h"
39 #include "ScrollingStateFrameScrollingNode.h"
40 #include "ScrollingStateOverflowScrollingNode.h"
41 #include "ScrollingStateStickyNode.h"
42 #include "ScrollingStateTree.h"
43
44 namespace WebCore {
45
46 AsyncScrollingCoordinator::AsyncScrollingCoordinator(Page* page)
47     : ScrollingCoordinator(page)
48     , m_updateNodeScrollPositionTimer(*this, &AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScrollTimerFired)
49     , m_scrollingStateTree(std::make_unique<ScrollingStateTree>(this))
50 {
51 }
52
53 AsyncScrollingCoordinator::~AsyncScrollingCoordinator()
54 {
55 }
56
57 void AsyncScrollingCoordinator::scrollingStateTreePropertiesChanged()
58 {
59     scheduleTreeStateCommit();
60 }
61
62 static inline void setStateScrollingNodeSnapOffsetsAsFloat(ScrollingStateScrollingNode& node, ScrollEventAxis axis, const Vector<LayoutUnit>& snapOffsets, float deviceScaleFactor)
63 {
64     // FIXME: Incorporate current page scale factor in snapping to device pixel. Perhaps we should just convert to float here and let UI process do the pixel snapping?
65     Vector<float> snapOffsetsAsFloat;
66     snapOffsetsAsFloat.reserveInitialCapacity(snapOffsets.size());
67     for (size_t i = 0; i < snapOffsets.size(); ++i)
68         snapOffsetsAsFloat.append(roundToDevicePixel(snapOffsets[i], deviceScaleFactor, false));
69
70     if (axis == ScrollEventAxis::Horizontal)
71         node.setHorizontalSnapOffsets(snapOffsetsAsFloat);
72     else
73         node.setVerticalSnapOffsets(snapOffsetsAsFloat);
74 }
75
76 void AsyncScrollingCoordinator::setNonFastScrollableRegionDirty()
77 {
78     m_nonFastScrollableRegionDirty = true;
79     // We have to schedule a commit, but the computed non-fast region may not have actually changed.
80     scheduleTreeStateCommit();
81 }
82
83 void AsyncScrollingCoordinator::willCommitTree()
84 {
85     updateNonFastScrollableRegion();
86 }
87
88 void AsyncScrollingCoordinator::updateNonFastScrollableRegion()
89 {
90     if (!m_nonFastScrollableRegionDirty)
91         return;
92
93     if (!m_scrollingStateTree->rootStateNode())
94         return;
95
96     m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(computeNonFastScrollableRegion(m_page->mainFrame(), IntPoint()));
97     m_nonFastScrollableRegionDirty = false;
98 }
99
100 void AsyncScrollingCoordinator::frameViewLayoutUpdated(FrameView& frameView)
101 {
102     ASSERT(isMainThread());
103     ASSERT(m_page);
104
105     // If there isn't a root node yet, don't do anything. We'll be called again after creating one.
106     if (!m_scrollingStateTree->rootStateNode())
107         return;
108
109     // Compute the region of the page that we can't do fast scrolling for. This currently includes
110     // all scrollable areas, such as subframes, overflow divs and list boxes. We need to do this even if the
111     // frame view whose layout was updated is not the main frame.
112     // In the future, we may want to have the ability to set non-fast scrolling regions for more than
113     // just the root node. But right now, this concept only applies to the root.
114     m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(computeNonFastScrollableRegion(m_page->mainFrame(), IntPoint()));
115     m_nonFastScrollableRegionDirty = false;
116
117     if (!coordinatesScrollingForFrameView(frameView))
118         return;
119
120     ScrollingStateFrameScrollingNode* node = downcast<ScrollingStateFrameScrollingNode>(m_scrollingStateTree->stateNodeForID(frameView.scrollLayerID()));
121     if (!node)
122         return;
123
124     Scrollbar* verticalScrollbar = frameView.verticalScrollbar();
125     Scrollbar* horizontalScrollbar = frameView.horizontalScrollbar();
126     node->setScrollbarPaintersFromScrollbars(verticalScrollbar, horizontalScrollbar);
127     
128     node->setFrameScaleFactor(frameView.frame().frameScaleFactor());
129     node->setHeaderHeight(frameView.headerHeight());
130     node->setFooterHeight(frameView.footerHeight());
131     node->setTopContentInset(frameView.topContentInset());
132
133     node->setScrollOrigin(frameView.scrollOrigin());
134     node->setScrollableAreaSize(frameView.visibleContentRect().size());
135     node->setTotalContentsSize(frameView.totalContentsSize());
136     node->setReachableContentsSize(frameView.totalContentsSize());
137
138 #if ENABLE(CSS_SCROLL_SNAP)
139     frameView.updateSnapOffsets();
140     if (const Vector<LayoutUnit>* horizontalSnapOffsets = frameView.horizontalSnapOffsets())
141         setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, *horizontalSnapOffsets, m_page->deviceScaleFactor());
142
143     if (const Vector<LayoutUnit>* verticalSnapOffsets = frameView.verticalSnapOffsets())
144         setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, *verticalSnapOffsets, m_page->deviceScaleFactor());
145 #endif
146
147     ScrollableAreaParameters scrollParameters;
148     scrollParameters.horizontalScrollElasticity = frameView.horizontalScrollElasticity();
149     scrollParameters.verticalScrollElasticity = frameView.verticalScrollElasticity();
150     scrollParameters.hasEnabledHorizontalScrollbar = horizontalScrollbar && horizontalScrollbar->enabled();
151     scrollParameters.hasEnabledVerticalScrollbar = verticalScrollbar && verticalScrollbar->enabled();
152     scrollParameters.horizontalScrollbarMode = frameView.horizontalScrollbarMode();
153     scrollParameters.verticalScrollbarMode = frameView.verticalScrollbarMode();
154
155     node->setScrollableAreaParameters(scrollParameters);
156 }
157
158 void AsyncScrollingCoordinator::frameViewNonFastScrollableRegionChanged(FrameView&)
159 {
160     if (!m_scrollingStateTree->rootStateNode())
161         return;
162
163     setNonFastScrollableRegionDirty();
164 }
165
166 void AsyncScrollingCoordinator::frameViewRootLayerDidChange(FrameView& frameView)
167 {
168     ASSERT(isMainThread());
169     ASSERT(m_page);
170
171     if (!coordinatesScrollingForFrameView(frameView))
172         return;
173     
174     // FIXME: In some navigation scenarios, the FrameView has no RenderView or that RenderView has not been composited.
175     // This needs cleaning up: https://bugs.webkit.org/show_bug.cgi?id=132724
176     if (!frameView.scrollLayerID())
177         return;
178     
179     // If the root layer does not have a ScrollingStateNode, then we should create one.
180     ensureRootStateNodeForFrameView(frameView);
181     ASSERT(m_scrollingStateTree->rootStateNode());
182
183     ScrollingCoordinator::frameViewRootLayerDidChange(frameView);
184
185     ScrollingStateFrameScrollingNode* node = downcast<ScrollingStateFrameScrollingNode>(m_scrollingStateTree->stateNodeForID(frameView.scrollLayerID()));
186     node->setLayer(scrollLayerForFrameView(frameView));
187     node->setScrolledContentsLayer(rootContentLayerForFrameView(frameView));
188     node->setCounterScrollingLayer(counterScrollingLayerForFrameView(frameView));
189     node->setInsetClipLayer(insetClipLayerForFrameView(frameView));
190     node->setContentShadowLayer(contentShadowLayerForFrameView(frameView));
191     node->setHeaderLayer(headerLayerForFrameView(frameView));
192     node->setFooterLayer(footerLayerForFrameView(frameView));
193     node->setScrollBehaviorForFixedElements(frameView.scrollBehaviorForFixedElements());
194 }
195
196 bool AsyncScrollingCoordinator::requestScrollPositionUpdate(FrameView& frameView, const IntPoint& scrollPosition)
197 {
198     ASSERT(isMainThread());
199     ASSERT(m_page);
200
201     if (!coordinatesScrollingForFrameView(frameView))
202         return false;
203
204     bool isProgrammaticScroll = frameView.inProgrammaticScroll();
205     if (isProgrammaticScroll || frameView.frame().document()->inPageCache())
206         updateScrollPositionAfterAsyncScroll(frameView.scrollLayerID(), scrollPosition, isProgrammaticScroll, SetScrollingLayerPosition);
207
208     // If this frame view's document is being put into the page cache, we don't want to update our
209     // main frame scroll position. Just let the FrameView think that we did.
210     if (frameView.frame().document()->inPageCache())
211         return true;
212
213     ScrollingStateScrollingNode* stateNode = downcast<ScrollingStateScrollingNode>(m_scrollingStateTree->stateNodeForID(frameView.scrollLayerID()));
214     if (!stateNode)
215         return false;
216
217     stateNode->setRequestedScrollPosition(scrollPosition, isProgrammaticScroll);
218     return true;
219 }
220
221 void AsyncScrollingCoordinator::scheduleUpdateScrollPositionAfterAsyncScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
222 {
223     ScheduledScrollUpdate scrollUpdate(nodeID, scrollPosition, programmaticScroll, scrollingLayerPositionAction);
224     
225     // For programmatic scrolls, requestScrollPositionUpdate() has already called updateScrollPositionAfterAsyncScroll().
226     if (programmaticScroll)
227         return;
228
229     if (m_updateNodeScrollPositionTimer.isActive()) {
230         if (m_scheduledScrollUpdate.matchesUpdateType(scrollUpdate)) {
231             m_scheduledScrollUpdate.scrollPosition = scrollPosition;
232             return;
233         }
234     
235         // If the parameters don't match what was previously scheduled, dispatch immediately.
236         m_updateNodeScrollPositionTimer.stop();
237         updateScrollPositionAfterAsyncScroll(m_scheduledScrollUpdate.nodeID, m_scheduledScrollUpdate.scrollPosition, m_scheduledScrollUpdate.isProgrammaticScroll, m_scheduledScrollUpdate.updateLayerPositionAction);
238         updateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, programmaticScroll, scrollingLayerPositionAction);
239         return;
240     }
241
242     m_scheduledScrollUpdate = scrollUpdate;
243     m_updateNodeScrollPositionTimer.startOneShot(0);
244 }
245
246 void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScrollTimerFired()
247 {
248     updateScrollPositionAfterAsyncScroll(m_scheduledScrollUpdate.nodeID, m_scheduledScrollUpdate.scrollPosition, m_scheduledScrollUpdate.isProgrammaticScroll, m_scheduledScrollUpdate.updateLayerPositionAction);
249 }
250
251 FrameView* AsyncScrollingCoordinator::frameViewForScrollingNode(ScrollingNodeID scrollingNodeID) const
252 {
253     if (!m_scrollingStateTree->rootStateNode())
254         return nullptr;
255     
256     if (scrollingNodeID == m_scrollingStateTree->rootStateNode()->scrollingNodeID())
257         return m_page->mainFrame().view();
258
259     ScrollingStateNode* stateNode = m_scrollingStateTree->stateNodeForID(scrollingNodeID);
260     if (!stateNode)
261         return nullptr;
262
263     // Find the enclosing frame scrolling node.
264     ScrollingStateNode* parentNode = stateNode;
265     while (parentNode && parentNode->nodeType() != FrameScrollingNode)
266         parentNode = parentNode->parent();
267     
268     if (!parentNode)
269         return nullptr;
270     
271     // Walk the frame tree to find the matching FrameView. This is not ideal, but avoids back pointers to FrameViews
272     // from ScrollingTreeStateNodes.
273     for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
274         if (FrameView* view = frame->view()) {
275             if (view->scrollLayerID() == parentNode->scrollingNodeID())
276                 return view;
277         }
278     }
279
280     return nullptr;
281 }
282
283 void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNodeID scrollingNodeID, const FloatPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
284 {
285     ASSERT(isMainThread());
286
287     if (!m_page)
288         return;
289
290     FrameView* frameViewPtr = frameViewForScrollingNode(scrollingNodeID);
291     if (!frameViewPtr)
292         return;
293
294     FrameView& frameView = *frameViewPtr;
295
296     if (scrollingNodeID == frameView.scrollLayerID()) {
297         bool oldProgrammaticScroll = frameView.inProgrammaticScroll();
298         frameView.setInProgrammaticScroll(programmaticScroll);
299
300         frameView.setConstrainsScrollingToContentEdge(false);
301         frameView.notifyScrollPositionChanged(roundedIntPoint(scrollPosition));
302         frameView.setConstrainsScrollingToContentEdge(true);
303
304         frameView.setInProgrammaticScroll(oldProgrammaticScroll);
305
306         if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
307             GraphicsLayer* counterScrollingLayer = counterScrollingLayerForFrameView(frameView);
308             GraphicsLayer* insetClipLayer = insetClipLayerForFrameView(frameView);
309             GraphicsLayer* contentShadowLayer = contentShadowLayerForFrameView(frameView);
310             GraphicsLayer* scrolledContentsLayer = rootContentLayerForFrameView(frameView);
311             GraphicsLayer* headerLayer = headerLayerForFrameView(frameView);
312             GraphicsLayer* footerLayer = footerLayerForFrameView(frameView);
313             LayoutSize scrollOffsetForFixed = frameView.scrollOffsetForFixedPosition();
314
315             float topContentInset = frameView.topContentInset();
316             FloatPoint positionForInsetClipLayer = FloatPoint(0, FrameView::yPositionForInsetClipLayer(scrollPosition, topContentInset));
317             FloatPoint positionForContentsLayer = FloatPoint(scrolledContentsLayer->position().x(),
318                 FrameView::yPositionForRootContentLayer(scrollPosition, topContentInset, frameView.headerHeight()));
319             FloatPoint positionForHeaderLayer = FloatPoint(scrollOffsetForFixed.width(), FrameView::yPositionForHeaderLayer(scrollPosition, topContentInset));
320             FloatPoint positionForFooterLayer = FloatPoint(scrollOffsetForFixed.width(),
321                 FrameView::yPositionForFooterLayer(scrollPosition, topContentInset, frameView.totalContentsSize().height(), frameView.footerHeight()));
322
323             if (programmaticScroll || scrollingLayerPositionAction == SetScrollingLayerPosition) {
324                 scrollLayer->setPosition(-frameView.scrollPosition());
325                 if (counterScrollingLayer)
326                     counterScrollingLayer->setPosition(toLayoutPoint(scrollOffsetForFixed));
327                 if (insetClipLayer)
328                     insetClipLayer->setPosition(positionForInsetClipLayer);
329                 if (contentShadowLayer)
330                     contentShadowLayer->setPosition(positionForContentsLayer);
331                 if (scrolledContentsLayer)
332                     scrolledContentsLayer->setPosition(positionForContentsLayer);
333                 if (headerLayer)
334                     headerLayer->setPosition(positionForHeaderLayer);
335                 if (footerLayer)
336                     footerLayer->setPosition(positionForFooterLayer);
337             } else {
338                 scrollLayer->syncPosition(-frameView.scrollPosition());
339                 if (counterScrollingLayer)
340                     counterScrollingLayer->syncPosition(toLayoutPoint(scrollOffsetForFixed));
341                 if (insetClipLayer)
342                     insetClipLayer->syncPosition(positionForInsetClipLayer);
343                 if (contentShadowLayer)
344                     contentShadowLayer->syncPosition(positionForContentsLayer);
345                 if (scrolledContentsLayer)
346                     scrolledContentsLayer->syncPosition(positionForContentsLayer);
347                 if (headerLayer)
348                     headerLayer->syncPosition(positionForHeaderLayer);
349                 if (footerLayer)
350                     footerLayer->syncPosition(positionForFooterLayer);
351
352                 LayoutRect viewportRect = frameView.viewportConstrainedVisibleContentRect();
353                 syncChildPositions(viewportRect);
354             }
355         }
356
357         return;
358     }
359
360     // Overflow-scroll area.
361     if (ScrollableArea* scrollableArea = frameView.scrollableAreaForScrollLayerID(scrollingNodeID)) {
362         scrollableArea->setIsUserScroll(scrollingLayerPositionAction == SyncScrollingLayerPosition);
363         scrollableArea->scrollToOffsetWithoutAnimation(scrollPosition);
364         scrollableArea->setIsUserScroll(false);
365         if (scrollingLayerPositionAction == SetScrollingLayerPosition)
366             m_page->editorClient().overflowScrollPositionChanged();
367     }
368 }
369
370 void AsyncScrollingCoordinator::scrollableAreaScrollbarLayerDidChange(ScrollableArea& scrollableArea, ScrollbarOrientation orientation)
371 {
372     ASSERT(isMainThread());
373     ASSERT(m_page);
374
375     if (&scrollableArea != static_cast<ScrollableArea*>(m_page->mainFrame().view()))
376         return;
377
378     if (orientation == VerticalScrollbar)
379         scrollableArea.verticalScrollbarLayerDidChange();
380     else
381         scrollableArea.horizontalScrollbarLayerDidChange();
382 }
383
384 ScrollingNodeID AsyncScrollingCoordinator::attachToStateTree(ScrollingNodeType nodeType, ScrollingNodeID newNodeID, ScrollingNodeID parentID)
385 {
386     return m_scrollingStateTree->attachNode(nodeType, newNodeID, parentID);
387 }
388
389 void AsyncScrollingCoordinator::detachFromStateTree(ScrollingNodeID nodeID)
390 {
391     m_scrollingStateTree->detachNode(nodeID);
392 }
393
394 void AsyncScrollingCoordinator::clearStateTree()
395 {
396     m_scrollingStateTree->clear();
397 }
398
399 void AsyncScrollingCoordinator::syncChildPositions(const LayoutRect& viewportRect)
400 {
401     if (!m_scrollingStateTree->rootStateNode())
402         return;
403
404     auto children = m_scrollingStateTree->rootStateNode()->children();
405     if (!children)
406         return;
407
408     // FIXME: We'll have to traverse deeper into the tree at some point.
409     for (auto& child : *children)
410         child->syncLayerPositionForViewportRect(viewportRect);
411 }
412
413 void AsyncScrollingCoordinator::ensureRootStateNodeForFrameView(FrameView& frameView)
414 {
415     ASSERT(frameView.scrollLayerID());
416     attachToStateTree(FrameScrollingNode, frameView.scrollLayerID(), 0);
417 }
418
419 void AsyncScrollingCoordinator::updateFrameScrollingNode(ScrollingNodeID nodeID, GraphicsLayer* layer, GraphicsLayer* scrolledContentsLayer, GraphicsLayer* counterScrollingLayer, GraphicsLayer* insetClipLayer, const ScrollingGeometry* scrollingGeometry)
420 {
421     ScrollingStateFrameScrollingNode* node = downcast<ScrollingStateFrameScrollingNode>(m_scrollingStateTree->stateNodeForID(nodeID));
422     ASSERT(node);
423     if (!node)
424         return;
425
426     node->setLayer(layer);
427     node->setInsetClipLayer(insetClipLayer);
428     node->setScrolledContentsLayer(scrolledContentsLayer);
429     node->setCounterScrollingLayer(counterScrollingLayer);
430
431     if (scrollingGeometry) {
432         node->setScrollOrigin(scrollingGeometry->scrollOrigin);
433         node->setScrollPosition(scrollingGeometry->scrollPosition);
434         node->setTotalContentsSize(scrollingGeometry->contentSize);
435         node->setReachableContentsSize(scrollingGeometry->reachableContentSize);
436         node->setScrollableAreaSize(scrollingGeometry->scrollableAreaSize);
437     }
438 }
439     
440 void AsyncScrollingCoordinator::updateOverflowScrollingNode(ScrollingNodeID nodeID, GraphicsLayer* layer, GraphicsLayer* scrolledContentsLayer, const ScrollingGeometry* scrollingGeometry)
441 {
442     ScrollingStateOverflowScrollingNode* node = downcast<ScrollingStateOverflowScrollingNode>(m_scrollingStateTree->stateNodeForID(nodeID));
443     ASSERT(node);
444     if (!node)
445         return;
446
447     node->setLayer(layer);
448     node->setScrolledContentsLayer(scrolledContentsLayer);
449     
450     if (scrollingGeometry) {
451         node->setScrollOrigin(scrollingGeometry->scrollOrigin);
452         node->setScrollPosition(scrollingGeometry->scrollPosition);
453         node->setTotalContentsSize(scrollingGeometry->contentSize);
454         node->setReachableContentsSize(scrollingGeometry->reachableContentSize);
455         node->setScrollableAreaSize(scrollingGeometry->scrollableAreaSize);
456 #if ENABLE(CSS_SCROLL_SNAP)
457         setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, scrollingGeometry->horizontalSnapOffsets, m_page->deviceScaleFactor());
458         setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, scrollingGeometry->verticalSnapOffsets, m_page->deviceScaleFactor());
459 #endif
460     }
461 }
462
463 void AsyncScrollingCoordinator::updateViewportConstrainedNode(ScrollingNodeID nodeID, const ViewportConstraints& constraints, GraphicsLayer* graphicsLayer)
464 {
465     ASSERT(supportsFixedPositionLayers());
466
467     ScrollingStateNode* node = m_scrollingStateTree->stateNodeForID(nodeID);
468     if (!node)
469         return;
470
471     switch (constraints.constraintType()) {
472     case ViewportConstraints::FixedPositionConstraint: {
473         ScrollingStateFixedNode& fixedNode = downcast<ScrollingStateFixedNode>(*node);
474         fixedNode.setLayer(graphicsLayer);
475         fixedNode.updateConstraints((const FixedPositionViewportConstraints&)constraints);
476         break;
477     }
478     case ViewportConstraints::StickyPositionConstraint: {
479         ScrollingStateStickyNode& stickyNode = downcast<ScrollingStateStickyNode>(*node);
480         stickyNode.setLayer(graphicsLayer);
481         stickyNode.updateConstraints((const StickyPositionViewportConstraints&)constraints);
482         break;
483     }
484     }
485 }
486
487 void AsyncScrollingCoordinator::setSynchronousScrollingReasons(SynchronousScrollingReasons reasons)
488 {
489     if (!m_scrollingStateTree->rootStateNode())
490         return;
491
492     // The FrameView's GraphicsLayer is likely to be out-of-synch with the PlatformLayer
493     // at this point. So we'll update it before we switch back to main thread scrolling
494     // in order to avoid layer positioning bugs.
495     if (reasons)
496         updateMainFrameScrollLayerPosition();
497     m_scrollingStateTree->rootStateNode()->setSynchronousScrollingReasons(reasons);
498 }
499
500 void AsyncScrollingCoordinator::updateMainFrameScrollLayerPosition()
501 {
502     ASSERT(isMainThread());
503
504     if (!m_page)
505         return;
506
507     FrameView* frameView = m_page->mainFrame().view();
508     if (!frameView)
509         return;
510
511     if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(*frameView))
512         scrollLayer->setPosition(-frameView->scrollPosition());
513 }
514
515 bool AsyncScrollingCoordinator::isRubberBandInProgress() const
516 {
517     return scrollingTree()->isRubberBandInProgress();
518 }
519
520 void AsyncScrollingCoordinator::setScrollPinningBehavior(ScrollPinningBehavior pinning)
521 {
522     scrollingTree()->setScrollPinningBehavior(pinning);
523 }
524
525 String AsyncScrollingCoordinator::scrollingStateTreeAsText() const
526 {
527     if (m_scrollingStateTree->rootStateNode()) {
528         if (m_nonFastScrollableRegionDirty)
529             m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(computeNonFastScrollableRegion(m_page->mainFrame(), IntPoint()));
530         return m_scrollingStateTree->rootStateNode()->scrollingStateTreeAsText();
531     }
532
533     return String();
534 }
535
536 } // namespace WebCore
537
538 #endif // ENABLE(ASYNC_SCROLLING)