summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-01-20 13:40:20 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-01-22 12:41:23 +0000
commit7961cea6d1041e3e454dae6a1da660b453efd238 (patch)
treec0eeb4a9ff9ba32986289c1653d9608e53ccb444 /chromium/third_party/blink/renderer/core/input/scroll_manager.cc
parentb7034d0803538058e5c9d904ef03cf5eab34f6ef (diff)
downloadqtwebengine-chromium-7961cea6d1041e3e454dae6a1da660b453efd238.tar.gz
BASELINE: Update Chromium to 78.0.3904.130
Change-Id: If185e0c0061b3437531c97c9c8c78f239352a68b Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/core/input/scroll_manager.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/input/scroll_manager.cc105
1 files changed, 82 insertions, 23 deletions
diff --git a/chromium/third_party/blink/renderer/core/input/scroll_manager.cc b/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
index 4c6de7e4e61..8408fb7ff18 100644
--- a/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
@@ -101,6 +101,7 @@ void ScrollManager::ClearGestureScrollState() {
last_gesture_scroll_over_embedded_content_view_ = false;
scroll_gesture_handling_node_ = nullptr;
previous_gesture_scrolled_node_ = nullptr;
+ last_scroll_delta_for_scroll_gesture_ = FloatSize();
delta_consumed_for_scroll_sequence_ = false;
did_scroll_x_for_scroll_gesture_ = false;
did_scroll_y_for_scroll_gesture_ = false;
@@ -113,6 +114,15 @@ void ScrollManager::ClearGestureScrollState() {
}
}
+Node* ScrollManager::GetScrollEventTarget() {
+ // Send the overscroll event to the node that scrolling is latched to which
+ // is either previously scrolled node or the last node in the scroll chain.
+ Node* scroll_target = previous_gesture_scrolled_node_;
+ if (!scroll_target && !current_scroll_chain_.IsEmpty())
+ scroll_target = DOMNodeIds::NodeForId(current_scroll_chain_.front());
+ return scroll_target;
+}
+
void ScrollManager::StopAutoscroll() {
if (AutoscrollController* controller = GetAutoscrollController())
controller->StopAutoscroll();
@@ -200,6 +210,17 @@ bool ScrollManager::CanScroll(const ScrollState& scroll_state,
if (current_node.GetLayoutBox()->IsGlobalRootScroller())
return true;
+ // If this is the main LayoutView, and it's not the root scroller, that means
+ // we have a non-default root scroller on the page. In this case, attempts to
+ // scroll the LayoutView should cause panning of the visual viewport as well
+ // so ensure it gets added to the scroll chain. See LTHI::ApplyScroll for the
+ // equivalent behavior in CC. Node::NativeApplyScroll contains a special
+ // handler for this case.
+ if (current_node.GetLayoutBox()->IsLayoutView() &&
+ current_node.GetDocument().GetFrame()->IsMainFrame()) {
+ return true;
+ }
+
ScrollableArea* scrollable_area =
current_node.GetLayoutBox()->GetScrollableArea();
@@ -317,11 +338,12 @@ bool ScrollManager::LogicalScroll(ScrollDirection direction,
}
ScrollableArea::ScrollCallback callback;
- if (RuntimeEnabledFeatures::UpdateHoverAtBeginFrameEnabled()) {
+ if (RuntimeEnabledFeatures::UpdateHoverAtBeginFrameEnabled() ||
+ RuntimeEnabledFeatures::OverscrollCustomizationEnabled()) {
callback = ScrollableArea::ScrollCallback(WTF::Bind(
[](WeakPersistent<ScrollableArea> area) {
if (area)
- area->MarkHoverStateDirty();
+ area->OnScrollFinished();
},
WrapWeakPersistent(scrollable_area)));
}
@@ -478,8 +500,21 @@ WebInputEventResult ScrollManager::HandleGestureScrollBegin(
scroll_state_data->delta_consumed_for_scroll_sequence =
delta_consumed_for_scroll_sequence_;
ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data));
- RecomputeScrollChain(*scroll_gesture_handling_node_.Get(), *scroll_state,
- current_scroll_chain_);
+ // For middle click autoscroll, only scrollable area for
+ // |scroll_gesture_handling_node_| should receive and handle all scroll
+ // events. It should not bubble up to the ancestor.
+ if (gesture_event.SourceDevice() == WebGestureDevice::kSyntheticAutoscroll) {
+ LayoutBox* scrollable = LayoutBox::FindAutoscrollable(
+ scroll_gesture_handling_node_->GetLayoutObject(),
+ /*is_middle_click_autoscroll*/ true);
+ if (scrollable) {
+ Node* scrollable_node = scrollable->GetNode();
+ current_scroll_chain_.push_back(DOMNodeIds::IdForNode(scrollable_node));
+ }
+ } else {
+ RecomputeScrollChain(*scroll_gesture_handling_node_.Get(), *scroll_state,
+ current_scroll_chain_);
+ }
TRACE_EVENT_INSTANT1("input", "Computed Scroll Chain",
TRACE_EVENT_SCOPE_THREAD, "length",
@@ -607,6 +642,8 @@ WebInputEventResult ScrollManager::HandleGestureScrollUpdate(
delta_consumed_for_scroll_sequence_ =
scroll_state->DeltaConsumedForScrollSequence();
+ last_scroll_delta_for_scroll_gesture_ = delta;
+
bool did_scroll_x = scroll_state->deltaX() != delta.Width();
bool did_scroll_y = scroll_state->deltaY() != delta.Height();
@@ -625,13 +662,7 @@ WebInputEventResult ScrollManager::HandleGestureScrollUpdate(
return WebInputEventResult::kHandledSystem;
if (RuntimeEnabledFeatures::OverscrollCustomizationEnabled()) {
- // Send the overscroll event to the node that scrolling is latched to which
- // is either previously scrolled node or the last node in the scroll chain.
- Node* overscroll_target = previous_gesture_scrolled_node_;
- if (!overscroll_target && !current_scroll_chain_.IsEmpty())
- overscroll_target = DOMNodeIds::NodeForId(current_scroll_chain_.front());
-
- if (overscroll_target) {
+ if (Node* overscroll_target = GetScrollEventTarget()) {
overscroll_target->GetDocument().EnqueueOverscrollEventForNode(
overscroll_target, delta.Width(), delta.Height());
}
@@ -689,19 +720,13 @@ WebInputEventResult ScrollManager::HandleGestureScrollEnd(
ScrollState* scroll_state =
ScrollState::Create(std::move(scroll_state_data));
CustomizedScroll(*scroll_state);
- snap_at_gesture_scroll_end = SnapAtGestureScrollEnd();
+
+ snap_at_gesture_scroll_end = SnapAtGestureScrollEnd(gesture_event);
NotifyScrollPhaseEndForCustomizedScroll();
- if (RuntimeEnabledFeatures::OverscrollCustomizationEnabled()) {
- // Send the scrollend event to the node that scrolling is latched to
- // which is either previously scrolled node or the last node in the
- // scroll chain.
- DCHECK(!current_scroll_chain_.IsEmpty());
- if (previous_gesture_scrolled_node_) {
- previous_gesture_scrolled_node_->GetDocument()
- .EnqueueScrollEndEventForNode(previous_gesture_scrolled_node_);
- } else if (Node* scroll_end_target =
- DOMNodeIds::NodeForId(current_scroll_chain_.front())) {
+ if (RuntimeEnabledFeatures::OverscrollCustomizationEnabled() &&
+ !snap_at_gesture_scroll_end) {
+ if (Node* scroll_end_target = GetScrollEventTarget()) {
scroll_end_target->GetDocument().EnqueueScrollEndEventForNode(
scroll_end_target);
}
@@ -727,7 +752,11 @@ LayoutBox* ScrollManager::LayoutBoxForSnapping() const {
return previous_gesture_scrolled_node_->GetLayoutBox();
}
-bool ScrollManager::SnapAtGestureScrollEnd() {
+ScrollOffset GetScrollDirection(FloatSize delta) {
+ return delta.ShrunkTo(FloatSize(1, 1)).ExpandedTo(FloatSize(-1, -1));
+}
+
+bool ScrollManager::SnapAtGestureScrollEnd(const WebGestureEvent& end_event) {
if (!previous_gesture_scrolled_node_ ||
(!did_scroll_x_for_scroll_gesture_ && !did_scroll_y_for_scroll_gesture_))
return false;
@@ -737,6 +766,30 @@ bool ScrollManager::SnapAtGestureScrollEnd() {
if (!snap_coordinator || !layout_box)
return false;
+ bool is_mouse_wheel =
+ end_event.SourceDevice() == WebGestureDevice::kTouchpad &&
+ end_event.data.scroll_end.delta_units !=
+ ScrollGranularity::kScrollByPrecisePixel;
+
+ // Treat mouse wheel scrolls as direction only scroll with its last scroll
+ // delta amout. This means each wheel tick will prefer the next snap position
+ // in the given direction. This leads to a much better UX for wheels.
+ //
+ // Precise wheel and trackpads continue to be treated similar as end position
+ // scrolling.
+ if (is_mouse_wheel && !last_scroll_delta_for_scroll_gesture_.IsZero()) {
+ // TODO(majidvp): Currently DirectionStrategy uses current offset + delta as
+ // the intended offset and chooses snap offset closest to that intended
+ // offset. In this case, this is not correct because we are already at the
+ // intended position. DirectionStategy should be updated to use current
+ // offset as intended position. This requires changing how we snap in
+ // |ScrollManager::LogicalScroll()|. For now use a unit scroll offset to
+ // limit the miscalculation to 1px.
+ ScrollOffset scroll_direction =
+ GetScrollDirection(last_scroll_delta_for_scroll_gesture_);
+ return snap_coordinator->SnapForDirection(*layout_box, scroll_direction);
+ }
+
return snap_coordinator->SnapAtCurrentPosition(
*layout_box, did_scroll_x_for_scroll_gesture_,
did_scroll_y_for_scroll_gesture_);
@@ -795,6 +848,12 @@ gfx::Vector2dF ScrollManager::ScrollByForSnapFling(
}
void ScrollManager::ScrollEndForSnapFling() {
+ if (RuntimeEnabledFeatures::OverscrollCustomizationEnabled()) {
+ if (Node* scroll_end_target = GetScrollEventTarget()) {
+ scroll_end_target->GetDocument().EnqueueScrollEndEventForNode(
+ scroll_end_target);
+ }
+ }
if (current_scroll_chain_.IsEmpty()) {
NotifyScrollPhaseEndForCustomizedScroll();
ClearGestureScrollState();