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 2d83af093989089e1fc5ccfb4e3ea20db6e51cb3..52643e4066c7086ad84b2d3c8030b21c0fda8b9d 100644 |
| --- a/cc/trees/layer_tree_impl.cc |
| +++ b/cc/trees/layer_tree_impl.cc |
| @@ -22,11 +22,57 @@ |
| namespace cc { |
| +class LayerScrollOffsetDelegateProxy : public LayerScrollOffsetDelegate { |
| + public: |
| + LayerScrollOffsetDelegateProxy(LayerImpl* layer, |
| + LayerScrollOffsetDelegate* delegate, |
| + LayerTreeImpl* layer_tree) |
| + : layer_(layer), |
| + delegate_(delegate), |
| + layer_tree_impl_(layer_tree) {} |
| + |
| + gfx::Vector2dF last_set_scroll_offset() const { |
| + return last_set_scroll_offset_; |
| + } |
| + |
| + // LayerScrollOffsetDelegate implementation. |
| + |
| + virtual void SetMaxScrollOffset(gfx::Vector2dF) OVERRIDE { |
| + NOTIMPLEMENTED(); |
| + } |
| + |
| + virtual void SetTotalScrollOffset(gfx::Vector2dF new_offset) OVERRIDE { |
| + last_set_scroll_offset_ = new_offset; |
| + layer_tree_impl_->UpdateScrollOffsetDelegate(); |
| + } |
| + |
| + virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE { |
| + return layer_tree_impl_->GetDelegatedScrollOffset(layer_); |
| + } |
| + |
| + virtual bool IsExternalFlingActive() const OVERRIDE { |
| + return delegate_->IsExternalFlingActive(); |
| + } |
| + |
| + virtual void SetTotalPageScaleFactor(float scale) OVERRIDE { |
| + NOTIMPLEMENTED(); |
| + } |
| + |
| + virtual void SetScrollableSize(gfx::SizeF size) OVERRIDE { |
| + NOTIMPLEMENTED(); |
| + } |
| + |
| + private: |
| + LayerImpl* layer_; |
| + LayerScrollOffsetDelegate* delegate_; |
| + LayerTreeImpl* layer_tree_impl_; |
| + gfx::Vector2dF last_set_scroll_offset_; |
| +}; |
| + |
| LayerTreeImpl::LayerTreeImpl(LayerTreeHostImpl* layer_tree_host_impl) |
| : layer_tree_host_impl_(layer_tree_host_impl), |
| source_frame_number_(-1), |
| hud_layer_(0), |
| - root_scroll_layer_(NULL), |
| currently_scrolling_layer_(NULL), |
| root_layer_scroll_offset_delegate_(NULL), |
| background_color_(0), |
| @@ -53,57 +99,77 @@ LayerTreeImpl::~LayerTreeImpl() { |
| root_layer_.reset(); |
| } |
| -static LayerImpl* FindRootScrollLayerRecursive(LayerImpl* layer) { |
| - if (!layer) |
| - return NULL; |
| +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_.reset(); |
| + outer_viewport_scroll_delegate_proxy_.reset(); |
| - if (layer->scrollable()) |
| - return layer; |
| + root_layer_ = layer.Pass(); |
| + currently_scrolling_layer_ = NULL; |
| + inner_viewport_scroll_layer_ = NULL; |
| + outer_viewport_scroll_layer_ = NULL; |
| + page_scale_layer_ = NULL; |
| - for (size_t i = 0; i < layer->children().size(); ++i) { |
| - LayerImpl* found = FindRootScrollLayerRecursive(layer->children()[i]); |
| - if (found) |
| - return found; |
| - } |
| + layer_tree_host_impl_->OnCanDrawStateChangedForTree(); |
| +} |
| - return NULL; |
| +LayerImpl* LayerTreeImpl::InnerViewportScrollLayer() const { |
| + return inner_viewport_scroll_layer_; |
| } |
| -void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) { |
| - if (root_scroll_layer_) |
| - root_scroll_layer_->SetScrollOffsetDelegate(NULL); |
| - root_layer_ = layer.Pass(); |
| - currently_scrolling_layer_ = NULL; |
| - root_scroll_layer_ = NULL; |
| +LayerImpl* LayerTreeImpl::OuterViewportScrollLayer() const { |
| + return outer_viewport_scroll_layer_; |
| +} |
| - layer_tree_host_impl_->OnCanDrawStateChangedForTree(); |
| +gfx::Vector2dF LayerTreeImpl::TotalScrollOffset() const { |
| + gfx::Vector2dF offset; |
| + |
| + if (inner_viewport_scroll_layer_) |
| + offset += inner_viewport_scroll_layer_->TotalScrollOffset(); |
| + |
| + if (outer_viewport_scroll_layer_) |
| + offset += outer_viewport_scroll_layer_->TotalScrollOffset(); |
| + |
| + return offset; |
| } |
| -void LayerTreeImpl::FindRootScrollLayer() { |
| - root_scroll_layer_ = FindRootScrollLayerRecursive(root_layer_.get()); |
| +gfx::Vector2dF LayerTreeImpl::TotalMaxScrollOffset() const { |
| + gfx::Vector2dF offset; |
| - if (root_scroll_layer_) { |
| - UpdateMaxScrollOffset(); |
| - root_scroll_layer_->SetScrollOffsetDelegate( |
| - root_layer_scroll_offset_delegate_); |
| - } |
| + if (inner_viewport_scroll_layer_) |
| + offset += inner_viewport_scroll_layer_->MaxScrollOffset(); |
| - if (scrolling_layer_id_from_previous_tree_) { |
| - currently_scrolling_layer_ = LayerTreeHostCommon::FindLayerInSubtree( |
| - root_layer_.get(), |
| - scrolling_layer_id_from_previous_tree_); |
| - } |
| + if (outer_viewport_scroll_layer_) |
| + offset += outer_viewport_scroll_layer_->MaxScrollOffset(); |
| - scrolling_layer_id_from_previous_tree_ = 0; |
| + return offset; |
| +} |
| +gfx::Vector2dF LayerTreeImpl::TotalScrollDelta() const { |
| + DCHECK(inner_viewport_scroll_layer_); |
| + gfx::Vector2dF delta = inner_viewport_scroll_layer_->ScrollDelta(); |
| + |
| + if (outer_viewport_scroll_layer_) |
| + delta += outer_viewport_scroll_layer_->ScrollDelta(); |
| + |
| + return delta; |
| } |
| 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 (root_scroll_layer_) |
| - root_scroll_layer_->SetScrollOffsetDelegate(NULL); |
| - root_scroll_layer_ = NULL; |
| + 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_.reset(); |
| + outer_viewport_scroll_delegate_proxy_.reset(); |
| + inner_viewport_scroll_layer_ = NULL; |
| + outer_viewport_scroll_layer_ = NULL; |
| + page_scale_layer_ = NULL; |
| currently_scrolling_layer_ = NULL; |
| render_surface_layer_list_.clear(); |
| @@ -128,12 +194,14 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { |
| target_tree->page_scale_delta() / target_tree->sent_page_scale_delta()); |
| target_tree->set_sent_page_scale_delta(1); |
| - if (settings().use_pinch_virtual_viewport) { |
| + if (page_scale_layer_ && inner_viewport_scroll_layer_) { |
| target_tree->SetViewportLayersFromIds( |
| page_scale_layer_->id(), |
| inner_viewport_scroll_layer_->id(), |
| outer_viewport_scroll_layer_ ? outer_viewport_scroll_layer_->id() |
| : Layer::INVALID_ID); |
| + } else { |
| + target_tree->ClearViewportLayers(); |
| } |
| // This should match the property synchronization in |
| // LayerTreeHost::finishCommitOnImplThread(). |
| @@ -159,12 +227,9 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { |
| target_tree->set_hud_layer(NULL); |
| } |
| -LayerImpl* LayerTreeImpl::RootScrollLayer() const { |
| - return root_scroll_layer_; |
| -} |
| - |
| LayerImpl* LayerTreeImpl::RootContainerLayer() const { |
| - return root_scroll_layer_ ? root_scroll_layer_->parent() : NULL; |
| + return inner_viewport_scroll_layer_ ? inner_viewport_scroll_layer_->parent() |
| + : NULL; |
| } |
| LayerImpl* LayerTreeImpl::CurrentlyScrollingLayer() const { |
| @@ -190,6 +255,29 @@ void LayerTreeImpl::ClearCurrentlyScrollingLayer() { |
| scrolling_layer_id_from_previous_tree_ = 0; |
| } |
| +float LayerTreeImpl::VerticalAdjust(const LayerImpl* layer) const { |
| + DCHECK(layer); |
| + if (layer->parent() != RootContainerLayer()) |
| + return 0.f; |
| + |
| + return layer_tree_host_impl_->UnscaledScrollableViewportSize().height() - |
| + RootContainerLayer()->bounds().height(); |
| +} |
| + |
| +namespace { |
| + |
| +void ForceScrollbarParameterUpdateAfterScaleChange(LayerImpl* current_layer) { |
| + if (!current_layer) |
| + return; |
| + |
| + while (current_layer) { |
| + current_layer->ScrollbarParametersDidChange(); |
| + current_layer = current_layer->parent(); |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| void LayerTreeImpl::SetPageScaleFactorAndLimits(float page_scale_factor, |
| float min_page_scale_factor, float max_page_scale_factor) { |
| if (!page_scale_factor) |
| @@ -203,6 +291,8 @@ void LayerTreeImpl::SetPageScaleFactorAndLimits(float page_scale_factor, |
| root_layer_scroll_offset_delegate_->SetTotalPageScaleFactor( |
| total_page_scale_factor()); |
| } |
| + |
| + ForceScrollbarParameterUpdateAfterScaleChange(page_scale_layer()); |
| } |
| void LayerTreeImpl::SetPageScaleDelta(float delta) { |
| @@ -227,7 +317,6 @@ void LayerTreeImpl::SetPageScaleDelta(float delta) { |
| } |
| } |
| - UpdateMaxScrollOffset(); |
| set_needs_update_draw_properties(); |
| if (root_layer_scroll_offset_delegate_) { |
| @@ -237,34 +326,26 @@ void LayerTreeImpl::SetPageScaleDelta(float delta) { |
| } |
| gfx::SizeF LayerTreeImpl::ScrollableViewportSize() const { |
|
aelias_OOO_until_Jul13
2014/01/16 03:44:04
The semantics of what this returns are now quite c
wjmaclean
2014/01/16 15:07:32
I agree with the renaming, though I think we need
|
| - return gfx::ScaleSize(layer_tree_host_impl_->UnscaledScrollableViewportSize(), |
| - 1.0f / total_page_scale_factor()); |
| + if (outer_viewport_scroll_layer_) |
| + return layer_tree_host_impl_->UnscaledScrollableViewportSize(); |
| + else |
| + return gfx::ScaleSize( |
| + layer_tree_host_impl_->UnscaledScrollableViewportSize(), |
| + 1.0f / total_page_scale_factor()); |
| } |
| gfx::Rect LayerTreeImpl::RootScrollLayerDeviceViewportBounds() const { |
| - if (!root_scroll_layer_ || root_scroll_layer_->children().empty()) |
| + LayerImpl* root_scroll_layer = |
| + OuterViewportScrollLayer() ? OuterViewportScrollLayer() |
| + : InnerViewportScrollLayer(); |
| + if (!root_scroll_layer || root_scroll_layer->children().empty()) |
| return gfx::Rect(); |
| - LayerImpl* layer = root_scroll_layer_->children()[0]; |
| + LayerImpl* layer = root_scroll_layer->children()[0]; |
| return MathUtil::MapClippedRect( |
| layer->screen_space_transform(), |
| gfx::Rect(layer->content_bounds())); |
| } |
| -void LayerTreeImpl::UpdateMaxScrollOffset() { |
| - LayerImpl* root_scroll = RootScrollLayer(); |
| - if (!root_scroll || !root_scroll->children().size()) |
| - return; |
| - |
| - gfx::Vector2dF max_scroll = gfx::Rect(ScrollableSize()).bottom_right() - |
| - gfx::RectF(ScrollableViewportSize()).bottom_right(); |
| - |
| - // The viewport may be larger than the contents in some cases, such as |
| - // having a vertical scrollbar but no horizontal overflow. |
| - max_scroll.SetToMax(gfx::Vector2dF()); |
| - |
| - root_scroll_layer_->SetMaxScrollOffset(gfx::ToFlooredVector2d(max_scroll)); |
| -} |
| - |
| static void ApplySentScrollDeltasFromAbortedCommitTo(LayerImpl* layer) { |
| layer->ApplySentScrollDeltasFromAbortedCommit(); |
| } |
| @@ -311,6 +392,20 @@ void LayerTreeImpl::SetViewportLayersFromIds( |
| LayerById(outer_viewport_scroll_layer_id); |
| DCHECK(outer_viewport_scroll_layer_ || |
| outer_viewport_scroll_layer_id == Layer::INVALID_ID); |
| + |
| + 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() { |
| @@ -319,42 +414,9 @@ void LayerTreeImpl::ClearViewportLayers() { |
| outer_viewport_scroll_layer_ = NULL; |
| } |
| -// TODO(wjmaclean) This needs to go away, and be replaced with a single core |
| -// of login that works for both scrollbar layer types. This is already planned |
| -// as part of the larger pinch-zoom re-factoring viewport. |
| -void LayerTreeImpl::UpdateSolidColorScrollbars() { |
| - LayerImpl* root_scroll = RootScrollLayer(); |
| - DCHECK(root_scroll); |
| - DCHECK(IsActiveTree()); |
| - |
| - gfx::RectF scrollable_viewport( |
| - gfx::PointAtOffsetFromOrigin(root_scroll->TotalScrollOffset()), |
| - ScrollableViewportSize()); |
| - float vertical_adjust = 0.0f; |
| - if (RootContainerLayer()) |
| - vertical_adjust = |
| - layer_tree_host_impl_->UnscaledScrollableViewportSize().height() - |
| - RootContainerLayer()->bounds().height(); |
| - if (ScrollbarLayerImplBase* horiz = |
| - root_scroll->horizontal_scrollbar_layer()) { |
| - horiz->SetVerticalAdjust(vertical_adjust); |
| - horiz->SetVisibleToTotalLengthRatio( |
| - scrollable_viewport.width() / ScrollableSize().width()); |
| - } |
| - if (ScrollbarLayerImplBase* vertical = |
| - root_scroll->vertical_scrollbar_layer()) { |
| - vertical->SetVerticalAdjust(vertical_adjust); |
| - vertical->SetVisibleToTotalLengthRatio( |
| - scrollable_viewport.height() / ScrollableSize().height()); |
| - } |
| -} |
| - |
| void LayerTreeImpl::UpdateDrawProperties() { |
| - if (IsActiveTree() && RootScrollLayer() && RootContainerLayer()) |
| - UpdateRootScrollLayerSizeDelta(); |
| - |
| if (IsActiveTree() && RootContainerLayer()) |
| - UpdateSolidColorScrollbars(); |
| + UpdateRootScrollLayerSizeDelta(); |
| needs_update_draw_properties_ = false; |
| render_surface_layer_list_.clear(); |
| @@ -434,9 +496,11 @@ const LayerImplList& LayerTreeImpl::RenderSurfaceLayerList() const { |
| } |
| gfx::Size LayerTreeImpl::ScrollableSize() const { |
| - if (!root_scroll_layer_ || root_scroll_layer_->children().empty()) |
| + LayerImpl* root_scroll_layer = OuterViewportScrollLayer() ? |
| + OuterViewportScrollLayer() : InnerViewportScrollLayer(); |
| + if (!root_scroll_layer || root_scroll_layer->children().empty()) |
| return gfx::Size(); |
| - return root_scroll_layer_->children()[0]->bounds(); |
| + return root_scroll_layer->children()[0]->bounds(); |
| } |
| LayerImpl* LayerTreeImpl::LayerById(int id) { |
| @@ -470,8 +534,13 @@ void LayerTreeImpl::DidBecomeActive() { |
| if (!root_layer()) |
| return; |
| + if (scrolling_layer_id_from_previous_tree_) { |
| + currently_scrolling_layer_ = LayerTreeHostCommon::FindLayerInSubtree( |
| + root_layer_.get(), |
| + scrolling_layer_id_from_previous_tree_); |
| + } |
| + |
| DidBecomeActiveRecursive(root_layer()); |
| - FindRootScrollLayer(); |
| } |
| bool LayerTreeImpl::ContentsTexturesPurged() const { |
| @@ -662,22 +731,110 @@ void LayerTreeImpl::SetRootLayerScrollOffsetDelegate( |
| if (root_layer_scroll_offset_delegate_ == root_layer_scroll_offset_delegate) |
| return; |
| - root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate; |
| - |
| - if (root_scroll_layer_) { |
| - root_scroll_layer_->SetScrollOffsetDelegate( |
| - root_layer_scroll_offset_delegate_); |
| + 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_.reset(); |
| + outer_viewport_scroll_delegate_proxy_.reset(); |
| } |
| + root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate; |
| + |
| if (root_layer_scroll_offset_delegate_) { |
| + root_layer_scroll_offset_delegate_->SetTotalScrollOffset( |
| + TotalScrollOffset()); |
| + root_layer_scroll_offset_delegate_->SetMaxScrollOffset( |
| + TotalMaxScrollOffset()); |
| root_layer_scroll_offset_delegate_->SetScrollableSize(ScrollableSize()); |
| root_layer_scroll_offset_delegate_->SetTotalPageScaleFactor( |
| total_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()); |
| + } |
| } |
| } |
| +void LayerTreeImpl::UpdateScrollOffsetDelegate() { |
| + DCHECK(InnerViewportScrollLayer()); |
| + DCHECK(root_layer_scroll_offset_delegate_); |
| + |
| + gfx::Vector2dF offset = |
| + inner_viewport_scroll_delegate_proxy_->last_set_scroll_offset(); |
| + |
| + if (OuterViewportScrollLayer()) |
| + offset += |
| + outer_viewport_scroll_delegate_proxy_->last_set_scroll_offset(); |
| + |
| + root_layer_scroll_offset_delegate_->SetTotalScrollOffset(offset); |
| + root_layer_scroll_offset_delegate_->SetMaxScrollOffset( |
| + TotalMaxScrollOffset()); |
| +} |
| + |
| +gfx::Vector2dF LayerTreeImpl::GetDelegatedScrollOffset(LayerImpl* layer) { |
| + DCHECK(root_layer_scroll_offset_delegate_); |
| + DCHECK(InnerViewportScrollLayer()); |
| + if (layer == InnerViewportScrollLayer() && !OuterViewportScrollLayer()) |
| + return root_layer_scroll_offset_delegate_->GetTotalScrollOffset(); |
| + |
| + // 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::Vector2dF inner_viewport_offset = |
| + inner_viewport_scroll_delegate_proxy_->last_set_scroll_offset(); |
| + gfx::Vector2dF outer_viewport_offset = |
| + outer_viewport_scroll_delegate_proxy_->last_set_scroll_offset(); |
| + |
| + // It may be nothing has changed. |
| + gfx::Vector2dF 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; |
| + } |
| + |
| + gfx::Vector2d max_outer_viewport_scroll_offset = |
| + OuterViewportScrollLayer()->MaxScrollOffset(); |
| + |
| + outer_viewport_offset = delegate_offset - inner_viewport_offset; |
| + outer_viewport_offset.SetToMin(max_outer_viewport_scroll_offset); |
| + outer_viewport_offset.SetToMax(gfx::Vector2d()); |
| + |
| + if (layer == OuterViewportScrollLayer()) |
| + return outer_viewport_offset; |
| + |
| + inner_viewport_offset = delegate_offset - outer_viewport_offset; |
| + |
| + return inner_viewport_offset; |
| +} |
| + |
| +// TODO(wjmaclean) Rename this function, as we no longer have a |
| +// "RootScrollLayer". |
| void LayerTreeImpl::UpdateRootScrollLayerSizeDelta() { |
| - LayerImpl* root_scroll = RootScrollLayer(); |
| + // TODO(wjmaclean) verify this is really the right thing to do in cases where |
| + // the pinch virtual viewport is active. |
| + LayerImpl* root_scroll = InnerViewportScrollLayer(); |
| LayerImpl* root_container = RootContainerLayer(); |
| DCHECK(root_scroll); |
| DCHECK(root_container); |