Index: Source/core/page/EventHandler.cpp |
diff --git a/Source/core/page/EventHandler.cpp b/Source/core/page/EventHandler.cpp |
index 7f2bf62203808476afff59d4924d8ac3c554a3d7..107c871e6bbb3c3f9093983f0d8e40d5b95c83c8 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,31 @@ static inline bool shouldRefetchEventTarget(const MouseEventWithHitTestResults& |
return targetNode->isShadowRoot() && isHTMLInputElement(*toShadowRoot(targetNode)->host()); |
} |
+void recomputeScrollChain(const LocalFrame& frame, const Node& startNode, |
+ WillBeHeapDeque<RefPtrWillBeMember<Element>>& scrollChain) |
+{ |
+ scrollChain.clear(); |
+ bool rootLayerScrolls = frame.settings() && frame.settings()->rootLayerScrolls(); |
+ |
+ ASSERT(startNode.layoutObject()); |
+ LayoutBox* curBox = startNode.layoutObject()->enclosingBox(); |
+ bool addedDocumentElement = false; |
+ |
+ while (curBox && (rootLayerScrolls || !curBox->isLayoutView())) { |
Rick Byers
2015/03/11 02:22:18
I think this deserves a comment describing why we'
tdresser
2015/03/20 18:00:37
Done.
|
+ Node* curNode = curBox->node(); |
+ curBox = curBox->containingBlock(); |
Rick Byers
2015/03/11 02:22:18
What if the first curBox is scrollable itself? It
tdresser
2015/03/20 18:00:37
We don't use curBox until the next iteration of th
Rick Byers
2015/03/26 21:22:49
Acknowledged.
|
+ // FIXME: this should reject more elements. |
+ if (!curNode || !curNode->isElementNode()) |
+ continue; |
+ scrollChain.prepend(toElement(curNode)); |
+ if (curNode == frame.document()->documentElement()) |
+ addedDocumentElement = true; |
+ } |
+ |
+ if (!addedDocumentElement) |
Rick Byers
2015/03/11 02:22:19
Do we want to do this even when rootLayerScrolls i
tdresser
2015/03/20 18:00:36
I've simplified the loop a bit. Actually determini
Rick Byers
2015/03/26 21:22:49
Acknowledged.
|
+ scrollChain.prepend(frame.document()->documentElement()); |
+} |
+ |
EventHandler::EventHandler(LocalFrame* frame) |
: m_frame(frame) |
, m_mousePressed(false) |
@@ -222,6 +248,7 @@ EventHandler::EventHandler(LocalFrame* frame) |
, m_longTapShouldInvokeContextMenu(false) |
, m_activeIntervalTimer(this, &EventHandler::activeIntervalTimerFired) |
, m_lastShowPressTimestamp(0) |
+ , m_deltaConsumedForScrollSequence(false) |
{ |
} |
@@ -250,6 +277,7 @@ DEFINE_TRACE(EventHandler) |
visitor->trace(m_scrollGestureHandlingNode); |
visitor->trace(m_previousGestureScrolledNode); |
visitor->trace(m_lastDeferredTapElement); |
+ visitor->trace(m_currentScrollChain); |
#endif |
} |
@@ -944,11 +972,23 @@ bool EventHandler::scroll(ScrollDirection direction, ScrollGranularity granulari |
return false; |
} |
+void EventHandler::customizedScroll(const Node& startNode, ScrollState& scrollState) |
+{ |
+ if (scrollState.fullyConsumed()) |
+ return; |
+ |
+ if (m_currentScrollChain.isEmpty()) |
+ recomputeScrollChain(*m_frame, startNode, m_currentScrollChain); |
+ scrollState.setScrollChain(m_currentScrollChain); |
+ scrollState.distributeToScrollChainDescendant(); |
+} |
+ |
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. |
Rick Byers
2015/03/11 02:22:18
you might want to reference your scroll customizat
tdresser
2015/03/20 18:00:37
Done.
|
if (scroll(direction, granularity, startingNode)) |
return true; |
LocalFrame* frame = m_frame; |
@@ -2059,6 +2099,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(); |
@@ -2195,7 +2237,6 @@ bool EventHandler::handleGestureScrollEvent(const PlatformGestureEvent& gestureE |
m_lastGestureScrollOverWidget = result.isOverWidget(); |
m_scrollGestureHandlingNode = eventTarget; |
- m_previousGestureScrolledNode = nullptr; |
Rick Byers
2015/03/11 02:22:19
why remove this?
tdresser
2015/03/20 18:00:37
Looks wrong to me. Fixed.
|
if (!scrollbar) |
scrollbar = result.scrollbar(); |
@@ -2448,11 +2489,19 @@ bool EventHandler::passScrollGestureEventToWidget(const PlatformGestureEvent& ge |
bool EventHandler::handleGestureScrollEnd(const PlatformGestureEvent& gestureEvent) { |
RefPtrWillBeRawPtr<Node> node = m_scrollGestureHandlingNode; |
- clearGestureScrollNodes(); |
- if (node) |
- passScrollGestureEventToWidget(gestureEvent, node->layoutObject()); |
+ if (node) { |
+ if (passScrollGestureEventToWidget(gestureEvent, node->layoutObject())) |
+ return false; |
Rick Byers
2015/03/11 02:22:18
this doesn't make sense to me. If the subframe ha
tdresser
2015/03/20 18:00:37
This was correct before, but _extremely_ confusing
Rick Byers
2015/03/26 21:22:49
Thanks, makes sense.
|
+ if (RuntimeEnabledFeatures::scrollCustomizationEnabled()) { |
+ RefPtrWillBeRawPtr<ScrollState> scrollState = ScrollState::create( |
+ 0, 0, 0, 0, 0, gestureEvent.inertial(), false, true, true); |
Rick Byers
2015/03/11 02:22:18
Blink coding style says: "Prefer enums to bools on
tdresser
2015/03/20 18:00:37
Done.
|
+ customizedScroll(*node.get(), *scrollState); |
+ } |
+ } |
+ clearGestureScrollNodes(); |
+ m_currentScrollChain.clear(); |
return false; |
} |
@@ -2471,24 +2520,30 @@ bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureE |
while (m_scrollGestureHandlingNode && !m_scrollGestureHandlingNode->layoutObject()) |
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; |
+ } |
+ ASSERT(m_scrollGestureHandlingNode); |
passScrollGestureEventToWidget(gestureEvent, m_scrollGestureHandlingNode->layoutObject()); |
+ if (!RuntimeEnabledFeatures::scrollCustomizationEnabled()) { |
Rick Byers
2015/03/11 02:22:18
this would be slightly clearer to me as a if(enabl
tdresser
2015/03/20 18:00:37
Done.
Rick Byers
2015/03/26 21:22:49
nit: I meants put the true case first to avoid a d
tdresser
2015/03/27 15:28:52
Done.
|
+ if (m_frame->isMainFrame()) |
+ m_frame->host()->topControls().scrollBegin(); |
+ return true; |
+ } |
- if (m_frame->isMainFrame()) |
- m_frame->host()->topControls().scrollBegin(); |
+ m_deltaConsumedForScrollSequence = false; |
+ m_currentScrollChain.clear(); |
+ RefPtrWillBeRawPtr<ScrollState> scrollState = ScrollState::create( |
+ 0, 0, 0, 0, 0, false, true, false, true); |
Rick Byers
2015/03/11 02:22:18
ditto
tdresser
2015/03/20 18:00:37
Done.
|
+ customizedScroll(*m_scrollGestureHandlingNode.get(), *scrollState); |
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; |
-} |
- |
bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gestureEvent) |
{ |
ASSERT(gestureEvent.type() == PlatformEvent::GestureScrollUpdate); |
@@ -2511,60 +2566,55 @@ bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gesture |
if (passScrollGestureEventToWidget(gestureEvent, renderer)) { |
if (gestureEvent.preventPropagation()) |
m_previousGestureScrolledNode = m_scrollGestureHandlingNode; |
- |
+ m_deltaConsumedForScrollSequence = true; |
return true; |
} |
+ bool scrolled = false; |
+ if (RuntimeEnabledFeatures::scrollCustomizationEnabled()) { |
+ RefPtrWillBeRawPtr<ScrollState> scrollState = ScrollState::create( |
+ gestureEvent.deltaX(), gestureEvent.deltaY(), |
+ 0, gestureEvent.velocityX(), gestureEvent.velocityY(), |
+ gestureEvent.inertial(), false, false, true, |
+ !gestureEvent.preventPropagation(), m_deltaConsumedForScrollSequence); |
+ if (m_previousGestureScrolledNode) { |
Rick Byers
2015/03/11 02:22:18
So does this field now represent just native scrol
tdresser
2015/03/20 18:00:37
Done.
|
+ ASSERT(m_previousGestureScrolledNode->isElementNode()); |
+ scrollState->setCurrentNativeScrollingElement(toElement(m_previousGestureScrolledNode.get())); |
+ } |
+ customizedScroll(*node, *scrollState); |
+ m_previousGestureScrolledNode = scrollState->currentNativeScrollingElement(); |
+ m_deltaConsumedForScrollSequence = scrollState->deltaConsumedForScrollSequence(); |
- 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()); |
+ scrolled = scrollState->deltaX() != gestureEvent.deltaX() |
+ || scrollState->deltaY() != gestureEvent.deltaY(); |
+ } else { |
+ if (gestureEvent.preventPropagation()) |
+ stopNode = m_previousGestureScrolledNode.get(); |
- if (gestureEvent.preventPropagation()) |
- m_previousGestureScrolledNode = stopNode; |
+ // 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()); |
Rick Byers
2015/03/11 02:22:19
This is a little subtle (I could imagine someone r
tdresser
2015/03/20 18:00:37
Done.
|
- if (horizontalScroll || verticalScroll) { |
+ if (gestureEvent.preventPropagation()) |
+ m_previousGestureScrolledNode = stopNode; |
+ } |
+ if (scrolled) { |
setFrameWasScrolledByUser(); |
return true; |
} |
} |
- // If this is main frame, allow top controls to scroll first and update |
- // delta accordingly |
- bool consumed = false; |
- if (m_frame->isMainFrame() && shouldTopControlsConsumeScroll(delta)) { |
- FloatSize excessDelta = m_frame->host()->topControls().scrollBy(delta); |
- consumed = excessDelta != delta; |
- delta = excessDelta; |
- |
- if (delta.isZero()) |
- return consumed; |
- } |
+ if (RuntimeEnabledFeatures::scrollCustomizationEnabled()) |
+ return false; |
// Try to scroll the frame view. |
- FrameView* view = m_frame->view(); |
- if (!view) |
- return consumed; |
- |
- if (scrollAreaOnBothAxes(delta, *view)) { |
+ if (m_frame->applyScrollDelta(delta, false)) { |
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())) { |
- setFrameWasScrolledByUser(); |
- return true; |
- } |
- |
- return consumed; |
+ return false; |
} |
void EventHandler::clearGestureScrollNodes() |
@@ -3394,6 +3444,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; |
@@ -3911,18 +3962,4 @@ unsigned EventHandler::accessKeyModifiers() |
#endif |
} |
-bool EventHandler::shouldTopControlsConsumeScroll(FloatSize scrollDelta) const |
-{ |
- // Always consume if it's in the direction to show the top controls. |
- if (scrollDelta.height() > 0) |
- return true; |
- |
- // If it's in the direction to hide the top controls, only consume when the frame can also scroll. |
- if (m_frame->view()->scrollPosition().y() < m_frame->view()->maximumScrollPosition().y()) |
- return true; |
- |
- return false; |
-} |
- |
- |
} // namespace blink |