2 * Copyright (C) 2008, 2011, 2014 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef ScrollableArea_h
27 #define ScrollableArea_h
29 #include "Scrollbar.h"
30 #include <wtf/Vector.h>
35 class GraphicsContext;
38 class PlatformTouchEvent;
39 class PlatformWheelEvent;
44 class ScrollableArea {
46 WEBCORE_EXPORT bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1);
47 WEBCORE_EXPORT void scrollToOffsetWithoutAnimation(const FloatPoint&);
48 void scrollToOffsetWithoutAnimation(ScrollbarOrientation, float offset);
50 // Should be called when the scroll position changes externally, for example if the scroll layer position
51 // is updated on the scrolling thread and we need to notify the main thread.
52 WEBCORE_EXPORT void notifyScrollPositionChanged(const IntPoint&);
54 // Allows subclasses to handle scroll position updates themselves. If this member function
55 // returns true, the scrollable area won't actually update the scroll position and instead
56 // expect it to happen sometime in the future.
57 virtual bool requestScrollPositionUpdate(const IntPoint&) { return false; }
59 WEBCORE_EXPORT bool handleWheelEvent(const PlatformWheelEvent&);
61 #if ENABLE(CSS_SCROLL_SNAP)
62 const Vector<LayoutUnit>* horizontalSnapOffsets() const { return m_horizontalSnapOffsets.get(); };
63 const Vector<LayoutUnit>* verticalSnapOffsets() const { return m_verticalSnapOffsets.get(); };
64 virtual void updateSnapOffsets() { };
65 void setHorizontalSnapOffsets(std::unique_ptr<Vector<LayoutUnit>>);
66 void setVerticalSnapOffsets(std::unique_ptr<Vector<LayoutUnit>>);
67 void clearHorizontalSnapOffsets();
68 void clearVerticalSnapOffsets();
71 #if ENABLE(TOUCH_EVENTS)
72 virtual bool isTouchScrollable() const { return false; }
73 virtual bool handleTouchEvent(const PlatformTouchEvent&);
77 virtual bool isOverflowScroll() const { return false; }
78 virtual void didStartScroll() { }
79 virtual void didEndScroll() { }
80 virtual void didUpdateScroll() { }
82 virtual void setIsUserScroll(bool) { }
84 // Functions for controlling if you can scroll past the end of the document.
85 bool constrainsScrollingToContentEdge() const { return m_constrainsScrollingToContentEdge; }
86 void setConstrainsScrollingToContentEdge(bool constrainsScrollingToContentEdge) { m_constrainsScrollingToContentEdge = constrainsScrollingToContentEdge; }
88 void setVerticalScrollElasticity(ScrollElasticity scrollElasticity) { m_verticalScrollElasticity = scrollElasticity; }
89 ScrollElasticity verticalScrollElasticity() const { return static_cast<ScrollElasticity>(m_verticalScrollElasticity); }
91 void setHorizontalScrollElasticity(ScrollElasticity scrollElasticity) { m_horizontalScrollElasticity = scrollElasticity; }
92 ScrollElasticity horizontalScrollElasticity() const { return static_cast<ScrollElasticity>(m_horizontalScrollElasticity); }
94 bool inLiveResize() const { return m_inLiveResize; }
95 WEBCORE_EXPORT virtual void willStartLiveResize();
96 WEBCORE_EXPORT virtual void willEndLiveResize();
98 WEBCORE_EXPORT void contentAreaWillPaint() const;
99 WEBCORE_EXPORT void mouseEnteredContentArea() const;
100 WEBCORE_EXPORT void mouseExitedContentArea() const;
101 WEBCORE_EXPORT void mouseMovedInContentArea() const;
102 WEBCORE_EXPORT void mouseEnteredScrollbar(Scrollbar*) const;
103 void mouseExitedScrollbar(Scrollbar*) const;
104 void contentAreaDidShow() const;
105 void contentAreaDidHide() const;
107 void lockOverlayScrollbarStateToHidden(bool shouldLockState) const;
108 WEBCORE_EXPORT bool scrollbarsCanBeActive() const;
110 WEBCORE_EXPORT virtual void didAddScrollbar(Scrollbar*, ScrollbarOrientation);
111 WEBCORE_EXPORT virtual void willRemoveScrollbar(Scrollbar*, ScrollbarOrientation);
113 WEBCORE_EXPORT virtual void contentsResized();
115 bool hasOverlayScrollbars() const;
116 WEBCORE_EXPORT virtual void setScrollbarOverlayStyle(ScrollbarOverlayStyle);
117 ScrollbarOverlayStyle scrollbarOverlayStyle() const { return static_cast<ScrollbarOverlayStyle>(m_scrollbarOverlayStyle); }
119 // This getter will create a ScrollAnimator if it doesn't already exist.
120 WEBCORE_EXPORT ScrollAnimator& scrollAnimator() const;
122 // This getter will return null if the ScrollAnimator hasn't been created yet.
123 ScrollAnimator* existingScrollAnimator() const { return m_scrollAnimator.get(); }
125 const IntPoint& scrollOrigin() const { return m_scrollOrigin; }
126 bool scrollOriginChanged() const { return m_scrollOriginChanged; }
128 virtual bool isActive() const = 0;
129 virtual int scrollSize(ScrollbarOrientation) const = 0;
130 virtual int scrollPosition(Scrollbar*) const = 0;
131 WEBCORE_EXPORT virtual void invalidateScrollbar(Scrollbar*, const IntRect&);
132 virtual bool isScrollCornerVisible() const = 0;
133 virtual IntRect scrollCornerRect() const = 0;
134 WEBCORE_EXPORT virtual void invalidateScrollCorner(const IntRect&);
136 virtual bool updatesScrollLayerPositionOnMainThread() const = 0;
138 virtual bool forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const = 0;
140 // Convert points and rects between the scrollbar and its containing view.
141 // The client needs to implement these in order to be aware of layout effects
142 // like CSS transforms.
143 virtual IntRect convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
145 return scrollbar->Widget::convertToContainingView(scrollbarRect);
147 virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
149 return scrollbar->Widget::convertFromContainingView(parentRect);
151 virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
153 return scrollbar->Widget::convertToContainingView(scrollbarPoint);
155 virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
157 return scrollbar->Widget::convertFromContainingView(parentPoint);
160 virtual Scrollbar* horizontalScrollbar() const { return 0; }
161 virtual Scrollbar* verticalScrollbar() const { return 0; }
163 virtual IntPoint scrollPosition() const;
164 virtual IntPoint minimumScrollPosition() const;
165 virtual IntPoint maximumScrollPosition() const;
166 WEBCORE_EXPORT virtual bool scrolledToTop() const;
167 WEBCORE_EXPORT virtual bool scrolledToBottom() const;
168 WEBCORE_EXPORT virtual bool scrolledToLeft() const;
169 WEBCORE_EXPORT virtual bool scrolledToRight() const;
171 bool isScrolledProgrammatically() const { return m_scrolledProgrammatically; }
172 void setScrolledProgrammatically(bool state) { m_scrolledProgrammatically = state; }
174 enum VisibleContentRectIncludesScrollbars { ExcludeScrollbars, IncludeScrollbars };
175 enum VisibleContentRectBehavior {
178 LegacyIOSDocumentViewRect,
179 LegacyIOSDocumentVisibleRect = LegacyIOSDocumentViewRect
181 LegacyIOSDocumentVisibleRect = ContentsVisibleRect
185 WEBCORE_EXPORT IntRect visibleContentRect(VisibleContentRectBehavior = ContentsVisibleRect) const;
186 WEBCORE_EXPORT IntRect visibleContentRectIncludingScrollbars(VisibleContentRectBehavior = ContentsVisibleRect) const;
188 int visibleWidth() const { return visibleSize().width(); }
189 int visibleHeight() const { return visibleSize().height(); }
190 virtual IntSize visibleSize() const = 0;
192 virtual IntSize contentsSize() const = 0;
193 virtual IntSize overhangAmount() const { return IntSize(); }
194 virtual IntPoint lastKnownMousePosition() const { return IntPoint(); }
195 virtual bool isHandlingWheelEvent() const { return false; }
197 virtual int headerHeight() const { return 0; }
198 virtual int footerHeight() const { return 0; }
200 // The totalContentsSize() is equivalent to the contentsSize() plus the header and footer heights.
201 WEBCORE_EXPORT IntSize totalContentsSize() const;
203 virtual bool shouldSuspendScrollAnimations() const { return true; }
204 virtual void scrollbarStyleChanged(int /*newStyle*/, bool /*forceUpdate*/) { }
205 virtual void setVisibleScrollerThumbRect(const IntRect&) { }
207 // Note that this only returns scrollable areas that can actually be scrolled.
208 virtual ScrollableArea* enclosingScrollableArea() const = 0;
210 virtual bool isScrollableOrRubberbandable() = 0;
211 virtual bool hasScrollableOrRubberbandableAncestor() = 0;
213 // Returns the bounding box of this scrollable area, in the coordinate system of the enclosing scroll view.
214 virtual IntRect scrollableAreaBoundingBox() const = 0;
216 virtual bool isRubberBandInProgress() const { return false; }
218 virtual bool scrollAnimatorEnabled() const { return false; }
220 // NOTE: Only called from Internals for testing.
221 WEBCORE_EXPORT void setScrollOffsetFromInternals(const IntPoint&);
223 WEBCORE_EXPORT static LayoutPoint constrainScrollPositionForOverhang(const LayoutRect& visibleContentRect, const LayoutSize& totalContentsSize, const LayoutPoint& scrollPosition, const LayoutPoint& scrollOrigin, int headerHeight, int footetHeight);
224 LayoutPoint constrainScrollPositionForOverhang(const LayoutPoint& scrollPosition);
226 // Computes the double value for the scrollbar's current position and the current overhang amount.
227 // This function is static so that it can be called from the main thread or the scrolling thread.
228 static void computeScrollbarValueAndOverhang(float currentPosition, float totalSize, float visibleSize, float& doubleValue, float& overhangAmount);
230 // Let subclasses provide a way of asking for and servicing scroll
232 virtual bool scheduleAnimation() { return false; }
233 void serviceScrollAnimations();
236 bool isHorizontalScrollerPinnedToMinimumPosition() const { return !horizontalScrollbar() || scrollPosition(horizontalScrollbar()) <= minimumScrollPosition().x(); }
237 bool isHorizontalScrollerPinnedToMaximumPosition() const { return !horizontalScrollbar() || scrollPosition(horizontalScrollbar()) >= maximumScrollPosition().x(); }
238 bool isVerticalScrollerPinnedToMinimumPosition() const { return !verticalScrollbar() || scrollPosition(verticalScrollbar()) <= minimumScrollPosition().y(); }
239 bool isVerticalScrollerPinnedToMaximumPosition() const { return !verticalScrollbar() || scrollPosition(verticalScrollbar()) >= maximumScrollPosition().y(); }
241 bool isPinnedInBothDirections(const IntSize&) const;
242 bool isPinnedHorizontallyInDirection(int horizontalScrollDelta) const;
243 bool isPinnedVerticallyInDirection(int verticalScrollDelta) const;
246 virtual TiledBacking* tiledBacking() const { return 0; }
247 virtual bool usesCompositedScrolling() const { return false; }
249 virtual GraphicsLayer* layerForHorizontalScrollbar() const { return 0; }
250 virtual GraphicsLayer* layerForVerticalScrollbar() const { return 0; }
252 bool hasLayerForHorizontalScrollbar() const;
253 bool hasLayerForVerticalScrollbar() const;
255 void verticalScrollbarLayerDidChange();
256 void horizontalScrollbarLayerDidChange();
259 WEBCORE_EXPORT ScrollableArea();
260 WEBCORE_EXPORT virtual ~ScrollableArea();
262 void setScrollOrigin(const IntPoint&);
263 void resetScrollOriginChanged() { m_scrollOriginChanged = false; }
265 WEBCORE_EXPORT virtual float adjustScrollStepForFixedContent(float step, ScrollbarOrientation, ScrollGranularity);
266 virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&) = 0;
267 virtual void invalidateScrollCornerRect(const IntRect&) = 0;
269 friend class ScrollingCoordinator;
270 virtual GraphicsLayer* layerForScrolling() const { return 0; }
271 virtual GraphicsLayer* layerForScrollCorner() const { return 0; }
272 #if ENABLE(RUBBER_BANDING)
273 virtual GraphicsLayer* layerForOverhangAreas() const { return 0; }
276 bool hasLayerForScrollCorner() const;
279 WEBCORE_EXPORT virtual IntRect visibleContentRectInternal(VisibleContentRectIncludesScrollbars, VisibleContentRectBehavior) const;
280 void scrollPositionChanged(const IntPoint&);
282 // NOTE: Only called from the ScrollAnimator.
283 friend class ScrollAnimator;
284 void setScrollOffsetFromAnimation(const IntPoint&);
286 // This function should be overriden by subclasses to perform the actual
287 // scroll of the content.
288 virtual void setScrollOffset(const IntPoint&) = 0;
290 mutable OwnPtr<ScrollAnimator> m_scrollAnimator;
292 #if ENABLE(CSS_SCROLL_SNAP)
293 std::unique_ptr<Vector<LayoutUnit>> m_horizontalSnapOffsets;
294 std::unique_ptr<Vector<LayoutUnit>> m_verticalSnapOffsets;
297 // There are 8 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis
298 // if there is any reversed direction or writing-mode. The combinations are:
299 // writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set
300 // horizontal-tb / ltr NO NO
301 // horizontal-tb / rtl YES NO
302 // horizontal-bt / ltr NO YES
303 // horizontal-bt / rtl YES YES
304 // vertical-lr / ltr NO NO
305 // vertical-lr / rtl NO YES
306 // vertical-rl / ltr YES NO
307 // vertical-rl / rtl YES YES
308 IntPoint m_scrollOrigin;
310 unsigned m_constrainsScrollingToContentEdge : 1;
312 unsigned m_inLiveResize : 1;
314 unsigned m_verticalScrollElasticity : 2; // ScrollElasticity
315 unsigned m_horizontalScrollElasticity : 2; // ScrollElasticity
317 unsigned m_scrollbarOverlayStyle : 2; // ScrollbarOverlayStyle
319 unsigned m_scrollOriginChanged : 1;
320 unsigned m_scrolledProgrammatically : 1;
323 } // namespace WebCore
325 #endif // ScrollableArea_h