Chromium Code Reviews| Index: cc/trees/layer_tree_impl.cc |
| diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc |
| index c2edaae65d308c7b3eca5b5b5607288d99012da5..8dfa560b66ea2218facc9ca7539ac369b13e3d88 100644 |
| --- a/cc/trees/layer_tree_impl.cc |
| +++ b/cc/trees/layer_tree_impl.cc |
| @@ -19,6 +19,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,43 +35,29 @@ |
| #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_); |
| - } |
| +// This class listens to the scroll offset changes of inner and outer viewport |
| +// scroll layer. When they change, the root layer scroll offset delegate needs |
| +// to be updated accordingly. |
| +class LayerExternalScrollOffsetListener |
| + : public LayerImpl::ExternalScrollOffsetListener { |
| + public: |
| + LayerExternalScrollOffsetListener(LayerScrollOffsetDelegate* delegate, |
| + LayerTreeImpl* layer_tree) |
| + : root_delegate_(delegate), layer_tree_impl_(layer_tree) {} |
| + virtual ~LayerExternalScrollOffsetListener() {} |
| bool IsExternalFlingActive() const override { |
| - return delegate_->IsExternalFlingActive(); |
| + return root_delegate_->IsExternalFlingActive(); |
| } |
| - void Update() const override { |
| - layer_tree_impl_->UpdateScrollOffsetDelegate(); |
| + void DidUpdateScrollOffset() const override { |
| + layer_tree_impl_->UpdateRootScrollOffsetDelegate(); |
| } |
| private: |
| - LayerImpl* layer_; |
| - LayerScrollOffsetDelegate* delegate_; |
| + LayerScrollOffsetDelegate* root_delegate_; |
| LayerTreeImpl* layer_tree_impl_; |
| - gfx::ScrollOffset last_set_scroll_offset_; |
| }; |
| LayerTreeImpl::LayerTreeImpl( |
| @@ -150,11 +137,10 @@ void LayerTreeImpl::GatherFrameTimingRequestIds( |
| void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) { |
| if (inner_viewport_scroll_layer_) |
| - inner_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL); |
| + inner_viewport_scroll_layer_->SetExternalScrollOffsetListener(NULL); |
| if (outer_viewport_scroll_layer_) |
| - outer_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL); |
| - inner_viewport_scroll_delegate_proxy_ = nullptr; |
| - outer_viewport_scroll_delegate_proxy_ = nullptr; |
| + outer_viewport_scroll_layer_->SetExternalScrollOffsetListener(NULL); |
| + layer_scroll_offset_listener_ = nullptr; |
| root_layer_ = layer.Pass(); |
| currently_scrolling_layer_ = NULL; |
| @@ -202,11 +188,10 @@ scoped_ptr<LayerImpl> LayerTreeImpl::DetachLayerTree() { |
| 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); |
| + inner_viewport_scroll_layer_->SetExternalScrollOffsetListener(NULL); |
| if (outer_viewport_scroll_layer_) |
| - outer_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL); |
| - inner_viewport_scroll_delegate_proxy_ = nullptr; |
| - outer_viewport_scroll_delegate_proxy_ = nullptr; |
| + outer_viewport_scroll_layer_->SetExternalScrollOffsetListener(NULL); |
| + layer_scroll_offset_listener_ = nullptr; |
| inner_viewport_scroll_layer_ = NULL; |
| outer_viewport_scroll_layer_ = NULL; |
| page_scale_layer_ = NULL; |
| @@ -532,16 +517,9 @@ 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)); |
| + layer_scroll_offset_listener_ = |
| + make_scoped_ptr(new LayerExternalScrollOffsetListener( |
| + root_layer_scroll_offset_delegate_, this)); |
| } |
| void LayerTreeImpl::ClearViewportLayers() { |
| @@ -1044,11 +1022,10 @@ void LayerTreeImpl::SetRootLayerScrollOffsetDelegate( |
| // Make sure we remove the proxies from their layers before |
| // releasing them. |
| if (InnerViewportScrollLayer()) |
| - InnerViewportScrollLayer()->SetScrollOffsetDelegate(NULL); |
| + InnerViewportScrollLayer()->SetExternalScrollOffsetListener(NULL); |
| if (OuterViewportScrollLayer()) |
| - OuterViewportScrollLayer()->SetScrollOffsetDelegate(NULL); |
| - inner_viewport_scroll_delegate_proxy_ = nullptr; |
| - outer_viewport_scroll_delegate_proxy_ = nullptr; |
| + OuterViewportScrollLayer()->SetExternalScrollOffsetListener(NULL); |
| + layer_scroll_offset_listener_ = nullptr; |
| } |
| root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate; |
| @@ -1059,54 +1036,31 @@ void LayerTreeImpl::SetRootLayerScrollOffsetDelegate( |
| current_page_scale_factor(), min_page_scale_factor(), |
| max_page_scale_factor()); |
| + layer_scroll_offset_listener_ = |
| + make_scoped_ptr(new LayerExternalScrollOffsetListener( |
| + root_layer_scroll_offset_delegate_, this)); |
| + |
| 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()); |
| + inner_viewport_scroll_layer_->SetExternalScrollOffsetListener( |
| + layer_scroll_offset_listener_.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()); |
| + outer_viewport_scroll_layer_->SetExternalScrollOffsetListener( |
| + layer_scroll_offset_listener_.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 +1068,61 @@ 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; |
| + |
| + if (!OuterViewportScrollLayer()) { |
|
aelias_OOO_until_Jul13
2015/04/06 19:57:32
You can delete this block and DCHECK that an Outer
hush (inactive)
2015/04/06 23:08:03
The tests are exercising the InnerViewportScrollLa
|
| + InnerViewportScrollLayer()->SetExternalScrollOffsetListener(NULL); |
| + InnerViewportScrollLayer()->SetCurrentScrollOffset(root_offset); |
| + InnerViewportScrollLayer()->SetExternalScrollOffsetListener( |
| + layer_scroll_offset_listener_.get()); |
| + UpdateRootScrollOffsetDelegate(); |
| + return; |
| + } |
| // 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_); |
| + // It is okay for inner and outer viewport scroll layer to have no scroll |
| + // delegate at this time. |
| 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; |
| + |
| + // Temporarily uninstall the scroll offset listeners so that the root scroll |
| + // offset delegate is not thrashed back and forth when the inner and outer |
| + // viewport scroll layer change their scroll offsets. |
| + InnerViewportScrollLayer()->SetExternalScrollOffsetListener(NULL); |
| + OuterViewportScrollLayer()->SetExternalScrollOffsetListener(NULL); |
| 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; |
| + OuterViewportScrollLayer()->SetCurrentScrollOffset(outer_viewport_offset); |
| + inner_viewport_offset = root_offset - outer_viewport_offset; |
| + InnerViewportScrollLayer()->SetCurrentScrollOffset(inner_viewport_offset); |
| - inner_viewport_offset = delegate_offset - outer_viewport_offset; |
| + InnerViewportScrollLayer()->SetExternalScrollOffsetListener( |
| + layer_scroll_offset_listener_.get()); |
| + OuterViewportScrollLayer()->SetExternalScrollOffsetListener( |
| + layer_scroll_offset_listener_.get()); |
| - return inner_viewport_offset; |
| + UpdateRootScrollOffsetDelegate(); |
| } |
| void LayerTreeImpl::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) { |