Home | History | Annotate | Download | only in scroll
      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.
     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.
     81     bool constrainsScrollingToContentEdge() const { return m_constrainsScrollingToContentEdge; }
     82     void setConstrainsScrollingToContentEdge(bool constrainsScrollingToContentEdge) { m_constrainsScrollingToContentEdge = constrainsScrollingToContentEdge; }
     83 
     84     void setVerticalScrollElasticity(ScrollElasticity scrollElasticity) { m_verticalScrollElasticity = scrollElasticity; }
     85     ScrollElasticity verticalScrollElasticity() const { return static_cast<ScrollElasticity>(m_verticalScrollElasticity); }
     86 
     87     void setHorizontalScrollElasticity(ScrollElasticity scrollElasticity) { m_horizontalScrollElasticity = scrollElasticity; }
     88     ScrollElasticity horizontalScrollElasticity() const { return static_cast<ScrollElasticity>(m_horizontalScrollElasticity); }
     89 
     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);
    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.
    118     ScrollAnimator* existingScrollAnimator() const { return m_animators ? m_animators->scrollAnimator.get() : 0; }
    119 
    120     ProgrammaticScrollAnimator* programmaticScrollAnimator() const;
    121     ProgrammaticScrollAnimator* existingProgrammaticScrollAnimator() const
    122     {
    123         return m_animators ? m_animators->programmaticScrollAnimator.get() : 0;
    124     }
    125 
    126     const IntPoint& scrollOrigin() const { return m_scrollOrigin; }
    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&);
    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.
    141     virtual IntRect convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
    142     {
    143         return scrollbar->Widget::convertToContainingView(scrollbarRect);
    144     }
    145     virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
    146     {
    147         return scrollbar->Widget::convertFromContainingView(parentRect);
    148     }
    149     virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
    150     {
    151         return scrollbar->Widget::convertToContainingView(scrollbarPoint);
    152     }
    153     virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
    154     {
    155         return scrollbar->Widget::convertFromContainingView(parentPoint);
    156     }
    157 
    158     virtual Scrollbar* horizontalScrollbar() const { return 0; }
    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;
    168     virtual int visibleHeight() const { return visibleContentRect().height(); }
    169     virtual int visibleWidth() const { return visibleContentRect().width(); }
    170     virtual IntSize contentsSize() const = 0;
    171     virtual IntSize overhangAmount() const { return IntSize(); }
    172     virtual IntPoint lastKnownMousePosition() const { return IntPoint(); }
    173 
    174     virtual bool shouldSuspendScrollAnimations() const { return true; }
    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 
    182     virtual bool isRubberBandInProgress() const { return false; }
    183 
    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 
    196     virtual bool usesCompositedScrolling() const { return false; }
    197 
    198     // Returns true if the GraphicsLayer tree needs to be rebuilt.
    199     virtual bool updateAfterCompositingChange() { return false; }
    200 
    201     virtual bool userInputScrollable(ScrollbarOrientation) const = 0;
    202     virtual bool shouldPlaceVerticalScrollbarOnLeft() const = 0;
    203 
    204     // Convenience functions
    205     int scrollPosition(ScrollbarOrientation orientation) { return orientation == HorizontalScrollbar ? scrollPosition().x() : scrollPosition().y(); }
    206     int minimumScrollPosition(ScrollbarOrientation orientation) { return orientation == HorizontalScrollbar ? minimumScrollPosition().x() : minimumScrollPosition().y(); }
    207     int maximumScrollPosition(ScrollbarOrientation orientation) { return orientation == HorizontalScrollbar ? maximumScrollPosition().x() : maximumScrollPosition().y(); }
    208     int clampScrollPosition(ScrollbarOrientation orientation, int pos)  { return std::max(std::min(pos, maximumScrollPosition(orientation)), minimumScrollPosition(orientation)); }
    209 
    210     bool hasVerticalBarDamage() const { return !m_verticalBarDamage.isEmpty(); }
    211     bool hasHorizontalBarDamage() const { return !m_horizontalBarDamage.isEmpty(); }
    212     const IntRect& verticalBarDamage() const { return m_verticalBarDamage; }
    213     const IntRect& horizontalBarDamage() const { return m_horizontalBarDamage; }
    214 
    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 
    223     void resetScrollbarDamage()
    224     {
    225         m_verticalBarDamage = IntRect();
    226         m_horizontalBarDamage = IntRect();
    227     }
    228 
    229     virtual GraphicsLayer* layerForContainer() const;
    230     virtual GraphicsLayer* layerForScrolling() const { return 0; }
    231     virtual GraphicsLayer* layerForHorizontalScrollbar() const { return 0; }
    232     virtual GraphicsLayer* layerForVerticalScrollbar() const { return 0; }
    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&);
    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