• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008, 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. ``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.
24  */
25 
26 #ifndef ScrollableArea_h
27 #define ScrollableArea_h
28 
29 #include "platform/PlatformExport.h"
30 #include "platform/scroll/ScrollAnimator.h"
31 #include "platform/scroll/Scrollbar.h"
32 #include "wtf/Noncopyable.h"
33 #include "wtf/Vector.h"
34 
35 namespace blink {
36 
37 class FloatPoint;
38 class GraphicsLayer;
39 class HostWindow;
40 class PlatformWheelEvent;
41 class ProgrammaticScrollAnimator;
42 class ScrollAnimator;
43 
44 enum ScrollBehavior {
45     ScrollBehaviorAuto,
46     ScrollBehaviorInstant,
47     ScrollBehaviorSmooth,
48 };
49 
50 enum IncludeScrollbarsInRect {
51     ExcludeScrollbars,
52     IncludeScrollbars,
53 };
54 
55 class PLATFORM_EXPORT ScrollableArea {
56     WTF_MAKE_NONCOPYABLE(ScrollableArea);
57 public:
58     static int pixelsPerLineStep();
59     static float minFractionToStepWhenPaging();
60     static int maxOverlapBetweenPages();
61 
62     // The window that hosts the ScrollView. The ScrollView will communicate scrolls and repaints to the
63     // host window in the window's coordinate space.
hostWindow()64     virtual HostWindow* hostWindow() const { return 0; };
65 
66     bool scroll(ScrollDirection, ScrollGranularity, float delta = 1);
67     void scrollToOffsetWithoutAnimation(const FloatPoint&);
68     void scrollToOffsetWithoutAnimation(ScrollbarOrientation, float offset);
69 
70     void programmaticallyScrollSmoothlyToOffset(const FloatPoint&);
71 
72     // Should be called when the scroll position changes externally, for example if the scroll layer position
73     // is updated on the scrolling thread and we need to notify the main thread.
74     void notifyScrollPositionChanged(const IntPoint&);
75 
76     static bool scrollBehaviorFromString(const String&, ScrollBehavior&);
77 
78     bool handleWheelEvent(const PlatformWheelEvent&);
79 
80     // Functions for controlling if you can scroll past the end of the document.
constrainsScrollingToContentEdge()81     bool constrainsScrollingToContentEdge() const { return m_constrainsScrollingToContentEdge; }
setConstrainsScrollingToContentEdge(bool constrainsScrollingToContentEdge)82     void setConstrainsScrollingToContentEdge(bool constrainsScrollingToContentEdge) { m_constrainsScrollingToContentEdge = constrainsScrollingToContentEdge; }
83 
setVerticalScrollElasticity(ScrollElasticity scrollElasticity)84     void setVerticalScrollElasticity(ScrollElasticity scrollElasticity) { m_verticalScrollElasticity = scrollElasticity; }
verticalScrollElasticity()85     ScrollElasticity verticalScrollElasticity() const { return static_cast<ScrollElasticity>(m_verticalScrollElasticity); }
86 
setHorizontalScrollElasticity(ScrollElasticity scrollElasticity)87     void setHorizontalScrollElasticity(ScrollElasticity scrollElasticity) { m_horizontalScrollElasticity = scrollElasticity; }
horizontalScrollElasticity()88     ScrollElasticity horizontalScrollElasticity() const { return static_cast<ScrollElasticity>(m_horizontalScrollElasticity); }
89 
inLiveResize()90     bool inLiveResize() const { return m_inLiveResize; }
91     void willStartLiveResize();
92     void willEndLiveResize();
93 
94     void contentAreaWillPaint() const;
95     void mouseEnteredContentArea() const;
96     void mouseExitedContentArea() const;
97     void mouseMovedInContentArea() const;
98     void mouseEnteredScrollbar(Scrollbar*) const;
99     void mouseExitedScrollbar(Scrollbar*) const;
100     void contentAreaDidShow() const;
101     void contentAreaDidHide() const;
102 
103     void finishCurrentScrollAnimations() const;
104 
105     virtual void didAddScrollbar(Scrollbar*, ScrollbarOrientation);
106     virtual void willRemoveScrollbar(Scrollbar*, ScrollbarOrientation);
107 
108     virtual void contentsResized();
109 
110     bool hasOverlayScrollbars() const;
111     void setScrollbarOverlayStyle(ScrollbarOverlayStyle);
scrollbarOverlayStyle()112     ScrollbarOverlayStyle scrollbarOverlayStyle() const { return static_cast<ScrollbarOverlayStyle>(m_scrollbarOverlayStyle); }
113 
114     // This getter will create a ScrollAnimator if it doesn't already exist.
115     ScrollAnimator* scrollAnimator() const;
116 
117     // This getter will return null if the ScrollAnimator hasn't been created yet.
existingScrollAnimator()118     ScrollAnimator* existingScrollAnimator() const { return m_animators ? m_animators->scrollAnimator.get() : 0; }
119 
120     ProgrammaticScrollAnimator* programmaticScrollAnimator() const;
existingProgrammaticScrollAnimator()121     ProgrammaticScrollAnimator* existingProgrammaticScrollAnimator() const
122     {
123         return m_animators ? m_animators->programmaticScrollAnimator.get() : 0;
124     }
125 
scrollOrigin()126     const IntPoint& scrollOrigin() const { return m_scrollOrigin; }
scrollOriginChanged()127     bool scrollOriginChanged() const { return m_scrollOriginChanged; }
128 
129     // FIXME(bokan): Meaningless name, rename to isActiveFocus
130     virtual bool isActive() const = 0;
131     virtual int scrollSize(ScrollbarOrientation) const = 0;
132     virtual void invalidateScrollbar(Scrollbar*, const IntRect&);
133     virtual bool isScrollCornerVisible() const = 0;
134     virtual IntRect scrollCornerRect() const = 0;
135     virtual void invalidateScrollCorner(const IntRect&);
getTickmarks(Vector<IntRect> &)136     virtual void getTickmarks(Vector<IntRect>&) const { }
137 
138     // Convert points and rects between the scrollbar and its containing view.
139     // The client needs to implement these in order to be aware of layout effects
140     // like CSS transforms.
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntRect & scrollbarRect)141     virtual IntRect convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
142     {
143         return scrollbar->Widget::convertToContainingView(scrollbarRect);
144     }
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntRect & parentRect)145     virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
146     {
147         return scrollbar->Widget::convertFromContainingView(parentRect);
148     }
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntPoint & scrollbarPoint)149     virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
150     {
151         return scrollbar->Widget::convertToContainingView(scrollbarPoint);
152     }
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntPoint & parentPoint)153     virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
154     {
155         return scrollbar->Widget::convertFromContainingView(parentPoint);
156     }
157 
horizontalScrollbar()158     virtual Scrollbar* horizontalScrollbar() const { return 0; }
verticalScrollbar()159     virtual Scrollbar* verticalScrollbar() const { return 0; }
160 
161     // scrollPosition is relative to the scrollOrigin. i.e. If the page is RTL
162     // then scrollPosition will be negative.
163     virtual IntPoint scrollPosition() const = 0;
164     virtual IntPoint minimumScrollPosition() const = 0;
165     virtual IntPoint maximumScrollPosition() const = 0;
166 
167     virtual IntRect visibleContentRect(IncludeScrollbarsInRect = ExcludeScrollbars) const;
visibleHeight()168     virtual int visibleHeight() const { return visibleContentRect().height(); }
visibleWidth()169     virtual int visibleWidth() const { return visibleContentRect().width(); }
170     virtual IntSize contentsSize() const = 0;
overhangAmount()171     virtual IntSize overhangAmount() const { return IntSize(); }
lastKnownMousePosition()172     virtual IntPoint lastKnownMousePosition() const { return IntPoint(); }
173 
shouldSuspendScrollAnimations()174     virtual bool shouldSuspendScrollAnimations() const { return true; }
scrollbarStyleChanged()175     virtual void scrollbarStyleChanged() { }
176 
177     virtual bool scrollbarsCanBeActive() const = 0;
178 
179     // Returns the bounding box of this scrollable area, in the coordinate system of the enclosing scroll view.
180     virtual IntRect scrollableAreaBoundingBox() const = 0;
181 
isRubberBandInProgress()182     virtual bool isRubberBandInProgress() const { return false; }
183 
scrollAnimatorEnabled()184     virtual bool scrollAnimatorEnabled() const { return false; }
185 
186     // NOTE: Only called from Internals for testing.
187     void setScrollOffsetFromInternals(const IntPoint&);
188 
189     IntPoint clampScrollPosition(const IntPoint&) const;
190 
191     // Let subclasses provide a way of asking for and servicing scroll
192     // animations.
193     bool scheduleAnimation();
194     void serviceScrollAnimations(double monotonicTime);
195 
usesCompositedScrolling()196     virtual bool usesCompositedScrolling() const { return false; }
197 
198     // Returns true if the GraphicsLayer tree needs to be rebuilt.
updateAfterCompositingChange()199     virtual bool updateAfterCompositingChange() { return false; }
200 
201     virtual bool userInputScrollable(ScrollbarOrientation) const = 0;
202     virtual bool shouldPlaceVerticalScrollbarOnLeft() const = 0;
203 
204     // Convenience functions
scrollPosition(ScrollbarOrientation orientation)205     int scrollPosition(ScrollbarOrientation orientation) { return orientation == HorizontalScrollbar ? scrollPosition().x() : scrollPosition().y(); }
minimumScrollPosition(ScrollbarOrientation orientation)206     int minimumScrollPosition(ScrollbarOrientation orientation) { return orientation == HorizontalScrollbar ? minimumScrollPosition().x() : minimumScrollPosition().y(); }
maximumScrollPosition(ScrollbarOrientation orientation)207     int maximumScrollPosition(ScrollbarOrientation orientation) { return orientation == HorizontalScrollbar ? maximumScrollPosition().x() : maximumScrollPosition().y(); }
clampScrollPosition(ScrollbarOrientation orientation,int pos)208     int clampScrollPosition(ScrollbarOrientation orientation, int pos)  { return std::max(std::min(pos, maximumScrollPosition(orientation)), minimumScrollPosition(orientation)); }
209 
hasVerticalBarDamage()210     bool hasVerticalBarDamage() const { return !m_verticalBarDamage.isEmpty(); }
hasHorizontalBarDamage()211     bool hasHorizontalBarDamage() const { return !m_horizontalBarDamage.isEmpty(); }
verticalBarDamage()212     const IntRect& verticalBarDamage() const { return m_verticalBarDamage; }
horizontalBarDamage()213     const IntRect& horizontalBarDamage() const { return m_horizontalBarDamage; }
214 
addScrollbarDamage(Scrollbar * scrollbar,const IntRect & rect)215     void addScrollbarDamage(Scrollbar* scrollbar, const IntRect& rect)
216     {
217         if (scrollbar == horizontalScrollbar())
218             m_horizontalBarDamage.unite(rect);
219         else
220             m_verticalBarDamage.unite(rect);
221     }
222 
resetScrollbarDamage()223     void resetScrollbarDamage()
224     {
225         m_verticalBarDamage = IntRect();
226         m_horizontalBarDamage = IntRect();
227     }
228 
229     virtual GraphicsLayer* layerForContainer() const;
layerForScrolling()230     virtual GraphicsLayer* layerForScrolling() const { return 0; }
layerForHorizontalScrollbar()231     virtual GraphicsLayer* layerForHorizontalScrollbar() const { return 0; }
layerForVerticalScrollbar()232     virtual GraphicsLayer* layerForVerticalScrollbar() const { return 0; }
layerForScrollCorner()233     virtual GraphicsLayer* layerForScrollCorner() const { return 0; }
234     bool hasLayerForHorizontalScrollbar() const;
235     bool hasLayerForVerticalScrollbar() const;
236     bool hasLayerForScrollCorner() const;
237 
238     void cancelProgrammaticScrollAnimation();
239 
240 protected:
241     ScrollableArea();
242     virtual ~ScrollableArea();
243 
244     void setScrollOrigin(const IntPoint&);
resetScrollOriginChanged()245     void resetScrollOriginChanged() { m_scrollOriginChanged = false; }
246 
247     virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&) = 0;
248     virtual void invalidateScrollCornerRect(const IntRect&) = 0;
249 
250 private:
251     void scrollPositionChanged(const IntPoint&);
252 
253     // NOTE: Only called from the ScrollAnimator.
254     friend class ScrollAnimator;
255     void setScrollOffsetFromAnimation(const IntPoint&);
256 
257     // This function should be overriden by subclasses to perform the actual
258     // scroll of the content.
259     virtual void setScrollOffset(const IntPoint&) = 0;
260 
261     virtual int lineStep(ScrollbarOrientation) const;
262     virtual int pageStep(ScrollbarOrientation) const;
263     virtual int documentStep(ScrollbarOrientation) const;
264     virtual float pixelStep(ScrollbarOrientation) const;
265 
266     // Stores the paint invalidations for the scrollbars during layout.
267     IntRect m_horizontalBarDamage;
268     IntRect m_verticalBarDamage;
269 
270     struct ScrollableAreaAnimators {
271         OwnPtr<ScrollAnimator> scrollAnimator;
272         OwnPtr<ProgrammaticScrollAnimator> programmaticScrollAnimator;
273     };
274 
275     mutable OwnPtr<ScrollableAreaAnimators> m_animators;
276     unsigned m_constrainsScrollingToContentEdge : 1;
277 
278     unsigned m_inLiveResize : 1;
279 
280     unsigned m_verticalScrollElasticity : 2; // ScrollElasticity
281     unsigned m_horizontalScrollElasticity : 2; // ScrollElasticity
282 
283     unsigned m_scrollbarOverlayStyle : 2; // ScrollbarOverlayStyle
284 
285     unsigned m_scrollOriginChanged : 1;
286 
287     // There are 8 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis
288     // if there is any reversed direction or writing-mode. The combinations are:
289     // writing-mode / direction     scrollOrigin.x() set    scrollOrigin.y() set
290     // horizontal-tb / ltr          NO                      NO
291     // horizontal-tb / rtl          YES                     NO
292     // horizontal-bt / ltr          NO                      YES
293     // horizontal-bt / rtl          YES                     YES
294     // vertical-lr / ltr            NO                      NO
295     // vertical-lr / rtl            NO                      YES
296     // vertical-rl / ltr            YES                     NO
297     // vertical-rl / rtl            YES                     YES
298     IntPoint m_scrollOrigin;
299 };
300 
301 } // namespace blink
302 
303 #endif // ScrollableArea_h
304