summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortdresser <tdresser@chromium.org>2015-07-31 06:15:07 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-31 13:15:39 +0000
commitd9e20147dd5649be4c9b742d3e6984034853715c (patch)
treeee23091180f4ab0895946dc803ca1041b6ec67ee
parent582211ec456040fb553264c1d61129cfbbc52ddb (diff)
downloadchromium_src-d9e20147dd5649be4c9b742d3e6984034853715c.zip
chromium_src-d9e20147dd5649be4c9b742d3e6984034853715c.tar.gz
chromium_src-d9e20147dd5649be4c9b742d3e6984034853715c.tar.bz2
Arrange compositor scrolling into scroll customization format (WIP)
This splits compositor driven scrolling into applyScroll and distributeScroll methods. Future patches will allow JavaScript on a CompositorWorker to override these methods. BUG=505851 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1215183004 Cr-Commit-Position: refs/heads/master@{#341323}
-rw-r--r--cc/BUILD.gn3
-rw-r--r--cc/cc.gyp2
-rw-r--r--cc/cc_tests.gyp1
-rw-r--r--cc/input/scroll_state.cc46
-rw-r--r--cc/input/scroll_state.h108
-rw-r--r--cc/input/scroll_state_unittest.cc79
-rw-r--r--cc/layers/layer_impl.cc25
-rw-r--r--cc/layers/layer_impl.h4
-rw-r--r--cc/layers/viewport.cc2
-rw-r--r--cc/trees/layer_tree_host_impl.cc156
-rw-r--r--cc/trees/layer_tree_host_impl.h1
-rw-r--r--cc/trees/layer_tree_impl.h4
12 files changed, 361 insertions, 70 deletions
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index c4cdb2d..e421db1 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -108,6 +108,8 @@ component("cc") {
"input/page_scale_animation.h",
"input/scroll_elasticity_helper.cc",
"input/scroll_elasticity_helper.h",
+ "input/scroll_state.cc",
+ "input/scroll_state.h",
"input/selection.h",
"input/selection_bound_type.h",
"input/top_controls_manager.cc",
@@ -733,6 +735,7 @@ test("cc_unittests") {
"base/tiling_data_unittest.cc",
"debug/frame_timing_tracker_unittest.cc",
"debug/micro_benchmark_controller_unittest.cc",
+ "input/scroll_state_unittest.cc",
"input/top_controls_manager_unittest.cc",
"layers/delegated_frame_provider_unittest.cc",
"layers/delegated_frame_resource_collection_unittest.cc",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index d4a2ea0..af4c83d 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -164,6 +164,8 @@
'input/page_scale_animation.h',
'input/scroll_elasticity_helper.cc',
'input/scroll_elasticity_helper.h',
+ 'input/scroll_state.cc',
+ 'input/scroll_state.h',
'input/selection_bound_type.h',
'input/selection.h',
'input/top_controls_manager.cc',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index c0be740..5dfd42a 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -32,6 +32,7 @@
'debug/frame_timing_tracker_unittest.cc',
'debug/micro_benchmark_controller_unittest.cc',
'debug/rendering_stats_unittest.cc',
+ 'input/scroll_state_unittest.cc',
'input/top_controls_manager_unittest.cc',
'layers/delegated_frame_provider_unittest.cc',
'layers/delegated_frame_resource_collection_unittest.cc',
diff --git a/cc/input/scroll_state.cc b/cc/input/scroll_state.cc
new file mode 100644
index 0000000..52a0cca
--- /dev/null
+++ b/cc/input/scroll_state.cc
@@ -0,0 +1,46 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/input/scroll_state.h"
+
+#include "cc/layers/layer_impl.h"
+
+namespace cc {
+
+ScrollState::ScrollState(double delta_x,
+ double delta_y,
+ int start_position_x,
+ int start_position_y,
+ bool should_propagate,
+ bool delta_consumed_for_scroll_sequence,
+ bool is_direct_manipulation)
+ : delta_x_(delta_x),
+ delta_y_(delta_y),
+ start_position_x_(start_position_x),
+ start_position_y_(start_position_y),
+ should_propagate_(should_propagate),
+ delta_consumed_for_scroll_sequence_(delta_consumed_for_scroll_sequence),
+ is_direct_manipulation_(is_direct_manipulation),
+ caused_scroll_x_(false),
+ caused_scroll_y_(false) {}
+
+ScrollState::~ScrollState() {}
+
+void ScrollState::ConsumeDelta(double x, double y) {
+ delta_x_ -= x;
+ delta_y_ -= y;
+
+ if (x || y)
+ delta_consumed_for_scroll_sequence_ = true;
+}
+
+void ScrollState::DistributeToScrollChainDescendant() {
+ if (!scroll_chain_.empty()) {
+ LayerImpl* next = scroll_chain_.front();
+ scroll_chain_.pop_front();
+ next->DistributeScroll(this);
+ }
+}
+
+} // namespace cc
diff --git a/cc/input/scroll_state.h b/cc/input/scroll_state.h
new file mode 100644
index 0000000..2cd437d
--- /dev/null
+++ b/cc/input/scroll_state.h
@@ -0,0 +1,108 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_INPUT_SCROLL_STATE_H_
+#define CC_INPUT_SCROLL_STATE_H_
+
+#include <list>
+
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+class LayerImpl;
+
+// ScrollState is based on the proposal for scroll customization in blink, found
+// here: https://goo.gl/1ipTpP.
+class CC_EXPORT ScrollState {
+ public:
+ ScrollState(double delta_x,
+ double delta_y,
+ int start_position_x,
+ int start_position_y,
+ bool should_propagate,
+ bool delta_consumed_for_scroll_sequence,
+ bool is_direct_manipulation);
+ ~ScrollState();
+
+ // Reduce deltas by x, y.
+ void ConsumeDelta(double x, double y);
+ // Pops the first layer off of |scroll_chain_| and calls
+ // |DistributeScroll| on it.
+ void DistributeToScrollChainDescendant();
+ // Positive when scrolling left.
+ double delta_x() const { return delta_x_; }
+ // Positive when scrolling up.
+ double delta_y() const { return delta_y_; }
+ // The location the scroll started at. For touch, the starting
+ // position of the finger. For mouse, the location of the cursor.
+ int start_position_x() const { return start_position_x_; }
+ int start_position_y() const { return start_position_y_; }
+
+ // True if this scroll is allowed to bubble upwards.
+ bool should_propagate() const { return should_propagate_; }
+ // True if the user interacts directly with the screen, e.g., via touch.
+ bool is_direct_manipulation() const { return is_direct_manipulation_; }
+
+ void set_scroll_chain(const std::list<LayerImpl*>& scroll_chain) {
+ scroll_chain_ = scroll_chain;
+ }
+
+ void set_current_native_scrolling_layer(LayerImpl* layer) {
+ current_native_scrolling_layer_ = layer;
+ }
+
+ LayerImpl* current_native_scrolling_layer() const {
+ return current_native_scrolling_layer_;
+ }
+
+ bool delta_consumed_for_scroll_sequence() const {
+ return delta_consumed_for_scroll_sequence_;
+ }
+
+ bool FullyConsumed() const { return !delta_x_ && !delta_y_; }
+
+ void set_caused_scroll(bool x, bool y) {
+ caused_scroll_x_ |= x;
+ caused_scroll_y_ |= y;
+ }
+
+ bool caused_scroll_x() const { return caused_scroll_x_; }
+ bool caused_scroll_y() const { return caused_scroll_y_; }
+
+ private:
+ ScrollState();
+ double delta_x_;
+ double delta_y_;
+ double start_position_x_;
+ double start_position_y_;
+
+ bool should_propagate_;
+
+ // The last layer to respond to a scroll, or null if none exists.
+ LayerImpl* current_native_scrolling_layer_;
+ // Whether the scroll sequence has had any delta consumed, in the
+ // current frame, or any child frames.
+ bool delta_consumed_for_scroll_sequence_;
+ // True if the user interacts directly with the display, e.g., via
+ // touch.
+ bool is_direct_manipulation_;
+ // TODO(tdresser): ScrollState shouldn't need to keep track of whether or not
+ // this ScrollState object has caused a scroll. Ideally, any native scroller
+ // consuming delta has caused a scroll. Currently, there are some cases where
+ // we consume delta without scrolling, such as in
+ // |Viewport::AdjustOverscroll|. Once these cases are fixed, we should get rid
+ // of |caused_scroll_*_|. See crbug.com/510045 for details.
+ bool caused_scroll_x_;
+ bool caused_scroll_y_;
+
+ // TODO(tdresser): Change LayerImpl* to an abstract scrollable type. See
+ // crbug.com/476553 for detail on the effort to unify impl and main thread
+ // scrolling, which will require an abstract scrollable type.
+ std::list<LayerImpl*> scroll_chain_;
+};
+
+} // namespace cc
+
+#endif // CC_INPUT_SCROLL_STATE_H_
diff --git a/cc/input/scroll_state_unittest.cc b/cc/input/scroll_state_unittest.cc
new file mode 100644
index 0000000..5e091df
--- /dev/null
+++ b/cc/input/scroll_state_unittest.cc
@@ -0,0 +1,79 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/input/scroll_state.h"
+
+#include "cc/layers/layer_impl.h"
+#include "cc/test/fake_impl_proxy.h"
+#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/test_shared_bitmap_manager.h"
+#include "cc/test/test_task_graph_runner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+
+class ScrollStateTest : public testing::Test {};
+
+TEST_F(ScrollStateTest, ConsumeDeltaNative) {
+ const float delta_x = 12.3f;
+ const float delta_y = 3.9f;
+
+ const float delta_x_to_consume = 1.2f;
+ const float delta_y_to_consume = 2.3f;
+
+ ScrollState scrollState(delta_x, delta_y, 0, 0, false /* should_propagate */,
+ false /* delta_consumed_for_scroll_sequence */,
+ false /* is_direct_manipulation */);
+ EXPECT_FLOAT_EQ(delta_x, scrollState.delta_x());
+ EXPECT_FLOAT_EQ(delta_y, scrollState.delta_y());
+ EXPECT_FALSE(scrollState.delta_consumed_for_scroll_sequence());
+ EXPECT_FALSE(scrollState.FullyConsumed());
+
+ scrollState.ConsumeDelta(0, 0);
+ EXPECT_FLOAT_EQ(delta_x, scrollState.delta_x());
+ EXPECT_FLOAT_EQ(delta_y, scrollState.delta_y());
+ EXPECT_FALSE(scrollState.delta_consumed_for_scroll_sequence());
+ EXPECT_FALSE(scrollState.FullyConsumed());
+
+ scrollState.ConsumeDelta(delta_x_to_consume, 0);
+ EXPECT_FLOAT_EQ(delta_x - delta_x_to_consume, scrollState.delta_x());
+ EXPECT_FLOAT_EQ(delta_y, scrollState.delta_y());
+ EXPECT_TRUE(scrollState.delta_consumed_for_scroll_sequence());
+ EXPECT_FALSE(scrollState.FullyConsumed());
+
+ scrollState.ConsumeDelta(0, delta_y_to_consume);
+ EXPECT_FLOAT_EQ(delta_x - delta_x_to_consume, scrollState.delta_x());
+ EXPECT_FLOAT_EQ(delta_y - delta_y_to_consume, scrollState.delta_y());
+ EXPECT_TRUE(scrollState.delta_consumed_for_scroll_sequence());
+ EXPECT_FALSE(scrollState.FullyConsumed());
+
+ scrollState.ConsumeDelta(scrollState.delta_x(), scrollState.delta_y());
+ EXPECT_TRUE(scrollState.delta_consumed_for_scroll_sequence());
+ EXPECT_TRUE(scrollState.FullyConsumed());
+}
+
+TEST_F(ScrollStateTest, CurrentNativeScrollingScrollable) {
+ ScrollState scrollState(0, 0, 0, 0, false, false, false);
+
+ FakeImplProxy proxy;
+ TestSharedBitmapManager shared_bitmap_manager;
+ TestTaskGraphRunner task_graph_runner;
+ FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager,
+ &task_graph_runner);
+
+ scoped_ptr<LayerImpl> layer_impl =
+ LayerImpl::Create(host_impl.active_tree(), 1);
+ scrollState.set_current_native_scrolling_layer(layer_impl.get());
+ EXPECT_EQ(layer_impl, scrollState.current_native_scrolling_layer());
+}
+
+TEST_F(ScrollStateTest, FullyConsumed) {
+ ScrollState scrollState(1, 3, 0, 0, 0, false, false);
+ EXPECT_FALSE(scrollState.FullyConsumed());
+
+ scrollState.ConsumeDelta(1, 3);
+ EXPECT_TRUE(scrollState.FullyConsumed());
+}
+} // namespace cc
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 5c20611..957bd2c 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -17,6 +17,7 @@
#include "cc/debug/layer_tree_debug_state.h"
#include "cc/debug/micro_benchmark_impl.h"
#include "cc/debug/traced_value.h"
+#include "cc/input/scroll_state.h"
#include "cc/layers/layer_utils.h"
#include "cc/layers/painted_scrollbar_layer_impl.h"
#include "cc/output/copy_output_request.h"
@@ -197,6 +198,30 @@ void LayerImpl::SetScrollChildren(std::set<LayerImpl*>* children) {
SetNeedsPushProperties();
}
+void LayerImpl::DistributeScroll(ScrollState* scroll_state) {
+ DCHECK(scroll_state);
+ if (scroll_state->FullyConsumed())
+ return;
+
+ scroll_state->DistributeToScrollChainDescendant();
+
+ // If the scroll doesn't propagate, and we're currently scrolling
+ // a layer other than this one, prevent the scroll from
+ // propagating to this layer.
+ if (!scroll_state->should_propagate() &&
+ scroll_state->delta_consumed_for_scroll_sequence() &&
+ scroll_state->current_native_scrolling_layer() != this) {
+ return;
+ }
+
+ ApplyScroll(scroll_state);
+}
+
+void LayerImpl::ApplyScroll(ScrollState* scroll_state) {
+ DCHECK(scroll_state);
+ layer_tree_impl()->ApplyScroll(this, scroll_state);
+}
+
void LayerImpl::SetNumDescendantsThatDrawContent(int num_descendants) {
if (num_descendants_that_draw_content_ == num_descendants)
return;
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index dce8d05..3fd6bc538 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -67,6 +67,7 @@ class ScrollbarLayerImplBase;
class SimpleEnclosedRegion;
class Tile;
class TransformTree;
+class ScrollState;
struct AppendQuadsData;
@@ -149,6 +150,9 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
return scroll_children_.get();
}
+ void DistributeScroll(ScrollState* scroll_state);
+ void ApplyScroll(ScrollState* scroll_state);
+
void set_property_tree_sequence_number(int sequence_number) {}
void SetTransformTreeIndex(int index);
diff --git a/cc/layers/viewport.cc b/cc/layers/viewport.cc
index d9ae5f4..e5e3053 100644
--- a/cc/layers/viewport.cc
+++ b/cc/layers/viewport.cc
@@ -148,6 +148,8 @@ bool Viewport::ShouldTopControlsConsumeScroll(
}
gfx::Vector2dF Viewport::AdjustOverscroll(const gfx::Vector2dF& delta) const {
+ // TODO(tdresser): Use a more rational epsilon. See crbug.com/510550 for
+ // details.
const float kEpsilon = 0.1f;
gfx::Vector2dF adjusted = delta;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 9bded52..e5a7e41 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"
@@ -2422,6 +2423,13 @@ static bool HasScrollAncestor(LayerImpl* child, LayerImpl* scroll_ancestor) {
return false;
}
+static LayerImpl* nextLayerInScrollOrder(LayerImpl* layer) {
+ if (layer->scroll_parent())
+ return layer->scroll_parent();
+
+ return layer->parent();
+}
+
InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl(
LayerImpl* scrolling_layer_impl,
InputHandler::ScrollInputType type) {
@@ -2628,11 +2636,62 @@ 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;
+ // TODO(tdresser): Use a more rational epsilon. See crbug.com/510550 for
+ // details.
+ const float kEpsilon = 0.1f;
+
+ if (layer == InnerViewportScrollLayer()) {
+ bool affect_top_controls = !wheel_scrolling_;
+ Viewport::ScrollResult result = viewport()->ScrollBy(
+ delta, viewport_point, scroll_state->is_direct_manipulation(),
+ affect_top_controls);
+ applied_delta = result.consumed_delta;
+ scroll_state->set_caused_scroll(
+ std::abs(result.content_scrolled_delta.x()) > kEpsilon,
+ std::abs(result.content_scrolled_delta.y()) > kEpsilon);
+ scroll_state->ConsumeDelta(applied_delta.x(), applied_delta.y());
+ } 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.
+ 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->set_caused_scroll(std::abs(applied_delta.x()) > kEpsilon,
+ std::abs(applied_delta.y()) > kEpsilon);
+ scroll_state->ConsumeDelta(applied_delta.x(), applied_delta.y());
+ }
- return layer->parent();
+ 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(
@@ -2642,86 +2701,41 @@ 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;
- float initial_top_controls_offset =
- top_controls_manager_->ControlsTopOffset();
-
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;
+ float initial_top_controls_offset =
+ top_controls_manager_->ControlsTopOffset();
+ ScrollState scroll_state(
+ scroll_delta.x(), scroll_delta.y(), viewport_point.x(),
+ viewport_point.y(), 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(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;
-
- gfx::Vector2dF applied_delta;
- if (layer_impl == InnerViewportScrollLayer()) {
- // Each wheel event triggers a ScrollBegin/Update/End. This can interact
- // poorly with the top controls animation, which is triggered after each
- // call to ScrollEnd.
- bool affect_top_controls = !wheel_scrolling_;
- Viewport::ScrollResult result =
- viewport()->ScrollBy(pending_delta, viewport_point, !wheel_scrolling_,
- affect_top_controls);
- applied_delta = result.content_scrolled_delta;
- unused_root_delta = pending_delta - result.consumed_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_move_layer_x = std::abs(applied_delta.x()) > kEpsilon;
- bool did_move_layer_y = std::abs(applied_delta.y()) > kEpsilon;
- did_scroll_x |= did_move_layer_x;
- did_scroll_y |= did_move_layer_y;
-
- if (did_move_layer_x || did_move_layer_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;
-
- // 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;
+ current_scroll_chain.push_front(layer_impl);
}
+ scroll_state.set_scroll_chain(current_scroll_chain);
+ scroll_state.DistributeToScrollChainDescendant();
+
+ active_tree_->SetCurrentlyScrollingLayer(
+ scroll_state.current_native_scrolling_layer());
+ did_lock_scrolling_layer_ = scroll_state.delta_consumed_for_scroll_sequence();
+ bool did_scroll_x = scroll_state.caused_scroll_x();
+ bool did_scroll_y = scroll_state.caused_scroll_y();
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
@@ -2739,6 +2753,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;
bool did_scroll_top_controls =
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 01f8792..077f904 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -168,6 +168,7 @@ class CC_EXPORT LayerTreeHostImpl
InputHandler::ScrollStatus ScrollAnimated(
const gfx::Point& viewport_point,
const gfx::Vector2dF& scroll_delta) override;
+ void ApplyScroll(LayerImpl* layer, ScrollState* scroll_state);
InputHandlerScrollResult ScrollBy(
const gfx::Point& viewport_point,
const gfx::Vector2dF& scroll_delta) override;
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index a3d3554..476d8aa 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -275,6 +275,10 @@ class CC_EXPORT LayerTreeImpl {
// The outer viewport scroll layer scrolls first.
void DistributeRootScrollOffset();
+ void ApplyScroll(LayerImpl* layer, ScrollState* scroll_state) {
+ layer_tree_host_impl_->ApplyScroll(layer, scroll_state);
+ }
+
// Call this function when you expect there to be a swap buffer.
// See swap_promise.h for how to use SwapPromise.
void QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise);