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