Chromium Code Reviews| 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 da263e34a63ed8038f642223923945bb3045a590..9f867e5b654ac9ff7f834064d8b5c2ab71b3c7f5 100644 |
| --- a/cc/trees/layer_tree_host_impl.cc |
| +++ b/cc/trees/layer_tree_host_impl.cc |
| @@ -34,6 +34,7 @@ |
| #include "cc/debug/traced_value.h" |
| #include "cc/input/page_scale_animation.h" |
| #include "cc/input/scroll_elasticity_helper.h" |
| +#include "cc/input/scroll_state.h" |
| #include "cc/input/top_controls_manager.h" |
| #include "cc/layers/append_quads_data.h" |
| #include "cc/layers/heads_up_display_layer_impl.h" |
| @@ -211,6 +212,7 @@ LayerTreeHostImpl::LayerTreeHostImpl( |
| should_bubble_scrolls_(false), |
| wheel_scrolling_(false), |
| scroll_affects_scroll_handler_(false), |
| + in_inertial_scroll_(false), |
| scroll_layer_id_when_mouse_over_scrollbar_(0), |
| tile_priorities_dirty_(false), |
| root_layer_scroll_offset_delegate_(NULL), |
| @@ -2438,6 +2440,13 @@ static bool HasScrollAncestor(LayerImpl* child, LayerImpl* scroll_ancestor) { |
| return false; |
| } |
| +static LayerImpl* nextLayerInScrollOrder(LayerImpl* layer) { |
|
Ian Vollick
2015/07/09 14:03:55
This feels like it would be a function in the Scro
|
| + if (layer->scroll_parent()) |
| + return layer->scroll_parent(); |
| + |
| + return layer->parent(); |
| +} |
| + |
| InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( |
| LayerImpl* scrolling_layer_impl, |
| InputHandler::ScrollInputType type) { |
| @@ -2449,6 +2458,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( |
| active_tree_->SetCurrentlyScrollingLayer(scrolling_layer_impl); |
| should_bubble_scrolls_ = (type != NON_BUBBLING_GESTURE); |
| wheel_scrolling_ = (type == WHEEL); |
| + in_inertial_scroll_ = false; |
| + |
| client_->RenewTreePriority(); |
| UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false); |
| return SCROLL_STARTED; |
| @@ -2557,7 +2568,7 @@ gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta( |
| gfx::Transform::kSkipInitialization); |
| bool did_invert = layer_impl->screen_space_transform().GetInverse( |
| &inverse_screen_space_transform); |
| - // TODO(shawnsingh): With the advent of impl-side crolling for non-root |
| + // TODO(shawnsingh): With the advent of impl-side scrolling for non-root |
| // layers, we may need to explicitly handle uninvertible transforms here. |
| DCHECK(did_invert); |
| @@ -2644,11 +2655,54 @@ gfx::Vector2dF LayerTreeHostImpl::ScrollLayer(LayerImpl* layer_impl, |
| return ScrollLayerWithLocalDelta(layer_impl, delta, scale_factor); |
| } |
| -static LayerImpl* nextLayerInScrollOrder(LayerImpl* layer) { |
| - if (layer->scroll_parent()) |
| - return layer->scroll_parent(); |
| +void LayerTreeHostImpl::ApplyScroll(LayerImpl* layer, |
| + ScrollState* scroll_state) { |
| + DCHECK(scroll_state); |
| + gfx::Point viewport_point(scroll_state->start_position_x(), |
| + scroll_state->start_position_y()); |
| + const gfx::Vector2dF delta(scroll_state->delta_x(), scroll_state->delta_y()); |
| + gfx::Vector2dF applied_delta; |
| - return layer->parent(); |
| + if (layer == InnerViewportScrollLayer()) { |
| + bool affect_top_controls = true; |
| + applied_delta = viewport()->ScrollBy(delta, viewport_point, |
| + scroll_state->is_direct_manipulation(), |
| + affect_top_controls); |
| + } else { |
| + applied_delta = ScrollLayer(layer, delta, viewport_point, |
| + scroll_state->is_direct_manipulation()); |
| + } |
| + |
| + // If the layer wasn't able to move, try the next one in the hierarchy. |
| + const float kEpsilon = 0.1f; |
|
Ian Vollick
2015/07/09 14:03:55
Why this number? Should it not be one device pixel
tdresser
2015/07/09 16:07:45
I'm trying to avoid introducing any functional cha
Ian Vollick
2015/07/09 16:46:51
Yes, please file a bug for this, add a TODO and ex
tdresser
2015/07/16 14:04:50
Done.
|
| + bool scrolled = std::abs(applied_delta.x()) > kEpsilon; |
| + scrolled = scrolled || std::abs(applied_delta.y()) > kEpsilon; |
| + |
| + if (scrolled && layer != InnerViewportScrollLayer()) { |
| + // If the applied delta is within 45 degrees of the input |
| + // delta, bail out to make it easier to scroll just one layer |
| + // in one direction without affecting any of its parents. |
| + float angle_threshold = 45; |
| + if (MathUtil::SmallestAngleBetweenVectors(applied_delta, delta) < |
| + angle_threshold) { |
| + applied_delta = delta; |
| + } else { |
| + // Allow further movement only on an axis perpendicular to the direction |
| + // in which the layer moved. |
| + applied_delta = MathUtil::ProjectVector(delta, applied_delta); |
| + } |
| + } |
| + |
| + scroll_state->ConsumeDelta(applied_delta.x(), applied_delta.y()); |
| + |
| + if (!scrolled) |
| + return; |
| + // When scrolls are allowed to bubble, it's important that the original |
| + // scrolling layer be preserved. This ensures that, after a scroll |
| + // bubbles, the user can reverse scroll directions and immediately resume |
| + // scrolling the original layer that scrolled. |
| + if (!scroll_state->should_propagate()) |
| + scroll_state->set_current_native_scrolling_layer(layer); |
| } |
| InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( |
| @@ -2658,81 +2712,45 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( |
| if (!CurrentlyScrollingLayer()) |
| return InputHandlerScrollResult(); |
| - gfx::Vector2dF pending_delta = scroll_delta; |
| - gfx::Vector2dF unused_root_delta; |
| - bool did_scroll_x = false; |
| - bool did_scroll_y = false; |
| - |
| if (pinch_gesture_active_ && settings().invert_viewport_scroll_order) { |
| // Scrolls during a pinch gesture should pan the visual viewport, rather |
| // than a typical bubbling scroll. |
| - viewport()->Pan(pending_delta); |
| + viewport()->Pan(scroll_delta); |
| return InputHandlerScrollResult(); |
| } |
| - for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); |
| - layer_impl; |
| + ScrollState scroll_state( |
| + scroll_delta.x(), scroll_delta.y(), viewport_point.x(), |
| + viewport_point.y(), in_inertial_scroll_ /* in_inertial_phase*/, |
| + should_bubble_scrolls_ /* should_propagate */, |
| + did_lock_scrolling_layer_ /* delta_consumed_for_scroll_sequence */, |
| + !wheel_scrolling_ /* is_direct_manipulation */); |
| + scroll_state.set_current_native_scrolling_layer( |
| + active_tree_->CurrentlyScrollingLayer()); |
| + |
| + std::list<LayerImpl*> current_scroll_chain; |
| + for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); layer_impl; |
| layer_impl = nextLayerInScrollOrder(layer_impl)) { |
| // Skip the outer viewport scroll layer so that we try to scroll the |
| // viewport only once. i.e. The inner viewport layer represents the |
| // viewport. |
| if (!layer_impl->scrollable() || layer_impl == OuterViewportScrollLayer()) |
| continue; |
| + current_scroll_chain.push_front(layer_impl); |
| + } |
| + scroll_state.set_scroll_chain(current_scroll_chain); |
| - gfx::Vector2dF applied_delta; |
| - if (layer_impl == InnerViewportScrollLayer()) { |
| - bool affect_top_controls = true; |
| - applied_delta = |
| - viewport()->ScrollBy(pending_delta, viewport_point, !wheel_scrolling_, |
| - affect_top_controls); |
| - unused_root_delta = pending_delta - applied_delta; |
| - } else { |
| - applied_delta = ScrollLayer(layer_impl, pending_delta, viewport_point, |
| - !wheel_scrolling_); |
| - } |
| - |
| - // If the layer wasn't able to move, try the next one in the hierarchy. |
| - const float kEpsilon = 0.1f; |
| - bool did_layer_consume_delta_x = std::abs(applied_delta.x()) > kEpsilon; |
| - bool did_layer_consume_delta_y = std::abs(applied_delta.y()) > kEpsilon; |
| - |
| - did_scroll_x |= did_layer_consume_delta_x; |
| - did_scroll_y |= did_layer_consume_delta_y; |
| - |
| - if (did_layer_consume_delta_x || did_layer_consume_delta_y) { |
| - did_lock_scrolling_layer_ = true; |
| - |
| - // When scrolls are allowed to bubble, it's important that the original |
| - // scrolling layer be preserved. This ensures that, after a scroll |
| - // bubbles, the user can reverse scroll directions and immediately resume |
| - // scrolling the original layer that scrolled. |
| - if (!should_bubble_scrolls_) { |
| - active_tree_->SetCurrentlyScrollingLayer(layer_impl); |
| - break; |
| - } |
| - |
| - // If the applied delta is within 45 degrees of the input delta, bail out |
| - // to make it easier to scroll just one layer in one direction without |
| - // affecting any of its parents. |
| - float angle_threshold = 45; |
| - if (MathUtil::SmallestAngleBetweenVectors(applied_delta, pending_delta) < |
| - angle_threshold) |
| - break; |
| + scroll_state.DistributeToScrollChainDescendant(); |
| - // Allow further movement only on an axis perpendicular to the direction |
| - // in which the layer moved. |
| - gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x()); |
| - pending_delta = |
| - MathUtil::ProjectVector(pending_delta, perpendicular_axis); |
| - |
| - if (gfx::ToRoundedVector2d(pending_delta).IsZero()) |
| - break; |
| - } |
| - |
| - if (!should_bubble_scrolls_ && did_lock_scrolling_layer_) |
| - break; |
| - } |
| + active_tree_->SetCurrentlyScrollingLayer( |
| + scroll_state.current_native_scrolling_layer()); |
| + did_lock_scrolling_layer_ = scroll_state.delta_consumed_for_scroll_sequence(); |
| + const float kEpsilon = 0.1f; |
| + bool did_scroll_x = |
| + std::abs(scroll_state.delta_x() - scroll_delta.x()) > kEpsilon; |
| + bool did_scroll_y = |
| + std::abs(scroll_state.delta_y() - scroll_delta.y()) > kEpsilon; |
| bool did_scroll_content = did_scroll_x || did_scroll_y; |
| if (did_scroll_content) { |
| // If we are scrolling with an active scroll handler, forward latency |
| @@ -2750,6 +2768,8 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( |
| accumulated_root_overscroll_.set_x(0); |
| if (did_scroll_y) |
| accumulated_root_overscroll_.set_y(0); |
| + gfx::Vector2dF unused_root_delta(scroll_state.delta_x(), |
| + scroll_state.delta_y()); |
| accumulated_root_overscroll_ += unused_root_delta; |
| InputHandlerScrollResult scroll_result; |
| @@ -2843,6 +2863,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::FlingScrollBegin() { |
| should_bubble_scrolls_ = false; |
| } |
| + in_inertial_scroll_ = true; |
| + |
| return SCROLL_STARTED; |
| } |