| 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 66af6cec6d026106850b51f84704ad3ce376f1a0..677cef149cf98485208a876bc79a706ac21882d4 100644
|
| --- a/cc/trees/layer_tree_host_impl.cc
|
| +++ b/cc/trees/layer_tree_host_impl.cc
|
| @@ -286,8 +286,7 @@ LayerTreeHostImpl::~LayerTreeHostImpl() {
|
| input_handler_client_->WillShutdown();
|
| input_handler_client_ = NULL;
|
| }
|
| - if (scroll_elasticity_helper_)
|
| - scroll_elasticity_helper_.reset();
|
| + root_scroll_elasticity_helper_.reset();
|
|
|
| // The layer trees must be destroyed before the layer tree host. We've
|
| // made a contract with our animation controllers that the animation_host
|
| @@ -614,13 +613,22 @@ LayerTreeHostImpl::CreateLatencyInfoSwapPromiseMonitor(
|
| new LatencyInfoSwapPromiseMonitor(latency, NULL, this));
|
| }
|
|
|
| -ScrollElasticityHelper* LayerTreeHostImpl::CreateScrollElasticityHelper() {
|
| - DCHECK(!scroll_elasticity_helper_);
|
| +ScrollElasticityHelper* LayerTreeHostImpl::CreateRootScrollElasticityHelper() {
|
| + DCHECK(!root_scroll_elasticity_helper_);
|
| if (settings_.enable_elastic_overscroll) {
|
| - scroll_elasticity_helper_.reset(
|
| + root_scroll_elasticity_helper_.reset(
|
| ScrollElasticityHelper::CreateForLayerTreeHostImpl(this));
|
| }
|
| - return scroll_elasticity_helper_.get();
|
| + return root_scroll_elasticity_helper_.get();
|
| +}
|
| +
|
| +base::WeakPtr<ScrollElasticityHelper>
|
| +LayerTreeHostImpl::ScrollElasticityHelperForScrollingLayer() {
|
| + LayerImpl* scrolling_layer_impl = CurrentlyScrollingLayer();
|
| + if (!scrolling_layer_impl)
|
| + return nullptr;
|
| +
|
| + return ScrollElasticityHelperForId(scrolling_layer_impl->id())->GetWeakPtr();
|
| }
|
|
|
| bool LayerTreeHostImpl::GetScrollOffsetForLayer(int layer_id,
|
| @@ -2616,8 +2624,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl(
|
| // in input_handler_proxy instead.
|
| wheel_scrolling_ = IsWheelBasedScroll(type);
|
| scroll_state->set_is_direct_manipulation(!wheel_scrolling_);
|
| - // Invoke |DistributeScrollDelta| even with zero delta and velocity to ensure
|
| - // scroll customization callbacks are invoked.
|
| + // Invoke |DistributeScrollDelta| even with zero delta and velocity to process
|
| + // overscroll and ensure scroll customization callbacks are invoked.
|
| DistributeScrollDelta(scroll_state);
|
|
|
| client_->RenewTreePriority();
|
| @@ -2652,6 +2660,18 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
|
|
|
| ClearCurrentlyScrollingLayer();
|
|
|
| + if (!scroll_state->is_beginning()) {
|
| + DCHECK(scroll_state->is_in_inertial_phase());
|
| + // When transitioning into a "flick", try to find the layer that was
|
| + // already scrolling. Without this, a flick may begin after elastic
|
| + // overscroll moves the scrolling layer out from beneath the event, causing
|
| + // a failed hit test.
|
| + LayerImpl* scrolling_layer_impl =
|
| + active_tree_->LayerById(active_tree_->LastScrolledLayerId());
|
| + if (scrolling_layer_impl)
|
| + return ScrollBeginImpl(scroll_state, scrolling_layer_impl, type);
|
| + }
|
| +
|
| gfx::Point viewport_point(scroll_state->position_x(),
|
| scroll_state->position_y());
|
|
|
| @@ -3075,6 +3095,21 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy(
|
| DCHECK(scroll_state);
|
|
|
| TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy");
|
| +
|
| + if (!CurrentlyScrollingLayer()) {
|
| + // If the InputHandlerClient didn't call ScrollBegin() to re-perform a
|
| + // hit-test but provided an element to scroll instead, scroll that. For now,
|
| + // just compare it against the last scrolled layer.
|
| + ElementId provided_element =
|
| + scroll_state->data()->current_native_scrolling_element();
|
| + int last_scrolled = active_tree()->LastScrolledLayerId();
|
| + if (provided_element && last_scrolled) {
|
| + LayerImpl* layer = active_tree()->LayerById(last_scrolled);
|
| + if (layer && layer->element_id() == provided_element)
|
| + active_tree_->SetCurrentlyScrollingLayer(layer);
|
| + }
|
| + }
|
| +
|
| if (!CurrentlyScrollingLayer())
|
| return InputHandlerScrollResult();
|
|
|
| @@ -3517,6 +3552,38 @@ LayerTreeHostImpl::ScrollbarAnimationControllerForId(
|
| return i->second.get();
|
| }
|
|
|
| +void LayerTreeHostImpl::RegisterScrollElasticityHelper(int scroll_layer_id) {
|
| + DCHECK(!InnerViewportScrollLayer() ||
|
| + scroll_layer_id != InnerViewportScrollLayer()->id());
|
| + DCHECK(!OuterViewportScrollLayer() ||
|
| + scroll_layer_id != OuterViewportScrollLayer()->id());
|
| + DCHECK(settings().enable_elastic_overscroll);
|
| +
|
| + auto& helper = scroll_elasticity_helpers_[scroll_layer_id];
|
| + if (!helper)
|
| + helper = active_tree_->CreateScrollElasticityHelper(scroll_layer_id);
|
| +}
|
| +
|
| +void LayerTreeHostImpl::UnregisterScrollElasticityHelper(int scroll_layer_id) {
|
| + scroll_elasticity_helpers_.erase(scroll_layer_id);
|
| +}
|
| +
|
| +ScrollElasticityHelper* LayerTreeHostImpl::ScrollElasticityHelperForId(
|
| + int scroll_layer_id) {
|
| + if (!settings().enable_elastic_overscroll)
|
| + return nullptr;
|
| +
|
| + auto i = scroll_elasticity_helpers_.find(scroll_layer_id);
|
| + if (i != scroll_elasticity_helpers_.end())
|
| + return i->second.get();
|
| +
|
| + if (!root_scroll_elasticity_helper_) {
|
| + root_scroll_elasticity_helper_.reset(
|
| + ScrollElasticityHelper::CreateForLayerTreeHostImpl(this));
|
| + }
|
| + return root_scroll_elasticity_helper_.get();
|
| +}
|
| +
|
| void LayerTreeHostImpl::PostDelayedScrollbarAnimationTask(
|
| const base::Closure& task,
|
| base::TimeDelta delay) {
|
|
|