| 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 3eb98bf211f2ee758f1558f42fcbaa1627b5c8cd..aff8a76e0014e1978985d9fa04c36a837fe81967 100644
|
| --- a/cc/trees/layer_tree_host_impl.cc
|
| +++ b/cc/trees/layer_tree_host_impl.cc
|
| @@ -432,11 +432,10 @@ void LayerTreeHostImpl::StartPageScaleAnimation(gfx::Vector2d target_offset,
|
| bool anchor_point,
|
| float page_scale,
|
| base::TimeDelta duration) {
|
| - if (!RootScrollLayer())
|
| + if (!InnerViewportScrollLayer())
|
| return;
|
|
|
| - gfx::Vector2dF scroll_total =
|
| - RootScrollLayer()->scroll_offset() + RootScrollLayer()->ScrollDelta();
|
| + gfx::Vector2dF scroll_total = active_tree_->TotalScrollOffset();
|
| gfx::SizeF scaled_scrollable_size = active_tree_->ScrollableSize();
|
| gfx::SizeF viewport_size = UnscaledScrollableViewportSize();
|
|
|
| @@ -1309,10 +1308,10 @@ CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const {
|
| metadata.overdraw_bottom_height = overdraw_bottom_height_;
|
| }
|
|
|
| - if (!RootScrollLayer())
|
| + if (!InnerViewportScrollLayer())
|
| return metadata;
|
|
|
| - metadata.root_scroll_offset = RootScrollLayer()->TotalScrollOffset();
|
| + metadata.root_scroll_offset = active_tree_->TotalScrollOffset();
|
|
|
| return metadata;
|
| }
|
| @@ -1515,15 +1514,19 @@ void LayerTreeHostImpl::Readback(void* pixels,
|
| }
|
|
|
| bool LayerTreeHostImpl::HaveRootScrollLayer() const {
|
| - return !!RootScrollLayer();
|
| + return !!InnerViewportScrollLayer();
|
| }
|
|
|
| LayerImpl* LayerTreeHostImpl::RootLayer() const {
|
| return active_tree_->root_layer();
|
| }
|
|
|
| -LayerImpl* LayerTreeHostImpl::RootScrollLayer() const {
|
| - return active_tree_->RootScrollLayer();
|
| +LayerImpl* LayerTreeHostImpl::InnerViewportScrollLayer() const {
|
| + return active_tree_->InnerViewportScrollLayer();
|
| +}
|
| +
|
| +LayerImpl* LayerTreeHostImpl::OuterViewportScrollLayer() const {
|
| + return active_tree_->OuterViewportScrollLayer();
|
| }
|
|
|
| LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const {
|
| @@ -1532,7 +1535,10 @@ LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const {
|
|
|
| bool LayerTreeHostImpl::IsCurrentlyScrolling() const {
|
| return CurrentlyScrollingLayer() ||
|
| - (RootScrollLayer() && RootScrollLayer()->IsExternalFlingActive());
|
| + (InnerViewportScrollLayer() &&
|
| + InnerViewportScrollLayer()->IsExternalFlingActive()) ||
|
| + (OuterViewportScrollLayer() &&
|
| + OuterViewportScrollLayer()->IsExternalFlingActive());
|
| }
|
|
|
| // Content layers can be either directly scrollable or contained in an outer
|
| @@ -1913,8 +1919,6 @@ void LayerTreeHostImpl::SetViewportSize(const gfx::Size& device_viewport_size) {
|
|
|
| device_viewport_size_ = device_viewport_size;
|
|
|
| - UpdateMaxScrollOffset();
|
| -
|
| client_->OnCanDrawStateChanged(CanDraw());
|
| SetFullRootLayerDamage();
|
| }
|
| @@ -1924,7 +1928,6 @@ void LayerTreeHostImpl::SetOverdrawBottomHeight(float overdraw_bottom_height) {
|
| return;
|
| overdraw_bottom_height_ = overdraw_bottom_height;
|
|
|
| - UpdateMaxScrollOffset();
|
| SetFullRootLayerDamage();
|
| }
|
|
|
| @@ -1940,7 +1943,6 @@ void LayerTreeHostImpl::SetDeviceScaleFactor(float device_scale_factor) {
|
| return;
|
| device_scale_factor_ = device_scale_factor;
|
|
|
| - UpdateMaxScrollOffset();
|
| SetFullRootLayerDamage();
|
| }
|
|
|
| @@ -1966,10 +1968,6 @@ const gfx::Transform& LayerTreeHostImpl::DrawTransform() const {
|
| return external_transform_;
|
| }
|
|
|
| -void LayerTreeHostImpl::UpdateMaxScrollOffset() {
|
| - active_tree_->UpdateMaxScrollOffset();
|
| -}
|
| -
|
| void LayerTreeHostImpl::DidChangeTopControlsPosition() {
|
| SetNeedsRedraw();
|
| active_tree_->set_needs_update_draw_properties();
|
| @@ -2055,8 +2053,11 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
|
| return ScrollOnMainThread;
|
| }
|
|
|
| + // If we want to send a DidOverscroll for this scroll it can't be ignored.
|
| if (!potentially_scrolling_layer_impl)
|
| - potentially_scrolling_layer_impl = RootScrollLayer();
|
| + potentially_scrolling_layer_impl = OuterViewportScrollLayer()
|
| + ? OuterViewportScrollLayer()
|
| + : InnerViewportScrollLayer();
|
|
|
| if (potentially_scrolling_layer_impl) {
|
| active_tree_->SetCurrentlyScrollingLayer(
|
| @@ -2163,10 +2164,14 @@ bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
|
| gfx::Vector2dF unused_root_delta;
|
| bool did_scroll_x = false;
|
| bool did_scroll_y = false;
|
| - bool consume_by_top_controls = top_controls_manager_ &&
|
| - (scroll_delta.y() < 0 ||
|
| - (RootScrollLayer() && CurrentlyScrollingLayer() == RootScrollLayer() &&
|
| - RootScrollLayer()->max_scroll_offset().y() > 0));
|
| + // 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);
|
|
|
| for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
|
| layer_impl;
|
| @@ -2174,12 +2179,18 @@ bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
|
| if (!layer_impl->scrollable())
|
| continue;
|
|
|
| - if (layer_impl == RootScrollLayer()) {
|
| + 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 (consume_by_top_controls) {
|
| - pending_delta = top_controls_manager_->ScrollBy(pending_delta);
|
| - UpdateMaxScrollOffset();
|
| + excess_delta = top_controls_manager_->ScrollBy(pending_delta);
|
| + applied_delta = pending_delta - excess_delta;
|
| + pending_delta = excess_delta;
|
| + // Force updating of vertical adjust values if needed.
|
| + if (applied_delta.y() != 0)
|
| + layer_impl->ScrollbarParametersDidChange();
|
| }
|
| // Track root layer deltas for reporting overscroll.
|
| unused_root_delta = pending_delta;
|
| @@ -2213,7 +2224,7 @@ bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
|
| break;
|
| }
|
|
|
| - if (layer_impl == RootScrollLayer())
|
| + if (layer_impl == InnerViewportScrollLayer())
|
| unused_root_delta.Subtract(applied_delta);
|
|
|
| did_lock_scrolling_layer_ = true;
|
| @@ -2280,10 +2291,10 @@ bool LayerTreeHostImpl::ScrollVerticallyByPage(gfx::Point viewport_point,
|
| if (!layer_impl->scrollable())
|
| continue;
|
|
|
| - if (!layer_impl->vertical_scrollbar_layer())
|
| + if (!layer_impl->HasScrollbar(VERTICAL))
|
| continue;
|
|
|
| - float height = layer_impl->vertical_scrollbar_layer()->bounds().height();
|
| + float height = layer_impl->clip_height();
|
|
|
| // These magical values match WebKit and are designed to scroll nearly the
|
| // entire visible content height but leave a bit of overlap.
|
| @@ -2339,8 +2350,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::FlingScrollBegin() {
|
| return ScrollIgnored;
|
|
|
| if (settings_.ignore_root_layer_flings &&
|
| - active_tree_->CurrentlyScrollingLayer() ==
|
| - active_tree_->RootScrollLayer()) {
|
| + (active_tree_->CurrentlyScrollingLayer() == InnerViewportScrollLayer() ||
|
| + active_tree_->CurrentlyScrollingLayer() == OuterViewportScrollLayer())) {
|
| ClearCurrentlyScrollingLayer();
|
| return ScrollIgnored;
|
| }
|
| @@ -2416,11 +2427,15 @@ void LayerTreeHostImpl::MouseMoveAt(gfx::Point viewport_point) {
|
| if (!animation_controller)
|
| return;
|
|
|
| - float distance_to_scrollbar = std::min(
|
| - DeviceSpaceDistanceToLayer(device_viewport_point,
|
| - scroll_layer_impl->horizontal_scrollbar_layer()),
|
| - DeviceSpaceDistanceToLayer(device_viewport_point,
|
| - scroll_layer_impl->vertical_scrollbar_layer()));
|
| + // TODO(wjmaclean) Is it ok to choose distance from more than two scrollbars?
|
| + float distance_to_scrollbar = std::numeric_limits<float>::max();
|
| + for (LayerImpl::ScrollbarSet::iterator it =
|
| + scroll_layer_impl->scrollbars()->begin();
|
| + it != scroll_layer_impl->scrollbars()->end();
|
| + ++it)
|
| + distance_to_scrollbar =
|
| + std::min(distance_to_scrollbar,
|
| + DeviceSpaceDistanceToLayer(device_viewport_point, *it));
|
|
|
| bool should_animate = animation_controller->DidMouseMoveNear(
|
| CurrentPhysicalTimeTicks(), distance_to_scrollbar / device_scale_factor_);
|
| @@ -2455,7 +2470,13 @@ void LayerTreeHostImpl::PinchGestureBegin() {
|
| previous_pinch_anchor_ = gfx::Point();
|
| client_->RenewTreePriority();
|
| pinch_gesture_end_should_clear_scrolling_layer_ = !CurrentlyScrollingLayer();
|
| - active_tree_->SetCurrentlyScrollingLayer(RootScrollLayer());
|
| + if (active_tree_->OuterViewportScrollLayer()) {
|
| + active_tree_->SetCurrentlyScrollingLayer(
|
| + active_tree_->OuterViewportScrollLayer());
|
| + } else {
|
| + active_tree_->SetCurrentlyScrollingLayer(
|
| + active_tree_->InnerViewportScrollLayer());
|
| + }
|
| if (top_controls_manager_)
|
| top_controls_manager_->PinchBegin();
|
| }
|
| @@ -2464,8 +2485,7 @@ void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
|
| gfx::Point anchor) {
|
| TRACE_EVENT0("cc", "LayerTreeHostImpl::PinchGestureUpdate");
|
|
|
| - if (!RootScrollLayer())
|
| - return;
|
| + DCHECK(InnerViewportScrollLayer());
|
|
|
| // Keep the center-of-pinch anchor specified by (x, y) in a stable
|
| // position over the course of the magnify.
|
| @@ -2481,8 +2501,24 @@ void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
|
| previous_pinch_anchor_ = anchor;
|
|
|
| move.Scale(1 / active_tree_->page_scale_factor());
|
| + // If clamping the inner viewport scroll offset causes a change, it should
|
| + // be accounted for from the intended move.
|
| + move -= InnerViewportScrollLayer()->ClampScrollToMaxScrollOffset();
|
|
|
| - RootScrollLayer()->ScrollBy(move);
|
| + // We manually manage the bubbling behaviour here as it is different to that
|
| + // implemented in LayerTreeHostImpl::ScrollBy(). Specifically:
|
| + // 1) we want to explicit limit the bubbling to the outer/inner viewports,
|
| + // 2) we don't want the directional limitations on the unused parts that
|
| + // ScrollBy() implements, and
|
| + // 3) pinching should not engage the top controls manager.
|
| + gfx::Vector2dF unused = OuterViewportScrollLayer()
|
| + ? OuterViewportScrollLayer()->ScrollBy(move)
|
| + : move;
|
| +
|
| + if (!unused.IsZero()) {
|
| + InnerViewportScrollLayer()->ScrollBy(unused);
|
| + InnerViewportScrollLayer()->ClampScrollToMaxScrollOffset();
|
| + }
|
|
|
| client_->SetNeedsCommitOnImplThread();
|
| SetNeedsRedraw();
|
| @@ -2533,13 +2569,24 @@ void LayerTreeHostImpl::SetFullRootLayerDamage() {
|
| SetViewportDamage(gfx::Rect(DrawViewportSize()));
|
| }
|
|
|
| +void LayerTreeHostImpl::ScrollViewportBy(gfx::Vector2dF scroll_delta) {
|
| + DCHECK(InnerViewportScrollLayer());
|
| + LayerImpl* scroll_layer = OuterViewportScrollLayer()
|
| + ? OuterViewportScrollLayer()
|
| + : InnerViewportScrollLayer();
|
| +
|
| + gfx::Vector2dF unused_delta = scroll_layer->ScrollBy(scroll_delta);
|
| +
|
| + if (!unused_delta.IsZero() && (scroll_layer == OuterViewportScrollLayer()))
|
| + InnerViewportScrollLayer()->ScrollBy(unused_delta);
|
| +}
|
| +
|
| void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) {
|
| - if (!page_scale_animation_ || !RootScrollLayer())
|
| + if (!page_scale_animation_)
|
| return;
|
|
|
| double monotonic_time = (time - base::TimeTicks()).InSecondsF();
|
| - gfx::Vector2dF scroll_total = RootScrollLayer()->scroll_offset() +
|
| - RootScrollLayer()->ScrollDelta();
|
| + gfx::Vector2dF scroll_total = active_tree_->TotalScrollOffset();
|
|
|
| if (!page_scale_animation_->IsAnimationStarted())
|
| page_scale_animation_->StartAnimation(monotonic_time);
|
| @@ -2550,7 +2597,7 @@ void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) {
|
| gfx::Vector2dF next_scroll =
|
| page_scale_animation_->ScrollOffsetAtTime(monotonic_time);
|
|
|
| - RootScrollLayer()->ScrollBy(next_scroll - scroll_total);
|
| + ScrollViewportBy(next_scroll - scroll_total);
|
| SetNeedsRedraw();
|
|
|
| if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) {
|
| @@ -2561,18 +2608,17 @@ void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) {
|
| }
|
|
|
| void LayerTreeHostImpl::AnimateTopControls(base::TimeTicks time) {
|
| - if (!top_controls_manager_ || !RootScrollLayer())
|
| + if (!top_controls_manager_)
|
| return;
|
| gfx::Vector2dF scroll = top_controls_manager_->Animate(time);
|
| - UpdateMaxScrollOffset();
|
| - if (RootScrollLayer()->TotalScrollOffset().y() == 0.f)
|
| + if (active_tree_->TotalScrollOffset().y() == 0.f)
|
| return;
|
| if (scroll.IsZero()) {
|
| // This may happen on the first animation step. Force redraw otherwise
|
| // the animation would stop because of no new frames.
|
| SetNeedsRedraw();
|
| } else {
|
| - RootScrollLayer()->ScrollBy(gfx::ScaleVector2d(
|
| + ScrollViewportBy(gfx::ScaleVector2d(
|
| scroll, 1.f / active_tree_->total_page_scale_factor()));
|
| }
|
| }
|
|
|