Chromium Code Reviews| Index: third_party/WebKit/Source/core/page/AutoscrollController.cpp |
| diff --git a/third_party/WebKit/Source/core/page/AutoscrollController.cpp b/third_party/WebKit/Source/core/page/AutoscrollController.cpp |
| index 454f53380c05baf2936ed47c1828d3c95a4e3c46..1ec5b9e524a5a6c5eb1e638bca708fd9ffb86e7e 100644 |
| --- a/third_party/WebKit/Source/core/page/AutoscrollController.cpp |
| +++ b/third_party/WebKit/Source/core/page/AutoscrollController.cpp |
| @@ -31,6 +31,7 @@ |
| #include "core/frame/FrameView.h" |
| #include "core/frame/LocalFrame.h" |
| +#include "core/html/HTMLFrameOwnerElement.h" |
| #include "core/input/EventHandler.h" |
| #include "core/layout/HitTestResult.h" |
| #include "core/layout/LayoutBox.h" |
| @@ -54,7 +55,8 @@ AutoscrollController::AutoscrollController(Page& page) |
| m_autoscrollLayoutObject(nullptr), |
| m_pressedLayoutObject(nullptr), |
| m_autoscrollType(NoAutoscroll), |
| - m_dragAndDropAutoscrollStartTime(0) {} |
| + m_dragAndDropAutoscrollStartTime(0), |
| + m_middleClickAutoscrolled(false) {} |
| DEFINE_TRACE(AutoscrollController) { |
| visitor->trace(m_page); |
| @@ -234,12 +236,64 @@ void AutoscrollController::startMiddleClickAutoscroll( |
| m_autoscrollType = AutoscrollForMiddleClick; |
| m_autoscrollLayoutObject = scrollable; |
| m_middleClickAutoscrollStartPos = lastKnownMousePosition; |
| + m_middleClickAutoscrolled = false; |
| UseCounter::count(m_page->mainFrame(), |
| UseCounter::MiddleClickAutoscrollStart); |
| startAutoscroll(); |
| } |
| +static inline int adjustedScrollDelta(int beginningDelta) { |
| + // This implemention matches Firefox's. |
| + // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856. |
| + const int speedReducer = 12; |
| + |
| + int adjustedDelta = beginningDelta / speedReducer; |
| + if (adjustedDelta > 1) { |
| + adjustedDelta = static_cast<int>(adjustedDelta * |
| + sqrt(static_cast<double>(adjustedDelta))) - |
| + 1; |
| + } else if (adjustedDelta < -1) { |
| + adjustedDelta = |
| + static_cast<int>(adjustedDelta * |
| + sqrt(static_cast<double>(-adjustedDelta))) + |
| + 1; |
| + } |
| + |
| + return adjustedDelta; |
| +} |
| + |
| +static inline IntSize adjustedScrollDelta(const IntSize& delta) { |
| + return IntSize(adjustedScrollDelta(delta.width()), |
| + adjustedScrollDelta(delta.height())); |
| +} |
| + |
| +FloatSize AutoscrollController::calculateAutoscrollDelta() { |
| + LocalFrame* frame = m_autoscrollLayoutObject->frame(); |
| + if (!frame) |
| + return FloatSize(); |
| + |
| + IntPoint lastKnownMousePosition = |
| + frame->eventHandler().lastKnownMousePosition(); |
| + |
| + // We need to check if the last known mouse position is out of the window. |
| + // When the mouse is out of the window, the position is incoherent |
| + static IntPoint previousMousePosition; |
| + if (lastKnownMousePosition.x() < 0 || lastKnownMousePosition.y() < 0) |
| + lastKnownMousePosition = previousMousePosition; |
| + else |
| + previousMousePosition = lastKnownMousePosition; |
| + |
| + IntSize delta = lastKnownMousePosition - m_middleClickAutoscrollStartPos; |
| + |
| + // at the center we let the space for the icon. |
| + if (abs(delta.width()) <= noMiddleClickAutoscrollRadius) |
| + delta.setWidth(0); |
| + if (abs(delta.height()) <= noMiddleClickAutoscrollRadius) |
| + delta.setHeight(0); |
| + return FloatSize(adjustedScrollDelta(delta)); |
| +} |
| + |
| void AutoscrollController::animate(double) { |
| if (!m_autoscrollLayoutObject || !m_autoscrollLayoutObject->frame()) { |
| stopAutoscroll(); |
| @@ -279,8 +333,30 @@ void AutoscrollController::animate(double) { |
| if (FrameView* view = m_autoscrollLayoutObject->frame()->view()) |
| updateMiddleClickAutoscrollState(view, |
| eventHandler.lastKnownMousePosition()); |
| - m_autoscrollLayoutObject->middleClickAutoscroll( |
| - m_middleClickAutoscrollStartPos); |
| + FloatSize delta = calculateAutoscrollDelta(); |
| + if (delta.isZero()) |
| + break; |
| + ScrollResult result = |
| + m_autoscrollLayoutObject->scroll(ScrollByPixel, delta); |
| + LayoutObject* layoutObject = m_autoscrollLayoutObject; |
| + while (!m_middleClickAutoscrolled && !result.didScroll()) { |
| + if (layoutObject->node() && layoutObject->node()->isDocumentNode()) { |
| + Element* owner = toDocument(layoutObject->node())->localOwner(); |
| + layoutObject = owner ? owner->layoutObject() : nullptr; |
| + } else { |
| + layoutObject = layoutObject->parent(); |
| + } |
| + if (!layoutObject) { |
| + break; |
| + } |
| + if (layoutObject && layoutObject->isBox() && |
| + toLayoutBox(layoutObject)->canBeScrolledAndHasScrollableArea()) |
| + result = toLayoutBox(layoutObject)->scroll(ScrollByPixel, delta); |
| + } |
| + if (result.didScroll()) { |
| + m_middleClickAutoscrolled = true; |
|
bokan
2016/11/11 19:48:46
This variable would be more descriptive as m_didLa
|
| + m_autoscrollLayoutObject = toLayoutBox(layoutObject); |
| + } |
| break; |
| } |
| if (m_autoscrollType != NoAutoscroll && m_autoscrollLayoutObject) |