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; |