[iOS] scrollIntoViewIfNeeded is not working with scroll-snap points
[WebKit-https.git] / Source / WebCore / page / scrolling / ScrollingCoordinator.h
1 /*
2  * Copyright (C) 2011, 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 #ifndef ScrollingCoordinator_h
27 #define ScrollingCoordinator_h
28
29 #include "IntRect.h"
30 #include "LayoutRect.h"
31 #include "PlatformWheelEvent.h"
32 #include "RenderObject.h"
33 #include "ScrollTypes.h"
34 #include <wtf/Forward.h>
35 #include <wtf/TypeCasts.h>
36
37 #if ENABLE(ASYNC_SCROLLING)
38 #include <wtf/HashMap.h>
39 #include <wtf/ThreadSafeRefCounted.h>
40 #include <wtf/Threading.h>
41 #endif
42
43 #if PLATFORM(COCOA)
44 #include <wtf/RetainPtr.h>
45 #endif
46
47 #if ENABLE(CSS_SCROLL_SNAP)
48 #include "AxisScrollSnapOffsets.h"
49 #endif
50
51 namespace WebCore {
52
53 typedef unsigned SynchronousScrollingReasons;
54 typedef uint64_t ScrollingNodeID;
55
56 enum ScrollingNodeType { FrameScrollingNode, OverflowScrollingNode, FixedNode, StickyNode };
57
58 class Document;
59 class Frame;
60 class FrameView;
61 class GraphicsLayer;
62 class Page;
63 class Region;
64 class ScrollableArea;
65 class ViewportConstraints;
66
67 #if ENABLE(ASYNC_SCROLLING)
68 class ScrollingTree;
69 #endif
70
71 enum SetOrSyncScrollingLayerPosition {
72     SetScrollingLayerPosition,
73     SyncScrollingLayerPosition
74 };
75
76 struct ScrollableAreaParameters {
77     ScrollElasticity horizontalScrollElasticity;
78     ScrollElasticity verticalScrollElasticity;
79
80     ScrollbarMode horizontalScrollbarMode;
81     ScrollbarMode verticalScrollbarMode;
82
83     bool hasEnabledHorizontalScrollbar;
84     bool hasEnabledVerticalScrollbar;
85     
86     ScrollableAreaParameters()
87         : horizontalScrollElasticity(ScrollElasticityNone)
88         , verticalScrollElasticity(ScrollElasticityNone)
89         , horizontalScrollbarMode(ScrollbarAuto)
90         , verticalScrollbarMode(ScrollbarAuto)
91         , hasEnabledHorizontalScrollbar(false)
92         , hasEnabledVerticalScrollbar(false)
93     {
94     }
95
96     bool operator==(const ScrollableAreaParameters& other) const
97     {
98         return horizontalScrollElasticity == other.horizontalScrollElasticity
99             && verticalScrollElasticity == other.verticalScrollElasticity
100             && horizontalScrollbarMode == other.horizontalScrollbarMode
101             && verticalScrollbarMode == other.verticalScrollbarMode
102             && hasEnabledHorizontalScrollbar == other.hasEnabledHorizontalScrollbar
103             && hasEnabledVerticalScrollbar == other.hasEnabledVerticalScrollbar;
104     }
105 };
106
107 class ScrollingCoordinator : public ThreadSafeRefCounted<ScrollingCoordinator> {
108 public:
109     static Ref<ScrollingCoordinator> create(Page*);
110     virtual ~ScrollingCoordinator();
111
112     WEBCORE_EXPORT virtual void pageDestroyed();
113     
114     virtual bool isAsyncScrollingCoordinator() const { return false; }
115     virtual bool isRemoteScrollingCoordinator() const { return false; }
116
117     // Return whether this scrolling coordinator handles scrolling for the given frame view.
118     virtual bool coordinatesScrollingForFrameView(const FrameView&) const;
119
120     // Should be called whenever the given frame view has been laid out.
121     virtual void frameViewLayoutUpdated(FrameView&) { }
122
123     // Should be called whenever the slow repaint objects counter changes between zero and one.
124     void frameViewHasSlowRepaintObjectsDidChange(FrameView&);
125
126     // Should be called whenever the set of fixed objects changes.
127     void frameViewFixedObjectsDidChange(FrameView&);
128
129     // Called whenever the non-fast scrollable region changes for reasons other than layout.
130     virtual void frameViewNonFastScrollableRegionChanged(FrameView&) { }
131
132     // Should be called whenever the root layer for the given frame view changes.
133     virtual void frameViewRootLayerDidChange(FrameView&);
134
135     // Return whether this scrolling coordinator can keep fixed position layers fixed to their
136     // containers while scrolling.
137     virtual bool supportsFixedPositionLayers() const { return false; }
138
139 #if PLATFORM(COCOA)
140     // Dispatched by the scrolling tree during handleWheelEvent. This is required as long as scrollbars are painted on the main thread.
141     void handleWheelEventPhase(PlatformWheelEventPhase);
142 #endif
143
144 #if ENABLE(WEB_REPLAY)
145     // Called when the page transitions between executing normally and deterministically.
146     void replaySessionStateDidChange();
147 #endif
148
149     // Force all scroll layer position updates to happen on the main thread.
150     WEBCORE_EXPORT void setForceSynchronousScrollLayerPositionUpdates(bool);
151
152     // These virtual functions are currently unique to the threaded scrolling architecture. 
153     // Their meaningful implementations are in ScrollingCoordinatorMac.
154     virtual void commitTreeStateIfNeeded() { }
155     virtual bool requestScrollPositionUpdate(FrameView&, const IntPoint&) { return false; }
156     virtual bool handleWheelEvent(FrameView&, const PlatformWheelEvent&) { return true; }
157     virtual ScrollingNodeID attachToStateTree(ScrollingNodeType, ScrollingNodeID newNodeID, ScrollingNodeID /*parentID*/) { return newNodeID; }
158     virtual void detachFromStateTree(ScrollingNodeID) { }
159     virtual void clearStateTree() { }
160     virtual void updateViewportConstrainedNode(ScrollingNodeID, const ViewportConstraints&, GraphicsLayer*) { }
161
162     struct ScrollingGeometry {
163         FloatSize scrollableAreaSize;
164         FloatSize contentSize;
165         FloatSize reachableContentSize; // Smaller than contentSize when overflow is hidden on one axis.
166         FloatPoint scrollPosition;
167         IntPoint scrollOrigin;
168 #if ENABLE(CSS_SCROLL_SNAP)
169         Vector<LayoutUnit> horizontalSnapOffsets;
170         Vector<LayoutUnit> verticalSnapOffsets;
171         unsigned currentHorizontalSnapPointIndex;
172         unsigned currentVerticalSnapPointIndex;
173 #endif
174     };
175
176     virtual void updateFrameScrollingNode(ScrollingNodeID, GraphicsLayer* /*scrollLayer*/, GraphicsLayer* /*scrolledContentsLayer*/, GraphicsLayer* /*counterScrollingLayer*/, GraphicsLayer* /*insetClipLayer*/, const ScrollingGeometry* = nullptr) { }
177     virtual void updateOverflowScrollingNode(ScrollingNodeID, GraphicsLayer* /*scrollLayer*/, GraphicsLayer* /*scrolledContentsLayer*/, const ScrollingGeometry* = nullptr) { }
178     virtual void syncChildPositions(const LayoutRect&) { }
179     virtual String scrollingStateTreeAsText() const;
180     virtual bool isRubberBandInProgress() const { return false; }
181     virtual bool isScrollSnapInProgress() const { return false; }
182     virtual void setScrollPinningBehavior(ScrollPinningBehavior) { }
183
184     // Generated a unique id for scroll layers.
185     ScrollingNodeID uniqueScrollLayerID();
186
187     enum MainThreadScrollingReasonFlags {
188         ForcedOnMainThread                                          = 1 << 0,
189         HasSlowRepaintObjects                                       = 1 << 1,
190         HasViewportConstrainedObjectsWithoutSupportingFixedLayers   = 1 << 2,
191         HasNonLayerViewportConstrainedObjects                       = 1 << 3,
192         IsImageDocument                                             = 1 << 4
193     };
194
195     SynchronousScrollingReasons synchronousScrollingReasons(const FrameView&) const;
196     bool shouldUpdateScrollLayerPositionSynchronously() const;
197
198     virtual void willDestroyScrollableArea(ScrollableArea&) { }
199     virtual void scrollableAreaScrollLayerDidChange(ScrollableArea&) { }
200     virtual void scrollableAreaScrollbarLayerDidChange(ScrollableArea&, ScrollbarOrientation) { }
201
202     static String synchronousScrollingReasonsAsText(SynchronousScrollingReasons);
203     String synchronousScrollingReasonsAsText() const;
204
205     Region absoluteNonFastScrollableRegion() const;
206
207 protected:
208     explicit ScrollingCoordinator(Page*);
209
210     static GraphicsLayer* scrollLayerForScrollableArea(ScrollableArea&);
211
212     GraphicsLayer* scrollLayerForFrameView(FrameView&);
213     GraphicsLayer* counterScrollingLayerForFrameView(FrameView&);
214     GraphicsLayer* insetClipLayerForFrameView(FrameView&);
215     GraphicsLayer* rootContentLayerForFrameView(FrameView&);
216     GraphicsLayer* contentShadowLayerForFrameView(FrameView&);
217     GraphicsLayer* headerLayerForFrameView(FrameView&);
218     GraphicsLayer* footerLayerForFrameView(FrameView&);
219
220     virtual void willCommitTree() { }
221
222     Page* m_page; // FIXME: ideally this would be a reference but it gets nulled on async teardown.
223
224 private:
225     virtual void setSynchronousScrollingReasons(SynchronousScrollingReasons) { }
226
227     virtual bool hasVisibleSlowRepaintViewportConstrainedObjects(const FrameView&) const;
228     void updateSynchronousScrollingReasons(FrameView&);
229
230     Region absoluteNonFastScrollableRegionForFrame(const Frame&) const;
231     
232     bool m_forceSynchronousScrollLayerPositionUpdates { false };
233 };
234
235 } // namespace WebCore
236
237 #define SPECIALIZE_TYPE_TRAITS_SCROLLING_COORDINATOR(ToValueTypeName, predicate) \
238 SPECIALIZE_TYPE_TRAITS_BEGIN(ToValueTypeName) \
239     static bool isType(const WebCore::ScrollingCoordinator& value) { return value.predicate; } \
240 SPECIALIZE_TYPE_TRAITS_END()
241
242 #endif // ScrollingCoordinator_h