Home | History | Annotate | Download | only in platform
      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 "core/platform/ScrollAnimator.h"
     33 
     34 #include <algorithm>
     35 #include "core/platform/PlatformWheelEvent.h"
     36 #include "core/platform/ScrollableArea.h"
     37 #include "core/platform/graphics/FloatPoint.h"
     38 #include "wtf/PassOwnPtr.h"
     39 
     40 using namespace std;
     41 
     42 namespace WebCore {
     43 
     44 ScrollAnimator::ScrollAnimator(ScrollableArea* scrollableArea)
     45     : m_scrollableArea(scrollableArea)
     46     , m_currentPosX(0)
     47     , m_currentPosY(0)
     48 {
     49 }
     50 
     51 ScrollAnimator::~ScrollAnimator()
     52 {
     53 }
     54 
     55 bool ScrollAnimator::scroll(ScrollbarOrientation orientation, ScrollGranularity, float step, float multiplier)
     56 {
     57     float* currentPos = (orientation == HorizontalScrollbar) ? &m_currentPosX : &m_currentPosY;
     58     float newPos = clampScrollPosition(orientation, *currentPos + step * multiplier);
     59     float delta = *currentPos - newPos;
     60     if (*currentPos == newPos)
     61         return false;
     62     *currentPos = newPos;
     63 
     64     notifyPositionChanged(orientation == HorizontalScrollbar ? FloatSize(delta, 0) : FloatSize(0, delta));
     65 
     66     return true;
     67 }
     68 
     69 void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
     70 {
     71     FloatSize delta = FloatSize(offset.x() - m_currentPosX, offset.y() - m_currentPosY);
     72     m_currentPosX = offset.x();
     73     m_currentPosY = offset.y();
     74     notifyPositionChanged(delta);
     75 }
     76 
     77 bool ScrollAnimator::handleWheelEvent(const PlatformWheelEvent& e)
     78 {
     79     bool canScrollX = m_scrollableArea->userInputScrollable(HorizontalScrollbar);
     80     bool canScrollY = m_scrollableArea->userInputScrollable(VerticalScrollbar);
     81 
     82     // Accept the event if we are scrollable in that direction and can still
     83     // scroll any further.
     84     float deltaX = canScrollX ? e.deltaX() : 0;
     85     float deltaY = canScrollY ? e.deltaY() : 0;
     86 
     87     bool handled = false;
     88 
     89 #if !OS(DARWIN)
     90     ScrollGranularity granularity = e.hasPreciseScrollingDeltas() ? ScrollByPrecisePixel : ScrollByPixel;
     91 #else
     92     ScrollGranularity granularity = ScrollByPixel;
     93 #endif
     94 
     95     IntSize maxForwardScrollDelta = m_scrollableArea->maximumScrollPosition() - m_scrollableArea->scrollPosition();
     96     IntSize maxBackwardScrollDelta = m_scrollableArea->scrollPosition() - m_scrollableArea->minimumScrollPosition();
     97     if ((deltaX < 0 && maxForwardScrollDelta.width() > 0)
     98         || (deltaX > 0 && maxBackwardScrollDelta.width() > 0)
     99         || (deltaY < 0 && maxForwardScrollDelta.height() > 0)
    100         || (deltaY > 0 && maxBackwardScrollDelta.height() > 0)) {
    101         handled = true;
    102 
    103         if (deltaY) {
    104             if (e.granularity() == ScrollByPageWheelEvent) {
    105                 bool negative = deltaY < 0;
    106                 deltaY = m_scrollableArea->pageStep(VerticalScrollbar);
    107                 if (negative)
    108                     deltaY = -deltaY;
    109             }
    110 
    111             scroll(VerticalScrollbar, granularity, m_scrollableArea->pixelStep(VerticalScrollbar), -deltaY);
    112         }
    113 
    114         if (deltaX) {
    115             if (e.granularity() == ScrollByPageWheelEvent) {
    116                 bool negative = deltaX < 0;
    117                 deltaX = m_scrollableArea->pageStep(HorizontalScrollbar);
    118                 if (negative)
    119                     deltaX = -deltaX;
    120             }
    121 
    122             scroll(HorizontalScrollbar, granularity, m_scrollableArea->pixelStep(HorizontalScrollbar), -deltaX);
    123         }
    124     }
    125     return handled;
    126 }
    127 
    128 void ScrollAnimator::setCurrentPosition(const FloatPoint& position)
    129 {
    130     m_currentPosX = position.x();
    131     m_currentPosY = position.y();
    132 }
    133 
    134 FloatPoint ScrollAnimator::currentPosition() const
    135 {
    136     return FloatPoint(m_currentPosX, m_currentPosY);
    137 }
    138 
    139 void ScrollAnimator::notifyPositionChanged(const FloatSize& delta)
    140 {
    141     UNUSED_PARAM(delta);
    142     m_scrollableArea->setScrollOffsetFromAnimation(IntPoint(m_currentPosX, m_currentPosY));
    143 }
    144 
    145 float ScrollAnimator::clampScrollPosition(ScrollbarOrientation orientation, float pos)
    146 {
    147     float maxScrollPos = m_scrollableArea->maximumScrollPosition(orientation);
    148     float minScrollPos = m_scrollableArea->minimumScrollPosition(orientation);
    149     return std::max(std::min(pos, maxScrollPos), minScrollPos);
    150 }
    151 
    152 } // namespace WebCore
    153