1 /* 2 * Copyright (c) 2010, Google 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "ScrollAnimator.h" 33 34 #include "FloatPoint.h" 35 #include "PlatformWheelEvent.h" 36 #include "ScrollableArea.h" 37 #include <algorithm> 38 #include <wtf/PassOwnPtr.h> 39 40 using namespace std; 41 42 namespace WebCore { 43 44 #if !ENABLE(SMOOTH_SCROLLING) 45 PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea) 46 { 47 return adoptPtr(new ScrollAnimator(scrollableArea)); 48 } 49 #endif 50 51 ScrollAnimator::ScrollAnimator(ScrollableArea* scrollableArea) 52 : m_scrollableArea(scrollableArea) 53 , m_currentPosX(0) 54 , m_currentPosY(0) 55 { 56 } 57 58 ScrollAnimator::~ScrollAnimator() 59 { 60 } 61 62 bool ScrollAnimator::scroll(ScrollbarOrientation orientation, ScrollGranularity, float step, float multiplier) 63 { 64 float* currentPos = (orientation == HorizontalScrollbar) ? &m_currentPosX : &m_currentPosY; 65 float newPos = std::max(std::min(*currentPos + (step * multiplier), static_cast<float>(m_scrollableArea->scrollSize(orientation))), 0.0f); 66 if (*currentPos == newPos) 67 return false; 68 *currentPos = newPos; 69 70 notityPositionChanged(); 71 72 return true; 73 } 74 75 void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset) 76 { 77 if (m_currentPosX != offset.x() || m_currentPosY != offset.y()) { 78 m_currentPosX = offset.x(); 79 m_currentPosY = offset.y(); 80 notityPositionChanged(); 81 } 82 } 83 84 void ScrollAnimator::handleWheelEvent(PlatformWheelEvent& e) 85 { 86 Scrollbar* horizontalScrollbar = m_scrollableArea->horizontalScrollbar(); 87 Scrollbar* verticalScrollbar = m_scrollableArea->verticalScrollbar(); 88 89 // Accept the event if we have a scrollbar in that direction and can still 90 // scroll any further. 91 float deltaX = horizontalScrollbar ? e.deltaX() : 0; 92 float deltaY = verticalScrollbar ? e.deltaY() : 0; 93 94 IntSize maxForwardScrollDelta = m_scrollableArea->maximumScrollPosition() - m_scrollableArea->scrollPosition(); 95 IntSize maxBackwardScrollDelta = m_scrollableArea->scrollPosition() - m_scrollableArea->minimumScrollPosition(); 96 if ((deltaX < 0 && maxForwardScrollDelta.width() > 0) 97 || (deltaX > 0 && maxBackwardScrollDelta.width() > 0) 98 || (deltaY < 0 && maxForwardScrollDelta.height() > 0) 99 || (deltaY > 0 && maxBackwardScrollDelta.height() > 0)) { 100 e.accept(); 101 if (e.granularity() == ScrollByPageWheelEvent) { 102 ASSERT(!e.deltaX()); 103 bool negative = deltaY < 0; 104 deltaY = max(max(static_cast<float>(m_scrollableArea->visibleHeight()) * Scrollbar::minFractionToStepWhenPaging(), static_cast<float>(m_scrollableArea->visibleHeight() - Scrollbar::maxOverlapBetweenPages())), 1.0f); 105 if (negative) 106 deltaY = -deltaY; 107 } 108 109 if (deltaY) 110 scroll(VerticalScrollbar, ScrollByPixel, verticalScrollbar->pixelStep(), -deltaY); 111 if (deltaX) 112 scroll(HorizontalScrollbar, ScrollByPixel, horizontalScrollbar->pixelStep(), -deltaX); 113 } 114 } 115 116 #if ENABLE(GESTURE_EVENTS) 117 void ScrollAnimator::handleGestureEvent(const PlatformGestureEvent&) 118 { 119 } 120 #endif 121 122 FloatPoint ScrollAnimator::currentPosition() const 123 { 124 return FloatPoint(m_currentPosX, m_currentPosY); 125 } 126 127 void ScrollAnimator::notityPositionChanged() 128 { 129 m_scrollableArea->setScrollOffsetFromAnimation(IntPoint(m_currentPosX, m_currentPosY)); 130 } 131 132 } // namespace WebCore 133