diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-06-18 14:10:49 +0200 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2015-06-18 13:53:24 +0000 |
commit | 813fbf95af77a531c57a8c497345ad2c61d475b3 (patch) | |
tree | 821b2c8de8365f21b6c9ba17a236fb3006a1d506 /chromium/cc/input | |
parent | af6588f8d723931a298c995fa97259bb7f7deb55 (diff) | |
download | qtwebengine-chromium-813fbf95af77a531c57a8c497345ad2c61d475b3.tar.gz |
BASELINE: Update chromium to 44.0.2403.47
Change-Id: Ie056fedba95cf5e5c76b30c4b2c80fca4764aa2f
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'chromium/cc/input')
-rw-r--r-- | chromium/cc/input/input_handler.h | 38 | ||||
-rw-r--r-- | chromium/cc/input/layer_selection_bound.h | 3 | ||||
-rw-r--r-- | chromium/cc/input/page_scale_animation.h | 19 | ||||
-rw-r--r-- | chromium/cc/input/scroll_elasticity_helper.cc | 91 | ||||
-rw-r--r-- | chromium/cc/input/scroll_elasticity_helper.h | 73 | ||||
-rw-r--r-- | chromium/cc/input/selection.h | 38 | ||||
-rw-r--r-- | chromium/cc/input/top_controls_manager.cc | 172 | ||||
-rw-r--r-- | chromium/cc/input/top_controls_manager.h | 34 | ||||
-rw-r--r-- | chromium/cc/input/top_controls_manager_client.h | 5 | ||||
-rw-r--r-- | chromium/cc/input/top_controls_manager_unittest.cc | 286 |
10 files changed, 536 insertions, 223 deletions
diff --git a/chromium/cc/input/input_handler.h b/chromium/cc/input/input_handler.h index 7a9c9919687..81d91b87143 100644 --- a/chromium/cc/input/input_handler.h +++ b/chromium/cc/input/input_handler.h @@ -9,8 +9,8 @@ #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "cc/base/cc_export.h" -#include "cc/base/swap_promise_monitor.h" #include "cc/input/scrollbar.h" +#include "cc/trees/swap_promise_monitor.h" namespace gfx { class Point; @@ -24,6 +24,7 @@ namespace ui { struct LatencyInfo; } namespace cc { class LayerScrollOffsetDelegate; +class ScrollElasticityHelper; struct CC_EXPORT InputHandlerScrollResult { InputHandlerScrollResult(); @@ -47,6 +48,7 @@ class CC_EXPORT InputHandlerClient { virtual void WillShutdown() = 0; virtual void Animate(base::TimeTicks time) = 0; virtual void MainThreadHasStoppedFlinging() = 0; + virtual void ReconcileElasticOverscrollAndRootScroll() = 0; protected: InputHandlerClient() {} @@ -64,14 +66,14 @@ class CC_EXPORT InputHandler { // Note these are used in a histogram. Do not reorder or delete existing // entries. enum ScrollStatus { - ScrollOnMainThread = 0, - ScrollStarted, - ScrollIgnored, - ScrollUnknown, + SCROLL_ON_MAIN_THREAD = 0, + SCROLL_STARTED, + SCROLL_IGNORED, + SCROLL_UNKNOWN, // This must be the last entry. ScrollStatusCount }; - enum ScrollInputType { Gesture, Wheel, NonBubblingGesture }; + enum ScrollInputType { GESTURE, WHEEL, NON_BUBBLING_GESTURE }; // Binds a client to this handler to receive notifications. Only one client // can be bound to an InputHandler. The client must live at least until the @@ -79,10 +81,10 @@ class CC_EXPORT InputHandler { virtual void BindToClient(InputHandlerClient* client) = 0; // Selects a layer to be scrolled at a given point in viewport (logical - // pixel) coordinates. Returns ScrollStarted if the layer at the coordinates - // can be scrolled, ScrollOnMainThread if the scroll event should instead be - // delegated to the main thread, or ScrollIgnored if there is nothing to be - // scrolled at the given coordinates. + // pixel) coordinates. Returns SCROLL_STARTED if the layer at the coordinates + // can be scrolled, SCROLL_ON_MAIN_THREAD if the scroll event should instead + // be delegated to the main thread, or SCROLL_IGNORED if there is nothing to + // be scrolled at the given coordinates. virtual ScrollStatus ScrollBegin(const gfx::Point& viewport_point, ScrollInputType type) = 0; @@ -100,7 +102,7 @@ class CC_EXPORT InputHandler { // If the scroll delta hits the root layer, and the layer can no longer move, // the root overscroll accumulated within this ScrollBegin() scope is reported // in the return value's |accumulated_overscroll| field. - // Should only be called if ScrollBegin() returned ScrollStarted. + // Should only be called if ScrollBegin() returned SCROLL_STARTED. virtual InputHandlerScrollResult ScrollBy( const gfx::Point& viewport_point, const gfx::Vector2dF& scroll_delta) = 0; @@ -108,14 +110,14 @@ class CC_EXPORT InputHandler { virtual bool ScrollVerticallyByPage(const gfx::Point& viewport_point, ScrollDirection direction) = 0; - // Returns ScrollStarted if a layer was being actively being scrolled, - // ScrollIgnored if not. + // Returns SCROLL_STARTED if a layer was being actively being scrolled, + // SCROLL_IGNORED if not. virtual ScrollStatus FlingScrollBegin() = 0; virtual void MouseMoveAt(const gfx::Point& mouse_position) = 0; // Stop scrolling the selected layer. Should only be called if ScrollBegin() - // returned ScrollStarted. + // returned SCROLL_STARTED. virtual void ScrollEnd() = 0; virtual void SetRootLayerScrollOffsetDelegate( @@ -140,7 +142,11 @@ class CC_EXPORT InputHandler { virtual bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point, ScrollInputType type) = 0; - virtual bool HaveTouchEventHandlersAt(const gfx::Point& viewport_point) = 0; + virtual bool HaveWheelEventHandlersAt(const gfx::Point& viewport_point) = 0; + + // Whether the page should be given the opportunity to suppress scrolling by + // consuming touch events that started at |viewport_point|. + virtual bool DoTouchEventsBlockScrollAt(const gfx::Point& viewport_point) = 0; // Calling CreateLatencyInfoSwapPromiseMonitor() to get a scoped // LatencyInfoSwapPromiseMonitor. During the life time of the @@ -150,6 +156,8 @@ class CC_EXPORT InputHandler { virtual scoped_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor( ui::LatencyInfo* latency) = 0; + virtual ScrollElasticityHelper* CreateScrollElasticityHelper() = 0; + protected: InputHandler() {} virtual ~InputHandler() {} diff --git a/chromium/cc/input/layer_selection_bound.h b/chromium/cc/input/layer_selection_bound.h index 21d52849cf3..10b14d904d2 100644 --- a/chromium/cc/input/layer_selection_bound.h +++ b/chromium/cc/input/layer_selection_bound.h @@ -6,6 +6,7 @@ #define CC_INPUT_LAYER_SELECTION_BOUND_H_ #include "cc/base/cc_export.h" +#include "cc/input/selection.h" #include "cc/input/selection_bound_type.h" #include "ui/gfx/geometry/point_f.h" @@ -25,6 +26,8 @@ struct CC_EXPORT LayerSelectionBound { bool operator==(const LayerSelectionBound& lhs, const LayerSelectionBound& rhs); bool operator!=(const LayerSelectionBound& lhs, const LayerSelectionBound& rhs); +typedef Selection<LayerSelectionBound> LayerSelection; + } // namespace cc #endif // CC_INPUT_LAYER_SELECTION_BOUND_H_ diff --git a/chromium/cc/input/page_scale_animation.h b/chromium/cc/input/page_scale_animation.h index ce13dcf8ba7..0e430c212fe 100644 --- a/chromium/cc/input/page_scale_animation.h +++ b/chromium/cc/input/page_scale_animation.h @@ -10,12 +10,31 @@ #include "base/time/time.h" #include "cc/base/cc_export.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { class TimingFunction; +// Used in the CC to pass around a scale animation that hasn't yet been +// initialized. +struct PendingPageScaleAnimation { + PendingPageScaleAnimation( + const gfx::Vector2d _target_offset, + bool _use_anchor, + float _scale, + const base::TimeDelta& _duration) + : target_offset(_target_offset), + use_anchor(_use_anchor), + scale(_scale), + duration(_duration) {} + gfx::Vector2d target_offset; + bool use_anchor; + float scale; + base::TimeDelta duration; +}; + // A small helper class that does the math for zoom animations, primarily for // double-tap zoom. Initialize it with starting and ending scroll/page scale // positions and an animation length time, then call ...AtTime() at every frame diff --git a/chromium/cc/input/scroll_elasticity_helper.cc b/chromium/cc/input/scroll_elasticity_helper.cc new file mode 100644 index 00000000000..1c496d90531 --- /dev/null +++ b/chromium/cc/input/scroll_elasticity_helper.cc @@ -0,0 +1,91 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/input/scroll_elasticity_helper.h" + +#include "cc/layers/layer_impl.h" +#include "cc/trees/layer_tree_host_impl.h" +#include "cc/trees/layer_tree_impl.h" + +namespace cc { + +class ScrollElasticityHelperImpl : public ScrollElasticityHelper { + public: + explicit ScrollElasticityHelperImpl(LayerTreeHostImpl* layer_tree_host_impl); + ~ScrollElasticityHelperImpl() override; + + bool IsUserScrollable() const override; + gfx::Vector2dF StretchAmount() const override; + void SetStretchAmount(const gfx::Vector2dF& stretch_amount) override; + gfx::ScrollOffset ScrollOffset() const override; + gfx::ScrollOffset MaxScrollOffset() const override; + void ScrollBy(const gfx::Vector2dF& delta) override; + void RequestAnimate() override; + + private: + LayerTreeHostImpl* layer_tree_host_impl_; +}; + +ScrollElasticityHelperImpl::ScrollElasticityHelperImpl( + LayerTreeHostImpl* layer_tree) + : layer_tree_host_impl_(layer_tree) { +} + +ScrollElasticityHelperImpl::~ScrollElasticityHelperImpl() { +} + +bool ScrollElasticityHelperImpl::IsUserScrollable() const { + LayerImpl* layer = layer_tree_host_impl_->OuterViewportScrollLayer(); + if (!layer) + return false; + return layer->user_scrollable_horizontal() || + layer->user_scrollable_vertical(); +} + +gfx::Vector2dF ScrollElasticityHelperImpl::StretchAmount() const { + return layer_tree_host_impl_->active_tree()->elastic_overscroll()->Current( + true); +} + +void ScrollElasticityHelperImpl::SetStretchAmount( + const gfx::Vector2dF& stretch_amount) { + if (stretch_amount == StretchAmount()) + return; + + layer_tree_host_impl_->active_tree()->elastic_overscroll()->SetCurrent( + stretch_amount); + layer_tree_host_impl_->active_tree()->set_needs_update_draw_properties(); + layer_tree_host_impl_->SetNeedsCommit(); + layer_tree_host_impl_->SetNeedsRedraw(); + layer_tree_host_impl_->SetFullRootLayerDamage(); +} + +gfx::ScrollOffset ScrollElasticityHelperImpl::ScrollOffset() const { + return layer_tree_host_impl_->active_tree()->TotalScrollOffset(); +} + +gfx::ScrollOffset ScrollElasticityHelperImpl::MaxScrollOffset() const { + return layer_tree_host_impl_->active_tree()->TotalMaxScrollOffset(); +} + +void ScrollElasticityHelperImpl::ScrollBy(const gfx::Vector2dF& delta) { + LayerImpl* root_scroll_layer = + layer_tree_host_impl_->OuterViewportScrollLayer() + ? layer_tree_host_impl_->OuterViewportScrollLayer() + : layer_tree_host_impl_->InnerViewportScrollLayer(); + if (root_scroll_layer) + root_scroll_layer->ScrollBy(delta); +} + +void ScrollElasticityHelperImpl::RequestAnimate() { + layer_tree_host_impl_->SetNeedsAnimate(); +} + +// static +ScrollElasticityHelper* ScrollElasticityHelper::CreateForLayerTreeHostImpl( + LayerTreeHostImpl* layer_tree_host_impl) { + return new ScrollElasticityHelperImpl(layer_tree_host_impl); +} + +} // namespace cc diff --git a/chromium/cc/input/scroll_elasticity_helper.h b/chromium/cc/input/scroll_elasticity_helper.h new file mode 100644 index 00000000000..a2bdbfe709f --- /dev/null +++ b/chromium/cc/input/scroll_elasticity_helper.h @@ -0,0 +1,73 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_INPUT_SCROLL_ELASTICITY_HELPER_H_ +#define CC_INPUT_SCROLL_ELASTICITY_HELPER_H_ + +#include "base/time/time.h" +#include "cc/base/cc_export.h" +#include "ui/gfx/geometry/scroll_offset.h" +#include "ui/gfx/geometry/vector2d_f.h" + +namespace cc { + +class LayerTreeHostImpl; + +// ScrollElasticityHelper is based on +// WebKit/Source/platform/mac/ScrollElasticityController.h +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Interface between a LayerTreeHostImpl and the ScrollElasticityController. It +// would be possible, in principle, for LayerTreeHostImpl to implement this +// interface itself. This artificial boundary is introduced to reduce the amount +// of logic and state held directly inside LayerTreeHostImpl. +class CC_EXPORT ScrollElasticityHelper { + public: + static ScrollElasticityHelper* CreateForLayerTreeHostImpl( + LayerTreeHostImpl* layer_tree_host_impl); + + virtual ~ScrollElasticityHelper() {} + + virtual bool IsUserScrollable() const = 0; + + // The amount that the view is stretched past the normal allowable bounds. + virtual gfx::Vector2dF StretchAmount() const = 0; + virtual void SetStretchAmount(const gfx::Vector2dF& stretch_amount) = 0; + + // Functions for the scrolling of the root scroll layer. + virtual gfx::ScrollOffset ScrollOffset() const = 0; + virtual gfx::ScrollOffset MaxScrollOffset() const = 0; + virtual void ScrollBy(const gfx::Vector2dF& delta) = 0; + + // Request that the controller have its Animate method called for the next + // frame. + virtual void RequestAnimate() = 0; +}; + +} // namespace cc + +#endif // CC_INPUT_SCROLL_ELASTICITY_HELPER_H_ diff --git a/chromium/cc/input/selection.h b/chromium/cc/input/selection.h new file mode 100644 index 00000000000..1f3c6ebac05 --- /dev/null +++ b/chromium/cc/input/selection.h @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_INPUT_SELECTION_H_ +#define CC_INPUT_SELECTION_H_ + +#include "cc/base/cc_export.h" + +namespace cc { + +template <typename BoundType> +struct CC_EXPORT Selection { + Selection() : is_editable(false), is_empty_text_form_control(false) {} + ~Selection() {} + + BoundType start, end; + bool is_editable; + bool is_empty_text_form_control; +}; + +template <typename BoundType> +inline bool operator==(const Selection<BoundType>& lhs, + const Selection<BoundType>& rhs) { + return lhs.start == rhs.start && lhs.end == rhs.end && + lhs.is_editable == rhs.is_editable && + lhs.is_empty_text_form_control == rhs.is_empty_text_form_control; +} + +template <typename BoundType> +inline bool operator!=(const Selection<BoundType>& lhs, + const Selection<BoundType>& rhs) { + return !(lhs == rhs); +} + +} // namespace cc + +#endif // CC_INPUT_SELECTION_H_ diff --git a/chromium/cc/input/top_controls_manager.cc b/chromium/cc/input/top_controls_manager.cc index cd3534c1764..c8bd5348721 100644 --- a/chromium/cc/input/top_controls_manager.cc +++ b/chromium/cc/input/top_controls_manager.cc @@ -26,29 +26,23 @@ const int64 kShowHideMaxDurationMs = 200; // static scoped_ptr<TopControlsManager> TopControlsManager::Create( TopControlsManagerClient* client, - float top_controls_height, float top_controls_show_threshold, float top_controls_hide_threshold) { return make_scoped_ptr(new TopControlsManager(client, - top_controls_height, top_controls_show_threshold, top_controls_hide_threshold)); } TopControlsManager::TopControlsManager(TopControlsManagerClient* client, - float top_controls_height, float top_controls_show_threshold, float top_controls_hide_threshold) : client_(client), animation_direction_(NO_ANIMATION), permitted_state_(BOTH), - top_controls_height_(top_controls_height), - current_scroll_delta_(0.f), - controls_scroll_begin_offset_(0.f), - top_controls_show_height_( - top_controls_height * top_controls_hide_threshold), - top_controls_hide_height_( - top_controls_height * (1.f - top_controls_show_threshold)), + accumulated_scroll_delta_(0.f), + baseline_content_offset_(0.f), + top_controls_show_threshold_(top_controls_hide_threshold), + top_controls_hide_threshold_(top_controls_show_threshold), pinch_gesture_active_(false) { CHECK(client_); } @@ -56,12 +50,20 @@ TopControlsManager::TopControlsManager(TopControlsManagerClient* client, TopControlsManager::~TopControlsManager() { } -float TopControlsManager::ControlsTopOffset() { - return client_->ControlsTopOffset(); +float TopControlsManager::ControlsTopOffset() const { + return ContentTopOffset() - TopControlsHeight(); } -float TopControlsManager::ContentTopOffset() { - return client_->ControlsTopOffset() + top_controls_height_; +float TopControlsManager::ContentTopOffset() const { + return TopControlsShownRatio() * TopControlsHeight(); +} + +float TopControlsManager::TopControlsShownRatio() const { + return client_->CurrentTopControlsShownRatio(); +} + +float TopControlsManager::TopControlsHeight() const { + return client_->TopControlsHeight(); } void TopControlsManager::UpdateTopControlsState(TopControlsState constraints, @@ -77,35 +79,31 @@ void TopControlsManager::UpdateTopControlsState(TopControlsState constraints, return; // Don't do anything if there is no change in offset. - float final_controls_position = 0.f; - if (constraints == HIDDEN || current == HIDDEN) { - final_controls_position = -top_controls_height_; - } - if (final_controls_position == client_->ControlsTopOffset()) { + float final_shown_ratio = 1.f; + if (constraints == HIDDEN || current == HIDDEN) + final_shown_ratio = 0.f; + if (final_shown_ratio == TopControlsShownRatio()) return; - } - AnimationDirection animation_direction = SHOWING_CONTROLS; - if (constraints == HIDDEN || current == HIDDEN) - animation_direction = HIDING_CONTROLS; - ResetAnimations(); if (animate) { - SetupAnimation(animation_direction); + SetupAnimation(final_shown_ratio ? SHOWING_CONTROLS : HIDING_CONTROLS); } else { - client_->SetControlsTopOffset(final_controls_position); + ResetAnimations(); + client_->SetCurrentTopControlsShownRatio(final_shown_ratio); } - client_->DidChangeTopControlsPosition(); } void TopControlsManager::ScrollBegin() { DCHECK(!pinch_gesture_active_); ResetAnimations(); - current_scroll_delta_ = 0.f; - controls_scroll_begin_offset_ = client_->ControlsTopOffset(); + ResetBaseline(); } gfx::Vector2dF TopControlsManager::ScrollBy( const gfx::Vector2dF& pending_delta) { + if (!TopControlsHeight()) + return pending_delta; + if (pinch_gesture_active_) return pending_delta; @@ -114,21 +112,21 @@ gfx::Vector2dF TopControlsManager::ScrollBy( else if (permitted_state_ == HIDDEN && pending_delta.y() < 0) return pending_delta; - current_scroll_delta_ += pending_delta.y(); + accumulated_scroll_delta_ += pending_delta.y(); - float old_offset = client_->ControlsTopOffset(); - SetControlsTopOffset(controls_scroll_begin_offset_ - current_scroll_delta_); + float old_offset = ContentTopOffset(); + client_->SetCurrentTopControlsShownRatio( + (baseline_content_offset_ - accumulated_scroll_delta_) / + TopControlsHeight()); // If the controls are fully visible, treat the current position as the // new baseline even if the gesture didn't end. - if (client_->ControlsTopOffset() == 0.f) { - current_scroll_delta_ = 0.f; - controls_scroll_begin_offset_ = 0.f; - } + if (TopControlsShownRatio() == 1.f) + ResetBaseline(); ResetAnimations(); - gfx::Vector2dF applied_delta(0.f, old_offset - client_->ControlsTopOffset()); + gfx::Vector2dF applied_delta(0.f, old_offset - ContentTopOffset()); return pending_delta - applied_delta; } @@ -151,31 +149,24 @@ void TopControlsManager::PinchEnd() { ScrollBegin(); } -void TopControlsManager::SetControlsTopOffset(float controls_top_offset) { - controls_top_offset = std::max(controls_top_offset, -top_controls_height_); - controls_top_offset = std::min(controls_top_offset, 0.f); - - if (client_->ControlsTopOffset() == controls_top_offset) - return; - - client_->SetControlsTopOffset(controls_top_offset); - - client_->DidChangeTopControlsPosition(); +void TopControlsManager::MainThreadHasStoppedFlinging() { + StartAnimationIfNecessary(); } gfx::Vector2dF TopControlsManager::Animate(base::TimeTicks monotonic_time) { if (!top_controls_animation_ || !client_->HaveRootScrollLayer()) return gfx::Vector2dF(); - double time = (monotonic_time - base::TimeTicks()).InMillisecondsF(); + base::TimeDelta time = monotonic_time - base::TimeTicks(); - float old_offset = client_->ControlsTopOffset(); - SetControlsTopOffset(top_controls_animation_->GetValue(time)); + float old_offset = ContentTopOffset(); + client_->SetCurrentTopControlsShownRatio( + top_controls_animation_->GetValue(time)); if (IsAnimationCompleteAtTime(monotonic_time)) ResetAnimations(); - gfx::Vector2dF scroll_delta(0.f, client_->ControlsTopOffset() - old_offset); + gfx::Vector2dF scroll_delta(0.f, ContentTopOffset() - old_offset); return scroll_delta; } @@ -185,55 +176,48 @@ void TopControlsManager::ResetAnimations() { } void TopControlsManager::SetupAnimation(AnimationDirection direction) { - DCHECK(direction != NO_ANIMATION); + DCHECK_NE(NO_ANIMATION, direction); + DCHECK_IMPLIES(direction == HIDING_CONTROLS, TopControlsShownRatio() > 0.f); + DCHECK_IMPLIES(direction == SHOWING_CONTROLS, TopControlsShownRatio() < 1.f); - if (direction == SHOWING_CONTROLS && client_->ControlsTopOffset() == 0) + if (top_controls_animation_ && animation_direction_ == direction) return; - if (direction == HIDING_CONTROLS && - client_->ControlsTopOffset() == -top_controls_height_) { + if (!TopControlsHeight()) { + client_->SetCurrentTopControlsShownRatio( + direction == HIDING_CONTROLS ? 0.f : 1.f); return; } - if (top_controls_animation_ && animation_direction_ == direction) - return; - top_controls_animation_ = KeyframedFloatAnimationCurve::Create(); - double start_time = - (gfx::FrameTime::Now() - base::TimeTicks()).InMillisecondsF(); - top_controls_animation_->AddKeyframe( - FloatKeyframe::Create(start_time, client_->ControlsTopOffset(), nullptr)); - float max_ending_offset = - (direction == SHOWING_CONTROLS ? 1 : -1) * top_controls_height_; + base::TimeDelta start_time = gfx::FrameTime::Now() - base::TimeTicks(); top_controls_animation_->AddKeyframe( - FloatKeyframe::Create(start_time + kShowHideMaxDurationMs, - client_->ControlsTopOffset() + max_ending_offset, - EaseTimingFunction::Create())); + FloatKeyframe::Create(start_time, TopControlsShownRatio(), nullptr)); + float max_ending_ratio = (direction == SHOWING_CONTROLS ? 1 : -1); + top_controls_animation_->AddKeyframe(FloatKeyframe::Create( + start_time + base::TimeDelta::FromMilliseconds(kShowHideMaxDurationMs), + TopControlsShownRatio() + max_ending_ratio, + EaseTimingFunction::Create())); animation_direction_ = direction; client_->DidChangeTopControlsPosition(); } void TopControlsManager::StartAnimationIfNecessary() { - if (client_->ControlsTopOffset() != 0 - && client_->ControlsTopOffset() != -top_controls_height_) { - AnimationDirection show_controls = NO_ANIMATION; - - if (client_->ControlsTopOffset() >= -top_controls_show_height_) { - // If we're showing so much that the hide threshold won't trigger, show. - show_controls = SHOWING_CONTROLS; - } else if (client_->ControlsTopOffset() <= -top_controls_hide_height_) { - // If we're showing so little that the show threshold won't trigger, hide. - show_controls = HIDING_CONTROLS; - } else { - // If we could be either showing or hiding, we determine which one to - // do based on whether or not the total scroll delta was moving up or - // down. - show_controls = current_scroll_delta_ <= 0.f ? - SHOWING_CONTROLS : HIDING_CONTROLS; - } - - if (show_controls != NO_ANIMATION) - SetupAnimation(show_controls); + if (TopControlsShownRatio() == 0.f || TopControlsShownRatio() == 1.f) + return; + + if (TopControlsShownRatio() >= 1.f - top_controls_hide_threshold_) { + // If we're showing so much that the hide threshold won't trigger, show. + SetupAnimation(SHOWING_CONTROLS); + } else if (TopControlsShownRatio() <= top_controls_show_threshold_) { + // If we're showing so little that the show threshold won't trigger, hide. + SetupAnimation(HIDING_CONTROLS); + } else { + // If we could be either showing or hiding, we determine which one to + // do based on whether or not the total scroll delta was moving up or + // down. + SetupAnimation(accumulated_scroll_delta_ <= 0.f ? SHOWING_CONTROLS + : HIDING_CONTROLS); } } @@ -241,15 +225,19 @@ bool TopControlsManager::IsAnimationCompleteAtTime(base::TimeTicks time) { if (!top_controls_animation_) return true; - double time_ms = (time - base::TimeTicks()).InMillisecondsF(); - float new_offset = top_controls_animation_->GetValue(time_ms); + base::TimeDelta animation_time = time - base::TimeTicks(); + float new_ratio = top_controls_animation_->GetValue(animation_time); - if ((animation_direction_ == SHOWING_CONTROLS && new_offset >= 0) || - (animation_direction_ == HIDING_CONTROLS - && new_offset <= -top_controls_height_)) { + if ((animation_direction_ == SHOWING_CONTROLS && new_ratio >= 1.f) || + (animation_direction_ == HIDING_CONTROLS && new_ratio <= 0.f)) { return true; } return false; } +void TopControlsManager::ResetBaseline() { + accumulated_scroll_delta_ = 0.f; + baseline_content_offset_ = ContentTopOffset(); +} + } // namespace cc diff --git a/chromium/cc/input/top_controls_manager.h b/chromium/cc/input/top_controls_manager.h index a90d33d3e4a..fc40378f5f8 100644 --- a/chromium/cc/input/top_controls_manager.h +++ b/chromium/cc/input/top_controls_manager.h @@ -34,14 +34,14 @@ class CC_EXPORT TopControlsManager static scoped_ptr<TopControlsManager> Create( TopControlsManagerClient* client, - float top_controls_height, float top_controls_show_threshold, float top_controls_hide_threshold); virtual ~TopControlsManager(); - float controls_height() { return top_controls_height_; } - float ControlsTopOffset(); - float ContentTopOffset(); + float ControlsTopOffset() const; + float ContentTopOffset() const; + float TopControlsShownRatio() const; + float TopControlsHeight() const; KeyframedFloatAnimationCurve* animation() { return top_controls_animation_.get(); @@ -61,13 +61,12 @@ class CC_EXPORT TopControlsManager void PinchBegin(); void PinchEnd(); + void MainThreadHasStoppedFlinging(); + gfx::Vector2dF Animate(base::TimeTicks monotonic_time); - void SetControlsTopOffset(float offset); - float top_controls_height() { return top_controls_height_; } protected: TopControlsManager(TopControlsManagerClient* client, - float top_controls_height, float top_controls_show_threshold, float top_controls_hide_threshold); @@ -76,6 +75,7 @@ class CC_EXPORT TopControlsManager void SetupAnimation(AnimationDirection direction); void StartAnimationIfNecessary(); bool IsAnimationCompleteAtTime(base::TimeTicks time); + void ResetBaseline(); TopControlsManagerClient* client_; // The client manages the lifecycle of // this. @@ -83,18 +83,20 @@ class CC_EXPORT TopControlsManager scoped_ptr<KeyframedFloatAnimationCurve> top_controls_animation_; AnimationDirection animation_direction_; TopControlsState permitted_state_; - float top_controls_height_; - float current_scroll_delta_; - float controls_scroll_begin_offset_; + // Accumulated scroll delta since last baseline reset + float accumulated_scroll_delta_; + + // Content offset when last baseline reset occurred + float baseline_content_offset_; - // The height of the visible top control such that it must be shown when - // the user stops the scroll. - float top_controls_show_height_; + // The percent height of the visible top control such that it must be shown + // when the user stops the scroll. + float top_controls_show_threshold_; - // The height of the visible top control such that it must be hidden when - // the user stops the scroll. - float top_controls_hide_height_; + // The percent height of the visible top control such that it must be hidden + // when the user stops the scroll. + float top_controls_hide_threshold_; bool pinch_gesture_active_; diff --git a/chromium/cc/input/top_controls_manager_client.h b/chromium/cc/input/top_controls_manager_client.h index 53b5978f097..a0f2f5b16ca 100644 --- a/chromium/cc/input/top_controls_manager_client.h +++ b/chromium/cc/input/top_controls_manager_client.h @@ -11,8 +11,9 @@ class LayerTreeImpl; class CC_EXPORT TopControlsManagerClient { public: - virtual void SetControlsTopOffset(float offset) = 0; - virtual float ControlsTopOffset() const = 0; + virtual float TopControlsHeight() const = 0; + virtual void SetCurrentTopControlsShownRatio(float ratio) = 0; + virtual float CurrentTopControlsShownRatio() const = 0; virtual void DidChangeTopControlsPosition() = 0; virtual bool HaveRootScrollLayer() const = 0; diff --git a/chromium/cc/input/top_controls_manager_unittest.cc b/chromium/cc/input/top_controls_manager_unittest.cc index 77b40c9de05..52e46e674ed 100644 --- a/chromium/cc/input/top_controls_manager_unittest.cc +++ b/chromium/cc/input/top_controls_manager_unittest.cc @@ -4,6 +4,10 @@ #include "cc/input/top_controls_manager.h" +#include <algorithm> +#include <cmath> + +#include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "cc/input/top_controls_manager_client.h" @@ -11,6 +15,7 @@ #include "cc/test/fake_impl_proxy.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/test_shared_bitmap_manager.h" +#include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_impl.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/frame_time.h" @@ -19,19 +24,21 @@ namespace cc { namespace { -static const float kTopControlsHeight = 100; - class MockTopControlsManagerClient : public TopControlsManagerClient { public: - MockTopControlsManagerClient(float top_controls_show_threshold, + MockTopControlsManagerClient(float top_controls_height, + float top_controls_show_threshold, float top_controls_hide_threshold) - : host_impl_(&proxy_, &shared_bitmap_manager_), + : host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_), redraw_needed_(false), update_draw_properties_needed_(false), - top_controls_top_offset_(0.f), + top_controls_shown_ratio_(1.f), + top_controls_height_(top_controls_height), top_controls_show_threshold_(top_controls_show_threshold), top_controls_hide_threshold_(top_controls_hide_threshold) { - active_tree_ = LayerTreeImpl::create(&host_impl_); + active_tree_ = LayerTreeImpl::create( + &host_impl_, new SyncedProperty<ScaleGroup>, new SyncedTopControls, + new SyncedElasticOverscroll); root_scroll_layer_ = LayerImpl::Create(active_tree_.get(), 1); } @@ -44,11 +51,20 @@ class MockTopControlsManagerClient : public TopControlsManagerClient { bool HaveRootScrollLayer() const override { return true; } - void SetControlsTopOffset(float offset) override { - top_controls_top_offset_ = offset; + float TopControlsHeight() const override { return top_controls_height_; } + + void SetCurrentTopControlsShownRatio(float ratio) override { + ASSERT_FALSE(std::isnan(ratio)); + ASSERT_FALSE(ratio == std::numeric_limits<float>::infinity()); + ASSERT_FALSE(ratio == -std::numeric_limits<float>::infinity()); + ratio = std::max(ratio, 0.f); + ratio = std::min(ratio, 1.f); + top_controls_shown_ratio_ = ratio; } - float ControlsTopOffset() const override { return top_controls_top_offset_; } + float CurrentTopControlsShownRatio() const override { + return top_controls_shown_ratio_; + } LayerImpl* rootScrollLayer() { return root_scroll_layer_.get(); @@ -57,16 +73,18 @@ class MockTopControlsManagerClient : public TopControlsManagerClient { TopControlsManager* manager() { if (!manager_) { manager_ = TopControlsManager::Create(this, - kTopControlsHeight, top_controls_show_threshold_, top_controls_hide_threshold_); } return manager_.get(); } + void SetTopControlsHeight(float height) { top_controls_height_ = height; } + private: FakeImplProxy proxy_; TestSharedBitmapManager shared_bitmap_manager_; + TestTaskGraphRunner task_graph_runner_; FakeLayerTreeHostImpl host_impl_; scoped_ptr<LayerTreeImpl> active_tree_; scoped_ptr<LayerImpl> root_scroll_layer_; @@ -74,263 +92,264 @@ class MockTopControlsManagerClient : public TopControlsManagerClient { bool redraw_needed_; bool update_draw_properties_needed_; - float top_controls_top_offset_; + float top_controls_shown_ratio_; + float top_controls_height_; float top_controls_show_threshold_; float top_controls_hide_threshold_; }; TEST(TopControlsManagerTest, EnsureScrollThresholdApplied) { - MockTopControlsManagerClient client(0.5f, 0.5f); + MockTopControlsManagerClient client(100.f, 0.5f, 0.5f); TopControlsManager* manager = client.manager(); manager->ScrollBegin(); // Scroll down to hide the controls entirely. manager->ScrollBy(gfx::Vector2dF(0.f, 30.f)); - EXPECT_EQ(-30.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset()); manager->ScrollBy(gfx::Vector2dF(0.f, 30.f)); - EXPECT_EQ(-60.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-60.f, manager->ControlsTopOffset()); manager->ScrollBy(gfx::Vector2dF(0.f, 100.f)); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); // Scroll back up a bit and ensure the controls don't move until we cross // the threshold. manager->ScrollBy(gfx::Vector2dF(0.f, -10.f)); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); manager->ScrollBy(gfx::Vector2dF(0.f, -50.f)); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); // After hitting the threshold, further scrolling up should result in the top // controls showing. manager->ScrollBy(gfx::Vector2dF(0.f, -10.f)); - EXPECT_EQ(-90.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-90.f, manager->ControlsTopOffset()); manager->ScrollBy(gfx::Vector2dF(0.f, -50.f)); - EXPECT_EQ(-40.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-40.f, manager->ControlsTopOffset()); // Reset the scroll threshold by going further up the page than the initial // threshold. manager->ScrollBy(gfx::Vector2dF(0.f, -100.f)); - EXPECT_EQ(0.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); // See that scrolling down the page now will result in the controls hiding. manager->ScrollBy(gfx::Vector2dF(0.f, 20.f)); - EXPECT_EQ(-20.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-20.f, manager->ControlsTopOffset()); manager->ScrollEnd(); } TEST(TopControlsManagerTest, PartialShownHideAnimation) { - MockTopControlsManagerClient client(0.5f, 0.5f); + MockTopControlsManagerClient client(100.f, 0.5f, 0.5f); TopControlsManager* manager = client.manager(); manager->ScrollBegin(); manager->ScrollBy(gfx::Vector2dF(0.f, 300.f)); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); - EXPECT_EQ(0.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); manager->ScrollEnd(); manager->ScrollBegin(); manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)); - EXPECT_EQ(-85.f, manager->ControlsTopOffset()); - EXPECT_EQ(15.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-85.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(15.f, manager->ContentTopOffset()); manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); base::TimeTicks time = gfx::FrameTime::Now(); - float previous_offset = manager->ControlsTopOffset(); + float previous; while (manager->animation()) { + previous = manager->TopControlsShownRatio(); time = base::TimeDelta::FromMicroseconds(100) + time; manager->Animate(time); - EXPECT_LT(manager->ControlsTopOffset(), previous_offset); - previous_offset = manager->ControlsTopOffset(); + EXPECT_LT(manager->TopControlsShownRatio(), previous); } EXPECT_FALSE(manager->animation()); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); - EXPECT_EQ(0.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); } TEST(TopControlsManagerTest, PartialShownShowAnimation) { - MockTopControlsManagerClient client(0.5f, 0.5f); + MockTopControlsManagerClient client(100.f, 0.5f, 0.5f); TopControlsManager* manager = client.manager(); manager->ScrollBegin(); manager->ScrollBy(gfx::Vector2dF(0.f, 300.f)); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); - EXPECT_EQ(0.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); manager->ScrollEnd(); manager->ScrollBegin(); manager->ScrollBy(gfx::Vector2dF(0.f, -70.f)); - EXPECT_EQ(-30.f, manager->ControlsTopOffset()); - EXPECT_EQ(70.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(70.f, manager->ContentTopOffset()); manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); base::TimeTicks time = gfx::FrameTime::Now(); - float previous_offset = manager->ControlsTopOffset(); + float previous; while (manager->animation()) { + previous = manager->TopControlsShownRatio(); time = base::TimeDelta::FromMicroseconds(100) + time; manager->Animate(time); - EXPECT_GT(manager->ControlsTopOffset(), previous_offset); - previous_offset = manager->ControlsTopOffset(); + EXPECT_GT(manager->TopControlsShownRatio(), previous); } EXPECT_FALSE(manager->animation()); - EXPECT_EQ(0.f, manager->ControlsTopOffset()); - EXPECT_EQ(100.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset()); } TEST(TopControlsManagerTest, PartialHiddenWithAmbiguousThresholdShows) { - MockTopControlsManagerClient client(0.25f, 0.25f); + MockTopControlsManagerClient client(100.f, 0.25f, 0.25f); TopControlsManager* manager = client.manager(); manager->ScrollBegin(); manager->ScrollBy(gfx::Vector2dF(0.f, 20.f)); - EXPECT_EQ(-20.f, manager->ControlsTopOffset()); - EXPECT_EQ(80.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-20.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(80.f, manager->ContentTopOffset()); manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); base::TimeTicks time = gfx::FrameTime::Now(); - float previous_offset = manager->ControlsTopOffset(); + float previous; while (manager->animation()) { + previous = manager->TopControlsShownRatio(); time = base::TimeDelta::FromMicroseconds(100) + time; manager->Animate(time); - EXPECT_GT(manager->ControlsTopOffset(), previous_offset); - previous_offset = manager->ControlsTopOffset(); + EXPECT_GT(manager->TopControlsShownRatio(), previous); } EXPECT_FALSE(manager->animation()); - EXPECT_EQ(0.f, manager->ControlsTopOffset()); - EXPECT_EQ(100.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset()); } TEST(TopControlsManagerTest, PartialHiddenWithAmbiguousThresholdHides) { - MockTopControlsManagerClient client(0.25f, 0.25f); + MockTopControlsManagerClient client(100.f, 0.25f, 0.25f); TopControlsManager* manager = client.manager(); manager->ScrollBegin(); manager->ScrollBy(gfx::Vector2dF(0.f, 30.f)); - EXPECT_EQ(-30.f, manager->ControlsTopOffset()); - EXPECT_EQ(70.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(70.f, manager->ContentTopOffset()); manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); base::TimeTicks time = gfx::FrameTime::Now(); - float previous_offset = manager->ControlsTopOffset(); + float previous; while (manager->animation()) { + previous = manager->TopControlsShownRatio(); time = base::TimeDelta::FromMicroseconds(100) + time; manager->Animate(time); - EXPECT_LT(manager->ControlsTopOffset(), previous_offset); - previous_offset = manager->ControlsTopOffset(); + EXPECT_LT(manager->TopControlsShownRatio(), previous); } EXPECT_FALSE(manager->animation()); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); - EXPECT_EQ(0.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); } TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdHides) { - MockTopControlsManagerClient client(0.25f, 0.25f); + MockTopControlsManagerClient client(100.f, 0.25f, 0.25f); TopControlsManager* manager = client.manager(); manager->ScrollBy(gfx::Vector2dF(0.f, 200.f)); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); - EXPECT_EQ(0.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); manager->ScrollBegin(); manager->ScrollBy(gfx::Vector2dF(0.f, -20.f)); - EXPECT_EQ(-80.f, manager->ControlsTopOffset()); - EXPECT_EQ(20.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset()); manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); base::TimeTicks time = gfx::FrameTime::Now(); - float previous_offset = manager->ControlsTopOffset(); + float previous; while (manager->animation()) { + previous = manager->TopControlsShownRatio(); time = base::TimeDelta::FromMicroseconds(100) + time; manager->Animate(time); - EXPECT_LT(manager->ControlsTopOffset(), previous_offset); - previous_offset = manager->ControlsTopOffset(); + EXPECT_LT(manager->TopControlsShownRatio(), previous); } EXPECT_FALSE(manager->animation()); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); - EXPECT_EQ(0.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); } TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdShows) { - MockTopControlsManagerClient client(0.25f, 0.25f); + MockTopControlsManagerClient client(100.f, 0.25f, 0.25f); TopControlsManager* manager = client.manager(); manager->ScrollBy(gfx::Vector2dF(0.f, 200.f)); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); - EXPECT_EQ(0.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); manager->ScrollBegin(); manager->ScrollBy(gfx::Vector2dF(0.f, -30.f)); - EXPECT_EQ(-70.f, manager->ControlsTopOffset()); - EXPECT_EQ(30.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-70.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(30.f, manager->ContentTopOffset()); manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); base::TimeTicks time = gfx::FrameTime::Now(); - float previous_offset = manager->ControlsTopOffset(); + float previous; while (manager->animation()) { + previous = manager->TopControlsShownRatio(); time = base::TimeDelta::FromMicroseconds(100) + time; manager->Animate(time); - EXPECT_GT(manager->ControlsTopOffset(), previous_offset); - previous_offset = manager->ControlsTopOffset(); + EXPECT_GT(manager->TopControlsShownRatio(), previous); } EXPECT_FALSE(manager->animation()); - EXPECT_EQ(0.f, manager->ControlsTopOffset()); - EXPECT_EQ(100.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset()); } TEST(TopControlsManagerTest, PinchIgnoresScroll) { - MockTopControlsManagerClient client(0.5f, 0.5f); + MockTopControlsManagerClient client(100.f, 0.5f, 0.5f); TopControlsManager* manager = client.manager(); // Hide the controls. manager->ScrollBegin(); - EXPECT_EQ(0.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); manager->ScrollBy(gfx::Vector2dF(0.f, 300.f)); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); manager->PinchBegin(); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); // Scrolls are ignored during pinch. manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); manager->PinchEnd(); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); // Scrolls should no long be ignored. manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)); - EXPECT_EQ(-85.f, manager->ControlsTopOffset()); - EXPECT_EQ(15.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-85.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(15.f, manager->ContentTopOffset()); manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); } TEST(TopControlsManagerTest, PinchBeginStartsAnimationIfNecessary) { - MockTopControlsManagerClient client(0.5f, 0.5f); + MockTopControlsManagerClient client(100.f, 0.5f, 0.5f); TopControlsManager* manager = client.manager(); manager->ScrollBegin(); manager->ScrollBy(gfx::Vector2dF(0.f, 300.f)); - EXPECT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); manager->PinchBegin(); EXPECT_FALSE(manager->animation()); @@ -339,19 +358,19 @@ TEST(TopControlsManagerTest, PinchBeginStartsAnimationIfNecessary) { EXPECT_FALSE(manager->animation()); manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)); - EXPECT_EQ(-85.f, manager->ControlsTopOffset()); - EXPECT_EQ(15.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-85.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(15.f, manager->ContentTopOffset()); manager->PinchBegin(); EXPECT_TRUE(manager->animation()); base::TimeTicks time = base::TimeTicks::Now(); - float previous_offset = manager->ControlsTopOffset(); + float previous; while (manager->animation()) { + previous = manager->TopControlsShownRatio(); time = base::TimeDelta::FromMicroseconds(100) + time; manager->Animate(time); - EXPECT_LT(manager->ControlsTopOffset(), previous_offset); - previous_offset = manager->ControlsTopOffset(); + EXPECT_LT(manager->TopControlsShownRatio(), previous); } EXPECT_FALSE(manager->animation()); @@ -359,24 +378,95 @@ TEST(TopControlsManagerTest, PinchBeginStartsAnimationIfNecessary) { EXPECT_FALSE(manager->animation()); manager->ScrollBy(gfx::Vector2dF(0.f, -55.f)); - EXPECT_EQ(-45.f, manager->ControlsTopOffset()); - EXPECT_EQ(55.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(-45.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(55.f, manager->ContentTopOffset()); EXPECT_FALSE(manager->animation()); manager->ScrollEnd(); EXPECT_TRUE(manager->animation()); time = base::TimeTicks::Now(); - previous_offset = manager->ControlsTopOffset(); while (manager->animation()) { + previous = manager->TopControlsShownRatio(); time = base::TimeDelta::FromMicroseconds(100) + time; manager->Animate(time); - EXPECT_GT(manager->ControlsTopOffset(), previous_offset); - previous_offset = manager->ControlsTopOffset(); + EXPECT_GT(manager->TopControlsShownRatio(), previous); } EXPECT_FALSE(manager->animation()); - EXPECT_EQ(0.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); +} + +TEST(TopControlsManagerTest, HeightChangeMaintainsFullyVisibleControls) { + MockTopControlsManagerClient client(0.f, 0.5f, 0.5f); + TopControlsManager* manager = client.manager(); + + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); + + client.SetTopControlsHeight(100.f); + EXPECT_FALSE(manager->animation()); + EXPECT_FLOAT_EQ(100.f, manager->TopControlsHeight()); + EXPECT_FLOAT_EQ(0, manager->ControlsTopOffset()); + + client.SetTopControlsHeight(50.f); + EXPECT_FALSE(manager->animation()); + EXPECT_FLOAT_EQ(50.f, manager->TopControlsHeight()); + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); +} + +TEST(TopControlsManagerTest, GrowingHeightKeepsTopControlsHidden) { + MockTopControlsManagerClient client(0.f, 0.5f, 0.5f); + TopControlsManager* manager = client.manager(); + client.SetTopControlsHeight(1.f); + manager->UpdateTopControlsState(HIDDEN, HIDDEN, false); + EXPECT_EQ(-1.f, manager->ControlsTopOffset()); + EXPECT_EQ(0.f, manager->ContentTopOffset()); + + client.SetTopControlsHeight(50.f); + EXPECT_FALSE(manager->animation()); + EXPECT_EQ(-50.f, manager->ControlsTopOffset()); + EXPECT_EQ(0.f, manager->ContentTopOffset()); + + client.SetTopControlsHeight(100.f); + EXPECT_FALSE(manager->animation()); + EXPECT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_EQ(0.f, manager->ContentTopOffset()); +} + +TEST(TopControlsManagerTest, ShrinkingHeightKeepsTopControlsHidden) { + MockTopControlsManagerClient client(100.f, 0.5f, 0.5f); + TopControlsManager* manager = client.manager(); + + manager->ScrollBegin(); + manager->ScrollBy(gfx::Vector2dF(0.f, 300.f)); + EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); + manager->ScrollEnd(); + + client.SetTopControlsHeight(50.f); + EXPECT_FALSE(manager->animation()); + EXPECT_FLOAT_EQ(-50.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); + + client.SetTopControlsHeight(0.f); + EXPECT_FALSE(manager->animation()); + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); +} + +TEST(TopControlsManagerTest, ScrollByWithZeroHeightControlsIsNoop) { + MockTopControlsManagerClient client(0.f, 0.5f, 0.5f); + TopControlsManager* manager = client.manager(); + manager->UpdateTopControlsState(BOTH, BOTH, false); + + manager->ScrollBegin(); + gfx::Vector2dF pending = manager->ScrollBy(gfx::Vector2dF(0.f, 20.f)); + EXPECT_FLOAT_EQ(20.f, pending.y()); + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio()); + manager->ScrollEnd(); } + } // namespace } // namespace cc |