| Index: third_party/WebKit/Source/core/input/EventHandler.cpp
|
| diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp
|
| index e142c70191dd7dc5ba452ec9985e361c8e69b634..c84317bf5523ee4dc4d7943e64cb1513f5f44cf7 100644
|
| --- a/third_party/WebKit/Source/core/input/EventHandler.cpp
|
| +++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
|
| @@ -164,6 +164,47 @@ bool shouldRefetchEventTarget(const MouseEventWithHitTestResults& mev)
|
| return targetNode->isShadowRoot() && isHTMLInputElement(*toShadowRoot(targetNode)->host());
|
| }
|
|
|
| +// TODO(bokan): This method can go away once all scrolls happen through the
|
| +// scroll customization path.
|
| +void computeScrollChainForSingleNode(Node& node, std::deque<int>& scrollChain)
|
| +{
|
| + scrollChain.clear();
|
| +
|
| + ASSERT(node.layoutObject());
|
| + Element* element = toElement(&node);
|
| +
|
| + scrollChain.push_front(DOMNodeIds::idForNode(element));
|
| +}
|
| +
|
| +void recomputeScrollChain(const LocalFrame& frame, const Node& startNode,
|
| + std::deque<int>& scrollChain)
|
| +{
|
| + scrollChain.clear();
|
| +
|
| + ASSERT(startNode.layoutObject());
|
| + LayoutBox* curBox = startNode.layoutObject()->enclosingBox();
|
| +
|
| + // Scrolling propagates along the containing block chain.
|
| + while (curBox && !curBox->isLayoutView()) {
|
| + Node* curNode = curBox->node();
|
| + // FIXME: this should reject more elements, as part of crbug.com/410974.
|
| + if (curNode && curNode->isElementNode()) {
|
| + Element* curElement = toElement(curNode);
|
| + if (curElement == frame.document()->scrollingElement())
|
| + break;
|
| + scrollChain.push_front(DOMNodeIds::idForNode(curElement));
|
| + }
|
| + curBox = curBox->containingBlock();
|
| + }
|
| + // TODO(tdresser): this should sometimes be excluded, as part of crbug.com/410974.
|
| + // We need to ensure that the scrollingElement is always part of
|
| + // the scroll chain. In quirks mode, when the scrollingElement is
|
| + // the body, some elements may use the documentElement as their
|
| + // containingBlock, so we ensure the scrollingElement is added
|
| + // here.
|
| + scrollChain.push_front(DOMNodeIds::idForNode(frame.document()->scrollingElement()));
|
| +}
|
| +
|
| } // namespace
|
|
|
| using namespace HTMLNames;
|
| @@ -222,35 +263,6 @@ private:
|
| Cursor m_cursor;
|
| };
|
|
|
| -void recomputeScrollChain(const LocalFrame& frame, const Node& startNode,
|
| - std::deque<int>& scrollChain)
|
| -{
|
| - scrollChain.clear();
|
| -
|
| - ASSERT(startNode.layoutObject());
|
| - LayoutBox* curBox = startNode.layoutObject()->enclosingBox();
|
| -
|
| - // Scrolling propagates along the containing block chain.
|
| - while (curBox && !curBox->isLayoutView()) {
|
| - Node* curNode = curBox->node();
|
| - // FIXME: this should reject more elements, as part of crbug.com/410974.
|
| - if (curNode && curNode->isElementNode()) {
|
| - Element* curElement = toElement(curNode);
|
| - if (curElement == frame.document()->scrollingElement())
|
| - break;
|
| - scrollChain.push_front(DOMNodeIds::idForNode(curElement));
|
| - }
|
| - curBox = curBox->containingBlock();
|
| - }
|
| - // TODO(tdresser): this should sometimes be excluded, as part of crbug.com/410974.
|
| - // We need to ensure that the scrollingElement is always part of
|
| - // the scroll chain. In quirks mode, when the scrollingElement is
|
| - // the body, some elements may use the documentElement as their
|
| - // containingBlock, so we ensure the scrollingElement is added
|
| - // here.
|
| - scrollChain.push_front(DOMNodeIds::idForNode(frame.document()->scrollingElement()));
|
| -}
|
| -
|
| EventHandler::EventHandler(LocalFrame* frame)
|
| : m_frame(frame)
|
| , m_mousePressed(false)
|
| @@ -611,7 +623,83 @@ void EventHandler::stopAutoscroll()
|
| controller->stopAutoscroll();
|
| }
|
|
|
| -ScrollResult EventHandler::physicalScroll(ScrollGranularity granularity, const FloatSize& delta, Node* startNode, Node** stopNode, bool* consumed)
|
| +ScrollResult EventHandler::scrollBox(LayoutBox* box,
|
| + ScrollGranularity granularity, const FloatSize& delta,
|
| + const FloatPoint& position, const FloatSize& velocity,
|
| + bool* wasRootScroller)
|
| +{
|
| + ASSERT(box);
|
| + Node* node = box->node();
|
| + Document* document = m_frame->document();
|
| + Element* scrollingElement = document->scrollingElement();
|
| +
|
| + bool isRootFrame = !document->ownerElement();
|
| +
|
| + // TODO(bokan): If the ViewportScrollCallback is installed on the body, we
|
| + // can still hit the HTML element for scrolling in which case it'll bubble
|
| + // up to the document node and try to scroll the LayoutView directly. Make
|
| + // sure we never scroll the LayoutView like this by manually resetting the
|
| + // scroll to happen on the scrolling element. This can also happen in
|
| + // QuirksMode when the body is scrollable and scrollingElement == nullptr.
|
| + if (node && node->isDocumentNode() && isRootFrame) {
|
| + node = scrollingElement
|
| + ? scrollingElement
|
| + : document->documentElement();
|
| + }
|
| +
|
| + // If there's no ApplyScroll callback on the element, scroll as usuall in
|
| + // the non-scroll-customization case.
|
| + if (!node || !node->isElementNode() || !toElement(node)->getApplyScroll()) {
|
| + ASSERT(!isRootFrame
|
| + || node != scrollingElement
|
| + || (!scrollingElement && node != document->documentElement()));
|
| + *wasRootScroller = false;
|
| + return box->scroll(granularity, delta);
|
| + }
|
| +
|
| + ASSERT(isRootFrame);
|
| +
|
| + // If there is an ApplyScroll callback, its because we placed one on the
|
| + // root scroller to control top controls and overscroll. Invoke a scroll
|
| + // using parts of the scroll customization framework on just this element.
|
| + computeScrollChainForSingleNode(*node, m_currentScrollChain);
|
| +
|
| + OwnPtr<ScrollStateData> scrollStateData = adoptPtr(new ScrollStateData());
|
| + scrollStateData->delta_x = delta.width();
|
| + scrollStateData->delta_y = delta.height();
|
| + scrollStateData->position_x = position.x();
|
| + scrollStateData->position_y = position.y();
|
| + // TODO(bokan): delta_granularity is meant to be the number of pixels per
|
| + // unit of delta but we can't determine that until we get to the area we'll
|
| + // scroll. This is a hack, we stuff the enum into the double value for
|
| + // now.
|
| + scrollStateData->delta_granularity = static_cast<double>(granularity);
|
| + scrollStateData->velocity_x = velocity.width();
|
| + scrollStateData->velocity_y = velocity.height();
|
| + scrollStateData->should_propagate = false;
|
| + scrollStateData->is_in_inertial_phase = false;
|
| + scrollStateData->from_user_input = true;
|
| + scrollStateData->delta_consumed_for_scroll_sequence = false;
|
| + ScrollState* scrollState =
|
| + ScrollState::create(scrollStateData.release());
|
| +
|
| + customizedScroll(*node, *scrollState);
|
| +
|
| + ScrollResult result(
|
| + scrollState->deltaX() != delta.width(),
|
| + scrollState->deltaY() != delta.height(),
|
| + scrollState->deltaX(),
|
| + scrollState->deltaY());
|
| +
|
| + *wasRootScroller = true;
|
| + m_currentScrollChain.clear();
|
| +
|
| + return result;
|
| +}
|
| +
|
| +ScrollResult EventHandler::physicalScroll(ScrollGranularity granularity,
|
| + const FloatSize& delta, const FloatPoint& position,
|
| + const FloatSize& velocity, Node* startNode, Node** stopNode, bool* consumed)
|
| {
|
| if (consumed)
|
| *consumed = false;
|
| @@ -631,7 +719,15 @@ ScrollResult EventHandler::physicalScroll(ScrollGranularity granularity, const F
|
| // chain past it.
|
| bool shouldStopChaining =
|
| stopNode && *stopNode && curBox->node() == *stopNode;
|
| - result = curBox->scroll(granularity, delta);
|
| + bool wasRootScroller = false;
|
| +
|
| + result = scrollBox(
|
| + curBox,
|
| + granularity,
|
| + delta,
|
| + position,
|
| + velocity,
|
| + &wasRootScroller);
|
|
|
| if (result.didScroll() && stopNode)
|
| *stopNode = curBox->node();
|
| @@ -641,6 +737,10 @@ ScrollResult EventHandler::physicalScroll(ScrollGranularity granularity, const F
|
| if (consumed)
|
| *consumed = true;
|
| return result;
|
| + } else if (wasRootScroller) {
|
| + // Don't try to chain past the root scroller, even if there's
|
| + // eligible ancestors.
|
| + break;
|
| }
|
|
|
| curBox = curBox->containingBlock();
|
| @@ -1894,13 +1994,18 @@ void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEv
|
|
|
| // FIXME: enable scroll customization in this case. See crbug.com/410974.
|
| bool consumed = false;
|
| - ScrollResult result = physicalScroll(granularity, delta, startNode, &node, &consumed);
|
| +
|
| + physicalScroll(
|
| + granularity,
|
| + delta,
|
| + FloatPoint(),
|
| + FloatSize(),
|
| + startNode,
|
| + &node,
|
| + &consumed);
|
|
|
| if (consumed)
|
| wheelEvent->setDefaultHandled();
|
| -
|
| - if (m_frame->isMainFrame())
|
| - handleOverscroll(result);
|
| }
|
|
|
| WebInputEventResult EventHandler::handleGestureShowPress()
|
| @@ -2393,6 +2498,20 @@ void EventHandler::handleOverscroll(const ScrollResult& scrollResult, const Floa
|
| }
|
| }
|
|
|
| +bool EventHandler::isRootScroller(const Node& node) const
|
| +{
|
| + // The root scroller is the one Element on the page designated to perform
|
| + // "viewport actions" like top controls movement and overscroll glow.
|
| +
|
| + if (!node.isElementNode() || node.document().ownerElement())
|
| + return false;
|
| +
|
| + Element* scrollingElement = node.document().scrollingElement();
|
| + return scrollingElement
|
| + ? toElement(&node) == node.document().scrollingElement()
|
| + : toElement(&node) == node.document().documentElement();
|
| +}
|
| +
|
| WebInputEventResult EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gestureEvent)
|
| {
|
| ASSERT(gestureEvent.type() == PlatformEvent::GestureScrollUpdate);
|
| @@ -2435,6 +2554,7 @@ WebInputEventResult EventHandler::handleGestureScrollUpdate(const PlatformGestur
|
| OwnPtr<ScrollStateData> scrollStateData = adoptPtr(new ScrollStateData());
|
| scrollStateData->delta_x = delta.width();
|
| scrollStateData->delta_y = delta.height();
|
| + scrollStateData->delta_granularity = ScrollByPrecisePixel;
|
| scrollStateData->velocity_x = velocity.width();
|
| scrollStateData->velocity_y = velocity.height();
|
| scrollStateData->should_propagate = !gestureEvent.preventPropagation();
|
| @@ -2464,17 +2584,20 @@ WebInputEventResult EventHandler::handleGestureScrollUpdate(const PlatformGestur
|
| stopNode = m_previousGestureScrolledNode.get();
|
|
|
| bool consumed = false;
|
| - ScrollResult result = physicalScroll(granularity, delta, node, &stopNode, &consumed);
|
| + ScrollResult result = physicalScroll(
|
| + granularity,
|
| + delta,
|
| + FloatPoint(gestureEvent.position()),
|
| + velocity,
|
| + node,
|
| + &stopNode,
|
| + &consumed);
|
|
|
| if (gestureEvent.preventPropagation())
|
| m_previousGestureScrolledNode = stopNode;
|
|
|
| - if (m_frame->isMainFrame() && (!stopNode || stopNode->layoutObject() == m_frame->view()->layoutView())) {
|
| - FloatPoint positionInRootFrame = FloatPoint(gestureEvent.position().x(), gestureEvent.position().y());
|
| - handleOverscroll(result, positionInRootFrame, velocity);
|
| - } else {
|
| + if (!stopNode || !isRootScroller(*stopNode))
|
| resetOverscroll(result.didScrollX, result.didScrollY);
|
| - }
|
|
|
| if (consumed)
|
| return WebInputEventResult::HandledSystem;
|
|
|