106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen/*
206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * Copyright (C) 2010 Google Inc. All rights reserved.
306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen *
406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * Redistribution and use in source and binary forms, with or without
506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * modification, are permitted provided that the following conditions are
606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * met:
706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen *
806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen *     * Redistributions of source code must retain the above copyright
906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * notice, this list of conditions and the following disclaimer.
1006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen *     * Redistributions in binary form must reproduce the above
1106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * copyright notice, this list of conditions and the following disclaimer
1206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * in the documentation and/or other materials provided with the
1306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * distribution.
1406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen *     * Neither the name of Google Inc. nor the names of its
1506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * contributors may be used to endorse or promote products derived from
1606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * this software without specific prior written permission.
1706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen *
1806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen */
3006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
3106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#include "config.h"
3206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#include "DragScrollTimer.h"
3306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
3406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#include "FrameView.h"
3506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
3606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenusing namespace WebCore;
3706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
3806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsennamespace WebKit {
3906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
4006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen// Computes the distance from a point outside a rect to the nearest edge of the rect.
4106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenstatic IntSize distanceToRect(const IntPoint& point, const IntRect& rect)
4206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
4306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    int dx = 0, dy = 0;
4406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (point.x() < rect.x())
4506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        dx = point.x() - rect.x();
462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    else if (rect.maxX() < point.x())
472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        dx = point.x() - rect.maxX();
4806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (point.y() < rect.y())
4906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        dy = point.y() - rect.y();
502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    else if (rect.maxY() < point.y())
512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        dy = point.y() - rect.maxY();
5206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    return IntSize(dx, dy);
5306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
5406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
5506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenDragScrollTimer::DragScrollTimer()
5606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    : m_timer(this, &DragScrollTimer::fired)
5706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    , m_view(0)
5806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    , m_scrolling(false)
5906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
6006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
6106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
6206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenDragScrollTimer::~DragScrollTimer()
6306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
6406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // We do this for detecting dead object earlier
6506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    stop();
6606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
6706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
6806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenvoid DragScrollTimer::stop()
6906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
7006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    m_timer.stop();
7106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    m_view = 0;
7206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    m_scrolling = false;
7306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
7406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
7506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenvoid DragScrollTimer::scroll()
7606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
7706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    m_view->scrollBy(m_lastDistance);
7806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    m_scrolling = true;
7906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
8006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
8106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenvoid DragScrollTimer::update()
8206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
8306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (shouldScroll())
8406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        scroll();
8506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    else
8606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        stop();
8706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
8806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
8906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenvoid DragScrollTimer::triggerScroll(FrameView* view, const WebPoint& location)
9006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
9106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (!view)
9206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        return;
9306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
9406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // Approximates Safari
9506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    static const double scrollStartDelay = 0.2;
9606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
9706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    m_view = view;
9806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    m_lastDistance = scrollDistanceFor(view, location);
9906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
10006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (m_scrolling)
10106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        update();
10206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    else if (shouldScroll() && !m_timer.isActive())
10306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        m_timer.startOneShot(scrollStartDelay);
10406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
10506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
10606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenIntSize DragScrollTimer::scrollDistanceFor(FrameView* view, const WebPoint& location) const
10706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{
10806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    static const int scrollMargin = 30;
10906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
11006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    IntRect bounds(0, 0, view->visibleWidth(), view->visibleHeight());
11106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (!bounds.contains(location))
11206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        return IntSize(0, 0); // The location is outside the border belt.
11306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
11406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    bounds.setY(bounds.y() + scrollMargin);
11506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    bounds.setHeight(bounds.height() - scrollMargin * 2);
11606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    bounds.setX(bounds.x() + scrollMargin);
11706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    bounds.setWidth(bounds.width() - scrollMargin * 2);
11806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
11906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    if (bounds.contains(location))
12006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        return IntSize(0, 0); // The location is inside the border belt.
12106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
12206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    // The location is over the border belt.
12306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    return distanceToRect(location, bounds);
12406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen}
12506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
12606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen} // namespace WebKit
127