4bdfe54161e5d348e2f0a478babd5f29a300a8be
[WebKit-https.git] / Source / WebCore / page / scrolling / ScrollingTree.h
1 /*
2  * Copyright (C) 2012-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 #pragma once
27
28 #if ENABLE(ASYNC_SCROLLING)
29
30 #include "EventTrackingRegions.h"
31 #include "PageIdentifier.h"
32 #include "PlatformWheelEvent.h"
33 #include "RectEdges.h"
34 #include "Region.h"
35 #include "ScrollTypes.h"
36 #include "ScrollingCoordinatorTypes.h"
37 #include "ScrollingTreeGestureState.h"
38 #include "ScrollingTreeLatchingController.h"
39 #include "WheelEventTestMonitor.h"
40 #include <wtf/HashMap.h>
41 #include <wtf/Lock.h>
42 #include <wtf/MonotonicTime.h>
43 #include <wtf/ThreadSafeRefCounted.h>
44 #include <wtf/TypeCasts.h>
45
46 namespace WebCore {
47
48 class IntPoint;
49 class ScrollingStateTree;
50 class ScrollingStateNode;
51 class ScrollingTreeFrameScrollingNode;
52 class ScrollingTreeNode;
53 class ScrollingTreeOverflowScrollProxyNode;
54 class ScrollingTreePositionedNode;
55 class ScrollingTreeScrollingNode;
56 enum class EventListenerRegionType : uint8_t;
57 using PlatformDisplayID = uint32_t;
58
59 struct WheelEventHandlingResult {
60     OptionSet<WheelEventProcessingSteps> steps;
61     bool wasHandled { false };
62     bool needsMainThreadProcessing() const { return steps.containsAny({ WheelEventProcessingSteps::MainThreadForScrolling, WheelEventProcessingSteps::MainThreadForDOMEventDispatch }); }
63
64     static WheelEventHandlingResult handled()
65     {
66         return { { }, true };
67     }
68     static WheelEventHandlingResult unhandled()
69     {
70         return { { }, false };
71     }
72     static WheelEventHandlingResult result(bool handled)
73     {
74         return { { }, handled };
75     }
76 };
77
78 class ScrollingTree : public ThreadSafeRefCounted<ScrollingTree> {
79 friend class ScrollingTreeLatchingController;
80 public:
81     WEBCORE_EXPORT ScrollingTree();
82     WEBCORE_EXPORT virtual ~ScrollingTree();
83
84     virtual bool isThreadedScrollingTree() const { return false; }
85     virtual bool isRemoteScrollingTree() const { return false; }
86     virtual bool isScrollingTreeIOS() const { return false; }
87
88     // This implies that we'll do hit-testing in the scrolling tree.
89     bool asyncFrameOrOverflowScrollingEnabled() const { return m_asyncFrameOrOverflowScrollingEnabled; }
90     void setAsyncFrameOrOverflowScrollingEnabled(bool);
91
92     WEBCORE_EXPORT OptionSet<WheelEventProcessingSteps> determineWheelEventProcessing(const PlatformWheelEvent&);
93     WEBCORE_EXPORT virtual WheelEventHandlingResult handleWheelEvent(const PlatformWheelEvent&);
94
95     void setMainFrameIsRubberBanding(bool);
96     bool isRubberBandInProgress();
97     void setMainFrameIsScrollSnapping(bool);
98     bool isScrollSnapInProgress();
99
100     virtual void invalidate() { }
101     WEBCORE_EXPORT virtual void commitTreeState(std::unique_ptr<ScrollingStateTree>&&);
102     
103     WEBCORE_EXPORT virtual void applyLayerPositions();
104     WEBCORE_EXPORT void applyLayerPositionsAfterCommit();
105
106     virtual Ref<ScrollingTreeNode> createScrollingTreeNode(ScrollingNodeType, ScrollingNodeID) = 0;
107     
108     WEBCORE_EXPORT ScrollingTreeNode* nodeForID(ScrollingNodeID) const;
109
110     using VisitorFunction = WTF::Function<void (ScrollingNodeID, ScrollingNodeType, Optional<FloatPoint> scrollPosition, Optional<FloatPoint> layoutViewportOrigin, bool scrolledSinceLastCommit)>;
111     void traverseScrollingTree(VisitorFunction&&);
112
113     // Called after a scrolling tree node has handled a scroll and updated its layers.
114     // Updates FrameView/RenderLayer scrolling state and GraphicsLayers.
115     virtual void scrollingTreeNodeDidScroll(ScrollingTreeScrollingNode&, ScrollingLayerPositionAction = ScrollingLayerPositionAction::Sync) = 0;
116
117     // Called for requested scroll position updates.
118     virtual void scrollingTreeNodeRequestsScroll(ScrollingNodeID, const FloatPoint& /*scrollPosition*/, ScrollType, ScrollClamping) { }
119
120     // Delegated scrolling/zooming has caused the viewport to change, so update viewport-constrained layers
121     WEBCORE_EXPORT void mainFrameViewportChangedViaDelegatedScrolling(const FloatPoint& scrollPosition, const WebCore::FloatRect& layoutViewport, double scale);
122
123     void setNeedsApplyLayerPositionsAfterCommit() { m_needsApplyLayerPositionsAfterCommit = true; }
124
125     void notifyRelatedNodesAfterScrollPositionChange(ScrollingTreeScrollingNode& changedNode);
126
127     virtual void reportSynchronousScrollingReasonsChanged(MonotonicTime, OptionSet<SynchronousScrollingReason>) { }
128     virtual void reportExposedUnfilledArea(MonotonicTime, unsigned /* unfilledArea */) { }
129
130 #if PLATFORM(IOS_FAMILY)
131     virtual void scrollingTreeNodeWillStartPanGesture() { }
132     virtual void scrollingTreeNodeWillStartScroll() { }
133     virtual void scrollingTreeNodeDidEndScroll() { }
134 #endif
135
136     WEBCORE_EXPORT TrackingType eventTrackingTypeForPoint(const AtomString& eventName, IntPoint);
137
138 #if PLATFORM(MAC)
139     virtual void handleWheelEventPhase(ScrollingNodeID, PlatformWheelEventPhase) = 0;
140     virtual void setActiveScrollSnapIndices(ScrollingNodeID, unsigned /*horizontalIndex*/, unsigned /*verticalIndex*/) { }
141
142     virtual void setWheelEventTestMonitor(RefPtr<WheelEventTestMonitor>&&) { }
143
144     virtual void deferWheelEventTestCompletionForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) { }
145     virtual void removeWheelEventTestCompletionDeferralForReason(WheelEventTestMonitor::ScrollableAreaIdentifier, WheelEventTestMonitor::DeferReason) { }
146 #else
147     void handleWheelEventPhase(ScrollingNodeID, PlatformWheelEventPhase) { }
148 #endif
149
150 #if PLATFORM(COCOA)
151     WEBCORE_EXPORT virtual void currentSnapPointIndicesDidChange(ScrollingNodeID, unsigned horizontal, unsigned vertical) = 0;
152 #endif
153
154     void setMainFramePinnedState(RectEdges<bool>);
155
156     // Can be called from any thread. Will update what edges allow rubber-banding.
157     WEBCORE_EXPORT void setMainFrameCanRubberBand(RectEdges<bool>);
158     bool mainFrameCanRubberBandInDirection(ScrollDirection);
159
160     bool isHandlingProgrammaticScroll() const { return m_isHandlingProgrammaticScroll; }
161     void setIsHandlingProgrammaticScroll(bool isHandlingProgrammaticScroll) { m_isHandlingProgrammaticScroll = isHandlingProgrammaticScroll; }
162     
163     void setScrollPinningBehavior(ScrollPinningBehavior);
164     WEBCORE_EXPORT ScrollPinningBehavior scrollPinningBehavior();
165
166     WEBCORE_EXPORT bool willWheelEventStartSwipeGesture(const PlatformWheelEvent&);
167
168     WEBCORE_EXPORT void setScrollingPerformanceLoggingEnabled(bool flag);
169     bool scrollingPerformanceLoggingEnabled();
170
171     ScrollingTreeFrameScrollingNode* rootNode() const { return m_rootNode.get(); }
172     Optional<ScrollingNodeID> latchedNodeID() const;
173     void clearLatchedNode();
174
175     bool hasFixedOrSticky() const { return !!m_fixedOrStickyNodeCount; }
176     void fixedOrStickyNodeAdded() { ++m_fixedOrStickyNodeCount; }
177     void fixedOrStickyNodeRemoved()
178     {
179         ASSERT(m_fixedOrStickyNodeCount);
180         --m_fixedOrStickyNodeCount;
181     }
182
183     // A map of overflow scrolling nodes to positioned nodes which need to be updated
184     // when the scroller changes, but are not descendants.
185     using RelatedNodesMap = HashMap<ScrollingNodeID, Vector<ScrollingNodeID>>;
186     RelatedNodesMap& overflowRelatedNodes() { return m_overflowRelatedNodesMap; }
187
188     HashSet<Ref<ScrollingTreeOverflowScrollProxyNode>>& activeOverflowScrollProxyNodes() { return m_activeOverflowScrollProxyNodes; }
189     HashSet<Ref<ScrollingTreePositionedNode>>& activePositionedNodes() { return m_activePositionedNodes; }
190
191     WEBCORE_EXPORT String scrollingTreeAsText(ScrollingStateTreeAsTextBehavior = ScrollingStateTreeAsTextBehaviorNormal);
192
193     bool isMonitoringWheelEvents() const { return m_isMonitoringWheelEvents; }
194     bool inCommitTreeState() const { return m_inCommitTreeState; }
195
196     void scrollBySimulatingWheelEventForTesting(ScrollingNodeID, FloatSize);
197
198     virtual void lockLayersForHitTesting() { }
199     virtual void unlockLayersForHitTesting() { }
200
201     Lock& treeMutex() { return m_treeMutex; }
202
203     void windowScreenDidChange(PlatformDisplayID, Optional<unsigned> nominalFramesPerSecond);
204     PlatformDisplayID displayID();
205
206 protected:
207     FloatPoint mainFrameScrollPosition() const;
208     void setMainFrameScrollPosition(FloatPoint);
209
210     Optional<unsigned> nominalFramesPerSecond();
211
212     void applyLayerPositionsInternal();
213     void removeAllNodes();
214
215     Lock m_treeMutex; // Protects the scrolling tree.
216
217 private:
218     void updateTreeFromStateNodeRecursive(const ScrollingStateNode*, struct CommitTreeState&);
219     virtual void propagateSynchronousScrollingReasons(const HashSet<ScrollingNodeID>&) { }
220
221     void applyLayerPositionsRecursive(ScrollingTreeNode&);
222     void notifyRelatedNodesRecursive(ScrollingTreeNode&);
223     void traverseScrollingTreeRecursive(ScrollingTreeNode&, const VisitorFunction&);
224
225     WEBCORE_EXPORT virtual RefPtr<ScrollingTreeNode> scrollingNodeForPoint(FloatPoint);
226     WEBCORE_EXPORT virtual OptionSet<EventListenerRegionType> eventListenerRegionTypesForPoint(FloatPoint) const;
227     virtual void receivedWheelEvent(const PlatformWheelEvent&) { }
228     
229     RefPtr<ScrollingTreeFrameScrollingNode> m_rootNode;
230
231     using ScrollingTreeNodeMap = HashMap<ScrollingNodeID, RefPtr<ScrollingTreeNode>>;
232     ScrollingTreeNodeMap m_nodeMap;
233
234     ScrollingTreeLatchingController m_latchingController;
235     ScrollingTreeGestureState m_gestureState;
236
237     RelatedNodesMap m_overflowRelatedNodesMap;
238
239     HashSet<Ref<ScrollingTreeOverflowScrollProxyNode>> m_activeOverflowScrollProxyNodes;
240     HashSet<Ref<ScrollingTreePositionedNode>> m_activePositionedNodes;
241
242     struct TreeState {
243         EventTrackingRegions eventTrackingRegions;
244         FloatPoint mainFrameScrollPosition;
245         PlatformDisplayID displayID { 0 };
246         Optional<unsigned> nominalFramesPerSecond;
247         bool mainFrameIsRubberBanding { false };
248         bool mainFrameIsScrollSnapping { false };
249     };
250     
251     Lock m_treeStateMutex;
252     TreeState m_treeState;
253
254     struct SwipeState {
255         ScrollPinningBehavior scrollPinningBehavior { DoNotPin };
256         bool rubberBandsAtLeft { true };
257         bool rubberBandsAtRight { true };
258         bool rubberBandsAtTop { true };
259         bool rubberBandsAtBottom { true };
260         
261         RectEdges<bool> canRubberBand  { true, true, true, true };
262         RectEdges<bool> mainFramePinnedState { true, true, true, true };
263     };
264
265     Lock m_swipeStateMutex;
266     SwipeState m_swipeState;
267
268 protected:
269     bool m_allowLatching { true };
270
271 private:
272     unsigned m_fixedOrStickyNodeCount { 0 };
273     bool m_isHandlingProgrammaticScroll { false };
274     bool m_isMonitoringWheelEvents { false };
275     bool m_scrollingPerformanceLoggingEnabled { false };
276     bool m_asyncFrameOrOverflowScrollingEnabled { false };
277     bool m_needsApplyLayerPositionsAfterCommit { false };
278     bool m_inCommitTreeState { false };
279 };
280
281 } // namespace WebCore
282
283 #define SPECIALIZE_TYPE_TRAITS_SCROLLING_TREE(ToValueTypeName, predicate) \
284 SPECIALIZE_TYPE_TRAITS_BEGIN(ToValueTypeName) \
285     static bool isType(const WebCore::ScrollingTree& tree) { return tree.predicate; } \
286 SPECIALIZE_TYPE_TRAITS_END()
287 #endif // ENABLE(ASYNC_SCROLLING)