summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/layers/layer_impl.cc50
-rw-r--r--cc/layers/layer_impl.h20
-rw-r--r--cc/layers/layer_impl_unittest.cc158
-rw-r--r--cc/trees/layer_tree_host_impl.cc2
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc103
-rw-r--r--cc/trees/layer_tree_impl.cc186
-rw-r--r--cc/trees/layer_tree_impl.h17
7 files changed, 161 insertions, 375 deletions
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 3ffeb73..8b37d12 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -16,7 +16,6 @@
#include "cc/debug/layer_tree_debug_state.h"
#include "cc/debug/micro_benchmark_impl.h"
#include "cc/debug/traced_value.h"
-#include "cc/input/layer_scroll_offset_delegate.h"
#include "cc/layers/layer_utils.h"
#include "cc/layers/painted_scrollbar_layer_impl.h"
#include "cc/output/copy_output_request.h"
@@ -49,7 +48,6 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl,
layer_id_(id),
layer_tree_impl_(tree_impl),
scroll_offset_(scroll_offset),
- scroll_offset_delegate_(nullptr),
scroll_clip_layer_(nullptr),
should_scroll_on_main_thread_(false),
have_wheel_event_handlers_(false),
@@ -164,9 +162,6 @@ void LayerImpl::SetScrollParent(LayerImpl* parent) {
if (scroll_parent_ == parent)
return;
- // Having both a scroll parent and a scroll offset delegate is unsupported.
- DCHECK(!scroll_offset_delegate_);
-
if (parent)
DCHECK_EQ(layer_tree_impl()->LayerById(parent->id()), parent);
@@ -385,8 +380,6 @@ void LayerImpl::GetContentsResourceId(ResourceProvider::ResourceId* resource_id,
}
gfx::Vector2dF LayerImpl::ScrollBy(const gfx::Vector2dF& scroll) {
- RefreshFromScrollDelegate();
-
gfx::ScrollOffset adjusted_scroll(scroll);
if (layer_tree_impl()->settings().use_pinch_virtual_viewport) {
if (!user_scrollable_horizontal_)
@@ -1108,25 +1101,21 @@ void LayerImpl::SetContentsScale(float contents_scale_x,
NoteLayerPropertyChanged();
}
-void LayerImpl::SetScrollOffsetDelegate(
- ScrollOffsetDelegate* scroll_offset_delegate) {
- // Having both a scroll parent and a scroll offset delegate is unsupported.
- DCHECK(!scroll_parent_);
- RefreshFromScrollDelegate();
- scroll_offset_delegate_ = scroll_offset_delegate;
- if (scroll_offset_delegate_)
- scroll_offset_delegate_->SetCurrentScrollOffset(CurrentScrollOffset());
-}
-
bool LayerImpl::IsExternalFlingActive() const {
- return scroll_offset_delegate_ &&
- scroll_offset_delegate_->IsExternalFlingActive();
+ return layer_tree_impl_->IsExternalFlingActive();
}
void LayerImpl::SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset) {
DCHECK(IsActive());
if (scroll_offset_->SetCurrent(scroll_offset))
- DidUpdateScrollOffset();
+ DidUpdateScrollOffset(false);
+}
+
+void LayerImpl::SetCurrentScrollOffsetFromDelegate(
+ const gfx::ScrollOffset& scroll_offset) {
+ DCHECK(IsActive());
+ if (scroll_offset_->SetCurrent(scroll_offset))
+ DidUpdateScrollOffset(true);
}
void LayerImpl::PushScrollOffsetFromMainThread(
@@ -1141,8 +1130,6 @@ void LayerImpl::PushScrollOffsetFromMainThreadAndClobberActiveValue(
}
gfx::ScrollOffset LayerImpl::PullDeltaForMainThread() {
- RefreshFromScrollDelegate();
-
// TODO(miletus): Remove all this temporary flooring machinery when
// Blink fully supports fractional scrolls.
gfx::ScrollOffset current_offset = CurrentScrollOffset();
@@ -1158,13 +1145,6 @@ gfx::ScrollOffset LayerImpl::PullDeltaForMainThread() {
return delta;
}
-void LayerImpl::RefreshFromScrollDelegate() {
- if (scroll_offset_delegate_) {
- SetCurrentScrollOffset(
- gfx::ScrollOffset(scroll_offset_delegate_->GetCurrentScrollOffset()));
- }
-}
-
gfx::ScrollOffset LayerImpl::CurrentScrollOffset() const {
return scroll_offset_->Current(IsActive());
}
@@ -1203,16 +1183,12 @@ void LayerImpl::PushScrollOffset(const gfx::ScrollOffset* scroll_offset) {
}
if (changed)
- DidUpdateScrollOffset();
+ DidUpdateScrollOffset(false);
}
-void LayerImpl::DidUpdateScrollOffset() {
- if (scroll_offset_delegate_) {
- scroll_offset_delegate_->SetCurrentScrollOffset(CurrentScrollOffset());
- scroll_offset_delegate_->Update();
- RefreshFromScrollDelegate();
- }
-
+void LayerImpl::DidUpdateScrollOffset(bool is_from_root_delegate) {
+ if (!is_from_root_delegate)
+ layer_tree_impl()->DidUpdateScrollOffset(id());
NoteLayerPropertyChangedForSubtree();
ScrollbarParametersDidChange(false);
}
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index b13dce9..2cfa040 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -80,16 +80,6 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
public LayerAnimationValueProvider,
public AnimationDelegate {
public:
- // Allows for the ownership of the total scroll offset to be delegated outside
- // of the layer.
- class ScrollOffsetDelegate {
- public:
- virtual void SetCurrentScrollOffset(const gfx::ScrollOffset& new_value) = 0;
- virtual gfx::ScrollOffset GetCurrentScrollOffset() = 0;
- virtual bool IsExternalFlingActive() const = 0;
- virtual void Update() const = 0;
- };
-
typedef SyncedProperty<AdditionGroup<gfx::ScrollOffset>> SyncedScrollOffset;
typedef LayerImplList RenderSurfaceListType;
typedef LayerImplList LayerListType;
@@ -390,11 +380,11 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
float contents_scale_y() const { return draw_properties_.contents_scale_y; }
void SetContentsScale(float contents_scale_x, float contents_scale_y);
- void SetScrollOffsetDelegate(ScrollOffsetDelegate* scroll_offset_delegate);
- void RefreshFromScrollDelegate();
bool IsExternalFlingActive() const;
void SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset);
+ void SetCurrentScrollOffsetFromDelegate(
+ const gfx::ScrollOffset& scroll_offset);
void PushScrollOffsetFromMainThread(const gfx::ScrollOffset& scroll_offset);
// This method is similar to PushScrollOffsetFromMainThread but will cause the
// scroll offset given to clobber any scroll changes on the active tree in the
@@ -636,7 +626,10 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
private:
void PushScrollOffset(const gfx::ScrollOffset* scroll_offset);
- void DidUpdateScrollOffset();
+ // If the new scroll offset is assigned from the root scroll offset delegate,
+ // LayerImpl won't inform the root scroll offset delegate about the scroll
+ // change to avoid feedback.
+ void DidUpdateScrollOffset(bool is_from_root_delegate);
void NoteLayerPropertyChangedForDescendantsInternal();
virtual const char* LayerTypeAsString() const;
@@ -672,7 +665,6 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
// Properties synchronized from the associated Layer.
gfx::Point3F transform_origin_;
gfx::Size bounds_;
- ScrollOffsetDelegate* scroll_offset_delegate_;
LayerImpl* scroll_clip_layer_;
bool scrollable_ : 1;
bool should_scroll_on_main_thread_ : 1;
diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc
index 1cdbd59..d9811bc 100644
--- a/cc/layers/layer_impl_unittest.cc
+++ b/cc/layers/layer_impl_unittest.cc
@@ -516,112 +516,7 @@ TEST_F(LayerImplScrollTest, ScrollByWithNonZeroOffset) {
EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
}
-class ScrollDelegateIgnore : public LayerImpl::ScrollOffsetDelegate {
- public:
- void SetCurrentScrollOffset(const gfx::ScrollOffset& new_value) override {
- last_attempted_set_offset_ = new_value;
- }
- gfx::ScrollOffset last_attempted_set_offset() const {
- return last_attempted_set_offset_;
- }
-
- gfx::ScrollOffset GetCurrentScrollOffset() override {
- return gfx::ScrollOffset(fixed_offset_);
- }
- bool IsExternalFlingActive() const override { return false; }
- void Update() const override { }
-
- void set_fixed_offset(const gfx::Vector2dF& fixed_offset) {
- fixed_offset_ = fixed_offset;
- }
-
- private:
- gfx::ScrollOffset last_attempted_set_offset_;
- gfx::Vector2dF fixed_offset_;
-};
-
-TEST_F(LayerImplScrollTest, ScrollByWithIgnoringDelegate) {
- gfx::ScrollOffset scroll_offset(10, 5);
- layer()->PushScrollOffsetFromMainThread(scroll_offset);
-
- EXPECT_VECTOR_EQ(scroll_offset, layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
- EXPECT_VECTOR_EQ(gfx::Vector2dF(), layer()->ScrollDelta());
-
- ScrollDelegateIgnore delegate;
- gfx::Vector2dF fixed_offset(32, 12);
- delegate.set_fixed_offset(fixed_offset);
- layer()->SetScrollOffsetDelegate(&delegate);
- layer()->RefreshFromScrollDelegate();
-
- EXPECT_VECTOR_EQ(fixed_offset, layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
-
- layer()->ScrollBy(gfx::Vector2dF(-100, 100));
-
- EXPECT_VECTOR_EQ(fixed_offset, layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
-
- layer()->SetScrollOffsetDelegate(nullptr);
-
- EXPECT_VECTOR_EQ(fixed_offset, layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
-
- gfx::Vector2dF scroll_delta(1, 1);
- layer()->ScrollBy(scroll_delta);
-
- EXPECT_VECTOR_EQ(fixed_offset + scroll_delta, layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
-}
-
-class ScrollDelegateAccept : public LayerImpl::ScrollOffsetDelegate {
- public:
- void SetCurrentScrollOffset(const gfx::ScrollOffset& new_value) override {
- current_offset_ = new_value;
- }
- gfx::ScrollOffset GetCurrentScrollOffset() override {
- return current_offset_;
- }
- bool IsExternalFlingActive() const override { return false; }
- void Update() const override { }
-
- private:
- gfx::ScrollOffset current_offset_;
-};
-
-TEST_F(LayerImplScrollTest, ScrollByWithAcceptingDelegate) {
- gfx::ScrollOffset scroll_offset(10, 5);
- layer()->PushScrollOffsetFromMainThread(scroll_offset);
-
- EXPECT_VECTOR_EQ(scroll_offset, layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
- EXPECT_VECTOR_EQ(gfx::Vector2dF(), layer()->ScrollDelta());
-
- ScrollDelegateAccept delegate;
- layer()->SetScrollOffsetDelegate(&delegate);
-
- EXPECT_VECTOR_EQ(scroll_offset, layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
- EXPECT_VECTOR_EQ(gfx::Vector2dF(), layer()->ScrollDelta());
-
- layer()->ScrollBy(gfx::Vector2dF(-100, 100));
-
- EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 80), layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
-
- layer()->SetScrollOffsetDelegate(nullptr);
-
- EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 80), layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
-
- gfx::Vector2dF scroll_delta(1, 1);
- layer()->ScrollBy(scroll_delta);
-
- EXPECT_VECTOR_EQ(gfx::Vector2dF(1, 80), layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
-}
-
-TEST_F(LayerImplScrollTest, ApplySentScrollsNoDelegate) {
+TEST_F(LayerImplScrollTest, ApplySentScrollsNoListener) {
gfx::ScrollOffset scroll_offset(10, 5);
gfx::Vector2dF scroll_delta(20.5f, 8.5f);
gfx::Vector2d sent_scroll_delta(12, -3);
@@ -646,57 +541,6 @@ TEST_F(LayerImplScrollTest, ApplySentScrollsNoDelegate) {
layer()->BaseScrollOffset());
}
-TEST_F(LayerImplScrollTest, ApplySentScrollsWithIgnoringDelegate) {
- gfx::ScrollOffset scroll_offset(10, 5);
- gfx::Vector2d sent_scroll_delta(12, -3);
- gfx::Vector2dF fixed_offset(32, 12);
-
- layer()->PushScrollOffsetFromMainThread(scroll_offset);
- layer()->ScrollBy(sent_scroll_delta);
- layer()->PullDeltaForMainThread();
- layer()->SetCurrentScrollOffset(scroll_offset);
- ScrollDelegateIgnore delegate;
- delegate.set_fixed_offset(fixed_offset);
- layer()->SetScrollOffsetDelegate(&delegate);
- layer()->RefreshFromScrollDelegate();
-
- EXPECT_VECTOR_EQ(fixed_offset, layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
-
- layer()->ApplySentScrollDeltasFromAbortedCommit();
-
- EXPECT_VECTOR_EQ(fixed_offset, delegate.last_attempted_set_offset());
-
- EXPECT_VECTOR_EQ(fixed_offset, layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(scroll_offset, sent_scroll_delta),
- layer()->BaseScrollOffset());
-}
-
-TEST_F(LayerImplScrollTest, ApplySentScrollsWithAcceptingDelegate) {
- gfx::ScrollOffset scroll_offset(10, 5);
- gfx::Vector2d sent_scroll_delta(12, -3);
- gfx::Vector2dF scroll_delta(20.5f, 8.5f);
-
- layer()->PushScrollOffsetFromMainThread(scroll_offset);
- layer()->ScrollBy(sent_scroll_delta);
- layer()->PullDeltaForMainThread();
- ScrollDelegateAccept delegate;
- layer()->SetScrollOffsetDelegate(&delegate);
- layer()->SetCurrentScrollOffset(scroll_offset +
- gfx::ScrollOffset(scroll_delta));
-
- EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(scroll_offset, scroll_delta),
- layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(scroll_offset, layer()->BaseScrollOffset());
-
- layer()->ApplySentScrollDeltasFromAbortedCommit();
-
- EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(scroll_offset, scroll_delta),
- layer()->CurrentScrollOffset());
- EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(scroll_offset, sent_scroll_delta),
- layer()->BaseScrollOffset());
-}
-
TEST_F(LayerImplScrollTest, ScrollUserUnscrollableLayer) {
gfx::ScrollOffset scroll_offset(10, 5);
gfx::Vector2dF scroll_delta(20.5f, 8.5f);
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index a29b9a5..56539d1 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2761,9 +2761,9 @@ void LayerTreeHostImpl::SetRootLayerScrollOffsetDelegate(
void LayerTreeHostImpl::OnRootLayerDelegatedScrollOffsetChanged() {
DCHECK(root_layer_scroll_offset_delegate_);
+ active_tree_->DistributeRootScrollOffset();
client_->SetNeedsCommitOnImplThread();
SetNeedsRedraw();
- active_tree_->OnRootLayerDelegatedScrollOffsetChanged();
active_tree_->set_needs_update_draw_properties();
}
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 979f1a9..442162d 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -224,9 +224,16 @@ class LayerTreeHostImplTest : public testing::Test,
LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
const gfx::Size& content_size) {
+ // Create both an inner viewport scroll layer and an outer viewport scroll
+ // layer. The MaxScrollOffset of the outer viewport scroll layer will be
+ // 0x0, so the scrolls will be applied directly to the inner viewport.
+ const int kOuterViewportClipLayerId = 116;
+ const int kOuterViewportScrollLayerId = 117;
+ const int kContentLayerId = 118;
const int kInnerViewportScrollLayerId = 2;
const int kInnerViewportClipLayerId = 4;
const int kPageScaleLayerId = 5;
+
scoped_ptr<LayerImpl> root =
LayerImpl::Create(layer_tree_impl, 1);
root->SetBounds(content_size);
@@ -234,44 +241,58 @@ class LayerTreeHostImplTest : public testing::Test,
root->SetPosition(gfx::PointF());
root->SetHasRenderSurface(true);
- scoped_ptr<LayerImpl> scroll =
+ scoped_ptr<LayerImpl> inner_scroll =
LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
- LayerImpl* scroll_layer = scroll.get();
- scroll->SetIsContainerForFixedPositionLayers(true);
- scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
+ inner_scroll->SetIsContainerForFixedPositionLayers(true);
+ inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
- scoped_ptr<LayerImpl> clip =
+ scoped_ptr<LayerImpl> inner_clip =
LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
- clip->SetBounds(
+ inner_clip->SetBounds(
gfx::Size(content_size.width() / 2, content_size.height() / 2));
scoped_ptr<LayerImpl> page_scale =
LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
- scroll->SetScrollClipLayer(clip->id());
- scroll->SetBounds(content_size);
- scroll->SetContentBounds(content_size);
- scroll->SetPosition(gfx::PointF());
- scroll->SetIsContainerForFixedPositionLayers(true);
+ inner_scroll->SetScrollClipLayer(inner_clip->id());
+ inner_scroll->SetBounds(content_size);
+ inner_scroll->SetContentBounds(content_size);
+ inner_scroll->SetPosition(gfx::PointF());
+
+ scoped_ptr<LayerImpl> outer_clip =
+ LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
+ outer_clip->SetBounds(content_size);
+ outer_clip->SetIsContainerForFixedPositionLayers(true);
+
+ scoped_ptr<LayerImpl> outer_scroll =
+ LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
+ outer_scroll->SetScrollClipLayer(outer_clip->id());
+ outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
+ outer_scroll->SetBounds(content_size);
+ outer_scroll->SetContentBounds(content_size);
+ outer_scroll->SetPosition(gfx::PointF());
scoped_ptr<LayerImpl> contents =
- LayerImpl::Create(layer_tree_impl, 3);
+ LayerImpl::Create(layer_tree_impl, kContentLayerId);
contents->SetDrawsContent(true);
contents->SetBounds(content_size);
contents->SetContentBounds(content_size);
contents->SetPosition(gfx::PointF());
- scroll->AddChild(contents.Pass());
- page_scale->AddChild(scroll.Pass());
- clip->AddChild(page_scale.Pass());
- root->AddChild(clip.Pass());
+ outer_scroll->AddChild(contents.Pass());
+ outer_clip->AddChild(outer_scroll.Pass());
+ inner_scroll->AddChild(outer_clip.Pass());
+ page_scale->AddChild(inner_scroll.Pass());
+ inner_clip->AddChild(page_scale.Pass());
+ root->AddChild(inner_clip.Pass());
layer_tree_impl->SetRootLayer(root.Pass());
layer_tree_impl->SetViewportLayersFromIds(
Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
- Layer::INVALID_ID);
+ kOuterViewportScrollLayerId);
- return scroll_layer;
+ layer_tree_impl->DidBecomeActive();
+ return layer_tree_impl->InnerViewportScrollLayer();
}
LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
@@ -1847,10 +1868,11 @@ TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
}
- // Root "overflow: hidden" properties should be reflected.
+ // Root "overflow: hidden" properties should be reflected on the outer
+ // viewport scroll layer.
{
host_impl_->active_tree()
- ->InnerViewportScrollLayer()
+ ->OuterViewportScrollLayer()
->set_user_scrollable_horizontal(false);
CompositorFrameMetadata metadata =
host_impl_->MakeCompositorFrameMetadata();
@@ -1858,7 +1880,7 @@ TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
EXPECT_FALSE(metadata.root_overflow_y_hidden);
host_impl_->active_tree()
- ->InnerViewportScrollLayer()
+ ->OuterViewportScrollLayer()
->set_user_scrollable_vertical(false);
metadata = host_impl_->MakeCompositorFrameMetadata();
EXPECT_TRUE(metadata.root_overflow_x_hidden);
@@ -3972,6 +3994,7 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
scroll_delegate.set_getter_return_value(current_offset);
EXPECT_EQ(InputHandler::SCROLL_STARTED,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
+ host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
@@ -3979,11 +4002,13 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
current_offset = gfx::ScrollOffset(42.f, 41.f);
scroll_delegate.set_getter_return_value(current_offset);
+ host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
scroll_delegate.last_set_scroll_offset());
host_impl_->ScrollEnd();
scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
+ host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
// Forces a full tree synchronization and ensures that the scroll delegate
// sees the correct size of the new tree.
@@ -3997,6 +4022,7 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
// the root scrollable layer.
current_offset = gfx::ScrollOffset(13.f, 12.f);
scroll_delegate.set_getter_return_value(current_offset);
+ host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
EXPECT_EQ(current_offset.ToString(),
@@ -7866,6 +7892,41 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
}
};
+TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) {
+ gfx::Size content_size = gfx::Size(100, 160);
+ gfx::Size outer_viewport = gfx::Size(50, 80);
+ gfx::Size inner_viewport = gfx::Size(25, 40);
+
+ SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
+
+ TestScrollOffsetDelegate scroll_delegate;
+ host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
+
+ LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
+ LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
+ DrawFrame();
+ {
+ gfx::ScrollOffset inner_expected;
+ gfx::ScrollOffset outer_expected;
+ EXPECT_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
+ EXPECT_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
+
+ gfx::ScrollOffset current_offset(70.f, 100.f);
+
+ scroll_delegate.set_getter_return_value(current_offset);
+ host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
+ EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->MaxScrollOffset());
+ EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), outer_scroll->MaxScrollOffset());
+
+ // Outer viewport scrolls first. Then the rest is applied to the inner
+ // viewport.
+ EXPECT_EQ(gfx::ScrollOffset(20.f, 20.f),
+ inner_scroll->CurrentScrollOffset());
+ EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f),
+ outer_scroll->CurrentScrollOffset());
+ }
+}
+
TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
gfx::Size content_size = gfx::Size(100, 160);
gfx::Size outer_viewport = gfx::Size(50, 80);
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index c2edaae..b831bb38 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -8,6 +8,7 @@
#include <limits>
#include <set>
+#include "base/auto_reset.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
#include "cc/animation/keyframed_animation_curve.h"
@@ -19,6 +20,7 @@
#include "cc/base/util.h"
#include "cc/debug/devtools_instrumentation.h"
#include "cc/debug/traced_value.h"
+#include "cc/input/layer_scroll_offset_delegate.h"
#include "cc/input/page_scale_animation.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/layer.h"
@@ -34,44 +36,6 @@
#include "ui/gfx/geometry/vector2d_conversions.h"
namespace cc {
-// This class exists to split the LayerScrollOffsetDelegate between the
-// InnerViewportScrollLayer and the OuterViewportScrollLayer in a manner
-// that never requires the embedder or LayerImpl to know about.
-class LayerScrollOffsetDelegateProxy : public LayerImpl::ScrollOffsetDelegate {
- public:
- LayerScrollOffsetDelegateProxy(LayerImpl* layer,
- LayerScrollOffsetDelegate* delegate,
- LayerTreeImpl* layer_tree)
- : layer_(layer), delegate_(delegate), layer_tree_impl_(layer_tree) {}
- virtual ~LayerScrollOffsetDelegateProxy() {}
-
- gfx::ScrollOffset last_set_scroll_offset() const {
- return last_set_scroll_offset_;
- }
-
- // LayerScrollOffsetDelegate implementation.
- void SetCurrentScrollOffset(const gfx::ScrollOffset& new_offset) override {
- last_set_scroll_offset_ = new_offset;
- }
-
- gfx::ScrollOffset GetCurrentScrollOffset() override {
- return layer_tree_impl_->GetDelegatedScrollOffset(layer_);
- }
-
- bool IsExternalFlingActive() const override {
- return delegate_->IsExternalFlingActive();
- }
-
- void Update() const override {
- layer_tree_impl_->UpdateScrollOffsetDelegate();
- }
-
- private:
- LayerImpl* layer_;
- LayerScrollOffsetDelegate* delegate_;
- LayerTreeImpl* layer_tree_impl_;
- gfx::ScrollOffset last_set_scroll_offset_;
-};
LayerTreeImpl::LayerTreeImpl(
LayerTreeHostImpl* layer_tree_host_impl,
@@ -148,14 +112,28 @@ void LayerTreeImpl::GatherFrameTimingRequestIds(
});
}
-void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) {
- if (inner_viewport_scroll_layer_)
- inner_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL);
- if (outer_viewport_scroll_layer_)
- outer_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL);
- inner_viewport_scroll_delegate_proxy_ = nullptr;
- outer_viewport_scroll_delegate_proxy_ = nullptr;
+bool LayerTreeImpl::IsExternalFlingActive() const {
+ return root_layer_scroll_offset_delegate_ &&
+ root_layer_scroll_offset_delegate_->IsExternalFlingActive();
+}
+
+void LayerTreeImpl::DidUpdateScrollOffset(int layer_id) {
+ int inner_layer_id = InnerViewportScrollLayer()
+ ? InnerViewportScrollLayer()->id()
+ : Layer::INVALID_ID;
+ int outer_layer_id = OuterViewportScrollLayer()
+ ? OuterViewportScrollLayer()->id()
+ : Layer::INVALID_ID;
+ if (layer_id != outer_layer_id && layer_id != inner_layer_id)
+ return;
+
+ if (!root_layer_scroll_offset_delegate_)
+ return;
+ UpdateRootScrollOffsetDelegate();
+}
+
+void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) {
root_layer_ = layer.Pass();
currently_scrolling_layer_ = NULL;
inner_viewport_scroll_layer_ = NULL;
@@ -201,12 +179,6 @@ scoped_ptr<LayerImpl> LayerTreeImpl::DetachLayerTree() {
// Clear all data structures that have direct references to the layer tree.
scrolling_layer_id_from_previous_tree_ =
currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0;
- if (inner_viewport_scroll_layer_)
- inner_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL);
- if (outer_viewport_scroll_layer_)
- outer_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL);
- inner_viewport_scroll_delegate_proxy_ = nullptr;
- outer_viewport_scroll_delegate_proxy_ = nullptr;
inner_viewport_scroll_layer_ = NULL;
outer_viewport_scroll_layer_ = NULL;
page_scale_layer_ = NULL;
@@ -531,17 +503,6 @@ void LayerTreeImpl::SetViewportLayersFromIds(
if (!root_layer_scroll_offset_delegate_)
return;
-
- inner_viewport_scroll_delegate_proxy_ = make_scoped_ptr(
- new LayerScrollOffsetDelegateProxy(inner_viewport_scroll_layer_,
- root_layer_scroll_offset_delegate_,
- this));
-
- if (outer_viewport_scroll_layer_)
- outer_viewport_scroll_delegate_proxy_ = make_scoped_ptr(
- new LayerScrollOffsetDelegateProxy(outer_viewport_scroll_layer_,
- root_layer_scroll_offset_delegate_,
- this));
}
void LayerTreeImpl::ClearViewportLayers() {
@@ -1040,17 +1001,6 @@ void LayerTreeImpl::SetRootLayerScrollOffsetDelegate(
if (root_layer_scroll_offset_delegate_ == root_layer_scroll_offset_delegate)
return;
- if (!root_layer_scroll_offset_delegate) {
- // Make sure we remove the proxies from their layers before
- // releasing them.
- if (InnerViewportScrollLayer())
- InnerViewportScrollLayer()->SetScrollOffsetDelegate(NULL);
- if (OuterViewportScrollLayer())
- OuterViewportScrollLayer()->SetScrollOffsetDelegate(NULL);
- inner_viewport_scroll_delegate_proxy_ = nullptr;
- outer_viewport_scroll_delegate_proxy_ = nullptr;
- }
-
root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate;
if (root_layer_scroll_offset_delegate_) {
@@ -1059,54 +1009,17 @@ void LayerTreeImpl::SetRootLayerScrollOffsetDelegate(
current_page_scale_factor(), min_page_scale_factor(),
max_page_scale_factor());
- if (inner_viewport_scroll_layer_) {
- inner_viewport_scroll_delegate_proxy_ = make_scoped_ptr(
- new LayerScrollOffsetDelegateProxy(InnerViewportScrollLayer(),
- root_layer_scroll_offset_delegate_,
- this));
- inner_viewport_scroll_layer_->SetScrollOffsetDelegate(
- inner_viewport_scroll_delegate_proxy_.get());
- }
-
- if (outer_viewport_scroll_layer_) {
- outer_viewport_scroll_delegate_proxy_ = make_scoped_ptr(
- new LayerScrollOffsetDelegateProxy(OuterViewportScrollLayer(),
- root_layer_scroll_offset_delegate_,
- this));
- outer_viewport_scroll_layer_->SetScrollOffsetDelegate(
- outer_viewport_scroll_delegate_proxy_.get());
- }
-
- if (inner_viewport_scroll_layer_)
- inner_viewport_scroll_layer_->RefreshFromScrollDelegate();
- if (outer_viewport_scroll_layer_)
- outer_viewport_scroll_layer_->RefreshFromScrollDelegate();
-
- if (inner_viewport_scroll_layer_)
- UpdateScrollOffsetDelegate();
- }
-}
-
-void LayerTreeImpl::OnRootLayerDelegatedScrollOffsetChanged() {
- DCHECK(root_layer_scroll_offset_delegate_);
- if (inner_viewport_scroll_layer_) {
- inner_viewport_scroll_layer_->RefreshFromScrollDelegate();
- }
- if (outer_viewport_scroll_layer_) {
- outer_viewport_scroll_layer_->RefreshFromScrollDelegate();
+ DistributeRootScrollOffset();
}
}
-void LayerTreeImpl::UpdateScrollOffsetDelegate() {
- DCHECK(InnerViewportScrollLayer());
- DCHECK(!OuterViewportScrollLayer() || outer_viewport_scroll_delegate_proxy_);
+void LayerTreeImpl::UpdateRootScrollOffsetDelegate() {
DCHECK(root_layer_scroll_offset_delegate_);
- gfx::ScrollOffset offset =
- inner_viewport_scroll_delegate_proxy_->last_set_scroll_offset();
+ gfx::ScrollOffset offset = InnerViewportScrollLayer()->CurrentScrollOffset();
if (OuterViewportScrollLayer())
- offset += outer_viewport_scroll_delegate_proxy_->last_set_scroll_offset();
+ offset += OuterViewportScrollLayer()->CurrentScrollOffset();
root_layer_scroll_offset_delegate_->UpdateRootLayerState(
offset, TotalMaxScrollOffset(), ScrollableSize(),
@@ -1114,44 +1027,43 @@ void LayerTreeImpl::UpdateScrollOffsetDelegate() {
max_page_scale_factor());
}
-gfx::ScrollOffset LayerTreeImpl::GetDelegatedScrollOffset(LayerImpl* layer) {
- DCHECK(root_layer_scroll_offset_delegate_);
- DCHECK(InnerViewportScrollLayer());
- if (layer == InnerViewportScrollLayer() && !OuterViewportScrollLayer())
- return root_layer_scroll_offset_delegate_->GetTotalScrollOffset();
+void LayerTreeImpl::DistributeRootScrollOffset() {
+ if (!root_layer_scroll_offset_delegate_)
+ return;
+
+ gfx::ScrollOffset root_offset =
+ root_layer_scroll_offset_delegate_->GetTotalScrollOffset();
+
+ if (!InnerViewportScrollLayer())
+ return;
+
+ DCHECK(OuterViewportScrollLayer());
// If we get here, we have both inner/outer viewports, and need to distribute
// the scroll offset between them.
- DCHECK(inner_viewport_scroll_delegate_proxy_);
- DCHECK(outer_viewport_scroll_delegate_proxy_);
gfx::ScrollOffset inner_viewport_offset =
- inner_viewport_scroll_delegate_proxy_->last_set_scroll_offset();
+ InnerViewportScrollLayer()->CurrentScrollOffset();
gfx::ScrollOffset outer_viewport_offset =
- outer_viewport_scroll_delegate_proxy_->last_set_scroll_offset();
+ OuterViewportScrollLayer()->CurrentScrollOffset();
// It may be nothing has changed.
- gfx::ScrollOffset delegate_offset =
- root_layer_scroll_offset_delegate_->GetTotalScrollOffset();
- if (inner_viewport_offset + outer_viewport_offset == delegate_offset) {
- if (layer == InnerViewportScrollLayer())
- return inner_viewport_offset;
- else
- return outer_viewport_offset;
- }
+ if (inner_viewport_offset + outer_viewport_offset == root_offset)
+ return;
gfx::ScrollOffset max_outer_viewport_scroll_offset =
OuterViewportScrollLayer()->MaxScrollOffset();
- outer_viewport_offset = delegate_offset - inner_viewport_offset;
+ outer_viewport_offset = root_offset - inner_viewport_offset;
outer_viewport_offset.SetToMin(max_outer_viewport_scroll_offset);
outer_viewport_offset.SetToMax(gfx::ScrollOffset());
- if (layer == OuterViewportScrollLayer())
- return outer_viewport_offset;
-
- inner_viewport_offset = delegate_offset - outer_viewport_offset;
+ OuterViewportScrollLayer()->SetCurrentScrollOffsetFromDelegate(
+ outer_viewport_offset);
+ inner_viewport_offset = root_offset - outer_viewport_offset;
+ InnerViewportScrollLayer()->SetCurrentScrollOffsetFromDelegate(
+ inner_viewport_offset);
- return inner_viewport_offset;
+ UpdateRootScrollOffsetDelegate();
}
void LayerTreeImpl::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) {
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 8ab4263..70f9809 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -33,7 +33,8 @@ class ContextProvider;
class DebugRectHistory;
class FrameRateCounter;
class HeadsUpDisplayLayerImpl;
-class LayerScrollOffsetDelegateProxy;
+class LayerExternalScrollOffsetListener;
+class LayerScrollOffsetDelegate;
class LayerTreeDebugState;
class LayerTreeImpl;
class LayerTreeSettings;
@@ -263,9 +264,10 @@ class CC_EXPORT LayerTreeImpl {
void SetRootLayerScrollOffsetDelegate(
LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate);
- void OnRootLayerDelegatedScrollOffsetChanged();
- void UpdateScrollOffsetDelegate();
- gfx::ScrollOffset GetDelegatedScrollOffset(LayerImpl* layer);
+ void UpdateRootScrollOffsetDelegate();
+ // Distribute the rool scroll between outer and inner viewport scroll layer.
+ // The outer viewport scroll layer scrolls first.
+ void DistributeRootScrollOffset();
// Call this function when you expect there to be a swap buffer.
// See swap_promise.h for how to use SwapPromise.
@@ -334,6 +336,9 @@ class CC_EXPORT LayerTreeImpl {
void GatherFrameTimingRequestIds(std::vector<int64_t>* request_ids);
+ bool IsExternalFlingActive() const;
+ void DidUpdateScrollOffset(int layer_id);
+
protected:
explicit LayerTreeImpl(
LayerTreeHostImpl* layer_tree_host_impl,
@@ -355,10 +360,6 @@ class CC_EXPORT LayerTreeImpl {
HeadsUpDisplayLayerImpl* hud_layer_;
LayerImpl* currently_scrolling_layer_;
LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate_;
- scoped_ptr<LayerScrollOffsetDelegateProxy>
- inner_viewport_scroll_delegate_proxy_;
- scoped_ptr<LayerScrollOffsetDelegateProxy>
- outer_viewport_scroll_delegate_proxy_;
SkColor background_color_;
bool has_transparent_background_;