blob: 45feb3ae2bfb0fa0e664b49d8531652de8dc0437 [file] [log] [blame]
// 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/scrollbar_animation_controller.h"
#include <algorithm>
#include "base/time/time.h"
#include "cc/trees/layer_tree_impl.h"
namespace cc {
ScrollbarAnimationController::ScrollbarAnimationController(
int scroll_layer_id,
ScrollbarAnimationControllerClient* client,
base::TimeDelta delay_before_starting,
base::TimeDelta resize_delay_before_starting,
base::TimeDelta duration)
: client_(client),
delay_before_starting_(delay_before_starting),
resize_delay_before_starting_(resize_delay_before_starting),
duration_(duration),
is_animating_(false),
scroll_layer_id_(scroll_layer_id),
currently_scrolling_(false),
scroll_gesture_has_scrolled_(false),
weak_factory_(this) {}
ScrollbarAnimationController::~ScrollbarAnimationController() {}
bool ScrollbarAnimationController::Animate(base::TimeTicks now) {
if (!is_animating_)
return false;
if (last_awaken_time_.is_null())
last_awaken_time_ = now;
float progress = AnimationProgressAtTime(now);
RunAnimationFrame(progress);
if (is_animating_)
client_->SetNeedsAnimateForScrollbarAnimation();
return true;
}
float ScrollbarAnimationController::AnimationProgressAtTime(
base::TimeTicks now) {
base::TimeDelta delta = now - last_awaken_time_;
float progress = delta.InSecondsF() / duration_.InSecondsF();
return std::max(std::min(progress, 1.f), 0.f);
}
void ScrollbarAnimationController::DidScrollBegin() {
currently_scrolling_ = true;
}
void ScrollbarAnimationController::DidScrollUpdate(bool on_resize) {
StopAnimation();
delayed_scrollbar_fade_.Cancel();
// 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
scroll_gesture_has_scrolled_ = true;
}
void ScrollbarAnimationController::DidScrollEnd() {
if (scroll_gesture_has_scrolled_) {
PostDelayedAnimationTask(false);
scroll_gesture_has_scrolled_ = false;
}
currently_scrolling_ = 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);
}
void ScrollbarAnimationController::StartAnimation() {
delayed_scrollbar_fade_.Cancel();
is_animating_ = true;
last_awaken_time_ = base::TimeTicks();
client_->SetNeedsAnimateForScrollbarAnimation();
}
void ScrollbarAnimationController::StopAnimation() {
is_animating_ = false;
}
ScrollbarSet ScrollbarAnimationController::Scrollbars() const {
return client_->ScrollbarsFor(scroll_layer_id_);
}
} // namespace cc