Chromium Code Reviews| Index: cc/trees/layer_tree_host_impl.cc |
| diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc |
| index 542143cea7af64c6cfc63ed93ba67bb66b77e5e8..d5bb0ba9f22fdc274bfdd255d0b6199ea2f5c005 100644 |
| --- a/cc/trees/layer_tree_host_impl.cc |
| +++ b/cc/trees/layer_tree_host_impl.cc |
| @@ -75,6 +75,45 @@ |
| #include "ui/gfx/size_conversions.h" |
| #include "ui/gfx/vector2d_conversions.h" |
| +namespace { |
|
danakj
2014/10/10 18:47:16
you could put this in the anon namespace we alread
bokan
2014/10/10 19:25:55
Done.
|
| + |
| +// Small helper class that saves the current viewport location as the user sees |
| +// it and resets to the same location on destruction. |
|
danakj
2014/10/10 18:47:16
i don't see a destructor, comment is wrong?
bokan
2014/10/10 19:25:55
Doh! Good catch.
|
| +class ViewportAnchor { |
| + public: |
| + ViewportAnchor(cc::LayerImpl* inner_scroll, cc::LayerImpl* outer_scroll) |
| + : inner_(inner_scroll) |
|
danakj
2014/10/10 18:47:16
this isn't formatted right is it?
bokan
2014/10/10 19:25:55
Blinkism, thanks.
|
| + , outer_(outer_scroll) { |
| + viewport_in_content_coordinates_ = inner_->TotalScrollOffset(); |
| + |
| + if (outer_) |
| + viewport_in_content_coordinates_ += outer_->TotalScrollOffset(); |
| + } |
| + |
| + void ResetViewportToAnchoredPosition() { |
| + DCHECK(outer_); |
| + |
| + inner_->ClampScrollToMaxScrollOffset(); |
| + outer_->ClampScrollToMaxScrollOffset(); |
| + |
| + gfx::ScrollOffset viewport_location = inner_->TotalScrollOffset() + |
| + outer_->TotalScrollOffset(); |
| + |
| + gfx::Vector2dF delta = |
| + viewport_in_content_coordinates_.DeltaFrom(viewport_location); |
| + |
| + delta = outer_->ScrollBy(delta); |
| + inner_->ScrollBy(delta); |
| + } |
| + |
| + private: |
| + cc::LayerImpl* inner_; |
| + cc::LayerImpl* outer_; |
| + gfx::ScrollOffset viewport_in_content_coordinates_; |
| +}; |
| + |
| +} // namespace |
| + |
| namespace cc { |
| namespace { |
| @@ -1654,16 +1693,41 @@ void LayerTreeHostImpl::WillBeginImplFrame(const BeginFrameArgs& args) { |
| begin_impl_frame_interval_ = args.interval; |
| } |
| -void LayerTreeHostImpl::UpdateInnerViewportContainerSize() { |
| - LayerImpl* container_layer = active_tree_->InnerViewportContainerLayer(); |
| - if (!container_layer) |
| +void LayerTreeHostImpl::UpdateViewportContainerSizes() { |
| + LayerImpl* inner_container = active_tree_->InnerViewportContainerLayer(); |
| + LayerImpl* outer_container = active_tree_->OuterViewportContainerLayer(); |
| + |
| + if (!inner_container || !top_controls_manager_) |
| return; |
| - if (top_controls_manager_) { |
| - container_layer->SetBoundsDelta( |
| - gfx::Vector2dF(0, active_tree_->top_controls_layout_height() - |
| - active_tree_->total_top_controls_content_offset())); |
| - } |
| + ViewportAnchor anchor(InnerViewportScrollLayer(), |
| + OuterViewportScrollLayer()); |
| + |
| + // Adjust the inner viewport by shrinking/expanding the container to account |
| + // for the change in top controls height since the last Resize from Blink. |
| + inner_container->SetBoundsDelta( |
| + gfx::Vector2dF(0, active_tree_->top_controls_layout_height() - |
| + active_tree_->total_top_controls_content_offset())); |
| + |
| + if (!outer_container || outer_container->BoundsForScrolling().IsEmpty()) |
| + return; |
| + |
| + // Adjust the outer viewport container as well, since adjusting only the |
| + // inner may cause its bounds to exceed those of the outer, causing scroll |
| + // clamping. We adjust it so it maintains the same aspect ratio as the |
| + // inner viewport. |
| + float aspect_ratio = inner_container->BoundsForScrolling().width() / |
| + inner_container->BoundsForScrolling().height(); |
| + float target_height = outer_container->BoundsForScrolling().width() / |
| + aspect_ratio; |
| + float current_outer_height = outer_container->BoundsForScrolling().height() - |
| + outer_container->bounds_delta().y(); |
| + gfx::Vector2dF delta(0, target_height - current_outer_height); |
| + |
| + outer_container->SetBoundsDelta(delta); |
| + active_tree_->InnerViewportScrollLayer()->SetBoundsDelta(delta); |
| + |
| + anchor.ResetViewportToAnchoredPosition(); |
| } |
| void LayerTreeHostImpl::SetTopControlsLayoutHeight(float height) { |
| @@ -1671,7 +1735,7 @@ void LayerTreeHostImpl::SetTopControlsLayoutHeight(float height) { |
| return; |
| active_tree_->set_top_controls_layout_height(height); |
| - UpdateInnerViewportContainerSize(); |
| + UpdateViewportContainerSizes(); |
| SetFullRootLayerDamage(); |
| } |
| @@ -1792,7 +1856,7 @@ void LayerTreeHostImpl::ActivateSyncTree() { |
| top_controls_manager_->top_controls_height()); |
| } |
| - UpdateInnerViewportContainerSize(); |
| + UpdateViewportContainerSizes(); |
| } else { |
| active_tree_->ProcessUIResourceRequestQueue(); |
| } |
| @@ -2155,7 +2219,7 @@ void LayerTreeHostImpl::SetViewportSize(const gfx::Size& device_viewport_size) { |
| device_viewport_size_ = device_viewport_size; |
| - UpdateInnerViewportContainerSize(); |
| + UpdateViewportContainerSizes(); |
| client_->OnCanDrawStateChanged(CanDraw()); |
| SetFullRootLayerDamage(); |
| active_tree_->set_needs_update_draw_properties(); |
| @@ -2206,7 +2270,7 @@ const gfx::Transform& LayerTreeHostImpl::DrawTransform() const { |
| } |
| void LayerTreeHostImpl::DidChangeTopControlsPosition() { |
| - UpdateInnerViewportContainerSize(); |
| + UpdateViewportContainerSizes(); |
| SetNeedsRedraw(); |
| SetNeedsAnimate(); |
| active_tree_->set_needs_update_draw_properties(); |
| @@ -2502,6 +2566,31 @@ static gfx::Vector2dF ScrollLayerWithLocalDelta(LayerImpl* layer_impl, |
| return layer_impl->ScrollDelta() - previous_delta; |
| } |
| +bool LayerTreeHostImpl::ShouldTopControlsConsumeScroll( |
| + const gfx::Vector2dF& scroll_delta) const { |
| + DCHECK(CurrentlyScrollingLayer()); |
| + |
| + if (!top_controls_manager_) |
| + return false; |
| + |
| + // Always consume if it's in the direction to show the top controls. |
| + if (scroll_delta.y() < 0) |
| + return true; |
| + |
| + if (CurrentlyScrollingLayer() != InnerViewportScrollLayer() && |
| + CurrentlyScrollingLayer() != OuterViewportScrollLayer()) |
| + return false; |
| + |
| + if (InnerViewportScrollLayer()->MaxScrollOffset().y() > 0) |
| + return true; |
| + |
| + if (OuterViewportScrollLayer() && |
| + OuterViewportScrollLayer()->MaxScrollOffset().y() > 0) |
| + return true; |
| + |
| + return false; |
| +} |
| + |
| bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point, |
| const gfx::Vector2dF& scroll_delta) { |
| TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); |
| @@ -2513,14 +2602,8 @@ bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point, |
| bool did_scroll_x = false; |
| bool did_scroll_y = false; |
| bool did_scroll_top_controls = false; |
| - // TODO(wjmaclean) Should we guard against CurrentlyScrollingLayer() == 0 |
| - // here? |
| - bool consume_by_top_controls = |
| - top_controls_manager_ && |
| - (((CurrentlyScrollingLayer() == InnerViewportScrollLayer() || |
| - CurrentlyScrollingLayer() == OuterViewportScrollLayer()) && |
| - InnerViewportScrollLayer()->MaxScrollOffset().y() > 0) || |
| - scroll_delta.y() < 0); |
| + |
| + bool consume_by_top_controls = ShouldTopControlsConsumeScroll(scroll_delta); |
| for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); |
| layer_impl; |
| @@ -2528,23 +2611,20 @@ bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point, |
| if (!layer_impl->scrollable()) |
| continue; |
| - if (layer_impl == InnerViewportScrollLayer()) { |
| - // Only allow bubble scrolling when the scroll is in the direction to make |
| - // the top controls visible. |
| - gfx::Vector2dF applied_delta; |
| - gfx::Vector2dF excess_delta; |
| + if (layer_impl == InnerViewportScrollLayer() || |
| + layer_impl == OuterViewportScrollLayer()) { |
| if (consume_by_top_controls) { |
| - excess_delta = top_controls_manager_->ScrollBy(pending_delta); |
| - applied_delta = pending_delta - excess_delta; |
| + gfx::Vector2dF excess_delta = |
| + top_controls_manager_->ScrollBy(pending_delta); |
| + gfx::Vector2dF applied_delta = pending_delta - excess_delta; |
| pending_delta = excess_delta; |
| // Force updating of vertical adjust values if needed. |
| - if (applied_delta.y() != 0) { |
| + if (applied_delta.y() != 0) |
| did_scroll_top_controls = true; |
| - layer_impl->ScrollbarParametersDidChange(false); |
| - } |
| } |
| // Track root layer deltas for reporting overscroll. |
| - unused_root_delta = pending_delta; |
| + if (layer_impl == InnerViewportScrollLayer()) |
| + unused_root_delta = pending_delta; |
| } |
| gfx::Vector2dF applied_delta; |