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 e0d2e26149d089785fae8fb3c501d32b5147a309..01a53ae876185ab15c60ccd55a8faa3861e81761 100644 |
--- a/cc/trees/layer_tree_host_impl.cc |
+++ b/cc/trees/layer_tree_host_impl.cc |
@@ -75,6 +75,48 @@ |
#include "ui/gfx/size_conversions.h" |
#include "ui/gfx/vector2d_conversions.h" |
+namespace { |
+ |
+// Small helper class that saves the current viewport location as the user sees |
+// it and resets to the same location on destruction. |
+class ViewportAnchor { |
+ public: |
+ ViewportAnchor(cc::LayerImpl* inner_scroll, cc::LayerImpl* outer_scroll) |
+ : inner_(inner_scroll) |
+ , outer_(outer_scroll) { |
+ viewportInContentCoordinates_ = inner_->TotalScrollOffset(); |
+ |
+ if (outer_) |
+ viewportInContentCoordinates_ += outer_->TotalScrollOffset(); |
+ } |
+ |
+ ~ViewportAnchor() { |
aelias_OOO_until_Jul13
2014/10/09 20:56:16
I'd prefer this to be an explicit method call rath
bokan
2014/10/09 21:51:37
Done.
|
+ // No-op scroll to force clamp to maxScrollOffset. |
+ inner_->ScrollBy(gfx::Vector2dF()); |
aelias_OOO_until_Jul13
2014/10/09 20:55:13
Please call LayerImpl::ClampScrollToMaxScrollOffse
bokan
2014/10/09 21:51:37
Done.
|
+ gfx::ScrollOffset viewport_location = inner_->TotalScrollOffset(); |
+ |
+ if (outer_) { |
aelias_OOO_until_Jul13
2014/10/09 20:55:13
These if (outer_) statements are mainly what makes
bokan
2014/10/09 21:51:37
Done. Doesn't even need a guard since it's below t
|
+ outer_->ScrollBy(gfx::Vector2dF()); |
+ viewport_location += outer_->TotalScrollOffset(); |
+ } |
+ |
+ gfx::Vector2dF delta = |
+ viewportInContentCoordinates_.DeltaFrom(viewport_location); |
+ |
+ if (outer_) |
+ delta = outer_->ScrollBy(delta); |
+ |
+ inner_->ScrollBy(delta); |
+ } |
+ |
+ private: |
+ cc::LayerImpl* inner_; |
+ cc::LayerImpl* outer_; |
+ gfx::ScrollOffset viewportInContentCoordinates_; |
aelias_OOO_until_Jul13
2014/10/09 20:55:13
nit: camel-case not Chromium style
bokan
2014/10/09 21:51:37
Done.
|
+}; |
+ |
+} // namespace |
+ |
namespace cc { |
namespace { |
@@ -1653,15 +1695,39 @@ 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( |
+ { |
+ ViewportAnchor anchor(InnerViewportScrollLayer(), |
aelias_OOO_until_Jul13
2014/10/09 03:51:36
Hmm, could you describe the clamping problem that
bokan
2014/10/09 13:30:13
These issues occur when the viewports are fully sc
aelias_OOO_until_Jul13
2014/10/09 20:55:13
OK, seems alright. Looks like an unavoidable cons
|
+ 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->bounds().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->bounds().width() / |
+ inner_container->bounds().height(); |
+ float target_height = outer_container->bounds().width() / aspect_ratio; |
+ float current_outer_height = outer_container->bounds().height() - |
+ outer_container->bounds_delta().y(); |
+ gfx::Vector2dF delta(0, target_height - current_outer_height); |
+ |
+ outer_container->SetBoundsDelta(delta); |
+ active_tree_->InnerViewportScrollLayer()->SetBoundsDelta(delta); |
} |
} |
@@ -1670,7 +1736,7 @@ void LayerTreeHostImpl::SetTopControlsLayoutHeight(float height) { |
return; |
active_tree_->set_top_controls_layout_height(height); |
- UpdateInnerViewportContainerSize(); |
+ UpdateViewportContainerSizes(); |
SetFullRootLayerDamage(); |
} |
@@ -1791,7 +1857,7 @@ void LayerTreeHostImpl::ActivateSyncTree() { |
top_controls_manager_->top_controls_height()); |
} |
- UpdateInnerViewportContainerSize(); |
+ UpdateViewportContainerSizes(); |
} else { |
active_tree_->ProcessUIResourceRequestQueue(); |
} |
@@ -2154,7 +2220,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(); |
@@ -2205,7 +2271,7 @@ const gfx::Transform& LayerTreeHostImpl::DrawTransform() const { |
} |
void LayerTreeHostImpl::DidChangeTopControlsPosition() { |
- UpdateInnerViewportContainerSize(); |
+ UpdateViewportContainerSizes(); |
SetNeedsRedraw(); |
SetNeedsAnimate(); |
active_tree_->set_needs_update_draw_properties(); |
@@ -2501,6 +2567,29 @@ static gfx::Vector2dF ScrollLayerWithLocalDelta(LayerImpl* layer_impl, |
return layer_impl->ScrollDelta() - previous_delta; |
} |
+bool LayerTreeHostImpl::ShouldTopControlsConsumeScroll( |
+ const gfx::Vector2dF& scroll_delta) const { |
+ if (!top_controls_manager_ || !CurrentlyScrollingLayer()) |
aelias_OOO_until_Jul13
2014/10/09 20:55:13
!CurrentlyScrollingLayer() condition is unnecessar
bokan
2014/10/09 21:51:37
Done.
|
+ 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"); |
@@ -2512,14 +2601,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; |
@@ -2527,23 +2610,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); |
bokan
2014/10/08 23:03:55
I think this is unneeded, it gets called when the
|
- } |
} |
// 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; |