Stub out scrolling tree classes for overflow scrolling nodes on macOS
[WebKit-https.git] / Source / WebCore / page / scrolling / ScrollingCoordinator.cpp
1 /*
2  * Copyright (C) 2011 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 #include "ScrollingCoordinator.h"
29
30 #include "Document.h"
31 #include "EventNames.h"
32 #include "Frame.h"
33 #include "FrameView.h"
34 #include "GraphicsLayer.h"
35 #include "Page.h"
36 #include "PlatformWheelEvent.h"
37 #include "PluginViewBase.h"
38 #include "Region.h"
39 #include "RenderLayerCompositor.h"
40 #include "RenderView.h"
41 #include "ScrollAnimator.h"
42 #include "Settings.h"
43 #include <wtf/MainThread.h>
44 #include <wtf/text/StringBuilder.h>
45 #include <wtf/text/TextStream.h>
46
47 namespace WebCore {
48
49 #if !PLATFORM(COCOA) && !USE(COORDINATED_GRAPHICS)
50 Ref<ScrollingCoordinator> ScrollingCoordinator::create(Page* page)
51 {
52     return adoptRef(*new ScrollingCoordinator(page));
53 }
54 #endif
55
56 ScrollingCoordinator::ScrollingCoordinator(Page* page)
57     : m_page(page)
58 {
59 }
60
61 ScrollingCoordinator::~ScrollingCoordinator()
62 {
63     ASSERT(!m_page);
64 }
65
66 void ScrollingCoordinator::pageDestroyed()
67 {
68     ASSERT(m_page);
69     m_page = nullptr;
70 }
71
72 bool ScrollingCoordinator::coordinatesScrollingForFrameView(const FrameView& frameView) const
73 {
74     ASSERT(isMainThread());
75     ASSERT(m_page);
76
77     if (!frameView.frame().isMainFrame() && !m_page->settings().scrollingTreeIncludesFrames()
78 #if PLATFORM(MAC)
79         && !m_page->settings().asyncFrameScrollingEnabled()
80 #endif
81     )
82         return false;
83
84     auto* renderView = frameView.frame().contentRenderer();
85     if (!renderView)
86         return false;
87     return renderView->usesCompositing();
88 }
89
90 bool ScrollingCoordinator::coordinatesScrollingForOverflowLayer(const RenderLayer& layer) const
91 {
92     ASSERT(isMainThread());
93     ASSERT(m_page);
94
95     return layer.hasCompositedScrollableOverflow();
96 }
97
98 EventTrackingRegions ScrollingCoordinator::absoluteEventTrackingRegionsForFrame(const Frame& frame) const
99 {
100     auto* renderView = frame.contentRenderer();
101     if (!renderView || renderView->renderTreeBeingDestroyed())
102         return EventTrackingRegions();
103
104 #if ENABLE(IOS_TOUCH_EVENTS)
105     // On iOS, we use nonFastScrollableRegion to represent the region covered by elements with touch event handlers.
106     ASSERT(frame.isMainFrame());
107     auto* document = frame.document();
108     if (!document)
109         return EventTrackingRegions();
110     return document->eventTrackingRegions();
111 #else
112     auto* frameView = frame.view();
113     if (!frameView)
114         return EventTrackingRegions();
115
116     Region nonFastScrollableRegion;
117
118     // FIXME: should ASSERT(!frameView->needsLayout()) here, but need to fix DebugPageOverlays
119     // to not ask for regions at bad times.
120
121     if (auto* scrollableAreas = frameView->scrollableAreas()) {
122         for (auto& scrollableArea : *scrollableAreas) {
123             // Composited scrollable areas can be scrolled off the main thread.
124             if (scrollableArea->usesAsyncScrolling())
125                 continue;
126
127             bool isInsideFixed;
128             IntRect box = scrollableArea->scrollableAreaBoundingBox(&isInsideFixed);
129             if (isInsideFixed)
130                 box = IntRect(frameView->fixedScrollableAreaBoundsInflatedForScrolling(LayoutRect(box)));
131
132             nonFastScrollableRegion.unite(box);
133         }
134     }
135
136     for (auto& widget : frameView->widgetsInRenderTree()) {
137         if (!is<PluginViewBase>(*widget))
138             continue;
139         if (!downcast<PluginViewBase>(*widget).wantsWheelEvents())
140             continue;
141         auto* renderWidget = RenderWidget::find(*widget);
142         if (!renderWidget)
143             continue;
144         nonFastScrollableRegion.unite(renderWidget->absoluteBoundingBoxRect());
145     }
146     
147     EventTrackingRegions eventTrackingRegions;
148
149     // FIXME: if we've already accounted for this subframe as a scrollable area, we can avoid recursing into it here.
150     for (auto* subframe = frame.tree().firstChild(); subframe; subframe = subframe->tree().nextSibling()) {
151         auto* subframeView = subframe->view();
152         if (!subframeView)
153             continue;
154
155         EventTrackingRegions subframeRegion = absoluteEventTrackingRegionsForFrame(*subframe);
156         // Map from the frame document to our document.
157         IntPoint offset = subframeView->contentsToContainingViewContents(IntPoint());
158
159         // FIXME: this translation ignores non-trival transforms on the frame.
160         subframeRegion.translate(toIntSize(offset));
161         eventTrackingRegions.unite(subframeRegion);
162     }
163
164     auto wheelHandlerRegion = frame.document()->absoluteRegionForEventTargets(frame.document()->wheelEventTargets());
165     bool wheelHandlerInFixedContent = wheelHandlerRegion.second;
166     if (wheelHandlerInFixedContent) {
167         // FIXME: need to handle position:sticky here too.
168         LayoutRect inflatedWheelHandlerBounds = frameView->fixedScrollableAreaBoundsInflatedForScrolling(LayoutRect(wheelHandlerRegion.first.bounds()));
169         wheelHandlerRegion.first.unite(enclosingIntRect(inflatedWheelHandlerBounds));
170     }
171     
172     nonFastScrollableRegion.unite(wheelHandlerRegion.first);
173
174     // FIXME: If this is not the main frame, we could clip the region to the frame's bounds.
175     eventTrackingRegions.uniteSynchronousRegion(eventNames().wheelEvent, nonFastScrollableRegion);
176
177     return eventTrackingRegions;
178 #endif
179 }
180
181 EventTrackingRegions ScrollingCoordinator::absoluteEventTrackingRegions() const
182 {
183     return absoluteEventTrackingRegionsForFrame(m_page->mainFrame());
184 }
185
186 void ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange(FrameView& frameView)
187 {
188     ASSERT(isMainThread());
189     ASSERT(m_page);
190
191     if (!coordinatesScrollingForFrameView(frameView))
192         return;
193
194     updateSynchronousScrollingReasons(frameView);
195 }
196
197 void ScrollingCoordinator::frameViewFixedObjectsDidChange(FrameView& frameView)
198 {
199     ASSERT(isMainThread());
200     ASSERT(m_page);
201
202     if (!coordinatesScrollingForFrameView(frameView))
203         return;
204
205     updateSynchronousScrollingReasons(frameView);
206 }
207
208 GraphicsLayer* ScrollingCoordinator::scrollLayerForScrollableArea(ScrollableArea& scrollableArea)
209 {
210     return scrollableArea.layerForScrolling();
211 }
212
213 GraphicsLayer* ScrollingCoordinator::scrollLayerForFrameView(FrameView& frameView)
214 {
215     if (auto* renderView = frameView.frame().contentRenderer())
216         return renderView->compositor().scrollLayer();
217     return nullptr;
218 }
219
220 GraphicsLayer* ScrollingCoordinator::headerLayerForFrameView(FrameView& frameView)
221 {
222 #if ENABLE(RUBBER_BANDING)
223     if (auto* renderView = frameView.frame().contentRenderer())
224         return renderView->compositor().headerLayer();
225     return nullptr;
226 #else
227     UNUSED_PARAM(frameView);
228     return nullptr;
229 #endif
230 }
231
232 GraphicsLayer* ScrollingCoordinator::footerLayerForFrameView(FrameView& frameView)
233 {
234 #if ENABLE(RUBBER_BANDING)
235     if (auto* renderView = frameView.frame().contentRenderer())
236         return renderView->compositor().footerLayer();
237     return nullptr;
238 #else
239     UNUSED_PARAM(frameView);
240     return nullptr;
241 #endif
242 }
243
244 GraphicsLayer* ScrollingCoordinator::counterScrollingLayerForFrameView(FrameView& frameView)
245 {
246     if (auto* renderView = frameView.frame().contentRenderer())
247         return renderView->compositor().fixedRootBackgroundLayer();
248     return nullptr;
249 }
250
251 GraphicsLayer* ScrollingCoordinator::insetClipLayerForFrameView(FrameView& frameView)
252 {
253     if (auto* renderView = frameView.frame().contentRenderer())
254         return renderView->compositor().clipLayer();
255     return nullptr;
256 }
257
258 GraphicsLayer* ScrollingCoordinator::contentShadowLayerForFrameView(FrameView& frameView)
259 {
260 #if ENABLE(RUBBER_BANDING)
261     if (auto* renderView = frameView.frame().contentRenderer())
262         return renderView->compositor().layerForContentShadow();
263     
264     return nullptr;
265 #else
266     UNUSED_PARAM(frameView);
267     return nullptr;
268 #endif
269 }
270
271 GraphicsLayer* ScrollingCoordinator::rootContentLayerForFrameView(FrameView& frameView)
272 {
273     if (auto* renderView = frameView.frame().contentRenderer())
274         return renderView->compositor().rootContentLayer();
275     return nullptr;
276 }
277
278 void ScrollingCoordinator::frameViewRootLayerDidChange(FrameView& frameView)
279 {
280     ASSERT(isMainThread());
281     ASSERT(m_page);
282
283     if (!coordinatesScrollingForFrameView(frameView))
284         return;
285
286     frameViewLayoutUpdated(frameView);
287     updateSynchronousScrollingReasons(frameView);
288 }
289
290 #if PLATFORM(COCOA)
291 void ScrollingCoordinator::handleWheelEventPhase(PlatformWheelEventPhase phase)
292 {
293     ASSERT(isMainThread());
294
295     if (!m_page)
296         return;
297
298     auto* frameView = m_page->mainFrame().view();
299     if (!frameView)
300         return;
301
302     frameView->scrollAnimator().handleWheelEventPhase(phase);
303 }
304 #endif
305
306 bool ScrollingCoordinator::hasVisibleSlowRepaintViewportConstrainedObjects(const FrameView& frameView) const
307 {
308     const FrameView::ViewportConstrainedObjectSet* viewportConstrainedObjects = frameView.viewportConstrainedObjects();
309     if (!viewportConstrainedObjects)
310         return false;
311
312     for (auto& viewportConstrainedObject : *viewportConstrainedObjects) {
313         if (!is<RenderBoxModelObject>(*viewportConstrainedObject) || !viewportConstrainedObject->hasLayer())
314             return true;
315         auto& layer = *downcast<RenderBoxModelObject>(*viewportConstrainedObject).layer();
316         // Any explicit reason that a fixed position element is not composited shouldn't cause slow scrolling.
317         if (!layer.isComposited() && layer.viewportConstrainedNotCompositedReason() == RenderLayer::NoNotCompositedReason)
318             return true;
319     }
320     return false;
321 }
322
323 SynchronousScrollingReasons ScrollingCoordinator::synchronousScrollingReasons(const FrameView& frameView) const
324 {
325     SynchronousScrollingReasons synchronousScrollingReasons = (SynchronousScrollingReasons)0;
326
327     if (m_forceSynchronousScrollLayerPositionUpdates)
328         synchronousScrollingReasons |= ForcedOnMainThread;
329     if (frameView.hasSlowRepaintObjects())
330         synchronousScrollingReasons |= HasSlowRepaintObjects;
331     if (hasVisibleSlowRepaintViewportConstrainedObjects(frameView))
332         synchronousScrollingReasons |= HasNonLayerViewportConstrainedObjects;
333     if (frameView.frame().mainFrame().document() && frameView.frame().document()->isImageDocument())
334         synchronousScrollingReasons |= IsImageDocument;
335
336     return synchronousScrollingReasons;
337 }
338
339 void ScrollingCoordinator::updateSynchronousScrollingReasons(FrameView& frameView)
340 {
341     ASSERT(coordinatesScrollingForFrameView(frameView));
342     setSynchronousScrollingReasons(frameView, synchronousScrollingReasons(frameView));
343 }
344
345 void ScrollingCoordinator::updateSynchronousScrollingReasonsForAllFrames()
346 {
347     for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
348         if (auto* frameView = frame->view()) {
349             if (coordinatesScrollingForFrameView(*frameView))
350                 updateSynchronousScrollingReasons(*frameView);
351         }
352     }
353 }
354
355 void ScrollingCoordinator::setForceSynchronousScrollLayerPositionUpdates(bool forceSynchronousScrollLayerPositionUpdates)
356 {
357     if (m_forceSynchronousScrollLayerPositionUpdates == forceSynchronousScrollLayerPositionUpdates)
358         return;
359
360     m_forceSynchronousScrollLayerPositionUpdates = forceSynchronousScrollLayerPositionUpdates;
361     updateSynchronousScrollingReasonsForAllFrames();
362 }
363
364 bool ScrollingCoordinator::shouldUpdateScrollLayerPositionSynchronously(const FrameView& frameView) const
365 {
366     if (&frameView == m_page->mainFrame().view())
367         return synchronousScrollingReasons(frameView);
368     
369     return true;
370 }
371
372 ScrollingNodeID ScrollingCoordinator::uniqueScrollingNodeID()
373 {
374     static ScrollingNodeID uniqueScrollingNodeID = 1;
375     return uniqueScrollingNodeID++;
376 }
377
378 String ScrollingCoordinator::scrollingStateTreeAsText(ScrollingStateTreeAsTextBehavior) const
379 {
380     return String();
381 }
382
383 String ScrollingCoordinator::synchronousScrollingReasonsAsText(SynchronousScrollingReasons reasons)
384 {
385     StringBuilder stringBuilder;
386
387     if (reasons & ScrollingCoordinator::ForcedOnMainThread)
388         stringBuilder.appendLiteral("Forced on main thread, ");
389     if (reasons & ScrollingCoordinator::HasSlowRepaintObjects)
390         stringBuilder.appendLiteral("Has slow repaint objects, ");
391     if (reasons & ScrollingCoordinator::HasViewportConstrainedObjectsWithoutSupportingFixedLayers)
392         stringBuilder.appendLiteral("Has viewport constrained objects without supporting fixed layers, ");
393     if (reasons & ScrollingCoordinator::HasNonLayerViewportConstrainedObjects)
394         stringBuilder.appendLiteral("Has non-layer viewport-constrained objects, ");
395     if (reasons & ScrollingCoordinator::IsImageDocument)
396         stringBuilder.appendLiteral("Is image document, ");
397
398     if (stringBuilder.length())
399         stringBuilder.resize(stringBuilder.length() - 2);
400     return stringBuilder.toString();
401 }
402
403 String ScrollingCoordinator::synchronousScrollingReasonsAsText() const
404 {
405     if (auto* frameView = m_page->mainFrame().view())
406         return synchronousScrollingReasonsAsText(synchronousScrollingReasons(*frameView));
407
408     return String();
409 }
410
411 TextStream& operator<<(TextStream& ts, ScrollableAreaParameters scrollableAreaParameters)
412 {
413     ts.dumpProperty("horizontal scroll elasticity", scrollableAreaParameters.horizontalScrollElasticity);
414     ts.dumpProperty("vertical scroll elasticity", scrollableAreaParameters.verticalScrollElasticity);
415     ts.dumpProperty("horizontal scrollbar mode", scrollableAreaParameters.horizontalScrollbarMode);
416     ts.dumpProperty("vertical scrollbar mode", scrollableAreaParameters.verticalScrollbarMode);
417     if (scrollableAreaParameters.hasEnabledHorizontalScrollbar)
418         ts.dumpProperty("has enabled horizontal scrollbar", scrollableAreaParameters.hasEnabledHorizontalScrollbar);
419     if (scrollableAreaParameters.hasEnabledVerticalScrollbar)
420         ts.dumpProperty("has enabled vertical scrollbar", scrollableAreaParameters.hasEnabledVerticalScrollbar);
421
422     return ts;
423 }
424
425 TextStream& operator<<(TextStream& ts, ScrollingNodeType nodeType)
426 {
427     switch (nodeType) {
428     case ScrollingNodeType::MainFrame:
429         ts << "main-frame-scrolling";
430         break;
431     case ScrollingNodeType::Subframe:
432         ts << "subframe-scrolling";
433         break;
434     case ScrollingNodeType::Overflow:
435         ts << "overflow-scrolling";
436         break;
437     case ScrollingNodeType::Fixed:
438         ts << "fixed";
439         break;
440     case ScrollingNodeType::Sticky:
441         ts << "sticky";
442         break;
443     }
444     return ts;
445 }
446
447 TextStream& operator<<(TextStream& ts, ScrollingLayerPositionAction action)
448 {
449     switch (action) {
450     case ScrollingLayerPositionAction::Set:
451         ts << "set";
452         break;
453     case ScrollingLayerPositionAction::SetApproximate:
454         ts << "set approximate";
455         break;
456     case ScrollingLayerPositionAction::Sync:
457         ts << "sync";
458         break;
459     }
460     return ts;
461 }
462
463 TextStream& operator<<(TextStream& ts, ViewportRectStability stability)
464 {
465     switch (stability) {
466     case ViewportRectStability::Stable:
467         ts << "stable";
468         break;
469     case ViewportRectStability::Unstable:
470         ts << "unstable";
471         break;
472     case ViewportRectStability::ChangingObscuredInsetsInteractively:
473         ts << "changing obscured insets interactively";
474         break;
475     }
476     return ts;
477 }
478
479 } // namespace WebCore