15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (c) 2010, Google Inc. All rights reserved. 302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met: 702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions in binary form must reproduce the above 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission. 1702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/scroll/ScrollAnimator.h" 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatPoint.h" 35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/scroll/ScrollableArea.h" 367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/PassOwnPtr.h" 371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include <algorithm> 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std; 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ScrollAnimator::ScrollAnimator(ScrollableArea* scrollableArea) 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_scrollableArea(scrollableArea) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_currentPosX(0) 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_currentPosY(0) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ScrollAnimator::~ScrollAnimator() 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool ScrollAnimator::scroll(ScrollbarOrientation orientation, ScrollGranularity, float step, float multiplier) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* currentPos = (orientation == HorizontalScrollbar) ? &m_currentPosX : &m_currentPosY; 575267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) float newPos = clampScrollPosition(orientation, *currentPos + step * multiplier); 58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) float delta = *currentPos - newPos; 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (*currentPos == newPos) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *currentPos = newPos; 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) notifyPositionChanged(orientation == HorizontalScrollbar ? FloatSize(delta, 0) : FloatSize(0, delta)); 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) FloatSize delta = FloatSize(offset.x() - m_currentPosX, offset.y() - m_currentPosY); 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_currentPosX = offset.x(); 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_currentPosY = offset.y(); 73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) notifyPositionChanged(delta); 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool ScrollAnimator::handleWheelEvent(const PlatformWheelEvent& e) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 78f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) bool canScrollX = m_scrollableArea->userInputScrollable(HorizontalScrollbar); 79f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) bool canScrollY = m_scrollableArea->userInputScrollable(VerticalScrollbar); 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 81f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) // Accept the event if we are scrollable in that direction and can still 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // scroll any further. 83f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) float deltaX = canScrollX ? e.deltaX() : 0; 84f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) float deltaY = canScrollY ? e.deltaY() : 0; 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool handled = false; 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 888abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#if !OS(MACOSX) 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ScrollGranularity granularity = e.hasPreciseScrollingDeltas() ? ScrollByPrecisePixel : ScrollByPixel; 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#else 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ScrollGranularity granularity = ScrollByPixel; 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntSize maxForwardScrollDelta = m_scrollableArea->maximumScrollPosition() - m_scrollableArea->scrollPosition(); 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntSize maxBackwardScrollDelta = m_scrollableArea->scrollPosition() - m_scrollableArea->minimumScrollPosition(); 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((deltaX < 0 && maxForwardScrollDelta.width() > 0) 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || (deltaX > 0 && maxBackwardScrollDelta.width() > 0) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || (deltaY < 0 && maxForwardScrollDelta.height() > 0) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || (deltaY > 0 && maxBackwardScrollDelta.height() > 0)) { 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) handled = true; 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (deltaY) { 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (e.granularity() == ScrollByPageWheelEvent) { 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool negative = deltaY < 0; 105f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) deltaY = m_scrollableArea->pageStep(VerticalScrollbar); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (negative) 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deltaY = -deltaY; 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 109f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) 110f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) scroll(VerticalScrollbar, granularity, m_scrollableArea->pixelStep(VerticalScrollbar), -deltaY); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (deltaX) { 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (e.granularity() == ScrollByPageWheelEvent) { 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool negative = deltaX < 0; 116f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) deltaX = m_scrollableArea->pageStep(HorizontalScrollbar); 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (negative) 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) deltaX = -deltaX; 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 120f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) 121f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) scroll(HorizontalScrollbar, granularity, m_scrollableArea->pixelStep(HorizontalScrollbar), -deltaX); 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return handled; 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimator::setCurrentPosition(const FloatPoint& position) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_currentPosX = position.x(); 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_currentPosY = position.y(); 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FloatPoint ScrollAnimator::currentPosition() const 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return FloatPoint(m_currentPosX, m_currentPosY); 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 138a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void ScrollAnimator::notifyPositionChanged(const FloatSize&) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_scrollableArea->setScrollOffsetFromAnimation(IntPoint(m_currentPosX, m_currentPosY)); 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)float ScrollAnimator::clampScrollPosition(ScrollbarOrientation orientation, float pos) 1445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 1455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) float maxScrollPos = m_scrollableArea->maximumScrollPosition(orientation); 1465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) float minScrollPos = m_scrollableArea->minimumScrollPosition(orientation); 1475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return std::max(std::min(pos, maxScrollPos), minScrollPos); 1485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 1495267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 151