Chromium Code Reviews| Index: cc/input/scrollbar_animation_controller.cc |
| diff --git a/cc/input/scrollbar_animation_controller.cc b/cc/input/scrollbar_animation_controller.cc |
| index dd4b6dac8665b458fd053abf32de443bb13c4b6b..4804fd1e6dc46086b0bbda67e84d6dbe10c1d8f3 100644 |
| --- a/cc/input/scrollbar_animation_controller.cc |
| +++ b/cc/input/scrollbar_animation_controller.cc |
| @@ -11,11 +11,37 @@ |
| namespace cc { |
| +std::unique_ptr<ScrollbarAnimationController> |
| +ScrollbarAnimationController::CreateScrollbarAnimationControllerLinearFade( |
| + int scroll_layer_id, |
| + ScrollbarAnimationControllerClient* client, |
| + base::TimeDelta delay_before_starting, |
| + base::TimeDelta resize_delay_before_starting, |
| + base::TimeDelta fade_duration) { |
| + return base::WrapUnique(new ScrollbarAnimationController( |
| + scroll_layer_id, client, delay_before_starting, |
| + resize_delay_before_starting, fade_duration)); |
| +} |
| + |
| +std::unique_ptr<ScrollbarAnimationController> |
| +ScrollbarAnimationController::CreateScrollbarAnimationControllerThinning( |
| + int scroll_layer_id, |
| + ScrollbarAnimationControllerClient* client, |
| + base::TimeDelta delay_before_starting, |
| + base::TimeDelta resize_delay_before_starting, |
| + base::TimeDelta fade_duration, |
| + base::TimeDelta thinning_duration) { |
| + return base::WrapUnique(new ScrollbarAnimationController( |
| + scroll_layer_id, client, delay_before_starting, |
| + resize_delay_before_starting, fade_duration, thinning_duration)); |
| +} |
| + |
| ScrollbarAnimationController::ScrollbarAnimationController( |
| int scroll_layer_id, |
| ScrollbarAnimationControllerClient* client, |
| base::TimeDelta delay_before_starting, |
| - base::TimeDelta resize_delay_before_starting) |
| + base::TimeDelta resize_delay_before_starting, |
| + base::TimeDelta fade_duration) |
| : client_(client), |
| delay_before_starting_(delay_before_starting), |
| resize_delay_before_starting_(resize_delay_before_starting), |
| @@ -23,21 +49,72 @@ ScrollbarAnimationController::ScrollbarAnimationController( |
| scroll_layer_id_(scroll_layer_id), |
| currently_scrolling_(false), |
| scroll_gesture_has_scrolled_(false), |
| + opacity_(0.0f), |
| + fade_duration_(fade_duration), |
| + need_thinning_animation_(false), |
| weak_factory_(this) { |
| + ApplyOpacityToScrollbars(0.0f); |
| +} |
| + |
| +ScrollbarAnimationController::ScrollbarAnimationController( |
| + int scroll_layer_id, |
| + ScrollbarAnimationControllerClient* client, |
| + base::TimeDelta delay_before_starting, |
| + base::TimeDelta resize_delay_before_starting, |
| + base::TimeDelta fade_duration, |
| + base::TimeDelta thinning_duration) |
| + : ScrollbarAnimationController(scroll_layer_id, |
| + client, |
| + delay_before_starting, |
| + resize_delay_before_starting, |
| + fade_duration) { |
| + need_thinning_animation_ = true; |
| + vertical_controller_ = SingleScrollbarAnimationControllerThinning::Create( |
| + scroll_layer_id, ScrollbarOrientation::VERTICAL, client, |
| + thinning_duration); |
| + horizontal_controller_ = SingleScrollbarAnimationControllerThinning::Create( |
| + scroll_layer_id, ScrollbarOrientation::HORIZONTAL, client, |
| + thinning_duration); |
| } |
| ScrollbarAnimationController::~ScrollbarAnimationController() {} |
| +ScrollbarSet ScrollbarAnimationController::Scrollbars() const { |
| + return client_->ScrollbarsFor(scroll_layer_id_); |
| +} |
| + |
| SingleScrollbarAnimationControllerThinning& |
| ScrollbarAnimationController::GetScrollbarAnimationController( |
| ScrollbarOrientation orientation) const { |
| - DCHECK(NeedThinningAnimation()); |
| + DCHECK(need_thinning_animation_); |
| if (orientation == ScrollbarOrientation::VERTICAL) |
| return *(vertical_controller_.get()); |
| else |
| return *(horizontal_controller_.get()); |
| } |
| +void ScrollbarAnimationController::StartAnimation() { |
| + delayed_scrollbar_fade_.Cancel(); |
| + is_animating_ = true; |
| + last_awaken_time_ = base::TimeTicks(); |
| + client_->SetNeedsAnimateForScrollbarAnimation(); |
| +} |
| + |
| +void ScrollbarAnimationController::StopAnimation() { |
| + delayed_scrollbar_fade_.Cancel(); |
| + is_animating_ = false; |
| +} |
| + |
| +void ScrollbarAnimationController::PostDelayedAnimationTask(bool on_resize) { |
| + base::TimeDelta delay = |
| + on_resize ? resize_delay_before_starting_ : delay_before_starting_; |
| + delayed_scrollbar_fade_.Reset( |
| + base::Bind(&ScrollbarAnimationController::StartAnimation, |
| + weak_factory_.GetWeakPtr())); |
| + client_->PostDelayedScrollbarAnimationTask(delayed_scrollbar_fade_.callback(), |
| + delay); |
| +} |
| + |
| bool ScrollbarAnimationController::Animate(base::TimeTicks now) { |
| bool animated = false; |
| @@ -53,7 +130,7 @@ bool ScrollbarAnimationController::Animate(base::TimeTicks now) { |
| animated = true; |
| } |
| - if (NeedThinningAnimation()) { |
| + if (need_thinning_animation_) { |
| animated |= vertical_controller_->Animate(now); |
| animated |= horizontal_controller_->Animate(now); |
| } |
| @@ -61,18 +138,10 @@ bool ScrollbarAnimationController::Animate(base::TimeTicks now) { |
| return animated; |
| } |
| -bool ScrollbarAnimationController::ScrollbarsHidden() const { |
| - return false; |
| -} |
| - |
| -bool ScrollbarAnimationController::NeedThinningAnimation() const { |
| - return false; |
| -} |
| - |
| float ScrollbarAnimationController::AnimationProgressAtTime( |
| base::TimeTicks now) { |
| base::TimeDelta delta = now - last_awaken_time_; |
| - float progress = delta.InSecondsF() / Duration().InSecondsF(); |
| + float progress = delta.InSecondsF() / fade_duration_.InSecondsF(); |
| return std::max(std::min(progress, 1.f), 0.f); |
| } |
| @@ -80,28 +149,55 @@ void ScrollbarAnimationController::DidScrollBegin() { |
| currently_scrolling_ = true; |
| } |
| +void ScrollbarAnimationController::RunAnimationFrame(float progress) { |
| + ApplyOpacityToScrollbars(1.f - progress); |
| + client_->SetNeedsRedrawForScrollbarAnimation(); |
| + if (progress == 1.f) |
| + StopAnimation(); |
| +} |
| + |
| void ScrollbarAnimationController::DidScrollUpdate(bool on_resize) { |
| + if (need_thinning_animation_ && Captured()) |
| + return; |
| + |
| StopAnimation(); |
| // As an optimization, we avoid spamming fade delay tasks during active fast |
| // scrolls. But if we're not within one, we need to post every scroll update. |
| - if (!currently_scrolling_) |
| - PostDelayedAnimationTask(on_resize); |
| - else |
| + if (!currently_scrolling_) { |
| + // We don't fade out scrollbar if they need thinning animation and mouse is |
| + // near. |
| + if (!need_thinning_animation_ || !mouse_is_near_any_scrollbar()) |
| + PostDelayedAnimationTask(on_resize); |
| + } else { |
| scroll_gesture_has_scrolled_ = true; |
| + } |
| + |
| + ApplyOpacityToScrollbars(1); |
| + |
| + if (need_thinning_animation_) { |
| + vertical_controller_->UpdateThumbThicknessScale(); |
| + horizontal_controller_->UpdateThumbThicknessScale(); |
| + } |
| } |
| void ScrollbarAnimationController::DidScrollEnd() { |
| - if (scroll_gesture_has_scrolled_) { |
| - PostDelayedAnimationTask(false); |
| - scroll_gesture_has_scrolled_ = false; |
| - } |
| + bool has_scrolled = scroll_gesture_has_scrolled_; |
| + scroll_gesture_has_scrolled_ = false; |
| currently_scrolling_ = false; |
| + |
| + // We don't fade out scrollbar if they need thinning animation and mouse is |
| + // near. |
| + if (need_thinning_animation_ && mouse_is_near_any_scrollbar()) |
| + return; |
| + |
| + if (has_scrolled) |
| + PostDelayedAnimationTask(false); |
| } |
| void ScrollbarAnimationController::DidMouseDown() { |
| - if (!NeedThinningAnimation() || ScrollbarsHidden()) |
| + if (!need_thinning_animation_ || ScrollbarsHidden()) |
| return; |
| vertical_controller_->DidMouseDown(); |
| @@ -109,7 +205,7 @@ void ScrollbarAnimationController::DidMouseDown() { |
| } |
| void ScrollbarAnimationController::DidMouseUp() { |
| - if (!NeedThinningAnimation()) |
| + if (!need_thinning_animation_) |
| return; |
| vertical_controller_->DidMouseUp(); |
| @@ -120,7 +216,7 @@ void ScrollbarAnimationController::DidMouseUp() { |
| } |
| void ScrollbarAnimationController::DidMouseLeave() { |
| - if (!NeedThinningAnimation()) |
| + if (!need_thinning_animation_) |
| return; |
| vertical_controller_->DidMouseLeave(); |
| @@ -135,7 +231,7 @@ void ScrollbarAnimationController::DidMouseLeave() { |
| void ScrollbarAnimationController::DidMouseMoveNear( |
| ScrollbarOrientation orientation, |
| float distance) { |
| - if (!NeedThinningAnimation()) |
| + if (!need_thinning_animation_) |
| return; |
| GetScrollbarAnimationController(orientation).DidMouseMoveNear(distance); |
| @@ -146,64 +242,72 @@ void ScrollbarAnimationController::DidMouseMoveNear( |
| if (mouse_is_near_any_scrollbar()) { |
| ApplyOpacityToScrollbars(1); |
| StopAnimation(); |
| - } else if (!animating_fade()) { |
| + } else if (!is_animating_) { |
| PostDelayedAnimationTask(false); |
| } |
| } |
| bool ScrollbarAnimationController::mouse_is_over_scrollbar( |
| ScrollbarOrientation orientation) const { |
| - DCHECK(NeedThinningAnimation()); |
| + DCHECK(need_thinning_animation_); |
| return GetScrollbarAnimationController(orientation).mouse_is_over_scrollbar(); |
| } |
| bool ScrollbarAnimationController::mouse_is_near_scrollbar( |
| ScrollbarOrientation orientation) const { |
| - DCHECK(NeedThinningAnimation()); |
| + DCHECK(need_thinning_animation_); |
| return GetScrollbarAnimationController(orientation).mouse_is_near_scrollbar(); |
| } |
| bool ScrollbarAnimationController::mouse_is_near_any_scrollbar() const { |
| - DCHECK(NeedThinningAnimation()); |
| + DCHECK(need_thinning_animation_); |
| return vertical_controller_->mouse_is_near_scrollbar() || |
| horizontal_controller_->mouse_is_near_scrollbar(); |
| } |
| +bool ScrollbarAnimationController::ScrollbarsHidden() const { |
| + return opacity_ == 0.0f; |
| +} |
| + |
| bool ScrollbarAnimationController::Captured() const { |
| - DCHECK(NeedThinningAnimation()); |
| + DCHECK(need_thinning_animation_); |
| return vertical_controller_->captured() || horizontal_controller_->captured(); |
| } |
| -void ScrollbarAnimationController::PostDelayedAnimationTask(bool on_resize) { |
| - base::TimeDelta delay = |
| - on_resize ? resize_delay_before_starting_ : delay_before_starting_; |
| - delayed_scrollbar_fade_.Reset( |
| - base::Bind(&ScrollbarAnimationController::StartAnimation, |
| - weak_factory_.GetWeakPtr())); |
| - client_->PostDelayedScrollbarAnimationTask(delayed_scrollbar_fade_.callback(), |
| - delay); |
| +void ScrollbarAnimationController::set_mouse_move_distance_for_test( |
|
weiliangc
2017/02/15 19:41:15
Since set_moust_move_distance_for_test is availabl
chaopeng
2017/02/15 19:59:50
This is the entry for layer_tree_host_impl_unittes
weiliangc
2017/02/15 20:06:08
I see three use cases there, none of which seems l
|
| + float distance) { |
| + vertical_controller_->set_mouse_move_distance_for_test(distance); |
| + horizontal_controller_->set_mouse_move_distance_for_test(distance); |
| } |
| -void ScrollbarAnimationController::StartAnimation() { |
| - delayed_scrollbar_fade_.Cancel(); |
| - is_animating_ = true; |
| - last_awaken_time_ = base::TimeTicks(); |
| - client_->SetNeedsAnimateForScrollbarAnimation(); |
| -} |
| +void ScrollbarAnimationController::ApplyOpacityToScrollbars(float opacity) { |
| + for (ScrollbarLayerImplBase* scrollbar : Scrollbars()) { |
| + if (!scrollbar->is_overlay_scrollbar()) |
| + continue; |
| + float effective_opacity = scrollbar->CanScrollOrientation() ? opacity : 0; |
| + PropertyTrees* property_trees = |
| + scrollbar->layer_tree_impl()->property_trees(); |
| + // If this method is called during LayerImpl::PushPropertiesTo, we may not |
| + // yet have valid layer_id_to_effect_node_index entries as property trees |
| + // are pushed after layers during activation. We can skip updating opacity |
| + // in that case as we are only registering a scrollbar and because opacity |
| + // will be overwritten anyway when property trees are pushed. |
| + if (property_trees->IsInIdToIndexMap(PropertyTrees::TreeType::EFFECT, |
| + scrollbar->id())) { |
| + property_trees->effect_tree.OnOpacityAnimated( |
| + effective_opacity, |
| + property_trees->layer_id_to_effect_node_index[scrollbar->id()], |
| + scrollbar->layer_tree_impl()); |
| + } |
| + } |
| -void ScrollbarAnimationController::StopAnimation() { |
| - delayed_scrollbar_fade_.Cancel(); |
| - is_animating_ = false; |
| -} |
| + bool previouslyVisible = opacity_ > 0.0f; |
| + bool currentlyVisible = opacity > 0.0f; |
| -ScrollbarSet ScrollbarAnimationController::Scrollbars() const { |
| - return client_->ScrollbarsFor(scroll_layer_id_); |
| -} |
| + opacity_ = opacity; |
| -void ScrollbarAnimationController::set_mouse_move_distance_for_test( |
| - float distance) { |
| - vertical_controller_->set_mouse_move_distance_for_test(distance); |
| - horizontal_controller_->set_mouse_move_distance_for_test(distance); |
| + if (previouslyVisible != currentlyVisible) |
| + client_->DidChangeScrollbarVisibility(); |
| } |
| } // namespace cc |