Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Unified Diff: third_party/WebKit/Source/core/input/EventHandler.cpp

Issue 1840113005: Move viewport actions into an ApplyScroll callback. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase over my own changes Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
« no previous file with comments | « third_party/WebKit/Source/core/input/EventHandler.h ('k') | third_party/WebKit/Source/core/layout/LayoutView.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698