123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991 |
- // Copyright (c) 2012 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 "ui/compositor/layer_animator.h"
- #include <stddef.h>
- #include <memory>
- #include "base/check_op.h"
- #include "base/containers/cxx20_erase.h"
- #include "base/observer_list.h"
- #include "base/trace_event/trace_event.h"
- #include "cc/animation/animation.h"
- #include "cc/animation/animation_host.h"
- #include "cc/animation/animation_id_provider.h"
- #include "cc/animation/animation_timeline.h"
- #include "cc/animation/element_animations.h"
- #include "components/viz/common/frame_sinks/begin_frame_args.h"
- #include "ui/compositor/compositor.h"
- #include "ui/compositor/layer.h"
- #include "ui/compositor/layer_animation_delegate.h"
- #include "ui/compositor/layer_animation_observer.h"
- #include "ui/compositor/layer_animation_sequence.h"
- #include "ui/compositor/layer_animator_collection.h"
- #define SAFE_INVOKE_VOID(function, running_anim, ...) \
- if (running_anim.is_sequence_alive()) \
- function(running_anim.sequence(), ##__VA_ARGS__)
- #define SAFE_INVOKE_BOOL(function, running_anim) \
- ((running_anim.is_sequence_alive()) \
- ? function(running_anim.sequence()) \
- : false)
- #define SAFE_INVOKE_PTR(function, running_anim) \
- ((running_anim.is_sequence_alive()) ? function(running_anim.sequence()) \
- : nullptr)
- namespace ui {
- namespace {
- const int kLayerAnimatorDefaultTransitionDurationMs = 120;
- } // namespace
- // LayerAnimator public --------------------------------------------------------
- LayerAnimator::LayerAnimator(base::TimeDelta transition_duration)
- : transition_duration_(transition_duration) {
- animation_ =
- cc::Animation::Create(cc::AnimationIdProvider::NextAnimationId());
- }
- LayerAnimator::~LayerAnimator() {
- for (size_t i = 0; i < running_animations_.size(); ++i) {
- if (running_animations_[i].is_sequence_alive())
- running_animations_[i].sequence()->OnAnimatorDestroyed();
- }
- ClearAnimationsInternal();
- delegate_ = nullptr;
- DCHECK(!animation_->animation_timeline());
- }
- // static
- LayerAnimator* LayerAnimator::CreateDefaultAnimator() {
- return new LayerAnimator(base::Milliseconds(0));
- }
- // static
- LayerAnimator* LayerAnimator::CreateImplicitAnimator() {
- return new LayerAnimator(
- base::Milliseconds(kLayerAnimatorDefaultTransitionDurationMs));
- }
- // This macro provides the implementation for the setter and getter (well,
- // the getter of the target value) for an animated property. For example,
- // it is used for the implementations of SetTransform and GetTargetTransform.
- // It is worth noting that SetFoo avoids invoking the usual animation machinery
- // if the transition duration is zero -- in this case we just set the property
- // on the layer animation delegate immediately.
- #define ANIMATED_PROPERTY(type, property, name, member_type, member) \
- void LayerAnimator::Set##name(type value) { \
- base::TimeDelta duration = GetTransitionDuration(); \
- if (duration.is_zero() && delegate() && \
- (preemption_strategy_ != ENQUEUE_NEW_ANIMATION)) { \
- /* Stopping an animation may result in destruction of `this`. */ \
- const auto weak_ptr = weak_ptr_factory_.GetWeakPtr(); \
- StopAnimatingProperty(LayerAnimationElement::property); \
- if (!weak_ptr || !delegate()) \
- return; \
- delegate()->Set##name##FromAnimation( \
- value, PropertyChangeReason::NOT_FROM_ANIMATION); \
- return; \
- } \
- std::unique_ptr<LayerAnimationElement> element = \
- LayerAnimationElement::Create##name##Element(value, duration); \
- element->set_tween_type(tween_type_); \
- StartAnimation(new LayerAnimationSequence(std::move(element))); \
- } \
- \
- member_type LayerAnimator::GetTarget##name() const { \
- LayerAnimationElement::TargetValue target(delegate()); \
- GetTargetValue(&target); \
- return target.member; \
- }
- ANIMATED_PROPERTY(const gfx::Transform&,
- TRANSFORM,
- Transform,
- gfx::Transform,
- transform)
- ANIMATED_PROPERTY(const gfx::Rect&, BOUNDS, Bounds, gfx::Rect, bounds)
- ANIMATED_PROPERTY(float, OPACITY, Opacity, float, opacity)
- ANIMATED_PROPERTY(bool, VISIBILITY, Visibility, bool, visibility)
- ANIMATED_PROPERTY(float, BRIGHTNESS, Brightness, float, brightness)
- ANIMATED_PROPERTY(float, GRAYSCALE, Grayscale, float, grayscale)
- ANIMATED_PROPERTY(SkColor, COLOR, Color, SkColor, color)
- ANIMATED_PROPERTY(const gfx::Rect&, CLIP, ClipRect, gfx::Rect, clip_rect)
- ANIMATED_PROPERTY(const gfx::RoundedCornersF&,
- ROUNDED_CORNERS,
- RoundedCorners,
- gfx::RoundedCornersF,
- rounded_corners)
- ANIMATED_PROPERTY(const gfx::LinearGradient&,
- GRADIENT_MASK,
- GradientMask,
- gfx::LinearGradient,
- gradient_mask)
- #undef ANIMATED_PROPERTY
- base::TimeDelta LayerAnimator::GetTransitionDuration() const {
- return transition_duration_;
- }
- void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) {
- if (delegate_ && is_started_) {
- LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
- if (collection)
- collection->StopAnimator(this);
- }
- SwitchToLayer(delegate ? delegate->GetCcLayer() : nullptr);
- delegate_ = delegate;
- if (delegate_ && is_started_) {
- LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
- if (collection)
- collection->StartAnimator(this);
- }
- }
- void LayerAnimator::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
- if (delegate_)
- DetachLayerFromAnimation();
- if (new_layer)
- AttachLayerToAnimation(new_layer->id());
- }
- void LayerAnimator::AttachLayerAndTimeline(Compositor* compositor) {
- DCHECK(compositor);
- cc::AnimationTimeline* timeline = compositor->GetAnimationTimeline();
- DCHECK(timeline);
- timeline->AttachAnimation(animation_);
- DCHECK(delegate_->GetCcLayer());
- AttachLayerToAnimation(delegate_->GetCcLayer()->id());
- for (auto& layer_animation_sequence : animation_queue_)
- layer_animation_sequence->OnAnimatorAttached(delegate());
- }
- void LayerAnimator::DetachLayerAndTimeline(Compositor* compositor) {
- DCHECK(compositor);
- cc::AnimationTimeline* timeline = compositor->GetAnimationTimeline();
- DCHECK(timeline);
- DetachLayerFromAnimation();
- timeline->DetachAnimation(animation_);
- for (auto& layer_animation_sequence : animation_queue_)
- layer_animation_sequence->OnAnimatorDetached();
- }
- void LayerAnimator::AttachLayerToAnimation(int layer_id) {
- // For ui, layer and element ids are equivalent.
- cc::ElementId element_id(layer_id);
- if (!animation_->element_id())
- animation_->AttachElement(element_id);
- else
- DCHECK_EQ(animation_->element_id(), element_id);
- animation_->set_animation_delegate(this);
- }
- void LayerAnimator::DetachLayerFromAnimation() {
- animation_->set_animation_delegate(nullptr);
- if (animation_->element_id())
- animation_->DetachElement();
- }
- void LayerAnimator::AddThreadedAnimation(
- std::unique_ptr<cc::KeyframeModel> animation) {
- animation_->AddKeyframeModel(std::move(animation));
- }
- void LayerAnimator::RemoveThreadedAnimation(int keyframe_model_id) {
- animation_->RemoveKeyframeModel(keyframe_model_id);
- }
- cc::Animation* LayerAnimator::GetAnimationForTesting() const {
- return animation_.get();
- }
- void LayerAnimator::StartAnimation(LayerAnimationSequence* animation) {
- scoped_refptr<LayerAnimator> retain(this);
- OnScheduled(animation);
- if (!StartSequenceImmediately(animation)) {
- // Attempt to preempt a running animation.
- switch (preemption_strategy_) {
- case IMMEDIATELY_SET_NEW_TARGET:
- ImmediatelySetNewTarget(animation);
- break;
- case IMMEDIATELY_ANIMATE_TO_NEW_TARGET:
- ImmediatelyAnimateToNewTarget(animation);
- break;
- case ENQUEUE_NEW_ANIMATION:
- EnqueueNewAnimation(animation);
- break;
- case REPLACE_QUEUED_ANIMATIONS:
- ReplaceQueuedAnimations(animation);
- break;
- }
- }
- FinishAnyAnimationWithZeroDuration();
- UpdateAnimationState();
- }
- void LayerAnimator::ScheduleAnimation(LayerAnimationSequence* animation) {
- scoped_refptr<LayerAnimator> retain(this);
- OnScheduled(animation);
- if (is_animating()) {
- animation_queue_.push_back(
- std::unique_ptr<LayerAnimationSequence>(animation));
- ProcessQueue();
- } else {
- StartSequenceImmediately(animation);
- }
- UpdateAnimationState();
- }
- void LayerAnimator::StartTogether(
- const std::vector<LayerAnimationSequence*>& animations) {
- scoped_refptr<LayerAnimator> retain(this);
- if (preemption_strategy_ == IMMEDIATELY_SET_NEW_TARGET) {
- std::vector<LayerAnimationSequence*>::const_iterator iter;
- for (iter = animations.begin(); iter != animations.end(); ++iter) {
- StartAnimation(*iter);
- }
- return;
- }
- adding_animations_ = true;
- if (!is_animating()) {
- LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
- if (collection && collection->HasActiveAnimators())
- last_step_time_ = collection->last_tick_time();
- else
- last_step_time_ = base::TimeTicks::Now();
- }
- // Collect all the affected properties.
- LayerAnimationElement::AnimatableProperties animated_properties =
- LayerAnimationElement::UNKNOWN;
- std::vector<LayerAnimationSequence*>::const_iterator iter;
- for (iter = animations.begin(); iter != animations.end(); ++iter)
- animated_properties |= (*iter)->properties();
- // Starting a zero duration pause that affects all the animated properties
- // will prevent any of the sequences from animating until there are no
- // running animations that affect any of these properties, as well as
- // handle preemption strategy.
- StartAnimation(new LayerAnimationSequence(
- LayerAnimationElement::CreatePauseElement(animated_properties,
- base::TimeDelta())));
- bool wait_for_group_start = false;
- for (iter = animations.begin(); iter != animations.end(); ++iter)
- wait_for_group_start |=
- delegate_ && (*iter)->IsFirstElementThreaded(delegate_);
- int group_id = cc::AnimationIdProvider::NextGroupId();
- // These animations (provided they don't animate any common properties) will
- // now animate together if trivially scheduled.
- for (iter = animations.begin(); iter != animations.end(); ++iter) {
- (*iter)->set_animation_group_id(group_id);
- (*iter)->set_waiting_for_group_start(wait_for_group_start);
- ScheduleAnimation(*iter);
- }
- adding_animations_ = false;
- UpdateAnimationState();
- }
- void LayerAnimator::ScheduleTogether(
- const std::vector<LayerAnimationSequence*>& animations) {
- scoped_refptr<LayerAnimator> retain(this);
- // Collect all the affected properties.
- LayerAnimationElement::AnimatableProperties animated_properties =
- LayerAnimationElement::UNKNOWN;
- std::vector<LayerAnimationSequence*>::const_iterator iter;
- for (iter = animations.begin(); iter != animations.end(); ++iter)
- animated_properties |= (*iter)->properties();
- // Scheduling a zero duration pause that affects all the animated properties
- // will prevent any of the sequences from animating until there are no
- // running animations that affect any of these properties.
- ScheduleAnimation(new LayerAnimationSequence(
- LayerAnimationElement::CreatePauseElement(animated_properties,
- base::TimeDelta())));
- bool wait_for_group_start = false;
- for (iter = animations.begin(); iter != animations.end(); ++iter)
- wait_for_group_start |=
- delegate_ && (*iter)->IsFirstElementThreaded(delegate_);
- int group_id = cc::AnimationIdProvider::NextGroupId();
- // These animations (provided they don't animate any common properties) will
- // now animate together if trivially scheduled.
- for (iter = animations.begin(); iter != animations.end(); ++iter) {
- (*iter)->set_animation_group_id(group_id);
- (*iter)->set_waiting_for_group_start(wait_for_group_start);
- ScheduleAnimation(*iter);
- }
- UpdateAnimationState();
- }
- void LayerAnimator::SchedulePauseForProperties(
- base::TimeDelta duration,
- LayerAnimationElement::AnimatableProperties properties_to_pause) {
- ScheduleAnimation(new ui::LayerAnimationSequence(
- ui::LayerAnimationElement::CreatePauseElement(
- properties_to_pause, duration)));
- }
- bool LayerAnimator::IsAnimatingOnePropertyOf(
- LayerAnimationElement::AnimatableProperties properties) const {
- for (auto& layer_animation_sequence : animation_queue_) {
- if (layer_animation_sequence->properties() & properties)
- return true;
- }
- return false;
- }
- void LayerAnimator::StopAnimatingProperty(
- LayerAnimationElement::AnimatableProperty property) {
- scoped_refptr<LayerAnimator> retain(this);
- while (true) {
- // GetRunningAnimation purges deleted animations before searching, so we are
- // guaranteed to find a live animation if any is returned at all.
- RunningAnimation* running = GetRunningAnimation(property);
- if (!running)
- break;
- // As was mentioned above, this sequence must be alive.
- DCHECK(running->is_sequence_alive());
- FinishAnimation(running->sequence(), false);
- }
- }
- void LayerAnimator::AddObserver(LayerAnimationObserver* observer) {
- if (!observers_.HasObserver(observer)) {
- observers_.AddObserver(observer);
- for (auto& layer_animation_sequence : animation_queue_)
- layer_animation_sequence->AddObserver(observer);
- }
- }
- void LayerAnimator::RemoveObserver(LayerAnimationObserver* observer) {
- observers_.RemoveObserver(observer);
- // Remove the observer from all sequences as well.
- for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
- queue_iter != animation_queue_.end(); ++queue_iter) {
- (*queue_iter)->RemoveObserver(observer);
- }
- }
- void LayerAnimator::AddOwnedObserver(
- std::unique_ptr<ImplicitAnimationObserver> animation_observer) {
- owned_observer_list_.push_back(std::move(animation_observer));
- }
- void LayerAnimator::RemoveAndDestroyOwnedObserver(
- ImplicitAnimationObserver* animation_observer) {
- base::EraseIf(owned_observer_list_,[animation_observer](
- const std::unique_ptr<ImplicitAnimationObserver>& other) {
- return other.get() == animation_observer;
- });
- }
- base::CallbackListSubscription LayerAnimator::AddSequenceScheduledCallback(
- SequenceScheduledCallback callback) {
- return sequence_scheduled_callbacks_.Add(std::move(callback));
- }
- void LayerAnimator::OnThreadedAnimationStarted(
- base::TimeTicks monotonic_time,
- cc::TargetProperty::Type target_property,
- int group_id) {
- LayerAnimationElement::AnimatableProperty property =
- LayerAnimationElement::ToAnimatableProperty(target_property);
- RunningAnimation* running = GetRunningAnimation(property);
- if (!running)
- return;
- DCHECK(running->is_sequence_alive());
- if (running->sequence()->animation_group_id() != group_id)
- return;
- running->sequence()->OnThreadedAnimationStarted(monotonic_time,
- target_property, group_id);
- if (!running->sequence()->waiting_for_group_start())
- return;
- base::TimeTicks start_time = monotonic_time;
- running->sequence()->set_waiting_for_group_start(false);
- // The call to GetRunningAnimation made above already purged deleted
- // animations, so we are guaranteed that all the animations we iterate
- // over now are alive.
- for (auto iter = running_animations_.begin();
- iter != running_animations_.end(); ++iter) {
- // Ensure that each sequence is only Started once, regardless of the
- // number of sequences in the group that have threaded first elements.
- if (((*iter).sequence()->animation_group_id() == group_id) &&
- !(*iter).sequence()->IsFirstElementThreaded(delegate_) &&
- (*iter).sequence()->waiting_for_group_start()) {
- (*iter).sequence()->set_start_time(start_time);
- (*iter).sequence()->set_waiting_for_group_start(false);
- (*iter).sequence()->Start(delegate());
- }
- }
- }
- void LayerAnimator::AddToCollection(LayerAnimatorCollection* collection) {
- DCHECK_EQ(collection, GetLayerAnimatorCollection());
- if (is_animating() && !is_started_) {
- collection->StartAnimator(this);
- is_started_ = true;
- }
- }
- void LayerAnimator::RemoveFromCollection(LayerAnimatorCollection* collection) {
- DCHECK_EQ(collection, GetLayerAnimatorCollection());
- if (is_started_) {
- collection->StopAnimator(this);
- is_started_ = false;
- }
- DCHECK(!animation_->element_animations() ||
- !animation_->element_animations()->HasTickingKeyframeEffect());
- }
- // LayerAnimator protected -----------------------------------------------------
- void LayerAnimator::ProgressAnimation(LayerAnimationSequence* sequence,
- base::TimeTicks now) {
- if (!delegate() || sequence->waiting_for_group_start())
- return;
- sequence->Progress(now, delegate());
- }
- void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence* sequence) {
- if (!delegate())
- return;
- sequence->ProgressToEnd(delegate());
- }
- bool LayerAnimator::HasAnimation(LayerAnimationSequence* sequence) const {
- for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin();
- queue_iter != animation_queue_.end(); ++queue_iter) {
- if ((*queue_iter).get() == sequence)
- return true;
- }
- return false;
- }
- // LayerAnimator private -------------------------------------------------------
- void LayerAnimator::Step(base::TimeTicks now) {
- TRACE_EVENT0("ui", "LayerAnimator::Step");
- scoped_refptr<LayerAnimator> retain(this);
- last_step_time_ = now;
- PurgeDeletedAnimations();
- // We need to make a copy of the running animations because progressing them
- // and finishing them may indirectly affect the collection of running
- // animations.
- RunningAnimations running_animations_copy = running_animations_;
- for (size_t i = 0; i < running_animations_copy.size(); ++i) {
- if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
- continue;
- if (running_animations_copy[i].sequence()->IsFinished(now)) {
- SAFE_INVOKE_VOID(FinishAnimation, running_animations_copy[i], false);
- } else {
- SAFE_INVOKE_VOID(ProgressAnimation, running_animations_copy[i], now);
- }
- }
- }
- void LayerAnimator::StopAnimatingInternal(bool abort) {
- scoped_refptr<LayerAnimator> retain(this);
- while (is_animating() && delegate()) {
- // We're going to attempt to finish the first running animation. Let's
- // ensure that it's valid.
- PurgeDeletedAnimations();
- // If we've purged all running animations, attempt to start one up.
- if (running_animations_.empty())
- ProcessQueue();
- DCHECK(!running_animations_.empty());
- // Still no luck, let's just bail and clear all animations.
- if (running_animations_.empty()) {
- ClearAnimationsInternal();
- break;
- }
- SAFE_INVOKE_VOID(FinishAnimation, running_animations_[0], abort);
- }
- }
- void LayerAnimator::UpdateAnimationState() {
- if (disable_timer_for_test_)
- return;
- const bool should_start = is_animating();
- LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
- if (collection) {
- if (should_start && !is_started_)
- collection->StartAnimator(this);
- else if (!should_start && is_started_)
- collection->StopAnimator(this);
- is_started_ = should_start;
- } else {
- is_started_ = false;
- }
- }
- LayerAnimationSequence* LayerAnimator::RemoveAnimation(
- LayerAnimationSequence* sequence) {
- std::unique_ptr<LayerAnimationSequence> to_return;
- bool is_running = false;
- // First remove from running animations
- for (auto iter = running_animations_.begin();
- iter != running_animations_.end(); ++iter) {
- if ((*iter).sequence() == sequence) {
- running_animations_.erase(iter);
- is_running = true;
- break;
- }
- }
- // Then remove from the queue
- for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
- queue_iter != animation_queue_.end(); ++queue_iter) {
- if (queue_iter->get() == sequence) {
- to_return = std::move(*queue_iter);
- animation_queue_.erase(queue_iter);
- break;
- }
- }
- // Do not continue and attempt to start other sequences if the delegate is
- // nullptr.
- // TODO(crbug.com/1247769): Guard other uses of delegate_ in this class.
- if (!delegate())
- return to_return.release();
- if (!to_return.get() || !to_return->waiting_for_group_start() ||
- !to_return->IsFirstElementThreaded(delegate_))
- return to_return.release();
- // The removed sequence may have been responsible for making other sequences
- // wait for a group start. If no other sequences in the group have a
- // threaded first element, the group no longer needs the additional wait.
- bool is_wait_still_needed = false;
- int group_id = to_return->animation_group_id();
- for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
- queue_iter != animation_queue_.end(); ++queue_iter) {
- if (((*queue_iter)->animation_group_id() == group_id) &&
- (*queue_iter)->IsFirstElementThreaded(delegate_)) {
- is_wait_still_needed = true;
- break;
- }
- }
- if (is_wait_still_needed)
- return to_return.release();
- for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
- queue_iter != animation_queue_.end(); ++queue_iter) {
- if ((*queue_iter)->animation_group_id() == group_id &&
- (*queue_iter)->waiting_for_group_start()) {
- (*queue_iter)->set_waiting_for_group_start(false);
- if (is_running) {
- (*queue_iter)->set_start_time(last_step_time_);
- (*queue_iter)->Start(delegate());
- }
- }
- }
- return to_return.release();
- }
- void LayerAnimator::FinishAnimation(
- LayerAnimationSequence* sequence, bool abort) {
- scoped_refptr<LayerAnimator> retain(this);
- std::unique_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence));
- if (abort)
- sequence->Abort(delegate());
- else
- ProgressAnimationToEnd(sequence);
- if (!delegate())
- return;
- ProcessQueue();
- UpdateAnimationState();
- }
- void LayerAnimator::FinishAnyAnimationWithZeroDuration() {
- scoped_refptr<LayerAnimator> retain(this);
- // Special case: if we've started a 0 duration animation, just finish it now
- // and get rid of it. We need to make a copy because Progress may indirectly
- // cause new animations to start running.
- RunningAnimations running_animations_copy = running_animations_;
- for (size_t i = 0; i < running_animations_copy.size(); ++i) {
- if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
- continue;
- if (running_animations_copy[i].sequence()->IsFinished(
- running_animations_copy[i].sequence()->start_time())) {
- SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
- std::unique_ptr<LayerAnimationSequence> removed(
- SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
- }
- }
- ProcessQueue();
- UpdateAnimationState();
- }
- void LayerAnimator::ClearAnimations() {
- scoped_refptr<LayerAnimator> retain(this);
- ClearAnimationsInternal();
- }
- LayerAnimator::RunningAnimation* LayerAnimator::GetRunningAnimation(
- LayerAnimationElement::AnimatableProperty property) {
- PurgeDeletedAnimations();
- for (auto iter = running_animations_.begin();
- iter != running_animations_.end(); ++iter) {
- if ((*iter).sequence()->properties() & property)
- return &(*iter);
- }
- return nullptr;
- }
- void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence* animation) {
- // If we don't have the animation in the queue yet, add it.
- bool found_sequence = false;
- for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
- queue_iter != animation_queue_.end(); ++queue_iter) {
- if (queue_iter->get() == animation) {
- found_sequence = true;
- break;
- }
- }
- if (!found_sequence) {
- animation_queue_.push_front(
- std::unique_ptr<LayerAnimationSequence>(animation));
- }
- }
- void LayerAnimator::RemoveAllAnimationsWithACommonProperty(
- LayerAnimationSequence* sequence, bool abort) {
- // For all the running animations, if they animate the same property,
- // progress them to the end and remove them. Note, Aborting or Progressing
- // animations may affect the collection of running animations, so we need to
- // operate on a copy.
- RunningAnimations running_animations_copy = running_animations_;
- for (size_t i = 0; i < running_animations_copy.size(); ++i) {
- if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
- continue;
- if (running_animations_copy[i].sequence()->HasConflictingProperty(
- sequence->properties())) {
- std::unique_ptr<LayerAnimationSequence> removed(
- SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
- if (abort)
- running_animations_copy[i].sequence()->Abort(delegate());
- else
- SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
- }
- }
- // Same for the queued animations that haven't been started. Again, we'll
- // need to operate on a copy.
- std::vector<base::WeakPtr<LayerAnimationSequence> > sequences;
- for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
- queue_iter != animation_queue_.end(); ++queue_iter)
- sequences.push_back((*queue_iter)->AsWeakPtr());
- for (size_t i = 0; i < sequences.size(); ++i) {
- if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
- continue;
- if (sequences[i]->HasConflictingProperty(sequence->properties())) {
- std::unique_ptr<LayerAnimationSequence> removed(
- RemoveAnimation(sequences[i].get()));
- if (abort)
- sequences[i]->Abort(delegate());
- else
- ProgressAnimationToEnd(sequences[i].get());
- }
- }
- }
- void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence* sequence) {
- // Need to detect if our sequence gets destroyed.
- base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
- sequence->AsWeakPtr();
- const bool abort = false;
- RemoveAllAnimationsWithACommonProperty(sequence, abort);
- if (!weak_sequence_ptr.get())
- return;
- LayerAnimationSequence* removed = RemoveAnimation(sequence);
- DCHECK(removed == nullptr || removed == sequence);
- if (!weak_sequence_ptr.get())
- return;
- ProgressAnimationToEnd(sequence);
- if (!weak_sequence_ptr.get())
- return;
- delete sequence;
- }
- void LayerAnimator::ImmediatelyAnimateToNewTarget(
- LayerAnimationSequence* sequence) {
- // Need to detect if our sequence gets destroyed.
- base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
- sequence->AsWeakPtr();
- const bool abort = true;
- RemoveAllAnimationsWithACommonProperty(sequence, abort);
- if (!weak_sequence_ptr.get())
- return;
- AddToQueueIfNotPresent(sequence);
- if (!weak_sequence_ptr.get())
- return;
- StartSequenceImmediately(sequence);
- }
- void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence* sequence) {
- // It is assumed that if there was no conflicting animation, we would
- // not have been called. No need to check for a collision; just
- // add to the queue.
- animation_queue_.push_back(std::unique_ptr<LayerAnimationSequence>(sequence));
- ProcessQueue();
- }
- void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence* sequence) {
- // Need to detect if our sequence gets destroyed.
- base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
- sequence->AsWeakPtr();
- // Remove all animations that aren't running. Note: at each iteration i is
- // incremented or an element is removed from the queue, so
- // animation_queue_.size() - i is always decreasing and we are always making
- // progress towards the loop terminating.
- for (size_t i = 0; i < animation_queue_.size();) {
- if (!weak_sequence_ptr.get())
- break;
- PurgeDeletedAnimations();
- bool is_running = false;
- for (RunningAnimations::const_iterator iter = running_animations_.begin();
- iter != running_animations_.end(); ++iter) {
- if ((*iter).sequence() == animation_queue_[i].get()) {
- is_running = true;
- break;
- }
- }
- if (!is_running)
- delete RemoveAnimation(animation_queue_[i].get());
- else
- ++i;
- }
- animation_queue_.push_back(std::unique_ptr<LayerAnimationSequence>(sequence));
- ProcessQueue();
- }
- void LayerAnimator::ProcessQueue() {
- bool started_sequence = false;
- do {
- started_sequence = false;
- // Build a list of all currently animated properties.
- LayerAnimationElement::AnimatableProperties animated =
- LayerAnimationElement::UNKNOWN;
- for (RunningAnimations::const_iterator iter = running_animations_.begin();
- iter != running_animations_.end(); ++iter) {
- if (!(*iter).is_sequence_alive())
- continue;
- animated |= (*iter).sequence()->properties();
- }
- // Try to find an animation that doesn't conflict with an animated
- // property or a property that will be animated before it. Note: starting
- // the animation may indirectly cause more animations to be started, so we
- // need to operate on a copy.
- std::vector<base::WeakPtr<LayerAnimationSequence> > sequences;
- for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
- queue_iter != animation_queue_.end(); ++queue_iter)
- sequences.push_back((*queue_iter)->AsWeakPtr());
- for (size_t i = 0; i < sequences.size(); ++i) {
- if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
- continue;
- if (!sequences[i]->HasConflictingProperty(animated)) {
- StartSequenceImmediately(sequences[i].get());
- started_sequence = true;
- break;
- }
- // Animation couldn't be started. Add its properties to the collection so
- // that we don't start a conflicting animation. For example, if our queue
- // has the elements { {T,B}, {B} } (that is, an element that animates both
- // the transform and the bounds followed by an element that animates the
- // bounds), and we're currently animating the transform, we can't start
- // the first element because it animates the transform, too. We cannot
- // start the second element, either, because the first element animates
- // bounds too, and needs to go first.
- animated |= sequences[i]->properties();
- }
- // If we started a sequence, try again. We may be able to start several.
- } while (started_sequence);
- }
- bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) {
- PurgeDeletedAnimations();
- // Ensure that no one is animating one of the sequence's properties already.
- for (RunningAnimations::const_iterator iter = running_animations_.begin();
- iter != running_animations_.end(); ++iter) {
- if ((*iter).sequence()->HasConflictingProperty(sequence->properties()))
- return false;
- }
- // All clear, actually start the sequence.
- // All LayerAnimators share the same LayerAnimatorCollection. Use the
- // last_tick_time() from there to ensure animations started during the same
- // event complete at the same time.
- base::TimeTicks start_time;
- LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
- if (is_animating() || adding_animations_)
- start_time = last_step_time_;
- else if (collection && collection->HasActiveAnimators())
- start_time = collection->last_tick_time();
- else
- start_time = base::TimeTicks::Now();
- if (!sequence->animation_group_id())
- sequence->set_animation_group_id(cc::AnimationIdProvider::NextGroupId());
- running_animations_.push_back(
- RunningAnimation(sequence->AsWeakPtr()));
- // Need to keep a reference to the animation.
- AddToQueueIfNotPresent(sequence);
- if (!sequence->waiting_for_group_start() ||
- sequence->IsFirstElementThreaded(delegate_)) {
- sequence->set_start_time(start_time);
- sequence->Start(delegate());
- }
- // Ensure that animations get stepped at their start time.
- Step(start_time);
- return true;
- }
- void LayerAnimator::GetTargetValue(
- LayerAnimationElement::TargetValue* target) const {
- for (AnimationQueue::const_iterator iter = animation_queue_.begin();
- iter != animation_queue_.end(); ++iter) {
- (*iter)->GetTargetValue(target);
- }
- }
- void LayerAnimator::OnScheduled(LayerAnimationSequence* sequence) {
- sequence_scheduled_callbacks_.Notify(sequence);
- for (LayerAnimationObserver& observer : observers_)
- sequence->AddObserver(&observer);
- sequence->OnScheduled();
- }
- void LayerAnimator::SetTransitionDuration(base::TimeDelta duration) {
- if (is_transition_duration_locked_)
- return;
- transition_duration_ = duration;
- }
- void LayerAnimator::ClearAnimationsInternal() {
- PurgeDeletedAnimations();
- // Abort should never affect the set of running animations, but just in case
- // clients are badly behaved, we will use a copy of the running animations.
- RunningAnimations running_animations_copy = running_animations_;
- for (size_t i = 0; i < running_animations_copy.size(); ++i) {
- if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
- continue;
- std::unique_ptr<LayerAnimationSequence> removed(
- RemoveAnimation(running_animations_copy[i].sequence()));
- if (removed.get())
- removed->Abort(delegate());
- }
- // This *should* have cleared the list of running animations.
- DCHECK(running_animations_.empty());
- running_animations_.clear();
- animation_queue_.clear();
- UpdateAnimationState();
- }
- void LayerAnimator::PurgeDeletedAnimations() {
- for (size_t i = 0; i < running_animations_.size();) {
- if (!running_animations_[i].is_sequence_alive())
- running_animations_.erase(running_animations_.begin() + i);
- else
- i++;
- }
- }
- LayerAnimatorCollection* LayerAnimator::GetLayerAnimatorCollection() {
- return delegate_ ? delegate_->GetLayerAnimatorCollection() : nullptr;
- }
- void LayerAnimator::NotifyAnimationStarted(base::TimeTicks monotonic_time,
- int target_property,
- int group) {
- OnThreadedAnimationStarted(
- monotonic_time, static_cast<cc::TargetProperty::Type>(target_property),
- group);
- }
- LayerAnimator::RunningAnimation::RunningAnimation(
- const base::WeakPtr<LayerAnimationSequence>& sequence)
- : sequence_(sequence) {
- }
- LayerAnimator::RunningAnimation::RunningAnimation(
- const RunningAnimation& other) = default;
- LayerAnimator::RunningAnimation::~RunningAnimation() { }
- } // namespace ui
|