| 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 d8b021a0ba9c3260278bea282a0dbf8cd8d011b3..1def91f9045d7c15c1cce995e0ca20d13e8a982d 100644
|
| --- a/cc/trees/layer_tree_host_impl.cc
|
| +++ b/cc/trees/layer_tree_host_impl.cc
|
| @@ -387,11 +387,14 @@ void LayerTreeHostImpl::StartPageScaleAnimation(gfx::Vector2d target_offset,
|
| bool anchor_point,
|
| float page_scale,
|
| base::TimeDelta duration) {
|
| - if (!RootScrollLayer())
|
| + if (!InnerViewportScrollLayer())
|
| return;
|
|
|
| + // Should we attempt to set to OuterViewportScrollingLayer if it's available?
|
| + active_tree_->SetCurrentlyScrollingLayer(InnerViewportScrollLayer());
|
| +
|
| gfx::Vector2dF scroll_total =
|
| - RootScrollLayer()->scroll_offset() + RootScrollLayer()->ScrollDelta();
|
| + active_tree_->TotalScrollOffset() + active_tree_->TotalScrollDelta();
|
| gfx::SizeF scaled_scrollable_size = active_tree_->ScrollableSize();
|
| gfx::SizeF viewport_size = UnscaledScrollableViewportSize();
|
|
|
| @@ -1244,10 +1247,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;
|
| }
|
| @@ -1435,15 +1438,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 {
|
| @@ -1452,7 +1459,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
|
| @@ -1826,8 +1836,6 @@ void LayerTreeHostImpl::SetViewportSize(gfx::Size device_viewport_size) {
|
|
|
| device_viewport_size_ = device_viewport_size;
|
|
|
| - UpdateMaxScrollOffset();
|
| -
|
| if (renderer_)
|
| renderer_->ViewportChanged();
|
|
|
| @@ -1840,7 +1848,6 @@ void LayerTreeHostImpl::SetOverdrawBottomHeight(float overdraw_bottom_height) {
|
| return;
|
| overdraw_bottom_height_ = overdraw_bottom_height;
|
|
|
| - UpdateMaxScrollOffset();
|
| SetFullRootLayerDamage();
|
| }
|
|
|
| @@ -1859,7 +1866,6 @@ void LayerTreeHostImpl::SetDeviceScaleFactor(float device_scale_factor) {
|
| if (renderer_)
|
| renderer_->ViewportChanged();
|
|
|
| - UpdateMaxScrollOffset();
|
| SetFullRootLayerDamage();
|
| }
|
|
|
| @@ -1885,10 +1891,6 @@ const gfx::Transform& LayerTreeHostImpl::DrawTransform() const {
|
| return external_transform_;
|
| }
|
|
|
| -void LayerTreeHostImpl::UpdateMaxScrollOffset() {
|
| - active_tree_->UpdateMaxScrollOffset();
|
| -}
|
| -
|
| void LayerTreeHostImpl::DidChangeTopControlsPosition() {
|
| client_->SetNeedsRedrawOnImplThread();
|
| active_tree_->set_needs_update_draw_properties();
|
| @@ -1948,7 +1950,9 @@ LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint(
|
| if (!potentially_scrolling_layer_impl && top_controls_manager_ &&
|
| top_controls_manager_->content_top_offset() !=
|
| settings_.top_controls_height) {
|
| - potentially_scrolling_layer_impl = RootScrollLayer();
|
| + potentially_scrolling_layer_impl =
|
| + OuterViewportScrollLayer() ? OuterViewportScrollLayer()
|
| + : InnerViewportScrollLayer();
|
| }
|
|
|
| return potentially_scrolling_layer_impl;
|
| @@ -1984,7 +1988,9 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
|
|
|
| // If we want to send a DidOverscroll for this scroll it can't be ignored.
|
| if (!potentially_scrolling_layer_impl && settings_.always_overscroll)
|
| - potentially_scrolling_layer_impl = RootScrollLayer();
|
| + potentially_scrolling_layer_impl =
|
| + OuterViewportScrollLayer() ? OuterViewportScrollLayer()
|
| + : InnerViewportScrollLayer();
|
|
|
| if (potentially_scrolling_layer_impl) {
|
| active_tree_->SetCurrentlyScrollingLayer(
|
| @@ -2093,7 +2099,7 @@ bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
|
| bool did_scroll_x = false;
|
| bool did_scroll_y = false;
|
| bool consume_by_top_controls = top_controls_manager_ &&
|
| - (CurrentlyScrollingLayer() == RootScrollLayer() || scroll_delta.y() < 0);
|
| + (CurrentlyScrollingLayer() == InnerViewportScrollLayer() || scroll_delta.y() < 0);
|
| last_scroll_did_bubble_ = false;
|
|
|
| for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
|
| @@ -2102,13 +2108,11 @@ 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.
|
| - if (consume_by_top_controls && layer_impl == RootScrollLayer()) {
|
| + if (consume_by_top_controls && layer_impl == InnerViewportScrollLayer())
|
| pending_delta = top_controls_manager_->ScrollBy(pending_delta);
|
| - UpdateMaxScrollOffset();
|
| - }
|
| // Track root layer deltas for reporting overscroll.
|
| unused_root_delta = pending_delta;
|
| }
|
| @@ -2146,7 +2150,8 @@ bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
|
| break;
|
| }
|
|
|
| - if (layer_impl == RootScrollLayer())
|
| + if (layer_impl == InnerViewportScrollLayer() ||
|
| + layer_impl == OuterViewportScrollLayer())
|
| unused_root_delta.Subtract(applied_delta);
|
|
|
| did_lock_scrolling_layer_ = true;
|
| @@ -2213,10 +2218,11 @@ 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();
|
| + // TODO(wjmaclean) make sure this is ok!
|
| + 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.
|
| @@ -2272,8 +2278,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;
|
| }
|
| @@ -2333,6 +2339,7 @@ void LayerTreeHostImpl::MouseMoveAt(gfx::Point viewport_point) {
|
| }
|
|
|
| bool scroll_on_main_thread = false;
|
| + // wjm - what does FindScrollLayerForDeviceViewportPoint exactly do?
|
| LayerImpl* scroll_layer_impl = FindScrollLayerForDeviceViewportPoint(
|
| device_viewport_point, InputHandler::Gesture, layer_impl,
|
| &scroll_on_main_thread);
|
| @@ -2344,11 +2351,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) What to do with this? is it ok to choose 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_);
|
| @@ -2382,14 +2393,24 @@ 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());
|
| + }
|
| }
|
|
|
| void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
|
| gfx::Point anchor) {
|
| TRACE_EVENT0("cc", "LayerTreeHostImpl::PinchGestureUpdate");
|
|
|
| - if (!RootScrollLayer())
|
| + LayerImpl* pinch_scroll_layer = CurrentlyScrollingLayer();
|
| + if (!pinch_scroll_layer)
|
| + pinch_scroll_layer = InnerViewportScrollLayer();
|
| +
|
| + if (!pinch_scroll_layer)
|
| return;
|
|
|
| // Keep the center-of-pinch anchor specified by (x, y) in a stable
|
| @@ -2406,9 +2427,43 @@ void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
|
| previous_pinch_anchor_ = anchor;
|
|
|
| move.Scale(1 / active_tree_->page_scale_factor());
|
| -
|
| - RootScrollLayer()->ScrollBy(move);
|
| -
|
| + // When shrinking the page, the current scroll offset of the inner viewport
|
| + // scroll layer may need to be adjusted so that it doesn't exceed its maximum
|
| + // at the new page scale factor.
|
| + if (magnify_delta < 1.f) {
|
| + // If clamping the inner viewport scroll offset causes a change, it should
|
| + // be accounted for from the intended move.
|
| + move -= InnerViewportScrollLayer()->ClampScrollToMaxScrollOffset();
|
| + }
|
| +
|
| + // 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 = pinch_scroll_layer->ScrollBy(move);
|
| +
|
| + if (!unused.IsZero() && pinch_scroll_layer == OuterViewportScrollLayer()) {
|
| + InnerViewportScrollLayer()->ScrollBy(unused);
|
| + InnerViewportScrollLayer()->ClampScrollToMaxScrollOffset();
|
| + active_tree_->SetCurrentlyScrollingLayer(
|
| + active_tree_->InnerViewportScrollLayer());
|
| + }
|
| +/*
|
| + // Don't enable during unit tests.
|
| + {
|
| + gfx::Vector2d maxi = InnerViewportScrollLayer()->MaxScrollOffset();
|
| + gfx::Vector2d maxo = OuterViewportScrollLayer()->MaxScrollOffset();
|
| + gfx::Vector2dF offi = InnerViewportScrollLayer()->TotalScrollOffset();
|
| + gfx::Vector2dF offo = OuterViewportScrollLayer()->TotalScrollOffset();
|
| + fprintf(stderr, "wjm: Viewport summary: ovsl = (%f,%f) of (%d,%d), ivsl = (%f,%f) of (%d,%d)\n",
|
| + offo.x(), offo.y(),
|
| + maxo.x(), maxo.y(),
|
| + offi.x(), offi.y(),
|
| + maxi.x(), maxi.y());
|
| + }
|
| +*/
|
| client_->SetNeedsCommitOnImplThread();
|
| client_->SetNeedsRedrawOnImplThread();
|
| client_->RenewTreePriority();
|
| @@ -2457,12 +2512,11 @@ void LayerTreeHostImpl::SetFullRootLayerDamage() {
|
| }
|
|
|
| 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);
|
| @@ -2473,7 +2527,7 @@ void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) {
|
| gfx::Vector2dF next_scroll =
|
| page_scale_animation_->ScrollOffsetAtTime(monotonic_time);
|
|
|
| - RootScrollLayer()->ScrollBy(next_scroll - scroll_total);
|
| + ScrollBy(gfx::Point(), next_scroll - scroll_total);
|
| client_->SetNeedsRedrawOnImplThread();
|
|
|
| if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) {
|
| @@ -2484,14 +2538,14 @@ 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;
|
| - RootScrollLayer()->ScrollBy(gfx::ScaleVector2d(
|
| - scroll, 1.f / active_tree_->total_page_scale_factor()));
|
| + ScrollBy(gfx::Point(),
|
| + gfx::ScaleVector2d(scroll,
|
| + 1.f / active_tree_->total_page_scale_factor()));
|
| }
|
|
|
| void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time,
|
|
|