1/* 2 * Copyright (C) 2008, 2011, 2014 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 "Scrollbar.h" 30#include <wtf/Vector.h> 31 32namespace WebCore { 33 34class FloatPoint; 35class GraphicsContext; 36class LayoutPoint; 37class LayoutSize; 38class PlatformTouchEvent; 39class PlatformWheelEvent; 40class ScrollAnimator; 41class GraphicsLayer; 42class TiledBacking; 43 44class ScrollableArea { 45public: 46 bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1); 47 void scrollToOffsetWithoutAnimation(const FloatPoint&); 48 void scrollToOffsetWithoutAnimation(ScrollbarOrientation, float offset); 49 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 void notifyScrollPositionChanged(const IntPoint&); 53 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; } 58 59 bool handleWheelEvent(const PlatformWheelEvent&); 60 61#if ENABLE(TOUCH_EVENTS) 62 virtual bool isTouchScrollable() const { return false; } 63 virtual bool handleTouchEvent(const PlatformTouchEvent&); 64#endif 65 66#if PLATFORM(IOS) 67 virtual bool isOverflowScroll() const { return false; } 68 virtual void didStartScroll() { } 69 virtual void didEndScroll() { } 70 virtual void didUpdateScroll() { } 71#endif 72 virtual void setIsUserScroll(bool) { } 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 virtual void willStartLiveResize(); 86 virtual 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 lockOverlayScrollbarStateToHidden(bool shouldLockState) const; 98 bool scrollbarsCanBeActive() const; 99 100 virtual void didAddScrollbar(Scrollbar*, ScrollbarOrientation); 101 virtual void willRemoveScrollbar(Scrollbar*, ScrollbarOrientation); 102 103 virtual void contentsResized(); 104 105 bool hasOverlayScrollbars() const; 106 virtual void setScrollbarOverlayStyle(ScrollbarOverlayStyle); 107 ScrollbarOverlayStyle scrollbarOverlayStyle() const { return static_cast<ScrollbarOverlayStyle>(m_scrollbarOverlayStyle); } 108 109 // This getter will create a ScrollAnimator if it doesn't already exist. 110 ScrollAnimator* scrollAnimator() const; 111 112 // This getter will return null if the ScrollAnimator hasn't been created yet. 113 ScrollAnimator* existingScrollAnimator() const { return m_scrollAnimator.get(); } 114 115 const IntPoint& scrollOrigin() const { return m_scrollOrigin; } 116 bool scrollOriginChanged() const { return m_scrollOriginChanged; } 117 118 virtual bool isActive() const = 0; 119 virtual int scrollSize(ScrollbarOrientation) const = 0; 120 virtual int scrollPosition(Scrollbar*) const = 0; 121 virtual void invalidateScrollbar(Scrollbar*, const IntRect&); 122 virtual bool isScrollCornerVisible() const = 0; 123 virtual IntRect scrollCornerRect() const = 0; 124 virtual void invalidateScrollCorner(const IntRect&); 125 126 virtual bool updatesScrollLayerPositionOnMainThread() const = 0; 127 128 virtual bool forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const = 0; 129 130 // Convert points and rects between the scrollbar and its containing view. 131 // The client needs to implement these in order to be aware of layout effects 132 // like CSS transforms. 133 virtual IntRect convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const 134 { 135 return scrollbar->Widget::convertToContainingView(scrollbarRect); 136 } 137 virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const 138 { 139 return scrollbar->Widget::convertFromContainingView(parentRect); 140 } 141 virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const 142 { 143 return scrollbar->Widget::convertToContainingView(scrollbarPoint); 144 } 145 virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const 146 { 147 return scrollbar->Widget::convertFromContainingView(parentPoint); 148 } 149 150 virtual Scrollbar* horizontalScrollbar() const { return 0; } 151 virtual Scrollbar* verticalScrollbar() const { return 0; } 152 153 virtual IntPoint scrollPosition() const; 154 virtual IntPoint minimumScrollPosition() const; 155 virtual IntPoint maximumScrollPosition() const; 156 virtual bool scrolledToTop() const; 157 virtual bool scrolledToBottom() const; 158 virtual bool scrolledToLeft() const; 159 virtual bool scrolledToRight() const; 160 161 bool isScrolledProgrammatically() const { return m_scrolledProgrammatically; } 162 void setScrolledProgrammatically(bool state) { m_scrolledProgrammatically = state; } 163 164 enum VisibleContentRectIncludesScrollbars { ExcludeScrollbars, IncludeScrollbars }; 165 enum VisibleContentRectBehavior { 166 ContentsVisibleRect, 167#if PLATFORM(IOS) 168 LegacyIOSDocumentViewRect, 169 LegacyIOSDocumentVisibleRect = LegacyIOSDocumentViewRect 170#else 171 LegacyIOSDocumentVisibleRect = ContentsVisibleRect 172#endif 173 }; 174 175 IntRect visibleContentRect(VisibleContentRectBehavior = ContentsVisibleRect) const; 176 IntRect visibleContentRectIncludingScrollbars(VisibleContentRectBehavior = ContentsVisibleRect) const; 177 178 int visibleWidth() const { return visibleSize().width(); } 179 int visibleHeight() const { return visibleSize().height(); } 180 virtual IntSize visibleSize() const = 0; 181 182 virtual IntSize contentsSize() const = 0; 183 virtual IntSize overhangAmount() const { return IntSize(); } 184 virtual IntPoint lastKnownMousePosition() const { return IntPoint(); } 185 virtual bool isHandlingWheelEvent() const { return false; } 186 187 virtual int headerHeight() const { return 0; } 188 virtual int footerHeight() const { return 0; } 189 190 // The totalContentsSize() is equivalent to the contentsSize() plus the header and footer heights. 191 IntSize totalContentsSize() const; 192 193 virtual bool shouldSuspendScrollAnimations() const { return true; } 194 virtual void scrollbarStyleChanged(int /*newStyle*/, bool /*forceUpdate*/) { } 195 virtual void setVisibleScrollerThumbRect(const IntRect&) { } 196 197 // Note that this only returns scrollable areas that can actually be scrolled. 198 virtual ScrollableArea* enclosingScrollableArea() const = 0; 199 200 // Returns the bounding box of this scrollable area, in the coordinate system of the enclosing scroll view. 201 virtual IntRect scrollableAreaBoundingBox() const = 0; 202 203 virtual bool isRubberBandInProgress() const { return false; } 204 205 virtual bool scrollAnimatorEnabled() const { return false; } 206 207 // NOTE: Only called from Internals for testing. 208 void setScrollOffsetFromInternals(const IntPoint&); 209 210 static LayoutPoint constrainScrollPositionForOverhang(const LayoutRect& visibleContentRect, const LayoutSize& totalContentsSize, const LayoutPoint& scrollPosition, const LayoutPoint& scrollOrigin, int headerHeight, int footetHeight); 211 LayoutPoint constrainScrollPositionForOverhang(const LayoutPoint& scrollPosition); 212 213 // Computes the double value for the scrollbar's current position and the current overhang amount. 214 // This function is static so that it can be called from the main thread or the scrolling thread. 215 static void computeScrollbarValueAndOverhang(float currentPosition, float totalSize, float visibleSize, float& doubleValue, float& overhangAmount); 216 217 // Let subclasses provide a way of asking for and servicing scroll 218 // animations. 219 virtual bool scheduleAnimation() { return false; } 220 void serviceScrollAnimations(); 221 222#if PLATFORM(IOS) 223 bool isHorizontalScrollerPinnedToMinimumPosition() const { return !horizontalScrollbar() || scrollPosition(horizontalScrollbar()) <= minimumScrollPosition().x(); } 224 bool isHorizontalScrollerPinnedToMaximumPosition() const { return !horizontalScrollbar() || scrollPosition(horizontalScrollbar()) >= maximumScrollPosition().x(); } 225 bool isVerticalScrollerPinnedToMinimumPosition() const { return !verticalScrollbar() || scrollPosition(verticalScrollbar()) <= minimumScrollPosition().y(); } 226 bool isVerticalScrollerPinnedToMaximumPosition() const { return !verticalScrollbar() || scrollPosition(verticalScrollbar()) >= maximumScrollPosition().y(); } 227 228 bool isPinnedInBothDirections(const IntSize&) const; 229 bool isPinnedHorizontallyInDirection(int horizontalScrollDelta) const; 230 bool isPinnedVerticallyInDirection(int verticalScrollDelta) const; 231#endif 232 233 virtual TiledBacking* tiledBacking() const { return 0; } 234 virtual bool usesCompositedScrolling() const { return false; } 235 236 virtual GraphicsLayer* layerForHorizontalScrollbar() const { return 0; } 237 virtual GraphicsLayer* layerForVerticalScrollbar() const { return 0; } 238 239 bool hasLayerForHorizontalScrollbar() const; 240 bool hasLayerForVerticalScrollbar() const; 241 242 void verticalScrollbarLayerDidChange(); 243 void horizontalScrollbarLayerDidChange(); 244 245protected: 246 ScrollableArea(); 247 virtual ~ScrollableArea(); 248 249 void setScrollOrigin(const IntPoint&); 250 void resetScrollOriginChanged() { m_scrollOriginChanged = false; } 251 252 virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&) = 0; 253 virtual void invalidateScrollCornerRect(const IntRect&) = 0; 254 255 friend class ScrollingCoordinator; 256 virtual GraphicsLayer* layerForScrolling() const { return 0; } 257 virtual GraphicsLayer* layerForScrollCorner() const { return 0; } 258#if ENABLE(RUBBER_BANDING) 259 virtual GraphicsLayer* layerForOverhangAreas() const { return 0; } 260#endif 261 262 bool hasLayerForScrollCorner() const; 263 264private: 265 virtual IntRect visibleContentRectInternal(VisibleContentRectIncludesScrollbars, VisibleContentRectBehavior) const; 266 void scrollPositionChanged(const IntPoint&); 267 268 // NOTE: Only called from the ScrollAnimator. 269 friend class ScrollAnimator; 270 void setScrollOffsetFromAnimation(const IntPoint&); 271 272 // This function should be overriden by subclasses to perform the actual 273 // scroll of the content. 274 virtual void setScrollOffset(const IntPoint&) = 0; 275 276 mutable OwnPtr<ScrollAnimator> m_scrollAnimator; 277 278 // There are 8 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis 279 // if there is any reversed direction or writing-mode. The combinations are: 280 // writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set 281 // horizontal-tb / ltr NO NO 282 // horizontal-tb / rtl YES NO 283 // horizontal-bt / ltr NO YES 284 // horizontal-bt / rtl YES YES 285 // vertical-lr / ltr NO NO 286 // vertical-lr / rtl NO YES 287 // vertical-rl / ltr YES NO 288 // vertical-rl / rtl YES YES 289 IntPoint m_scrollOrigin; 290 291 unsigned m_constrainsScrollingToContentEdge : 1; 292 293 unsigned m_inLiveResize : 1; 294 295 unsigned m_verticalScrollElasticity : 2; // ScrollElasticity 296 unsigned m_horizontalScrollElasticity : 2; // ScrollElasticity 297 298 unsigned m_scrollbarOverlayStyle : 2; // ScrollbarOverlayStyle 299 300 unsigned m_scrollOriginChanged : 1; 301 unsigned m_scrolledProgrammatically : 1; 302}; 303 304} // namespace WebCore 305 306#endif // ScrollableArea_h 307