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