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) { |