Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / compositor / layer_animator.cc
blob4d063ecd6e94d2afd591b0569ed2bdf6aa90a509
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/compositor/layer_animator.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/trace_event/trace_event.h"
10 #include "cc/animation/animation_id_provider.h"
11 #include "cc/output/begin_frame_args.h"
12 #include "ui/compositor/compositor.h"
13 #include "ui/compositor/layer.h"
14 #include "ui/compositor/layer_animation_delegate.h"
15 #include "ui/compositor/layer_animation_observer.h"
16 #include "ui/compositor/layer_animation_sequence.h"
17 #include "ui/compositor/layer_animator_collection.h"
19 #define SAFE_INVOKE_VOID(function, running_anim, ...) \
20 if (running_anim.is_sequence_alive()) \
21 function(running_anim.sequence(), ##__VA_ARGS__)
22 #define SAFE_INVOKE_BOOL(function, running_anim) \
23 ((running_anim.is_sequence_alive()) \
24 ? function(running_anim.sequence()) \
25 : false)
26 #define SAFE_INVOKE_PTR(function, running_anim) \
27 ((running_anim.is_sequence_alive()) \
28 ? function(running_anim.sequence()) \
29 : NULL)
31 namespace ui {
33 namespace {
35 const int kDefaultTransitionDurationMs = 120;
37 } // namespace
39 // LayerAnimator public --------------------------------------------------------
41 LayerAnimator::LayerAnimator(base::TimeDelta transition_duration)
42 : delegate_(NULL),
43 preemption_strategy_(IMMEDIATELY_SET_NEW_TARGET),
44 is_transition_duration_locked_(false),
45 transition_duration_(transition_duration),
46 tween_type_(gfx::Tween::LINEAR),
47 is_started_(false),
48 disable_timer_for_test_(false),
49 adding_animations_(false) {
52 LayerAnimator::~LayerAnimator() {
53 for (size_t i = 0; i < running_animations_.size(); ++i) {
54 if (running_animations_[i].is_sequence_alive())
55 running_animations_[i].sequence()->OnAnimatorDestroyed();
57 ClearAnimationsInternal();
58 delegate_ = NULL;
61 // static
62 LayerAnimator* LayerAnimator::CreateDefaultAnimator() {
63 return new LayerAnimator(base::TimeDelta::FromMilliseconds(0));
66 // static
67 LayerAnimator* LayerAnimator::CreateImplicitAnimator() {
68 return new LayerAnimator(
69 base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs));
72 // This macro provides the implementation for the setter and getter (well,
73 // the getter of the target value) for an animated property. For example,
74 // it is used for the implementations of SetTransform and GetTargetTransform.
75 // It is worth noting that SetFoo avoids invoking the usual animation machinery
76 // if the transition duration is zero -- in this case we just set the property
77 // on the layer animation delegate immediately.
78 #define ANIMATED_PROPERTY(type, property, name, member_type, member) \
79 void LayerAnimator::Set##name(type value) { \
80 base::TimeDelta duration = GetTransitionDuration(); \
81 if (duration == base::TimeDelta() && delegate() && \
82 (preemption_strategy_ != ENQUEUE_NEW_ANIMATION)) { \
83 StopAnimatingProperty(LayerAnimationElement::property); \
84 delegate()->Set##name##FromAnimation(value); \
85 return; \
86 } \
87 scoped_ptr<LayerAnimationElement> element( \
88 LayerAnimationElement::Create##name##Element(value, duration)); \
89 element->set_tween_type(tween_type_); \
90 StartAnimation(new LayerAnimationSequence(element.release())); \
91 } \
93 member_type LayerAnimator::GetTarget##name() const { \
94 LayerAnimationElement::TargetValue target(delegate()); \
95 GetTargetValue(&target); \
96 return target.member; \
99 ANIMATED_PROPERTY(
100 const gfx::Transform&, TRANSFORM, Transform, gfx::Transform, transform);
101 ANIMATED_PROPERTY(const gfx::Rect&, BOUNDS, Bounds, gfx::Rect, bounds);
102 ANIMATED_PROPERTY(float, OPACITY, Opacity, float, opacity);
103 ANIMATED_PROPERTY(bool, VISIBILITY, Visibility, bool, visibility);
104 ANIMATED_PROPERTY(float, BRIGHTNESS, Brightness, float, brightness);
105 ANIMATED_PROPERTY(float, GRAYSCALE, Grayscale, float, grayscale);
106 ANIMATED_PROPERTY(SkColor, COLOR, Color, SkColor, color);
108 base::TimeDelta LayerAnimator::GetTransitionDuration() const {
109 return transition_duration_;
112 void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) {
113 if (delegate_ && is_started_) {
114 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
115 if (collection)
116 collection->StopAnimator(this);
118 delegate_ = delegate;
119 if (delegate_ && is_started_) {
120 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
121 if (collection)
122 collection->StartAnimator(this);
126 void LayerAnimator::StartAnimation(LayerAnimationSequence* animation) {
127 scoped_refptr<LayerAnimator> retain(this);
128 OnScheduled(animation);
129 if (!StartSequenceImmediately(animation)) {
130 // Attempt to preempt a running animation.
131 switch (preemption_strategy_) {
132 case IMMEDIATELY_SET_NEW_TARGET:
133 ImmediatelySetNewTarget(animation);
134 break;
135 case IMMEDIATELY_ANIMATE_TO_NEW_TARGET:
136 ImmediatelyAnimateToNewTarget(animation);
137 break;
138 case ENQUEUE_NEW_ANIMATION:
139 EnqueueNewAnimation(animation);
140 break;
141 case REPLACE_QUEUED_ANIMATIONS:
142 ReplaceQueuedAnimations(animation);
143 break;
144 case BLEND_WITH_CURRENT_ANIMATION: {
145 // TODO(vollick) Add support for blended sequences and use them here.
146 NOTIMPLEMENTED();
147 break;
151 FinishAnyAnimationWithZeroDuration();
152 UpdateAnimationState();
155 void LayerAnimator::ScheduleAnimation(LayerAnimationSequence* animation) {
156 scoped_refptr<LayerAnimator> retain(this);
157 OnScheduled(animation);
158 if (is_animating()) {
159 animation_queue_.push_back(make_linked_ptr(animation));
160 ProcessQueue();
161 } else {
162 StartSequenceImmediately(animation);
164 UpdateAnimationState();
167 void LayerAnimator::StartTogether(
168 const std::vector<LayerAnimationSequence*>& animations) {
169 scoped_refptr<LayerAnimator> retain(this);
170 if (preemption_strategy_ == IMMEDIATELY_SET_NEW_TARGET) {
171 std::vector<LayerAnimationSequence*>::const_iterator iter;
172 for (iter = animations.begin(); iter != animations.end(); ++iter) {
173 StartAnimation(*iter);
175 return;
178 adding_animations_ = true;
179 if (!is_animating()) {
180 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
181 if (collection && collection->HasActiveAnimators())
182 last_step_time_ = collection->last_tick_time();
183 else
184 last_step_time_ = base::TimeTicks::Now();
187 // Collect all the affected properties.
188 LayerAnimationElement::AnimatableProperties animated_properties =
189 LayerAnimationElement::UNKNOWN;
191 std::vector<LayerAnimationSequence*>::const_iterator iter;
192 for (iter = animations.begin(); iter != animations.end(); ++iter)
193 animated_properties |= (*iter)->properties();
195 // Starting a zero duration pause that affects all the animated properties
196 // will prevent any of the sequences from animating until there are no
197 // running animations that affect any of these properties, as well as
198 // handle preemption strategy.
199 StartAnimation(new LayerAnimationSequence(
200 LayerAnimationElement::CreatePauseElement(animated_properties,
201 base::TimeDelta())));
203 bool wait_for_group_start = false;
204 for (iter = animations.begin(); iter != animations.end(); ++iter)
205 wait_for_group_start |= (*iter)->IsFirstElementThreaded();
207 int group_id = cc::AnimationIdProvider::NextGroupId();
209 // These animations (provided they don't animate any common properties) will
210 // now animate together if trivially scheduled.
211 for (iter = animations.begin(); iter != animations.end(); ++iter) {
212 (*iter)->set_animation_group_id(group_id);
213 (*iter)->set_waiting_for_group_start(wait_for_group_start);
214 ScheduleAnimation(*iter);
217 adding_animations_ = false;
218 UpdateAnimationState();
222 void LayerAnimator::ScheduleTogether(
223 const std::vector<LayerAnimationSequence*>& animations) {
224 scoped_refptr<LayerAnimator> retain(this);
226 // Collect all the affected properties.
227 LayerAnimationElement::AnimatableProperties animated_properties =
228 LayerAnimationElement::UNKNOWN;
230 std::vector<LayerAnimationSequence*>::const_iterator iter;
231 for (iter = animations.begin(); iter != animations.end(); ++iter)
232 animated_properties |= (*iter)->properties();
234 // Scheduling a zero duration pause that affects all the animated properties
235 // will prevent any of the sequences from animating until there are no
236 // running animations that affect any of these properties.
237 ScheduleAnimation(new LayerAnimationSequence(
238 LayerAnimationElement::CreatePauseElement(animated_properties,
239 base::TimeDelta())));
241 bool wait_for_group_start = false;
242 for (iter = animations.begin(); iter != animations.end(); ++iter)
243 wait_for_group_start |= (*iter)->IsFirstElementThreaded();
245 int group_id = cc::AnimationIdProvider::NextGroupId();
247 // These animations (provided they don't animate any common properties) will
248 // now animate together if trivially scheduled.
249 for (iter = animations.begin(); iter != animations.end(); ++iter) {
250 (*iter)->set_animation_group_id(group_id);
251 (*iter)->set_waiting_for_group_start(wait_for_group_start);
252 ScheduleAnimation(*iter);
255 UpdateAnimationState();
258 void LayerAnimator::SchedulePauseForProperties(
259 base::TimeDelta duration,
260 LayerAnimationElement::AnimatableProperties properties_to_pause) {
261 ScheduleAnimation(new ui::LayerAnimationSequence(
262 ui::LayerAnimationElement::CreatePauseElement(
263 properties_to_pause, duration)));
266 bool LayerAnimator::IsAnimatingProperty(
267 LayerAnimationElement::AnimatableProperty property) const {
268 for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin();
269 queue_iter != animation_queue_.end(); ++queue_iter) {
270 if ((*queue_iter)->properties() & property)
271 return true;
273 return false;
276 void LayerAnimator::StopAnimatingProperty(
277 LayerAnimationElement::AnimatableProperty property) {
278 scoped_refptr<LayerAnimator> retain(this);
279 while (true) {
280 // GetRunningAnimation purges deleted animations before searching, so we are
281 // guaranteed to find a live animation if any is returned at all.
282 RunningAnimation* running = GetRunningAnimation(property);
283 if (!running)
284 break;
285 // As was mentioned above, this sequence must be alive.
286 DCHECK(running->is_sequence_alive());
287 FinishAnimation(running->sequence(), false);
291 void LayerAnimator::AddObserver(LayerAnimationObserver* observer) {
292 if (!observers_.HasObserver(observer))
293 observers_.AddObserver(observer);
296 void LayerAnimator::RemoveObserver(LayerAnimationObserver* observer) {
297 observers_.RemoveObserver(observer);
298 // Remove the observer from all sequences as well.
299 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
300 queue_iter != animation_queue_.end(); ++queue_iter) {
301 (*queue_iter)->RemoveObserver(observer);
305 void LayerAnimator::OnThreadedAnimationStarted(
306 const cc::AnimationEvent& event) {
307 LayerAnimationElement::AnimatableProperty property =
308 LayerAnimationElement::ToAnimatableProperty(event.target_property);
310 RunningAnimation* running = GetRunningAnimation(property);
311 if (!running)
312 return;
313 DCHECK(running->is_sequence_alive());
315 if (running->sequence()->animation_group_id() != event.group_id)
316 return;
318 running->sequence()->OnThreadedAnimationStarted(event);
319 if (!running->sequence()->waiting_for_group_start())
320 return;
322 base::TimeTicks start_time = event.monotonic_time;
324 running->sequence()->set_waiting_for_group_start(false);
326 // The call to GetRunningAnimation made above already purged deleted
327 // animations, so we are guaranteed that all the animations we iterate
328 // over now are alive.
329 for (RunningAnimations::iterator iter = running_animations_.begin();
330 iter != running_animations_.end(); ++iter) {
331 // Ensure that each sequence is only Started once, regardless of the
332 // number of sequences in the group that have threaded first elements.
333 if (((*iter).sequence()->animation_group_id() == event.group_id) &&
334 !(*iter).sequence()->IsFirstElementThreaded() &&
335 (*iter).sequence()->waiting_for_group_start()) {
336 (*iter).sequence()->set_start_time(start_time);
337 (*iter).sequence()->set_waiting_for_group_start(false);
338 (*iter).sequence()->Start(delegate());
343 void LayerAnimator::AddToCollection(LayerAnimatorCollection* collection) {
344 if (is_animating() && !is_started_) {
345 collection->StartAnimator(this);
346 is_started_ = true;
350 void LayerAnimator::RemoveFromCollection(LayerAnimatorCollection* collection) {
351 if (is_animating() && is_started_) {
352 collection->StopAnimator(this);
353 is_started_ = false;
357 // LayerAnimator protected -----------------------------------------------------
359 void LayerAnimator::ProgressAnimation(LayerAnimationSequence* sequence,
360 base::TimeTicks now) {
361 if (!delegate() || sequence->waiting_for_group_start())
362 return;
364 sequence->Progress(now, delegate());
367 void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence* sequence) {
368 if (!delegate())
369 return;
371 sequence->ProgressToEnd(delegate());
374 bool LayerAnimator::HasAnimation(LayerAnimationSequence* sequence) const {
375 for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin();
376 queue_iter != animation_queue_.end(); ++queue_iter) {
377 if ((*queue_iter).get() == sequence)
378 return true;
380 return false;
383 // LayerAnimator private -------------------------------------------------------
385 void LayerAnimator::Step(base::TimeTicks now) {
386 TRACE_EVENT0("ui", "LayerAnimator::Step");
387 scoped_refptr<LayerAnimator> retain(this);
389 last_step_time_ = now;
391 PurgeDeletedAnimations();
393 // We need to make a copy of the running animations because progressing them
394 // and finishing them may indirectly affect the collection of running
395 // animations.
396 RunningAnimations running_animations_copy = running_animations_;
397 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
398 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
399 continue;
401 if (running_animations_copy[i].sequence()->IsFinished(now)) {
402 SAFE_INVOKE_VOID(FinishAnimation, running_animations_copy[i], false);
403 } else {
404 SAFE_INVOKE_VOID(ProgressAnimation, running_animations_copy[i], now);
409 void LayerAnimator::StopAnimatingInternal(bool abort) {
410 scoped_refptr<LayerAnimator> retain(this);
411 while (is_animating() && delegate()) {
412 // We're going to attempt to finish the first running animation. Let's
413 // ensure that it's valid.
414 PurgeDeletedAnimations();
416 // If we've purged all running animations, attempt to start one up.
417 if (running_animations_.empty())
418 ProcessQueue();
420 DCHECK(!running_animations_.empty());
422 // Still no luck, let's just bail and clear all animations.
423 if (running_animations_.empty()) {
424 ClearAnimationsInternal();
425 break;
428 SAFE_INVOKE_VOID(FinishAnimation, running_animations_[0], abort);
432 void LayerAnimator::UpdateAnimationState() {
433 if (disable_timer_for_test_)
434 return;
436 const bool should_start = is_animating();
437 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
438 if (collection) {
439 if (should_start && !is_started_)
440 collection->StartAnimator(this);
441 else if (!should_start && is_started_)
442 collection->StopAnimator(this);
443 is_started_ = should_start;
444 } else {
445 is_started_ = false;
449 LayerAnimationSequence* LayerAnimator::RemoveAnimation(
450 LayerAnimationSequence* sequence) {
451 linked_ptr<LayerAnimationSequence> to_return;
453 bool is_running = false;
455 // First remove from running animations
456 for (RunningAnimations::iterator iter = running_animations_.begin();
457 iter != running_animations_.end(); ++iter) {
458 if ((*iter).sequence() == sequence) {
459 running_animations_.erase(iter);
460 is_running = true;
461 break;
465 // Then remove from the queue
466 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
467 queue_iter != animation_queue_.end(); ++queue_iter) {
468 if ((*queue_iter) == sequence) {
469 to_return = *queue_iter;
470 animation_queue_.erase(queue_iter);
471 break;
475 if (!to_return.get() ||
476 !to_return->waiting_for_group_start() ||
477 !to_return->IsFirstElementThreaded())
478 return to_return.release();
480 // The removed sequence may have been responsible for making other sequences
481 // wait for a group start. If no other sequences in the group have a
482 // threaded first element, the group no longer needs the additional wait.
483 bool is_wait_still_needed = false;
484 int group_id = to_return->animation_group_id();
485 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
486 queue_iter != animation_queue_.end(); ++queue_iter) {
487 if (((*queue_iter)->animation_group_id() == group_id) &&
488 (*queue_iter)->IsFirstElementThreaded()) {
489 is_wait_still_needed = true;
490 break;
494 if (is_wait_still_needed)
495 return to_return.release();
497 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
498 queue_iter != animation_queue_.end(); ++queue_iter) {
499 if ((*queue_iter)->animation_group_id() == group_id &&
500 (*queue_iter)->waiting_for_group_start()) {
501 (*queue_iter)->set_waiting_for_group_start(false);
502 if (is_running) {
503 (*queue_iter)->set_start_time(last_step_time_);
504 (*queue_iter)->Start(delegate());
508 return to_return.release();
511 void LayerAnimator::FinishAnimation(
512 LayerAnimationSequence* sequence, bool abort) {
513 scoped_refptr<LayerAnimator> retain(this);
514 scoped_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence));
515 if (abort)
516 sequence->Abort(delegate());
517 else
518 ProgressAnimationToEnd(sequence);
519 if (!delegate())
520 return;
521 ProcessQueue();
522 UpdateAnimationState();
525 void LayerAnimator::FinishAnyAnimationWithZeroDuration() {
526 scoped_refptr<LayerAnimator> retain(this);
527 // Special case: if we've started a 0 duration animation, just finish it now
528 // and get rid of it. We need to make a copy because Progress may indirectly
529 // cause new animations to start running.
530 RunningAnimations running_animations_copy = running_animations_;
531 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
532 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
533 continue;
535 if (running_animations_copy[i].sequence()->IsFinished(
536 running_animations_copy[i].sequence()->start_time())) {
537 SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
538 scoped_ptr<LayerAnimationSequence> removed(
539 SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
542 ProcessQueue();
543 UpdateAnimationState();
546 void LayerAnimator::ClearAnimations() {
547 scoped_refptr<LayerAnimator> retain(this);
548 ClearAnimationsInternal();
551 LayerAnimator::RunningAnimation* LayerAnimator::GetRunningAnimation(
552 LayerAnimationElement::AnimatableProperty property) {
553 PurgeDeletedAnimations();
554 for (RunningAnimations::iterator iter = running_animations_.begin();
555 iter != running_animations_.end(); ++iter) {
556 if ((*iter).sequence()->properties() & property)
557 return &(*iter);
559 return NULL;
562 void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence* animation) {
563 // If we don't have the animation in the queue yet, add it.
564 bool found_sequence = false;
565 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
566 queue_iter != animation_queue_.end(); ++queue_iter) {
567 if ((*queue_iter) == animation) {
568 found_sequence = true;
569 break;
573 if (!found_sequence)
574 animation_queue_.push_front(make_linked_ptr(animation));
577 void LayerAnimator::RemoveAllAnimationsWithACommonProperty(
578 LayerAnimationSequence* sequence, bool abort) {
579 // For all the running animations, if they animate the same property,
580 // progress them to the end and remove them. Note, Aborting or Progressing
581 // animations may affect the collection of running animations, so we need to
582 // operate on a copy.
583 RunningAnimations running_animations_copy = running_animations_;
584 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
585 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
586 continue;
588 if (running_animations_copy[i].sequence()->HasConflictingProperty(
589 sequence->properties())) {
590 scoped_ptr<LayerAnimationSequence> removed(
591 SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
592 if (abort)
593 running_animations_copy[i].sequence()->Abort(delegate());
594 else
595 SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
599 // Same for the queued animations that haven't been started. Again, we'll
600 // need to operate on a copy.
601 std::vector<base::WeakPtr<LayerAnimationSequence> > sequences;
602 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
603 queue_iter != animation_queue_.end(); ++queue_iter)
604 sequences.push_back((*queue_iter)->AsWeakPtr());
606 for (size_t i = 0; i < sequences.size(); ++i) {
607 if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
608 continue;
610 if (sequences[i]->HasConflictingProperty(sequence->properties())) {
611 scoped_ptr<LayerAnimationSequence> removed(
612 RemoveAnimation(sequences[i].get()));
613 if (abort)
614 sequences[i]->Abort(delegate());
615 else
616 ProgressAnimationToEnd(sequences[i].get());
621 void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence* sequence) {
622 // Need to detect if our sequence gets destroyed.
623 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
624 sequence->AsWeakPtr();
626 const bool abort = false;
627 RemoveAllAnimationsWithACommonProperty(sequence, abort);
628 if (!weak_sequence_ptr.get())
629 return;
631 LayerAnimationSequence* removed = RemoveAnimation(sequence);
632 DCHECK(removed == NULL || removed == sequence);
633 if (!weak_sequence_ptr.get())
634 return;
636 ProgressAnimationToEnd(sequence);
637 if (!weak_sequence_ptr.get())
638 return;
640 delete sequence;
643 void LayerAnimator::ImmediatelyAnimateToNewTarget(
644 LayerAnimationSequence* sequence) {
645 // Need to detect if our sequence gets destroyed.
646 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
647 sequence->AsWeakPtr();
649 const bool abort = true;
650 RemoveAllAnimationsWithACommonProperty(sequence, abort);
651 if (!weak_sequence_ptr.get())
652 return;
654 AddToQueueIfNotPresent(sequence);
655 if (!weak_sequence_ptr.get())
656 return;
658 StartSequenceImmediately(sequence);
661 void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence* sequence) {
662 // It is assumed that if there was no conflicting animation, we would
663 // not have been called. No need to check for a collision; just
664 // add to the queue.
665 animation_queue_.push_back(make_linked_ptr(sequence));
666 ProcessQueue();
669 void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence* sequence) {
670 // Need to detect if our sequence gets destroyed.
671 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
672 sequence->AsWeakPtr();
674 // Remove all animations that aren't running. Note: at each iteration i is
675 // incremented or an element is removed from the queue, so
676 // animation_queue_.size() - i is always decreasing and we are always making
677 // progress towards the loop terminating.
678 for (size_t i = 0; i < animation_queue_.size();) {
679 if (!weak_sequence_ptr.get())
680 break;
682 PurgeDeletedAnimations();
684 bool is_running = false;
685 for (RunningAnimations::const_iterator iter = running_animations_.begin();
686 iter != running_animations_.end(); ++iter) {
687 if ((*iter).sequence() == animation_queue_[i].get()) {
688 is_running = true;
689 break;
693 if (!is_running)
694 delete RemoveAnimation(animation_queue_[i].get());
695 else
696 ++i;
698 animation_queue_.push_back(make_linked_ptr(sequence));
699 ProcessQueue();
702 void LayerAnimator::ProcessQueue() {
703 bool started_sequence = false;
704 do {
705 started_sequence = false;
706 // Build a list of all currently animated properties.
707 LayerAnimationElement::AnimatableProperties animated =
708 LayerAnimationElement::UNKNOWN;
709 for (RunningAnimations::const_iterator iter = running_animations_.begin();
710 iter != running_animations_.end(); ++iter) {
711 if (!(*iter).is_sequence_alive())
712 continue;
714 animated |= (*iter).sequence()->properties();
717 // Try to find an animation that doesn't conflict with an animated
718 // property or a property that will be animated before it. Note: starting
719 // the animation may indirectly cause more animations to be started, so we
720 // need to operate on a copy.
721 std::vector<base::WeakPtr<LayerAnimationSequence> > sequences;
722 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
723 queue_iter != animation_queue_.end(); ++queue_iter)
724 sequences.push_back((*queue_iter)->AsWeakPtr());
726 for (size_t i = 0; i < sequences.size(); ++i) {
727 if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
728 continue;
730 if (!sequences[i]->HasConflictingProperty(animated)) {
731 StartSequenceImmediately(sequences[i].get());
732 started_sequence = true;
733 break;
736 // Animation couldn't be started. Add its properties to the collection so
737 // that we don't start a conflicting animation. For example, if our queue
738 // has the elements { {T,B}, {B} } (that is, an element that animates both
739 // the transform and the bounds followed by an element that animates the
740 // bounds), and we're currently animating the transform, we can't start
741 // the first element because it animates the transform, too. We cannot
742 // start the second element, either, because the first element animates
743 // bounds too, and needs to go first.
744 animated |= sequences[i]->properties();
747 // If we started a sequence, try again. We may be able to start several.
748 } while (started_sequence);
751 bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) {
752 PurgeDeletedAnimations();
754 // Ensure that no one is animating one of the sequence's properties already.
755 for (RunningAnimations::const_iterator iter = running_animations_.begin();
756 iter != running_animations_.end(); ++iter) {
757 if ((*iter).sequence()->HasConflictingProperty(sequence->properties()))
758 return false;
761 // All clear, actually start the sequence.
762 // All LayerAnimators share the same LayerAnimatorCollection. Use the
763 // last_tick_time() from there to ensure animations started during the same
764 // event complete at the same time.
765 base::TimeTicks start_time;
766 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
767 if (is_animating() || adding_animations_)
768 start_time = last_step_time_;
769 else if (collection && collection->HasActiveAnimators())
770 start_time = collection->last_tick_time();
771 else
772 start_time = base::TimeTicks::Now();
774 if (!sequence->animation_group_id())
775 sequence->set_animation_group_id(cc::AnimationIdProvider::NextGroupId());
776 if (!sequence->waiting_for_group_start() ||
777 sequence->IsFirstElementThreaded()) {
778 sequence->set_start_time(start_time);
779 sequence->Start(delegate());
781 running_animations_.push_back(
782 RunningAnimation(sequence->AsWeakPtr()));
784 // Need to keep a reference to the animation.
785 AddToQueueIfNotPresent(sequence);
787 // Ensure that animations get stepped at their start time.
788 Step(start_time);
790 return true;
793 void LayerAnimator::GetTargetValue(
794 LayerAnimationElement::TargetValue* target) const {
795 for (AnimationQueue::const_iterator iter = animation_queue_.begin();
796 iter != animation_queue_.end(); ++iter) {
797 (*iter)->GetTargetValue(target);
801 void LayerAnimator::OnScheduled(LayerAnimationSequence* sequence) {
802 if (observers_.might_have_observers()) {
803 base::ObserverListBase<LayerAnimationObserver>::Iterator it(&observers_);
804 LayerAnimationObserver* obs;
805 while ((obs = it.GetNext()) != NULL) {
806 sequence->AddObserver(obs);
809 sequence->OnScheduled();
812 void LayerAnimator::SetTransitionDuration(base::TimeDelta duration) {
813 if (is_transition_duration_locked_)
814 return;
815 transition_duration_ = duration;
818 void LayerAnimator::ClearAnimationsInternal() {
819 PurgeDeletedAnimations();
821 // Abort should never affect the set of running animations, but just in case
822 // clients are badly behaved, we will use a copy of the running animations.
823 RunningAnimations running_animations_copy = running_animations_;
824 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
825 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
826 continue;
828 scoped_ptr<LayerAnimationSequence> removed(
829 RemoveAnimation(running_animations_copy[i].sequence()));
830 if (removed.get())
831 removed->Abort(delegate());
833 // This *should* have cleared the list of running animations.
834 DCHECK(running_animations_.empty());
835 running_animations_.clear();
836 animation_queue_.clear();
837 UpdateAnimationState();
840 void LayerAnimator::PurgeDeletedAnimations() {
841 for (size_t i = 0; i < running_animations_.size();) {
842 if (!running_animations_[i].is_sequence_alive())
843 running_animations_.erase(running_animations_.begin() + i);
844 else
845 i++;
849 LayerAnimatorCollection* LayerAnimator::GetLayerAnimatorCollection() {
850 return delegate_ ? delegate_->GetLayerAnimatorCollection() : NULL;
853 LayerAnimator::RunningAnimation::RunningAnimation(
854 const base::WeakPtr<LayerAnimationSequence>& sequence)
855 : sequence_(sequence) {
858 LayerAnimator::RunningAnimation::~RunningAnimation() { }
860 } // namespace ui