Promote main thread assertions related to sendWithAsyncReply() to be release assertions
[WebKit-https.git] / Source / WebCore / page / scrolling / AsyncScrollingCoordinator.cpp
1 /*
2  * Copyright (C) 2014-2015 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 "DebugPageOverlays.h"
32 #include "Document.h"
33 #include "EditorClient.h"
34 #include "Frame.h"
35 #include "FrameView.h"
36 #include "GraphicsLayer.h"
37 #include "Logging.h"
38 #include "Page.h"
39 #include "PerformanceLoggingClient.h"
40 #include "RenderLayerCompositor.h"
41 #include "RenderView.h"
42 #include "ScrollAnimator.h"
43 #include "ScrollingConstraints.h"
44 #include "ScrollingStateFixedNode.h"
45 #include "ScrollingStateFrameHostingNode.h"
46 #include "ScrollingStateFrameScrollingNode.h"
47 #include "ScrollingStateOverflowScrollProxyNode.h"
48 #include "ScrollingStateOverflowScrollingNode.h"
49 #include "ScrollingStatePositionedNode.h"
50 #include "ScrollingStateStickyNode.h"
51 #include "ScrollingStateTree.h"
52 #include "Settings.h"
53 #include "WheelEventTestMonitor.h"
54 #include <wtf/ProcessID.h>
55 #include <wtf/text/TextStream.h>
56
57 namespace WebCore {
58
59 AsyncScrollingCoordinator::AsyncScrollingCoordinator(Page* page)
60     : ScrollingCoordinator(page)
61     , m_updateNodeScrollPositionTimer(*this, &AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScrollTimerFired)
62     , m_scrollingStateTree(makeUnique<ScrollingStateTree>(this))
63 {
64 }
65
66 AsyncScrollingCoordinator::~AsyncScrollingCoordinator() = default;
67
68 void AsyncScrollingCoordinator::scrollingStateTreePropertiesChanged()
69 {
70     scheduleTreeStateCommit();
71 }
72
73 #if ENABLE(CSS_SCROLL_SNAP)
74 static inline void setStateScrollingNodeSnapOffsetsAsFloat(ScrollingStateScrollingNode& node, ScrollEventAxis axis, const Vector<LayoutUnit>* snapOffsets, const Vector<ScrollOffsetRange<LayoutUnit>>* snapOffsetRanges, float deviceScaleFactor)
75 {
76     // 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?
77     Vector<float> snapOffsetsAsFloat;
78     if (snapOffsets) {
79         snapOffsetsAsFloat.reserveInitialCapacity(snapOffsets->size());
80         for (auto& offset : *snapOffsets)
81             snapOffsetsAsFloat.uncheckedAppend(roundToDevicePixel(offset, deviceScaleFactor, false));
82     }
83
84     Vector<ScrollOffsetRange<float>> snapOffsetRangesAsFloat;
85     if (snapOffsetRanges) {
86         snapOffsetRangesAsFloat.reserveInitialCapacity(snapOffsetRanges->size());
87         for (auto& range : *snapOffsetRanges)
88             snapOffsetRangesAsFloat.uncheckedAppend({ roundToDevicePixel(range.start, deviceScaleFactor, false), roundToDevicePixel(range.end, deviceScaleFactor, false) });
89     }
90     if (axis == ScrollEventAxis::Horizontal) {
91         node.setHorizontalSnapOffsets(snapOffsetsAsFloat);
92         node.setHorizontalSnapOffsetRanges(snapOffsetRangesAsFloat);
93     } else {
94         node.setVerticalSnapOffsets(snapOffsetsAsFloat);
95         node.setVerticalSnapOffsetRanges(snapOffsetRangesAsFloat);
96     }
97 }
98 #endif
99
100 void AsyncScrollingCoordinator::setEventTrackingRegionsDirty()
101 {
102     m_eventTrackingRegionsDirty = true;
103     // We have to schedule a commit, but the computed non-fast region may not have actually changed.
104     scheduleTreeStateCommit();
105 }
106
107 void AsyncScrollingCoordinator::willCommitTree()
108 {
109     updateEventTrackingRegions();
110 }
111
112 void AsyncScrollingCoordinator::updateEventTrackingRegions()
113 {
114     if (!m_eventTrackingRegionsDirty)
115         return;
116
117     if (!m_scrollingStateTree->rootStateNode())
118         return;
119
120     m_scrollingStateTree->rootStateNode()->setEventTrackingRegions(absoluteEventTrackingRegions());
121     m_eventTrackingRegionsDirty = false;
122 }
123
124 void AsyncScrollingCoordinator::frameViewLayoutUpdated(FrameView& frameView)
125 {
126     ASSERT(isMainThread());
127     ASSERT(m_page);
128
129     // If there isn't a root node yet, don't do anything. We'll be called again after creating one.
130     if (!m_scrollingStateTree->rootStateNode())
131         return;
132
133     setEventTrackingRegionsDirty();
134
135 #if PLATFORM(COCOA)
136     if (!coordinatesScrollingForFrameView(frameView))
137         return;
138
139     auto* page = frameView.frame().page();
140     if (page && page->isMonitoringWheelEvents()) {
141         LOG_WITH_STREAM(WheelEventTestMonitor, stream << "    AsyncScrollingCoordinator::frameViewLayoutUpdated: Expects wheel event test trigger: " << page->isMonitoringWheelEvents());
142
143         auto* node = m_scrollingStateTree->stateNodeForID(frameView.scrollingNodeID());
144         if (!is<ScrollingStateFrameScrollingNode>(node))
145             return;
146
147         auto& frameScrollingNode = downcast<ScrollingStateFrameScrollingNode>(*node);
148         frameScrollingNode.setIsMonitoringWheelEvents(page->isMonitoringWheelEvents());
149     }
150 #else
151     UNUSED_PARAM(frameView);
152 #endif
153 }
154
155 void AsyncScrollingCoordinator::frameViewVisualViewportChanged(FrameView& frameView)
156 {
157     ASSERT(isMainThread());
158     ASSERT(m_page);
159
160     if (!coordinatesScrollingForFrameView(frameView))
161         return;
162     
163     // If the root layer does not have a ScrollingStateNode, then we should create one.
164     auto* node = m_scrollingStateTree->stateNodeForID(frameView.scrollingNodeID());
165     if (!node)
166         return;
167
168     auto& frameScrollingNode = downcast<ScrollingStateFrameScrollingNode>(*node);
169
170     auto visualViewportIsSmallerThanLayoutViewport = [](const FrameView& frameView) {
171         auto layoutViewport = frameView.layoutViewportRect();
172         auto visualViewport = frameView.visualViewportRect();
173         return visualViewport.width() < layoutViewport.width() || visualViewport.height() < layoutViewport.height();
174     };
175     frameScrollingNode.setVisualViewportIsSmallerThanLayoutViewport(visualViewportIsSmallerThanLayoutViewport(frameView));
176 }
177
178 void AsyncScrollingCoordinator::updateIsMonitoringWheelEventsForFrameView(const FrameView& frameView)
179 {
180     auto* page = frameView.frame().page();
181     if (!page)
182         return;
183
184     auto* node = downcast<ScrollingStateFrameScrollingNode>(m_scrollingStateTree->stateNodeForID(frameView.scrollingNodeID()));
185     if (!node)
186         return;
187
188     node->setIsMonitoringWheelEvents(page->isMonitoringWheelEvents());
189 }
190
191 void AsyncScrollingCoordinator::frameViewEventTrackingRegionsChanged(FrameView& frameView)
192 {
193     if (!m_scrollingStateTree->rootStateNode())
194         return;
195
196     setEventTrackingRegionsDirty();
197     DebugPageOverlays::didChangeEventHandlers(frameView.frame());
198 }
199
200 void AsyncScrollingCoordinator::frameViewRootLayerDidChange(FrameView& frameView)
201 {
202     ASSERT(isMainThread());
203     ASSERT(m_page);
204
205     if (!coordinatesScrollingForFrameView(frameView))
206         return;
207     
208     // FIXME: In some navigation scenarios, the FrameView has no RenderView or that RenderView has not been composited.
209     // This needs cleaning up: https://bugs.webkit.org/show_bug.cgi?id=132724
210     if (!frameView.scrollingNodeID())
211         return;
212     
213     // If the root layer does not have a ScrollingStateNode, then we should create one.
214     ensureRootStateNodeForFrameView(frameView);
215     ASSERT(m_scrollingStateTree->stateNodeForID(frameView.scrollingNodeID()));
216
217     ScrollingCoordinator::frameViewRootLayerDidChange(frameView);
218
219     auto* node = downcast<ScrollingStateFrameScrollingNode>(m_scrollingStateTree->stateNodeForID(frameView.scrollingNodeID()));
220     node->setScrollContainerLayer(scrollContainerLayerForFrameView(frameView));
221     node->setScrolledContentsLayer(scrolledContentsLayerForFrameView(frameView));
222     node->setRootContentsLayer(rootContentsLayerForFrameView(frameView));
223     node->setCounterScrollingLayer(counterScrollingLayerForFrameView(frameView));
224     node->setInsetClipLayer(insetClipLayerForFrameView(frameView));
225     node->setContentShadowLayer(contentShadowLayerForFrameView(frameView));
226     node->setHeaderLayer(headerLayerForFrameView(frameView));
227     node->setFooterLayer(footerLayerForFrameView(frameView));
228     node->setScrollBehaviorForFixedElements(frameView.scrollBehaviorForFixedElements());
229     node->setVerticalScrollbarLayer(frameView.layerForVerticalScrollbar());
230     node->setHorizontalScrollbarLayer(frameView.layerForHorizontalScrollbar());
231 }
232
233 bool AsyncScrollingCoordinator::requestScrollPositionUpdate(ScrollableArea& scrollableArea, const IntPoint& scrollPosition)
234 {
235     ASSERT(isMainThread());
236     ASSERT(m_page);
237
238     auto scrollingNodeID = scrollableArea.scrollingNodeID();
239     if (!scrollingNodeID)
240         return false;
241
242     auto* frameView = frameViewForScrollingNode(scrollingNodeID);
243     if (!frameView)
244         return false;
245
246     if (!coordinatesScrollingForFrameView(*frameView))
247         return false;
248
249     bool inBackForwardCache = frameView->frame().document()->backForwardCacheState() != Document::NotInBackForwardCache;
250     bool inProgrammaticScroll = scrollableArea.currentScrollType() == ScrollType::Programmatic;
251     if (inProgrammaticScroll || inBackForwardCache)
252         updateScrollPositionAfterAsyncScroll(scrollingNodeID, scrollPosition, { }, ScrollType::Programmatic, ScrollingLayerPositionAction::Set);
253
254     // If this frame view's document is being put into the back/forward cache, we don't want to update our
255     // main frame scroll position. Just let the FrameView think that we did.
256     if (inBackForwardCache)
257         return true;
258
259     auto* stateNode = downcast<ScrollingStateScrollingNode>(m_scrollingStateTree->stateNodeForID(scrollingNodeID));
260     if (!stateNode)
261         return false;
262
263     stateNode->setRequestedScrollPosition(scrollPosition, inProgrammaticScroll);
264     return true;
265 }
266
267 void AsyncScrollingCoordinator::applyScrollingTreeLayerPositions()
268 {
269     m_scrollingTree->applyLayerPositions();
270 }
271
272 void AsyncScrollingCoordinator::scheduleUpdateScrollPositionAfterAsyncScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, ScrollingLayerPositionAction scrollingLayerPositionAction)
273 {
274     ScheduledScrollUpdate scrollUpdate(nodeID, scrollPosition, layoutViewportOrigin, scrollingLayerPositionAction);
275     
276     if (m_updateNodeScrollPositionTimer.isActive()) {
277         if (m_scheduledScrollUpdate.matchesUpdateType(scrollUpdate)) {
278             m_scheduledScrollUpdate.scrollPosition = scrollPosition;
279             m_scheduledScrollUpdate.layoutViewportOrigin = layoutViewportOrigin;
280             return;
281         }
282     
283         // If the parameters don't match what was previously scheduled, dispatch immediately.
284         m_updateNodeScrollPositionTimer.stop();
285         updateScrollPositionAfterAsyncScroll(m_scheduledScrollUpdate.nodeID, m_scheduledScrollUpdate.scrollPosition, m_scheduledScrollUpdate.layoutViewportOrigin, ScrollType::User, m_scheduledScrollUpdate.updateLayerPositionAction);
286         updateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, layoutViewportOrigin, ScrollType::User, scrollingLayerPositionAction);
287         return;
288     }
289
290     m_scheduledScrollUpdate = scrollUpdate;
291     m_updateNodeScrollPositionTimer.startOneShot(0_s);
292 }
293
294 void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScrollTimerFired()
295 {
296     updateScrollPositionAfterAsyncScroll(m_scheduledScrollUpdate.nodeID, m_scheduledScrollUpdate.scrollPosition, m_scheduledScrollUpdate.layoutViewportOrigin, ScrollType::User, m_scheduledScrollUpdate.updateLayerPositionAction);
297 }
298
299 FrameView* AsyncScrollingCoordinator::frameViewForScrollingNode(ScrollingNodeID scrollingNodeID) const
300 {
301     if (!m_scrollingStateTree->rootStateNode())
302         return nullptr;
303     
304     if (scrollingNodeID == m_scrollingStateTree->rootStateNode()->scrollingNodeID())
305         return m_page->mainFrame().view();
306
307     auto* stateNode = m_scrollingStateTree->stateNodeForID(scrollingNodeID);
308     if (!stateNode)
309         return nullptr;
310
311     // Find the enclosing frame scrolling node.
312     auto* parentNode = stateNode;
313     while (parentNode && !parentNode->isFrameScrollingNode())
314         parentNode = parentNode->parent();
315     
316     if (!parentNode)
317         return nullptr;
318     
319     // Walk the frame tree to find the matching FrameView. This is not ideal, but avoids back pointers to FrameViews
320     // from ScrollingTreeStateNodes.
321     for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
322         if (auto* view = frame->view()) {
323             if (view->scrollingNodeID() == parentNode->scrollingNodeID())
324                 return view;
325         }
326     }
327
328     return nullptr;
329 }
330
331 void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNodeID scrollingNodeID, const FloatPoint& scrollPosition, Optional<FloatPoint> layoutViewportOrigin, ScrollType scrollType, ScrollingLayerPositionAction scrollingLayerPositionAction)
332 {
333     ASSERT(isMainThread());
334
335     if (!m_page)
336         return;
337
338     auto* frameViewPtr = frameViewForScrollingNode(scrollingNodeID);
339     if (!frameViewPtr)
340         return;
341
342     LOG_WITH_STREAM(Scrolling, stream << "AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll node " << scrollingNodeID << " scrollPosition " << scrollPosition << " action " << scrollingLayerPositionAction);
343
344     auto& frameView = *frameViewPtr;
345     
346     if (!frameViewPtr->frame().isMainFrame()) {
347         if (scrollingLayerPositionAction == ScrollingLayerPositionAction::Set)
348             m_page->editorClient().subFrameScrollPositionChanged();
349     }
350
351     if (scrollingNodeID == frameView.scrollingNodeID()) {
352         reconcileScrollingState(frameView, scrollPosition, layoutViewportOrigin, scrollType, ViewportRectStability::Stable, scrollingLayerPositionAction);
353         return;
354     }
355
356     // Overflow-scroll area.
357     if (auto* scrollableArea = frameView.scrollableAreaForScrollLayerID(scrollingNodeID)) {
358         auto previousScrollType = scrollableArea->currentScrollType();
359         scrollableArea->setCurrentScrollType(scrollType);
360         scrollableArea->scrollToOffsetWithoutAnimation(ScrollableArea::scrollOffsetFromPosition(scrollPosition, toFloatSize(scrollableArea->scrollOrigin())));
361         scrollableArea->setCurrentScrollType(previousScrollType);
362
363         if (scrollingLayerPositionAction == ScrollingLayerPositionAction::Set)
364             m_page->editorClient().overflowScrollPositionChanged();
365     }
366 }
367
368 void AsyncScrollingCoordinator::reconcileScrollingState(FrameView& frameView, const FloatPoint& scrollPosition, const LayoutViewportOriginOrOverrideRect& layoutViewportOriginOrOverrideRect, ScrollType scrollType, ViewportRectStability viewportRectStability, ScrollingLayerPositionAction scrollingLayerPositionAction)
369 {
370     auto previousScrollType = frameView.currentScrollType();
371     frameView.setCurrentScrollType(scrollType);
372
373     LOG_WITH_STREAM(Scrolling, stream << getCurrentProcessID() << " AsyncScrollingCoordinator " << this << " reconcileScrollingState scrollPosition " << scrollPosition << " type " << scrollType << " stability " << viewportRectStability << " " << scrollingLayerPositionAction);
374
375     Optional<FloatRect> layoutViewportRect;
376
377     WTF::switchOn(layoutViewportOriginOrOverrideRect,
378         [&frameView](Optional<FloatPoint> origin) {
379             if (origin)
380                 frameView.setBaseLayoutViewportOrigin(LayoutPoint(origin.value()), FrameView::TriggerLayoutOrNot::No);
381         }, [&frameView, &layoutViewportRect, viewportRectStability](Optional<FloatRect> overrideRect) {
382             if (!overrideRect)
383                 return;
384
385             layoutViewportRect = overrideRect;
386             if (viewportRectStability != ViewportRectStability::ChangingObscuredInsetsInteractively)
387                 frameView.setLayoutViewportOverrideRect(LayoutRect(overrideRect.value()), viewportRectStability == ViewportRectStability::Stable ? FrameView::TriggerLayoutOrNot::Yes : FrameView::TriggerLayoutOrNot::No);
388         }
389     );
390
391     frameView.setConstrainsScrollingToContentEdge(false);
392     frameView.notifyScrollPositionChanged(roundedIntPoint(scrollPosition));
393     frameView.setConstrainsScrollingToContentEdge(true);
394
395     frameView.setCurrentScrollType(previousScrollType);
396
397     if (scrollType == ScrollType::User && scrollingLayerPositionAction != ScrollingLayerPositionAction::Set) {
398         auto scrollingNodeID = frameView.scrollingNodeID();
399         if (viewportRectStability == ViewportRectStability::Stable)
400             reconcileViewportConstrainedLayerPositions(scrollingNodeID, frameView.rectForFixedPositionLayout(), scrollingLayerPositionAction);
401         else if (layoutViewportRect)
402             reconcileViewportConstrainedLayerPositions(scrollingNodeID, LayoutRect(layoutViewportRect.value()), scrollingLayerPositionAction);
403     }
404
405     if (!scrolledContentsLayerForFrameView(frameView))
406         return;
407
408     auto* counterScrollingLayer = counterScrollingLayerForFrameView(frameView);
409     auto* insetClipLayer = insetClipLayerForFrameView(frameView);
410     auto* contentShadowLayer = contentShadowLayerForFrameView(frameView);
411     auto* rootContentsLayer = rootContentsLayerForFrameView(frameView);
412     auto* headerLayer = headerLayerForFrameView(frameView);
413     auto* footerLayer = footerLayerForFrameView(frameView);
414
415     ASSERT(frameView.scrollPosition() == roundedIntPoint(scrollPosition));
416     LayoutPoint scrollPositionForFixed = frameView.scrollPositionForFixedPosition();
417     float topContentInset = frameView.topContentInset();
418
419     FloatPoint positionForInsetClipLayer;
420     if (insetClipLayer)
421         positionForInsetClipLayer = FloatPoint(insetClipLayer->position().x(), FrameView::yPositionForInsetClipLayer(scrollPosition, topContentInset));
422     FloatPoint positionForContentsLayer = frameView.positionForRootContentLayer();
423     
424     FloatPoint positionForHeaderLayer = FloatPoint(scrollPositionForFixed.x(), FrameView::yPositionForHeaderLayer(scrollPosition, topContentInset));
425     FloatPoint positionForFooterLayer = FloatPoint(scrollPositionForFixed.x(),
426         FrameView::yPositionForFooterLayer(scrollPosition, topContentInset, frameView.totalContentsSize().height(), frameView.footerHeight()));
427
428     if (scrollType == ScrollType::Programmatic || scrollingLayerPositionAction == ScrollingLayerPositionAction::Set) {
429         reconcileScrollPosition(frameView, ScrollingLayerPositionAction::Set);
430
431         if (counterScrollingLayer)
432             counterScrollingLayer->setPosition(scrollPositionForFixed);
433         if (insetClipLayer)
434             insetClipLayer->setPosition(positionForInsetClipLayer);
435         if (contentShadowLayer)
436             contentShadowLayer->setPosition(positionForContentsLayer);
437         if (rootContentsLayer)
438             rootContentsLayer->setPosition(positionForContentsLayer);
439         if (headerLayer)
440             headerLayer->setPosition(positionForHeaderLayer);
441         if (footerLayer)
442             footerLayer->setPosition(positionForFooterLayer);
443     } else {
444         reconcileScrollPosition(frameView, ScrollingLayerPositionAction::Sync);
445
446         if (counterScrollingLayer)
447             counterScrollingLayer->syncPosition(scrollPositionForFixed);
448         if (insetClipLayer)
449             insetClipLayer->syncPosition(positionForInsetClipLayer);
450         if (contentShadowLayer)
451             contentShadowLayer->syncPosition(positionForContentsLayer);
452         if (rootContentsLayer)
453             rootContentsLayer->syncPosition(positionForContentsLayer);
454         if (headerLayer)
455             headerLayer->syncPosition(positionForHeaderLayer);
456         if (footerLayer)
457             footerLayer->syncPosition(positionForFooterLayer);
458     }
459 }
460
461 void AsyncScrollingCoordinator::reconcileScrollPosition(FrameView& frameView, ScrollingLayerPositionAction scrollingLayerPositionAction)
462 {
463 #if PLATFORM(IOS_FAMILY)
464     // Doing all scrolling like this (UIScrollView style) would simplify code.
465     auto* scrollContainerLayer = scrollContainerLayerForFrameView(frameView);
466     if (!scrollContainerLayer)
467         return;
468     if (scrollingLayerPositionAction == ScrollingLayerPositionAction::Set)
469         scrollContainerLayer->setBoundsOrigin(frameView.scrollPosition());
470     else
471         scrollContainerLayer->syncBoundsOrigin(frameView.scrollPosition());
472 #else
473     // This uses scrollPosition because the root content layer accounts for scrollOrigin (see FrameView::positionForRootContentLayer()).
474     auto* scrolledContentsLayer = scrolledContentsLayerForFrameView(frameView);
475     if (!scrolledContentsLayer)
476         return;
477     if (scrollingLayerPositionAction == ScrollingLayerPositionAction::Set)
478         scrolledContentsLayer->setPosition(-frameView.scrollPosition());
479     else
480         scrolledContentsLayer->syncPosition(-frameView.scrollPosition());
481 #endif
482 }
483
484 void AsyncScrollingCoordinator::scrollableAreaScrollbarLayerDidChange(ScrollableArea& scrollableArea, ScrollbarOrientation orientation)
485 {
486     ASSERT(isMainThread());
487     ASSERT(m_page);
488
489     auto* node = m_scrollingStateTree->stateNodeForID(scrollableArea.scrollingNodeID());
490     if (is<ScrollingStateScrollingNode>(node)) {
491         auto& scrollingNode = downcast<ScrollingStateScrollingNode>(*node);
492         if (orientation == VerticalScrollbar)
493             scrollingNode.setVerticalScrollbarLayer(scrollableArea.layerForVerticalScrollbar());
494         else
495             scrollingNode.setHorizontalScrollbarLayer(scrollableArea.layerForHorizontalScrollbar());
496     }
497
498     if (orientation == VerticalScrollbar)
499         scrollableArea.verticalScrollbarLayerDidChange();
500     else
501         scrollableArea.horizontalScrollbarLayerDidChange();
502 }
503
504 ScrollingNodeID AsyncScrollingCoordinator::createNode(ScrollingNodeType nodeType, ScrollingNodeID newNodeID)
505 {
506     LOG_WITH_STREAM(Scrolling, stream << "AsyncScrollingCoordinator::createNode " << nodeType << " node " << newNodeID);
507     return m_scrollingStateTree->createUnparentedNode(nodeType, newNodeID);
508 }
509
510 ScrollingNodeID AsyncScrollingCoordinator::insertNode(ScrollingNodeType nodeType, ScrollingNodeID newNodeID, ScrollingNodeID parentID, size_t childIndex)
511 {
512     LOG_WITH_STREAM(Scrolling, stream << "AsyncScrollingCoordinator::insertNode " << nodeType << " node " << newNodeID << " parent " << parentID << " index " << childIndex);
513     return m_scrollingStateTree->insertNode(nodeType, newNodeID, parentID, childIndex);
514 }
515
516 void AsyncScrollingCoordinator::unparentNode(ScrollingNodeID nodeID)
517 {
518     m_scrollingStateTree->unparentNode(nodeID);
519 }
520
521 void AsyncScrollingCoordinator::unparentChildrenAndDestroyNode(ScrollingNodeID nodeID)
522 {
523     m_scrollingStateTree->unparentChildrenAndDestroyNode(nodeID);
524 }
525
526 void AsyncScrollingCoordinator::detachAndDestroySubtree(ScrollingNodeID nodeID)
527 {
528     m_scrollingStateTree->detachAndDestroySubtree(nodeID);
529 }
530
531 void AsyncScrollingCoordinator::clearAllNodes()
532 {
533     m_scrollingStateTree->clear();
534 }
535
536 ScrollingNodeID AsyncScrollingCoordinator::parentOfNode(ScrollingNodeID nodeID) const
537 {
538     auto* scrollingNode = m_scrollingStateTree->stateNodeForID(nodeID);
539     if (!scrollingNode)
540         return 0;
541
542     return scrollingNode->parentNodeID();
543 }
544
545 Vector<ScrollingNodeID> AsyncScrollingCoordinator::childrenOfNode(ScrollingNodeID nodeID) const
546 {
547     auto* scrollingNode = m_scrollingStateTree->stateNodeForID(nodeID);
548     if (!scrollingNode)
549         return { };
550
551     auto* children = scrollingNode->children();
552     if (!children || children->isEmpty())
553         return { };
554     
555     Vector<ScrollingNodeID> childNodeIDs;
556     childNodeIDs.reserveInitialCapacity(children->size());
557     for (const auto& childNode : *children)
558         childNodeIDs.uncheckedAppend(childNode->scrollingNodeID());
559
560     return childNodeIDs;
561 }
562
563 void AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions(ScrollingNodeID scrollingNodeID, const LayoutRect& viewportRect, ScrollingLayerPositionAction action)
564 {
565     LOG_WITH_STREAM(Scrolling, stream << getCurrentProcessID() << " AsyncScrollingCoordinator::reconcileViewportConstrainedLayerPositions for viewport rect " << viewportRect << " and node " << scrollingNodeID);
566
567     m_scrollingStateTree->reconcileViewportConstrainedLayerPositions(scrollingNodeID, viewportRect, action);
568 }
569
570 void AsyncScrollingCoordinator::ensureRootStateNodeForFrameView(FrameView& frameView)
571 {
572     ASSERT(frameView.scrollingNodeID());
573     if (m_scrollingStateTree->stateNodeForID(frameView.scrollingNodeID()))
574         return;
575
576     // For non-main frames, it is only possible to arrive in this function from
577     // RenderLayerCompositor::updateBacking where the node has already been created.
578     ASSERT(frameView.frame().isMainFrame());
579     insertNode(ScrollingNodeType::MainFrame, frameView.scrollingNodeID(), 0, 0);
580 }
581
582 void AsyncScrollingCoordinator::setNodeLayers(ScrollingNodeID nodeID, const NodeLayers& nodeLayers)
583 {
584     auto* node = m_scrollingStateTree->stateNodeForID(nodeID);
585     ASSERT(node);
586     if (!node)
587         return;
588
589     node->setLayer(nodeLayers.layer);
590
591     if (is<ScrollingStateScrollingNode>(node)) {
592         auto& scrollingNode = downcast<ScrollingStateScrollingNode>(*node);
593         scrollingNode.setScrollContainerLayer(nodeLayers.scrollContainerLayer);
594         scrollingNode.setScrolledContentsLayer(nodeLayers.scrolledContentsLayer);
595         scrollingNode.setHorizontalScrollbarLayer(nodeLayers.horizontalScrollbarLayer);
596         scrollingNode.setVerticalScrollbarLayer(nodeLayers.verticalScrollbarLayer);
597
598         if (is<ScrollingStateFrameScrollingNode>(node)) {
599             auto& frameScrollingNode = downcast<ScrollingStateFrameScrollingNode>(*node);
600             frameScrollingNode.setInsetClipLayer(nodeLayers.insetClipLayer);
601             frameScrollingNode.setCounterScrollingLayer(nodeLayers.counterScrollingLayer);
602             frameScrollingNode.setRootContentsLayer(nodeLayers.rootContentsLayer);
603         }
604     }
605 }
606
607 void AsyncScrollingCoordinator::setRectRelativeToParentNode(ScrollingNodeID nodeID, const LayoutRect& parentRelativeScrollableRect)
608 {
609     auto* stateNode = m_scrollingStateTree->stateNodeForID(nodeID);
610     ASSERT(stateNode);
611     if (!stateNode)
612         return;
613
614     if (is<ScrollingStateFrameHostingNode>(*stateNode)) {
615         auto& frameHostingStateNode = downcast<ScrollingStateFrameHostingNode>(*stateNode);
616         frameHostingStateNode.setParentRelativeScrollableRect(parentRelativeScrollableRect);
617         return;
618     }
619
620     if (is<ScrollingStateScrollingNode>(stateNode)) {
621         auto& scrollingStateNode = downcast<ScrollingStateScrollingNode>(*stateNode);
622         scrollingStateNode.setParentRelativeScrollableRect(parentRelativeScrollableRect);
623     }
624 }
625
626 void AsyncScrollingCoordinator::setFrameScrollingNodeState(ScrollingNodeID nodeID, const FrameView& frameView)
627 {
628     auto* stateNode = m_scrollingStateTree->stateNodeForID(nodeID);
629     ASSERT(stateNode);
630     if (!is<ScrollingStateFrameScrollingNode>(stateNode))
631         return;
632
633     auto& frameScrollingNode = downcast<ScrollingStateFrameScrollingNode>(*stateNode);
634
635     frameScrollingNode.setFrameScaleFactor(frameView.frame().frameScaleFactor());
636     frameScrollingNode.setHeaderHeight(frameView.headerHeight());
637     frameScrollingNode.setFooterHeight(frameView.footerHeight());
638     frameScrollingNode.setTopContentInset(frameView.topContentInset());
639     frameScrollingNode.setLayoutViewport(frameView.layoutViewportRect());
640     frameScrollingNode.setAsyncFrameOrOverflowScrollingEnabled(asyncFrameOrOverflowScrollingEnabled());
641
642     frameScrollingNode.setMinLayoutViewportOrigin(frameView.minStableLayoutViewportOrigin());
643     frameScrollingNode.setMaxLayoutViewportOrigin(frameView.maxStableLayoutViewportOrigin());
644
645     if (auto visualOverrideRect = frameView.visualViewportOverrideRect())
646         frameScrollingNode.setOverrideVisualViewportSize(FloatSize(visualOverrideRect.value().size()));
647     else
648         frameScrollingNode.setOverrideVisualViewportSize(WTF::nullopt);
649
650     frameScrollingNode.setFixedElementsLayoutRelativeToFrame(frameView.fixedElementsLayoutRelativeToFrame());
651
652     auto visualViewportIsSmallerThanLayoutViewport = [](const FrameView& frameView) {
653         auto layoutViewport = frameView.layoutViewportRect();
654         auto visualViewport = frameView.visualViewportRect();
655         return visualViewport.width() < layoutViewport.width() || visualViewport.height() < layoutViewport.height();
656     };
657     frameScrollingNode.setVisualViewportIsSmallerThanLayoutViewport(visualViewportIsSmallerThanLayoutViewport(frameView));
658     
659     frameScrollingNode.setScrollBehaviorForFixedElements(frameView.scrollBehaviorForFixedElements());
660 }
661
662 void AsyncScrollingCoordinator::setScrollingNodeScrollableAreaGeometry(ScrollingNodeID nodeID, ScrollableArea& scrollableArea)
663 {
664     auto* stateNode = m_scrollingStateTree->stateNodeForID(nodeID);
665     ASSERT(stateNode);
666     if (!stateNode)
667         return;
668
669     auto& scrollingNode = downcast<ScrollingStateScrollingNode>(*stateNode);
670
671     auto* verticalScrollbar = scrollableArea.verticalScrollbar();
672     auto* horizontalScrollbar = scrollableArea.horizontalScrollbar();
673     scrollingNode.setScrollerImpsFromScrollbars(verticalScrollbar, horizontalScrollbar);
674
675     scrollingNode.setScrollOrigin(scrollableArea.scrollOrigin());
676     scrollingNode.setScrollPosition(scrollableArea.scrollPosition());
677     scrollingNode.setTotalContentsSize(scrollableArea.totalContentsSize());
678     scrollingNode.setReachableContentsSize(scrollableArea.reachableTotalContentsSize());
679     scrollingNode.setScrollableAreaSize(scrollableArea.visibleSize());
680
681     ScrollableAreaParameters scrollParameters;
682     scrollParameters.horizontalScrollElasticity = scrollableArea.horizontalScrollElasticity();
683     scrollParameters.verticalScrollElasticity = scrollableArea.verticalScrollElasticity();
684     scrollParameters.hasEnabledHorizontalScrollbar = horizontalScrollbar && horizontalScrollbar->enabled();
685     scrollParameters.hasEnabledVerticalScrollbar = verticalScrollbar && verticalScrollbar->enabled();
686     scrollParameters.horizontalScrollbarMode = scrollableArea.horizontalScrollbarMode();
687     scrollParameters.verticalScrollbarMode = scrollableArea.verticalScrollbarMode();
688     scrollParameters.horizontalScrollbarHiddenByStyle = scrollableArea.horizontalScrollbarHiddenByStyle();
689     scrollParameters.verticalScrollbarHiddenByStyle = scrollableArea.verticalScrollbarHiddenByStyle();
690     scrollParameters.useDarkAppearanceForScrollbars = scrollableArea.useDarkAppearanceForScrollbars();
691
692     scrollingNode.setScrollableAreaParameters(scrollParameters);
693
694 #if ENABLE(CSS_SCROLL_SNAP)
695     scrollableArea.updateSnapOffsets();
696     setStateScrollingNodeSnapOffsetsAsFloat(scrollingNode, ScrollEventAxis::Horizontal, scrollableArea.horizontalSnapOffsets(), scrollableArea.horizontalSnapOffsetRanges(), m_page->deviceScaleFactor());
697     setStateScrollingNodeSnapOffsetsAsFloat(scrollingNode, ScrollEventAxis::Vertical, scrollableArea.verticalSnapOffsets(), scrollableArea.verticalSnapOffsetRanges(), m_page->deviceScaleFactor());
698     scrollingNode.setCurrentHorizontalSnapPointIndex(scrollableArea.currentHorizontalSnapPointIndex());
699     scrollingNode.setCurrentVerticalSnapPointIndex(scrollableArea.currentVerticalSnapPointIndex());
700 #endif
701 }
702
703 void AsyncScrollingCoordinator::setViewportConstraintedNodeConstraints(ScrollingNodeID nodeID, const ViewportConstraints& constraints)
704 {
705     auto* node = m_scrollingStateTree->stateNodeForID(nodeID);
706     if (!node)
707         return;
708
709     switch (constraints.constraintType()) {
710     case ViewportConstraints::FixedPositionConstraint: {
711         auto& fixedNode = downcast<ScrollingStateFixedNode>(*node);
712         fixedNode.updateConstraints((const FixedPositionViewportConstraints&)constraints);
713         break;
714     }
715     case ViewportConstraints::StickyPositionConstraint: {
716         auto& stickyNode = downcast<ScrollingStateStickyNode>(*node);
717         stickyNode.updateConstraints((const StickyPositionViewportConstraints&)constraints);
718         break;
719     }
720     }
721 }
722
723 void AsyncScrollingCoordinator::setPositionedNodeConstraints(ScrollingNodeID nodeID, const AbsolutePositionConstraints& constraints)
724 {
725     auto* node = m_scrollingStateTree->stateNodeForID(nodeID);
726     if (!node)
727         return;
728
729     ASSERT(is<ScrollingStatePositionedNode>(*node));
730     if (auto* positionedNode = downcast<ScrollingStatePositionedNode>(node))
731         positionedNode->updateConstraints(constraints);
732 }
733
734 void AsyncScrollingCoordinator::setRelatedOverflowScrollingNodes(ScrollingNodeID nodeID, Vector<ScrollingNodeID>&& relatedNodes)
735 {
736     auto* node = m_scrollingStateTree->stateNodeForID(nodeID);
737     if (!node)
738         return;
739
740     if (is<ScrollingStatePositionedNode>(node))
741         downcast<ScrollingStatePositionedNode>(node)->setRelatedOverflowScrollingNodes(WTFMove(relatedNodes));
742     else if (is<ScrollingStateOverflowScrollProxyNode>(node)) {
743         auto* overflowScrollProxyNode = downcast<ScrollingStateOverflowScrollProxyNode>(node);
744         if (!relatedNodes.isEmpty())
745             overflowScrollProxyNode->setOverflowScrollingNode(relatedNodes[0]);
746         else
747             overflowScrollProxyNode->setOverflowScrollingNode(0);
748     } else
749         ASSERT_NOT_REACHED();
750 }
751
752 void AsyncScrollingCoordinator::setSynchronousScrollingReasons(FrameView& frameView, SynchronousScrollingReasons reasons)
753 {
754     auto* scrollingStateNode = static_cast<ScrollingStateFrameScrollingNode*>(m_scrollingStateTree->stateNodeForID(frameView.scrollingNodeID()));
755     if (!scrollingStateNode)
756         return;
757
758     // The FrameView's GraphicsLayer is likely to be out-of-synch with the PlatformLayer
759     // at this point. So we'll update it before we switch back to main thread scrolling
760     // in order to avoid layer positioning bugs.
761     if (reasons)
762         reconcileScrollPosition(frameView, ScrollingLayerPositionAction::Set);
763     scrollingStateNode->setSynchronousScrollingReasons(reasons);
764 }
765
766 bool AsyncScrollingCoordinator::isRubberBandInProgress() const
767 {
768     return scrollingTree()->isRubberBandInProgress();
769 }
770
771 void AsyncScrollingCoordinator::setScrollPinningBehavior(ScrollPinningBehavior pinning)
772 {
773     scrollingTree()->setScrollPinningBehavior(pinning);
774 }
775
776 bool AsyncScrollingCoordinator::asyncFrameOrOverflowScrollingEnabled() const
777 {
778     auto& settings = m_page->mainFrame().settings();
779     return settings.asyncFrameScrollingEnabled() || settings.asyncOverflowScrollingEnabled();
780 }
781
782 ScrollingNodeID AsyncScrollingCoordinator::scrollableContainerNodeID(const RenderObject& renderer) const
783 {
784     if (auto overflowScrollingNodeID = renderer.view().compositor().asyncScrollableContainerNodeID(renderer))
785         return overflowScrollingNodeID;
786
787     // If we're in a scrollable frame, return that.
788     auto* frameView = renderer.frame().view();
789     if (!frameView)
790         return 0;
791
792     if (auto scrollingNodeID = frameView->scrollingNodeID())
793         return scrollingNodeID;
794
795     // Otherwise, look for a scrollable element in the containing frame.
796     if (auto* ownerElement = renderer.document().ownerElement()) {
797         if (auto* frameRenderer = ownerElement->renderer())
798             return scrollableContainerNodeID(*frameRenderer);
799     }
800
801     return 0;
802 }
803
804 String AsyncScrollingCoordinator::scrollingStateTreeAsText(ScrollingStateTreeAsTextBehavior behavior) const
805 {
806     if (m_scrollingStateTree->rootStateNode()) {
807         if (m_eventTrackingRegionsDirty)
808             m_scrollingStateTree->rootStateNode()->setEventTrackingRegions(absoluteEventTrackingRegions());
809         return m_scrollingStateTree->rootStateNode()->scrollingStateTreeAsText(behavior);
810     }
811
812     return String();
813 }
814
815 #if PLATFORM(COCOA)
816 void AsyncScrollingCoordinator::setActiveScrollSnapIndices(ScrollingNodeID scrollingNodeID, unsigned horizontalIndex, unsigned verticalIndex)
817 {
818     ASSERT(isMainThread());
819     
820     if (!m_page)
821         return;
822     
823     auto* frameView = frameViewForScrollingNode(scrollingNodeID);
824     if (!frameView)
825         return;
826     
827     if (scrollingNodeID == frameView->scrollingNodeID()) {
828         frameView->setCurrentHorizontalSnapPointIndex(horizontalIndex);
829         frameView->setCurrentVerticalSnapPointIndex(verticalIndex);
830         return;
831     }
832     
833     // Overflow-scroll area.
834     if (auto* scrollableArea = frameView->scrollableAreaForScrollLayerID(scrollingNodeID)) {
835         scrollableArea->setCurrentHorizontalSnapPointIndex(horizontalIndex);
836         scrollableArea->setCurrentVerticalSnapPointIndex(verticalIndex);
837     }
838 }
839
840 void AsyncScrollingCoordinator::deferWheelEventTestCompletionForReason(WheelEventTestMonitor::ScrollableAreaIdentifier identifier, WheelEventTestMonitor::DeferReason reason) const
841 {
842     ASSERT(isMainThread());
843     if (!m_page || !m_page->isMonitoringWheelEvents())
844         return;
845
846     if (const auto& trigger = m_page->wheelEventTestMonitor()) {
847         LOG_WITH_STREAM(WheelEventTestMonitor, stream << "    (!) AsyncScrollingCoordinator::deferForReason: Deferring " << identifier << " for reason " << reason);
848         trigger->deferForReason(identifier, reason);
849     }
850 }
851
852 void AsyncScrollingCoordinator::removeWheelEventTestCompletionDeferralForReason(WheelEventTestMonitor::ScrollableAreaIdentifier identifier, WheelEventTestMonitor::DeferReason reason) const
853 {
854     ASSERT(isMainThread());
855     if (!m_page || !m_page->isMonitoringWheelEvents())
856         return;
857
858     if (const auto& trigger = m_page->wheelEventTestMonitor()) {
859         LOG_WITH_STREAM(WheelEventTestMonitor, stream << "    (!) AsyncScrollingCoordinator::removeWheelEventTestCompletionDeferralForReason: Deferring " << identifier << " for reason " << reason);
860         trigger->removeDeferralForReason(identifier, reason);
861     }
862 }
863 #endif
864
865 #if ENABLE(CSS_SCROLL_SNAP)
866 bool AsyncScrollingCoordinator::isScrollSnapInProgress() const
867 {
868     return scrollingTree()->isScrollSnapInProgress();
869 }
870
871 void AsyncScrollingCoordinator::updateScrollSnapPropertiesWithFrameView(const FrameView& frameView)
872 {
873     if (auto node = downcast<ScrollingStateFrameScrollingNode>(m_scrollingStateTree->stateNodeForID(frameView.scrollingNodeID()))) {
874         setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Horizontal, frameView.horizontalSnapOffsets(), frameView.horizontalSnapOffsetRanges(), m_page->deviceScaleFactor());
875         setStateScrollingNodeSnapOffsetsAsFloat(*node, ScrollEventAxis::Vertical, frameView.verticalSnapOffsets(), frameView.verticalSnapOffsetRanges(), m_page->deviceScaleFactor());
876         node->setCurrentHorizontalSnapPointIndex(frameView.currentHorizontalSnapPointIndex());
877         node->setCurrentVerticalSnapPointIndex(frameView.currentVerticalSnapPointIndex());
878     }
879 }
880 #endif
881
882 void AsyncScrollingCoordinator::reportExposedUnfilledArea(MonotonicTime timestamp, unsigned unfilledArea)
883 {
884     if (m_page && m_page->performanceLoggingClient())
885         m_page->performanceLoggingClient()->logScrollingEvent(PerformanceLoggingClient::ScrollingEvent::ExposedTilelessArea, timestamp, unfilledArea);
886 }
887
888 void AsyncScrollingCoordinator::reportSynchronousScrollingReasonsChanged(MonotonicTime timestamp, SynchronousScrollingReasons reasons)
889 {
890     if (m_page && m_page->performanceLoggingClient())
891         m_page->performanceLoggingClient()->logScrollingEvent(PerformanceLoggingClient::ScrollingEvent::SwitchedScrollingMode, timestamp, reasons);
892 }
893
894 } // namespace WebCore
895
896 #endif // ENABLE(ASYNC_SCROLLING)