Index: cc/trees/layer_tree_host_impl.cc |
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc |
index ca294bf786ab2a1c533314c7a626ab1c66886511..b59670284a4a16121fd6d87074071c1fe7407e6c 100644 |
--- a/cc/trees/layer_tree_host_impl.cc |
+++ b/cc/trees/layer_tree_host_impl.cc |
@@ -2770,6 +2770,15 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( |
// scroll customization callbacks are invoked. |
DistributeScrollDelta(scroll_state); |
+ // If the CurrentlyScrollingNode doesn't exist after distributing scroll |
+ // delta, no scroller can scroll in the given delta hint direction(s). |
+ if (!active_tree_->CurrentlyScrollingNode()) { |
+ scroll_status.thread = InputHandler::SCROLL_IGNORED; |
+ scroll_status.main_thread_scrolling_reasons = |
+ MainThreadScrollingReason::kNotScrollingOnMain; |
+ return scroll_status; |
+ } |
+ |
client_->RenewTreePriority(); |
RecordCompositorSlowScrollMetric(type, CC_THREAD); |
@@ -2896,7 +2905,7 @@ bool LayerTreeHostImpl::IsInitialScrollHitTestReliable( |
} |
InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( |
- const gfx::Point& viewport_point) { |
+ ScrollState* scroll_state) { |
InputHandler::ScrollStatus scroll_status; |
scroll_status.main_thread_scrolling_reasons = |
MainThreadScrollingReason::kNotScrollingOnMain; |
@@ -2914,16 +2923,12 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( |
} |
return scroll_status; |
} |
- ScrollStateData scroll_state_data; |
- scroll_state_data.position_x = viewport_point.x(); |
- scroll_state_data.position_y = viewport_point.y(); |
- ScrollState scroll_state(scroll_state_data); |
// ScrollAnimated is used for animated wheel scrolls. We find the first layer |
// that can scroll and set up an animation of its scroll offset. Note that |
// this does not currently go through the scroll customization machinery |
// that ScrollBy uses for non-animated wheel scrolls. |
- scroll_status = ScrollBegin(&scroll_state, WHEEL); |
+ scroll_status = ScrollBegin(scroll_state, WHEEL); |
if (scroll_status.thread == SCROLL_ON_IMPL_THREAD) { |
scroll_animating_latched_node_id_ = ScrollTree::kInvalidNodeId; |
ScrollStateData scroll_state_end_data; |
@@ -3299,21 +3304,45 @@ void LayerTreeHostImpl::DistributeScrollDelta(ScrollState* scroll_state) { |
// reach that, we should scroll the viewport which is represented by the |
// main viewport scroll layer. |
DCHECK(viewport_scroll_node); |
- current_scroll_chain.push_front(viewport_scroll_node); |
+ if (CanConsumeDelta(viewport_scroll_node, *scroll_state)) |
+ current_scroll_chain.push_front(viewport_scroll_node); |
break; |
} |
if (!scroll_node->scrollable) |
continue; |
- current_scroll_chain.push_front(scroll_node); |
+ if (CanConsumeDelta(scroll_node, *scroll_state)) |
+ current_scroll_chain.push_front(scroll_node); |
} |
} |
+ active_tree_->SetCurrentlyScrollingNode( |
+ current_scroll_chain.empty() ? nullptr : current_scroll_chain.back()); |
scroll_state->set_scroll_chain_and_layer_tree(current_scroll_chain, |
active_tree()); |
scroll_state->DistributeToScrollChainDescendant(); |
} |
+bool LayerTreeHostImpl::CanConsumeDelta(ScrollNode* scroll_node, |
+ const ScrollState& scroll_state) { |
+ gfx::Vector2dF delta_to_scroll; |
+ if (scroll_state.is_beginning()) { |
+ if (scroll_state.ignore_delta_hints()) |
+ return true; |
+ |
+ delta_to_scroll = gfx::Vector2dF(scroll_state.delta_x_hint(), |
+ scroll_state.delta_y_hint()); |
+ } else { |
+ delta_to_scroll = |
+ gfx::Vector2dF(scroll_state.delta_x(), scroll_state.delta_y()); |
+ } |
+ |
+ if (delta_to_scroll == gfx::Vector2dF()) |
+ return true; |
+ |
+ return ComputeScrollDelta(scroll_node, delta_to_scroll) != gfx::Vector2dF(); |
+} |
+ |
InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( |
ScrollState* scroll_state) { |
DCHECK(scroll_state); |