| Index: Source/core/page/EventHandler.cpp
|
| diff --git a/Source/core/page/EventHandler.cpp b/Source/core/page/EventHandler.cpp
|
| index b8548bb6582db3a974f41d39422710f492c3ee7f..cd2f34027eed7121f923fb6735bf71868437409f 100644
|
| --- a/Source/core/page/EventHandler.cpp
|
| +++ b/Source/core/page/EventHandler.cpp
|
| @@ -80,6 +80,7 @@
|
| #include "core/page/Page.h"
|
| #include "core/page/SpatialNavigation.h"
|
| #include "core/page/TouchAdjustment.h"
|
| +#include "core/page/scrolling/ScrollState.h"
|
| #include "core/svg/SVGDocumentExtensions.h"
|
| #include "platform/PlatformGestureEvent.h"
|
| #include "platform/PlatformKeyboardEvent.h"
|
| @@ -195,6 +196,32 @@ static inline bool shouldRefetchEventTarget(const MouseEventWithHitTestResults&
|
| return targetNode->isShadowRoot() && isHTMLInputElement(*toShadowRoot(targetNode)->host());
|
| }
|
|
|
| +void recomputeScrollChain(LocalFrame* const frame, Node* scrollGestureHandlingNode, WillBeHeapVector<RefPtrWillBeMember<Element>>& scrollChain)
|
| +{
|
| + ASSERT(frame);
|
| + ASSERT(scrollGestureHandlingNode);
|
| + scrollChain.clear();
|
| + bool rootLayerScrolls = frame->settings() && frame->settings()->rootLayerScrolls();
|
| + LayoutBox* curBox = scrollGestureHandlingNode->renderer()->enclosingBox();
|
| +
|
| + bool includesDocument = false;
|
| + while (curBox && (rootLayerScrolls || !curBox->isLayoutView())) {
|
| + Node* curNode = curBox->node();
|
| + curBox = curBox->containingBlock();
|
| +
|
| + includesDocument = includesDocument || curNode == frame->document()->documentElement();
|
| +
|
| + // FIXME: this should reject more elements.
|
| + if (!curNode || !curNode->isElementNode())
|
| + continue;
|
| + ASSERT(curNode->isElementNode());
|
| + scrollChain.prepend(toElement(curNode));
|
| + }
|
| +
|
| + if (!includesDocument)
|
| + scrollChain.prepend(frame->document()->documentElement());
|
| +}
|
| +
|
| EventHandler::EventHandler(LocalFrame* frame)
|
| : m_frame(frame)
|
| , m_mousePressed(false)
|
| @@ -222,6 +249,7 @@ EventHandler::EventHandler(LocalFrame* frame)
|
| , m_longTapShouldInvokeContextMenu(false)
|
| , m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired)
|
| , m_lastShowPressTimestamp(0)
|
| + , m_scrollLockedToElement(false)
|
| {
|
| }
|
|
|
| @@ -250,6 +278,8 @@ DEFINE_TRACE(EventHandler)
|
| visitor->trace(m_scrollGestureHandlingNode);
|
| visitor->trace(m_previousGestureScrolledNode);
|
| visitor->trace(m_lastDeferredTapElement);
|
| + visitor->trace(m_currentNativeScrollingElement);
|
| + visitor->trace(m_currentScrollChain);
|
| #endif
|
| }
|
|
|
| @@ -943,11 +973,44 @@ bool EventHandler::scroll(ScrollDirection direction, ScrollGranularity granulari
|
| return false;
|
| }
|
|
|
| +// FIXME: handle flipped direction (toPhysicalDirection) and granularity.
|
| +bool EventHandler::customizedScroll(ScrollState* scrollState, Node* startNode)
|
| +{
|
| + Node* node = startNode;
|
| +
|
| + if (!node)
|
| + node = m_frame->document()->focusedElement();
|
| +
|
| + if (!node)
|
| + node = m_mousePressNode.get();
|
| +
|
| + if (!node || !node->renderer())
|
| + return false;
|
| +
|
| + if (!m_currentScrollChain.size() && m_scrollGestureHandlingNode.get())
|
| + recomputeScrollChain(m_frame, m_scrollGestureHandlingNode.get(), m_currentScrollChain);
|
| + scrollState->setScrollChain(m_currentScrollChain);
|
| +
|
| + double deltaX = scrollState->deltaX();
|
| + double deltaY = scrollState->deltaY();
|
| + scrollState->distributeToScrollChainDescendant();
|
| + bool didScroll = deltaX != scrollState->deltaX() || deltaY != scrollState->deltaY();
|
| +
|
| + if (didScroll) {
|
| + if (scrollState->fromUserInput())
|
| + setFrameWasScrolledByUser();
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| bool EventHandler::bubblingScroll(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode)
|
| {
|
| // The layout needs to be up to date to determine if we can scroll. We may be
|
| // here because of an onLoad event, in which case the final layout hasn't been performed yet.
|
| m_frame->document()->updateLayoutIgnorePendingStylesheets();
|
| + // FIXME: enable scroll customization in this case.
|
| if (scroll(direction, granularity, startingNode))
|
| return true;
|
| LocalFrame* frame = m_frame;
|
| @@ -2062,6 +2125,8 @@ void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEv
|
|
|
| // Break up into two scrolls if we need to. Diagonal movement on
|
| // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
|
| +
|
| + // FIXME: enable scroll customization in this case.
|
| if (scroll(ScrollRight, granularity, startNode, &stopNode, wheelEvent->deltaX(), roundedIntPoint(wheelEvent->absoluteLocation())))
|
| wheelEvent->setDefaultHandled();
|
|
|
| @@ -2454,9 +2519,19 @@ bool EventHandler::handleGestureScrollEnd(const PlatformGestureEvent& gestureEve
|
| RefPtrWillBeRawPtr<Node> node = m_scrollGestureHandlingNode;
|
| clearGestureScrollNodes();
|
|
|
| - if (node)
|
| - passScrollGestureEventToWidget(gestureEvent, node->renderer());
|
| + if (node) {
|
| + if (passScrollGestureEventToWidget(gestureEvent, node->renderer()))
|
| + return false;
|
| + if (RuntimeEnabledFeatures::scrollCustomizationEnabled()) {
|
| + ScrollState* scrollState = ScrollState::create(gestureEvent.deltaX(), gestureEvent.deltaY(),
|
| + 0, gestureEvent.velocityX(), gestureEvent.velocityY(), gestureEvent.inertial(), true, true);
|
| + customizedScroll(scrollState, node.get());
|
| + }
|
| + }
|
|
|
| + m_currentNativeScrollingElement = nullptr;
|
| + m_scrollLockedToElement = false;
|
| + m_currentScrollChain.clear();
|
| return false;
|
| }
|
|
|
| @@ -2475,22 +2550,26 @@ bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureE
|
| while (m_scrollGestureHandlingNode && !m_scrollGestureHandlingNode->renderer())
|
| m_scrollGestureHandlingNode = m_scrollGestureHandlingNode->parentOrShadowHostNode();
|
|
|
| - if (!m_scrollGestureHandlingNode)
|
| - return false;
|
| + if (!m_scrollGestureHandlingNode) {
|
| + if (RuntimeEnabledFeatures::scrollCustomizationEnabled())
|
| + m_scrollGestureHandlingNode = m_frame->document()->documentElement();
|
| + else
|
| + return false;
|
| + }
|
|
|
| passScrollGestureEventToWidget(gestureEvent, m_scrollGestureHandlingNode->renderer());
|
|
|
| if (m_frame->isMainFrame())
|
| m_frame->host()->topControls().scrollBegin();
|
|
|
| - return true;
|
| -}
|
| + if (!RuntimeEnabledFeatures::scrollCustomizationEnabled())
|
| + return true;
|
|
|
| -static bool scrollAreaOnBothAxes(const FloatSize& delta, ScrollableArea& view)
|
| -{
|
| - bool scrolledHorizontal = view.scroll(ScrollLeft, ScrollByPrecisePixel, delta.width());
|
| - bool scrolledVertical = view.scroll(ScrollUp, ScrollByPrecisePixel, delta.height());
|
| - return scrolledHorizontal || scrolledVertical;
|
| + m_currentNativeScrollingElement = nullptr;
|
| + m_scrollLockedToElement = false;
|
| +
|
| + recomputeScrollChain(m_frame, m_scrollGestureHandlingNode.get(), m_currentScrollChain);
|
| + return true;
|
| }
|
|
|
| bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gestureEvent)
|
| @@ -2515,28 +2594,43 @@ bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gesture
|
| if (passScrollGestureEventToWidget(gestureEvent, renderer)) {
|
| if (gestureEvent.preventPropagation())
|
| m_previousGestureScrolledNode = m_scrollGestureHandlingNode;
|
| -
|
| + m_scrollLockedToElement = true;
|
| return true;
|
| }
|
|
|
| -
|
| if (gestureEvent.preventPropagation())
|
| stopNode = m_previousGestureScrolledNode.get();
|
|
|
| - // First try to scroll the closest scrollable LayoutBox ancestor of |node|.
|
| - ScrollGranularity granularity = ScrollByPixel;
|
| - bool horizontalScroll = scroll(ScrollLeft, granularity, node, &stopNode, delta.width());
|
| - bool verticalScroll = scroll(ScrollUp, granularity, node, &stopNode, delta.height());
|
| + bool scrolled = false;
|
| + if (RuntimeEnabledFeatures::scrollCustomizationEnabled()) {
|
| + ScrollState* scrollState = ScrollState::create(gestureEvent.deltaX(), gestureEvent.deltaY(),
|
| + 0, gestureEvent.velocityX(), gestureEvent.velocityY(), gestureEvent.inertial(), false, true,
|
| + !gestureEvent.preventPropagation());
|
| + scrollState->setCurrentNativeScrollingElement(m_currentNativeScrollingElement.get());
|
| + scrollState->setScrollLockedToElement(m_scrollLockedToElement);
|
| + scrolled = customizedScroll(scrollState, node);
|
| + m_currentNativeScrollingElement = scrollState->currentNativeScrollingElement();
|
| + m_scrollLockedToElement = scrollState->scrollLockedToElement();
|
| + } else {
|
| + // First try to scroll the closest scrollable LayoutBox ancestor of |node|.
|
| + ScrollGranularity granularity = ScrollByPixel;
|
| + scrolled = scroll(ScrollLeft, granularity, node, &stopNode, delta.width())
|
| + | scroll(ScrollUp, granularity, node, &stopNode, delta.height());
|
| + }
|
|
|
| if (gestureEvent.preventPropagation())
|
| m_previousGestureScrolledNode = stopNode;
|
|
|
| - if (horizontalScroll || verticalScroll) {
|
| + if (scrolled) {
|
| setFrameWasScrolledByUser();
|
| return true;
|
| }
|
| }
|
|
|
| +
|
| + if (RuntimeEnabledFeatures::scrollCustomizationEnabled())
|
| + return false;
|
| +
|
| // If this is main frame, allow top controls to scroll first and update
|
| // delta accordingly
|
| bool consumed = false;
|
| @@ -2554,16 +2648,7 @@ bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gesture
|
| if (!view)
|
| return consumed;
|
|
|
| - if (scrollAreaOnBothAxes(delta, *view)) {
|
| - setFrameWasScrolledByUser();
|
| - return true;
|
| - }
|
| -
|
| - // If this is the main frame and it didn't scroll, propagate up to the pinch viewport.
|
| - if (!m_frame->settings()->pinchVirtualViewportEnabled() || !m_frame->isMainFrame())
|
| - return consumed;
|
| -
|
| - if (scrollAreaOnBothAxes(delta, m_frame->host()->pinchViewport())) {
|
| + if (m_frame->scrollByDelta(delta)) {
|
| setFrameWasScrolledByUser();
|
| return true;
|
| }
|
| @@ -3404,6 +3489,7 @@ void EventHandler::defaultSpaceEventHandler(KeyboardEvent* event)
|
| return;
|
|
|
| ScrollDirection direction = event->shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward;
|
| + // FIXME: enable scroll customization in this case.
|
| if (scroll(direction, ScrollByPage)) {
|
| event->setDefaultHandled();
|
| return;
|
|
|