| Index: Source/WebCore/page/EventHandler.cpp
|
| ===================================================================
|
| --- Source/WebCore/page/EventHandler.cpp (revision 145820)
|
| +++ Source/WebCore/page/EventHandler.cpp (working copy)
|
| @@ -403,6 +403,7 @@
|
| #if ENABLE(GESTURE_EVENTS)
|
| m_scrollGestureHandlingNode = 0;
|
| m_lastHitTestResultOverWidget = false;
|
| + m_previousGestureScrolledNode = 0;
|
| m_scrollbarHandlingScrollGesture = 0;
|
| #endif
|
| m_maxMouseMovedDuration = 0;
|
| @@ -2498,6 +2499,9 @@
|
| case PlatformEvent::GestureScrollUpdate:
|
| case PlatformEvent::GestureScrollUpdateWithoutPropagation:
|
| return handleGestureScrollUpdate(gestureEvent);
|
| + case PlatformEvent::GestureScrollEnd:
|
| + clearGestureScrollNodes();
|
| + return true;
|
| case PlatformEvent::GestureTap:
|
| return handleGestureTap(gestureEvent);
|
| case PlatformEvent::GestureTapDown:
|
| @@ -2508,7 +2512,6 @@
|
| return handleGestureLongTap(gestureEvent);
|
| case PlatformEvent::GestureTwoFingerTap:
|
| return handleGestureTwoFingerTap(gestureEvent);
|
| - case PlatformEvent::GestureScrollEnd:
|
| case PlatformEvent::GestureDoubleTap:
|
| case PlatformEvent::GesturePinchBegin:
|
| case PlatformEvent::GesturePinchEnd:
|
| @@ -2636,18 +2639,6 @@
|
| return false;
|
| }
|
|
|
| -static const Node* closestScrollableNodeCandidate(const Node* node)
|
| -{
|
| - for (const Node* scrollableNode = node; scrollableNode; scrollableNode = scrollableNode->parentNode()) {
|
| - if (scrollableNode->isDocumentNode())
|
| - return scrollableNode;
|
| - RenderObject* renderer = scrollableNode->renderer();
|
| - if (renderer && renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())
|
| - return scrollableNode;
|
| - }
|
| - return node;
|
| -}
|
| -
|
| bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureEvent)
|
| {
|
| Document* document = m_frame->document();
|
| @@ -2666,6 +2657,7 @@
|
|
|
| m_lastHitTestResultOverWidget = result.isOverWidget();
|
| m_scrollGestureHandlingNode = result.innerNode();
|
| + m_previousGestureScrolledNode = 0;
|
|
|
| Node* node = m_scrollGestureHandlingNode.get();
|
| if (node)
|
| @@ -2676,50 +2668,81 @@
|
|
|
| bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gestureEvent)
|
| {
|
| - // Ignore this event if we don't already have a targeted node with a valid renderer.
|
| - const Node* node = m_scrollGestureHandlingNode.get();
|
| - if (!node)
|
| + FloatSize delta(gestureEvent.deltaX(), gestureEvent.deltaY());
|
| + if (delta.isZero())
|
| return false;
|
|
|
| - RenderObject* latchedRenderer = node->renderer();
|
| - if (!latchedRenderer)
|
| - return false;
|
| + const float scaleFactor = m_frame->pageZoomFactor() * m_frame->frameScaleFactor();
|
| + delta.scale(1 / scaleFactor, 1 / scaleFactor);
|
|
|
| - IntSize delta(-gestureEvent.deltaX(), -gestureEvent.deltaY());
|
| - if (delta.isZero())
|
| + Node* node = m_scrollGestureHandlingNode.get();
|
| + if (!node)
|
| + return sendScrollEventToView(gestureEvent, delta);
|
| +
|
| + // Ignore this event if the targeted node does not have a valid renderer.
|
| + RenderObject* renderer = node->renderer();
|
| + if (!renderer)
|
| return false;
|
|
|
| RefPtr<FrameView> protector(m_frame->view());
|
|
|
| // Try to send the event to the correct view.
|
| - if (passGestureEventToWidgetIfPossible(gestureEvent, latchedRenderer))
|
| + if (passGestureEventToWidgetIfPossible(gestureEvent, renderer))
|
| return true;
|
|
|
| - // Otherwise if this is the correct view for the event, find the closest scrollable
|
| - // ancestor of the targeted node and scroll the layer that contains this node's renderer.
|
| - node = closestScrollableNodeCandidate(node);
|
| - if (!node)
|
| - return false;
|
| + Node* stopNode = 0;
|
| + bool scrollShouldNotPropagate = gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation;
|
| + if (scrollShouldNotPropagate)
|
| + stopNode = m_previousGestureScrolledNode.get();
|
|
|
| - latchedRenderer = node->renderer();
|
| - if (!latchedRenderer)
|
| - return false;
|
| + // First try to scroll the closest scrollable RenderBox ancestor of |node|.
|
| + ScrollGranularity granularity = ScrollByPixel;
|
| + bool horizontalScroll = scrollNode(delta.width(), granularity, ScrollLeft, ScrollRight, node, &stopNode);
|
| + bool verticalScroll = scrollNode(delta.height(), granularity, ScrollUp, ScrollDown, node, &stopNode);
|
|
|
| - RenderLayer::ScrollPropagation shouldPropagate = RenderLayer::ShouldPropagateScroll;
|
| - if (gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation)
|
| - shouldPropagate = RenderLayer::DontPropagateScroll;
|
| + if (scrollShouldNotPropagate)
|
| + m_previousGestureScrolledNode = stopNode;
|
|
|
| - const float scaleFactor = m_frame->pageZoomFactor() * m_frame->frameScaleFactor();
|
| - delta.scale(1 / scaleFactor, 1 / scaleFactor);
|
| + if (horizontalScroll || verticalScroll) {
|
| + setFrameWasScrolledByUser();
|
| + return true;
|
| + }
|
|
|
| - bool result = latchedRenderer->enclosingLayer()->scrollBy(delta, RenderLayer::ScrollOffsetClamped, shouldPropagate);
|
| + // Otherwise try to scroll the view.
|
| + return sendScrollEventToView(gestureEvent, delta);
|
| +}
|
|
|
| - if (result)
|
| +bool EventHandler::sendScrollEventToView(const PlatformGestureEvent& gestureEvent, const FloatSize& scaledDelta)
|
| +{
|
| + FrameView* view = m_frame->view();
|
| + if (!view)
|
| + return false;
|
| +
|
| + const float tickDivisor = static_cast<float>(WheelEvent::TickMultiplier);
|
| + IntPoint point(gestureEvent.position().x(), gestureEvent.position().y());
|
| + IntPoint globalPoint(gestureEvent.globalPosition().x(), gestureEvent.globalPosition().y());
|
| + PlatformWheelEvent syntheticWheelEvent(point, globalPoint,
|
| + scaledDelta.width(), scaledDelta.height(),
|
| + scaledDelta.width() / tickDivisor, scaledDelta.height() / tickDivisor,
|
| + ScrollByPixelWheelEvent,
|
| + gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey());
|
| +#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
|
| + syntheticWheelEvent.setHasPreciseScrollingDeltas(true);
|
| +#endif
|
| +
|
| + bool scrolledFrame = view->wheelEvent(syntheticWheelEvent);
|
| + if (scrolledFrame)
|
| setFrameWasScrolledByUser();
|
|
|
| - return result;
|
| + return scrolledFrame;
|
| }
|
|
|
| +void EventHandler::clearGestureScrollNodes()
|
| +{
|
| + m_scrollGestureHandlingNode = 0;
|
| + m_previousGestureScrolledNode = 0;
|
| +}
|
| +
|
| bool EventHandler::isScrollbarHandlingGestures() const
|
| {
|
| return m_scrollbarHandlingScrollGesture.get();
|
|
|