diff options
-rw-r--r-- | cc/layers/layer_impl.cc | 50 | ||||
-rw-r--r-- | cc/layers/layer_impl.h | 20 | ||||
-rw-r--r-- | cc/layers/layer_impl_unittest.cc | 158 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.cc | 2 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl_unittest.cc | 103 | ||||
-rw-r--r-- | cc/trees/layer_tree_impl.cc | 186 | ||||
-rw-r--r-- | cc/trees/layer_tree_impl.h | 17 |
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_; |