blob: 2e14588f02b4ce9410b418f7d3f34fd817812242 [file] [log] [blame]
Avi Drissman3e1a26c2022-09-15 20:26:031// Copyright 2012 The Chromium Authors
[email protected]710a98d2011-06-23 20:13:292// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]116302fc2012-05-05 21:45:415#include "ui/compositor/layer_animator.h"
[email protected]710a98d2011-06-23 20:13:296
avi87b8b582015-12-24 21:35:257#include <stddef.h>
8
danakj25c52c32016-04-12 21:51:089#include <memory>
Andrew Rayskiy0b0a1482024-02-27 16:07:5610#include <vector>
danakj25c52c32016-04-12 21:51:0811
Hans Wennborg8586102b2020-05-05 13:43:2912#include "base/check_op.h"
David Sandersde5fee542022-03-23 02:47:4413#include "base/observer_list.h"
ssid334fb87a2015-01-27 20:12:0714#include "base/trace_event/trace_event.h"
Yi Gub0422c42020-01-13 17:00:3615#include "cc/animation/animation.h"
loyso3338dfb2016-03-09 03:07:3216#include "cc/animation/animation_host.h"
[email protected]95e4e1a02013-03-18 07:09:0917#include "cc/animation/animation_id_provider.h"
loyso841229002015-12-21 10:03:2418#include "cc/animation/animation_timeline.h"
19#include "cc/animation/element_animations.h"
Fady Samuelc296f5fb2017-07-21 04:02:1920#include "components/viz/common/frame_sinks/begin_frame_args.h"
[email protected]116302fc2012-05-05 21:45:4121#include "ui/compositor/compositor.h"
22#include "ui/compositor/layer.h"
23#include "ui/compositor/layer_animation_delegate.h"
24#include "ui/compositor/layer_animation_observer.h"
25#include "ui/compositor/layer_animation_sequence.h"
[email protected]9034a282014-06-05 03:11:4726#include "ui/compositor/layer_animator_collection.h"
[email protected]0ed187e2011-10-21 20:07:4227
[email protected]a48f30d2012-10-30 00:35:4128#define SAFE_INVOKE_VOID(function, running_anim, ...) \
29 if (running_anim.is_sequence_alive()) \
30 function(running_anim.sequence(), ##__VA_ARGS__)
31#define SAFE_INVOKE_BOOL(function, running_anim) \
32 ((running_anim.is_sequence_alive()) \
33 ? function(running_anim.sequence()) \
34 : false)
Bartek Nowierskieb07a5e2020-06-03 06:45:1735#define SAFE_INVOKE_PTR(function, running_anim) \
36 ((running_anim.is_sequence_alive()) ? function(running_anim.sequence()) \
37 : nullptr)
[email protected]a48f30d2012-10-30 00:35:4138
[email protected]21445e472011-10-21 20:36:3239namespace ui {
[email protected]0ed187e2011-10-21 20:07:4240
[email protected]b4db9372011-10-24 14:44:1941namespace {
42
Daniel Bratellc2fecad52017-12-21 22:36:2243const int kLayerAnimatorDefaultTransitionDurationMs = 120;
[email protected]1778cbc2012-09-06 04:31:1944
[email protected]9861f1752012-06-01 07:16:1445} // namespace
46
[email protected]b4db9372011-10-24 14:44:1947// LayerAnimator public --------------------------------------------------------
48
49LayerAnimator::LayerAnimator(base::TimeDelta transition_duration)
Allen Bauer8a3cd652021-09-13 22:20:0350 : transition_duration_(transition_duration) {
Yi Gub0422c42020-01-13 17:00:3651 animation_ =
52 cc::Animation::Create(cc::AnimationIdProvider::NextAnimationId());
[email protected]710a98d2011-06-23 20:13:2953}
54
55LayerAnimator::~LayerAnimator() {
[email protected]a48f30d2012-10-30 00:35:4156 for (size_t i = 0; i < running_animations_.size(); ++i) {
57 if (running_animations_[i].is_sequence_alive())
58 running_animations_[i].sequence()->OnAnimatorDestroyed();
59 }
[email protected]5d86a112012-09-23 00:21:5860 ClearAnimationsInternal();
Bartek Nowierskieb07a5e2020-06-03 06:45:1761 delegate_ = nullptr;
Yi Guaa830ff2018-02-22 03:09:1162 DCHECK(!animation_->animation_timeline());
[email protected]710a98d2011-06-23 20:13:2963}
64
[email protected]b4db9372011-10-24 14:44:1965// static
Tom Sepezce830302023-06-30 22:58:4366scoped_refptr<LayerAnimator> LayerAnimator::CreateDefaultAnimator() {
67 return base::MakeRefCounted<LayerAnimator>(base::Milliseconds(0));
[email protected]b4db9372011-10-24 14:44:1968}
69
70// static
Tom Sepezce830302023-06-30 22:58:4371scoped_refptr<LayerAnimator> LayerAnimator::CreateImplicitAnimator() {
72 return base::MakeRefCounted<LayerAnimator>(
Peter Kastinge5a38ed2021-10-02 03:06:3573 base::Milliseconds(kLayerAnimatorDefaultTransitionDurationMs));
[email protected]b4db9372011-10-24 14:44:1974}
75
[email protected]7713e242012-11-15 17:43:1976// This macro provides the implementation for the setter and getter (well,
77// the getter of the target value) for an animated property. For example,
78// it is used for the implementations of SetTransform and GetTargetTransform.
79// It is worth noting that SetFoo avoids invoking the usual animation machinery
80// if the transition duration is zero -- in this case we just set the property
81// on the layer animation delegate immediately.
Francois Doray91e63fb72017-11-08 14:21:5282#define ANIMATED_PROPERTY(type, property, name, member_type, member) \
83 void LayerAnimator::Set##name(type value) { \
84 base::TimeDelta duration = GetTransitionDuration(); \
85 if (duration.is_zero() && delegate() && \
86 (preemption_strategy_ != ENQUEUE_NEW_ANIMATION)) { \
David Black4304b5a2021-10-29 15:58:4587 /* Stopping an animation may result in destruction of `this`. */ \
88 const auto weak_ptr = weak_ptr_factory_.GetWeakPtr(); \
Francois Doray91e63fb72017-11-08 14:21:5289 StopAnimatingProperty(LayerAnimationElement::property); \
David Black4304b5a2021-10-29 15:58:4590 if (!weak_ptr || !delegate()) \
Toni Barzic8be24e0e22021-03-12 07:48:4291 return; \
Francois Doray91e63fb72017-11-08 14:21:5292 delegate()->Set##name##FromAnimation( \
93 value, PropertyChangeReason::NOT_FROM_ANIMATION); \
94 return; \
95 } \
96 std::unique_ptr<LayerAnimationElement> element = \
97 LayerAnimationElement::Create##name##Element(value, duration); \
98 element->set_tween_type(tween_type_); \
99 StartAnimation(new LayerAnimationSequence(std::move(element))); \
100 } \
101 \
102 member_type LayerAnimator::GetTarget##name() const { \
103 LayerAnimationElement::TargetValue target(delegate()); \
104 GetTargetValue(&target); \
105 return target.member; \
danakj25c52c32016-04-12 21:51:08106 }
[email protected]fe7074c62011-10-28 15:22:54107
Nico Weber3a6c6372019-02-21 14:26:18108ANIMATED_PROPERTY(const gfx::Transform&,
109 TRANSFORM,
110 Transform,
111 gfx::Transform,
112 transform)
113ANIMATED_PROPERTY(const gfx::Rect&, BOUNDS, Bounds, gfx::Rect, bounds)
114ANIMATED_PROPERTY(float, OPACITY, Opacity, float, opacity)
115ANIMATED_PROPERTY(bool, VISIBILITY, Visibility, bool, visibility)
116ANIMATED_PROPERTY(float, BRIGHTNESS, Brightness, float, brightness)
117ANIMATED_PROPERTY(float, GRAYSCALE, Grayscale, float, grayscale)
Zoraiz Naeem3abbe3d2024-12-06 00:06:59118ANIMATED_PROPERTY(SkColor4f, COLOR, Color, SkColor4f, color)
Malay Keshavb8ac9e572019-07-03 00:26:55119ANIMATED_PROPERTY(const gfx::Rect&, CLIP, ClipRect, gfx::Rect, clip_rect)
Jun Mukaia343db33b2019-07-17 23:25:50120ANIMATED_PROPERTY(const gfx::RoundedCornersF&,
121 ROUNDED_CORNERS,
122 RoundedCorners,
123 gfx::RoundedCornersF,
124 rounded_corners)
Sasha McIntosh93a0e962022-03-31 20:02:41125ANIMATED_PROPERTY(const gfx::LinearGradient&,
126 GRADIENT_MASK,
127 GradientMask,
128 gfx::LinearGradient,
129 gradient_mask)
Nico Weber3a6c6372019-02-21 14:26:18130
131#undef ANIMATED_PROPERTY
[email protected]e81480f1f2012-10-11 23:06:45132
[email protected]0d316252014-01-20 15:31:19133base::TimeDelta LayerAnimator::GetTransitionDuration() const {
134 return transition_duration_;
135}
136
[email protected]e876c272011-11-02 16:42:45137void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) {
[email protected]9034a282014-06-05 03:11:47138 if (delegate_ && is_started_) {
139 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
140 if (collection)
141 collection->StopAnimator(this);
142 }
loyso1fbd9f92015-12-17 07:43:13143 SwitchToLayer(delegate ? delegate->GetCcLayer() : nullptr);
[email protected]b4db9372011-10-24 14:44:19144 delegate_ = delegate;
[email protected]9034a282014-06-05 03:11:47145 if (delegate_ && is_started_) {
146 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
147 if (collection)
148 collection->StartAnimator(this);
149 }
[email protected]b4db9372011-10-24 14:44:19150}
151
loyso1fbd9f92015-12-17 07:43:13152void LayerAnimator::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
loysoe2fed922016-03-09 04:41:55153 if (delegate_)
Yi Guaa830ff2018-02-22 03:09:11154 DetachLayerFromAnimation();
loysoe2fed922016-03-09 04:41:55155 if (new_layer)
Yi Guaa830ff2018-02-22 03:09:11156 AttachLayerToAnimation(new_layer->id());
loyso841229002015-12-21 10:03:24157}
158
loysocc8e3db2016-10-04 05:22:03159void LayerAnimator::AttachLayerAndTimeline(Compositor* compositor) {
loyso841229002015-12-21 10:03:24160 DCHECK(compositor);
loyso841229002015-12-21 10:03:24161
loysoe2fed922016-03-09 04:41:55162 cc::AnimationTimeline* timeline = compositor->GetAnimationTimeline();
163 DCHECK(timeline);
Yi Guaa830ff2018-02-22 03:09:11164 timeline->AttachAnimation(animation_);
loysoe2fed922016-03-09 04:41:55165
loysocc8e3db2016-10-04 05:22:03166 DCHECK(delegate_->GetCcLayer());
Yi Guaa830ff2018-02-22 03:09:11167 AttachLayerToAnimation(delegate_->GetCcLayer()->id());
Xiyuan Xiaadecd672020-02-25 17:00:57168
169 for (auto& layer_animation_sequence : animation_queue_)
170 layer_animation_sequence->OnAnimatorAttached(delegate());
loyso841229002015-12-21 10:03:24171}
172
loysocc8e3db2016-10-04 05:22:03173void LayerAnimator::DetachLayerAndTimeline(Compositor* compositor) {
loyso841229002015-12-21 10:03:24174 DCHECK(compositor);
loyso3338dfb2016-03-09 03:07:32175
loysode0a0022016-04-15 02:28:38176 cc::AnimationTimeline* timeline = compositor->GetAnimationTimeline();
177 DCHECK(timeline);
178
Yi Guaa830ff2018-02-22 03:09:11179 DetachLayerFromAnimation();
180 timeline->DetachAnimation(animation_);
Xiyuan Xiaadecd672020-02-25 17:00:57181
182 for (auto& layer_animation_sequence : animation_queue_)
183 layer_animation_sequence->OnAnimatorDetached();
loyso841229002015-12-21 10:03:24184}
185
Yi Guaa830ff2018-02-22 03:09:11186void LayerAnimator::AttachLayerToAnimation(int layer_id) {
vollickef2ae922016-06-29 17:54:27187 // For ui, layer and element ids are equivalent.
chrishtrc3daf272017-05-11 11:08:02188 cc::ElementId element_id(layer_id);
Yi Guaa830ff2018-02-22 03:09:11189 if (!animation_->element_id())
190 animation_->AttachElement(element_id);
loyso841229002015-12-21 10:03:24191 else
Yi Guaa830ff2018-02-22 03:09:11192 DCHECK_EQ(animation_->element_id(), element_id);
loyso841229002015-12-21 10:03:24193
Yi Guaa830ff2018-02-22 03:09:11194 animation_->set_animation_delegate(this);
loyso841229002015-12-21 10:03:24195}
196
Yi Guaa830ff2018-02-22 03:09:11197void LayerAnimator::DetachLayerFromAnimation() {
198 animation_->set_animation_delegate(nullptr);
loyso841229002015-12-21 10:03:24199
Yi Guaa830ff2018-02-22 03:09:11200 if (animation_->element_id())
201 animation_->DetachElement();
loyso841229002015-12-21 10:03:24202}
203
Yi Gu4e1dce32018-07-04 20:52:15204void LayerAnimator::AddThreadedAnimation(
205 std::unique_ptr<cc::KeyframeModel> animation) {
206 animation_->AddKeyframeModel(std::move(animation));
loyso841229002015-12-21 10:03:24207}
208
Yi Gu4e1dce32018-07-04 20:52:15209void LayerAnimator::RemoveThreadedAnimation(int keyframe_model_id) {
210 animation_->RemoveKeyframeModel(keyframe_model_id);
loyso1fbd9f92015-12-17 07:43:13211}
212
Yi Gub0422c42020-01-13 17:00:36213cc::Animation* LayerAnimator::GetAnimationForTesting() const {
Yi Guaa830ff2018-02-22 03:09:11214 return animation_.get();
loysod4127442016-02-03 02:29:40215}
216
[email protected]b4db9372011-10-24 14:44:19217void LayerAnimator::StartAnimation(LayerAnimationSequence* animation) {
[email protected]5d86a112012-09-23 00:21:58218 scoped_refptr<LayerAnimator> retain(this);
[email protected]e876c272011-11-02 16:42:45219 OnScheduled(animation);
[email protected]b4db9372011-10-24 14:44:19220 if (!StartSequenceImmediately(animation)) {
221 // Attempt to preempt a running animation.
222 switch (preemption_strategy_) {
223 case IMMEDIATELY_SET_NEW_TARGET:
224 ImmediatelySetNewTarget(animation);
225 break;
226 case IMMEDIATELY_ANIMATE_TO_NEW_TARGET:
227 ImmediatelyAnimateToNewTarget(animation);
228 break;
229 case ENQUEUE_NEW_ANIMATION:
230 EnqueueNewAnimation(animation);
231 break;
232 case REPLACE_QUEUED_ANIMATIONS:
233 ReplaceQueuedAnimations(animation);
234 break;
[email protected]7fca53d42011-09-29 15:38:12235 }
[email protected]b4db9372011-10-24 14:44:19236 }
237 FinishAnyAnimationWithZeroDuration();
[email protected]fe7074c62011-10-28 15:22:54238 UpdateAnimationState();
[email protected]b4db9372011-10-24 14:44:19239}
240
241void LayerAnimator::ScheduleAnimation(LayerAnimationSequence* animation) {
[email protected]5d86a112012-09-23 00:21:58242 scoped_refptr<LayerAnimator> retain(this);
[email protected]e876c272011-11-02 16:42:45243 OnScheduled(animation);
[email protected]b4db9372011-10-24 14:44:19244 if (is_animating()) {
Ian Vollick37e51bd12018-12-18 14:32:09245 animation_queue_.push_back(
246 std::unique_ptr<LayerAnimationSequence>(animation));
[email protected]b4db9372011-10-24 14:44:19247 ProcessQueue();
248 } else {
249 StartSequenceImmediately(animation);
[email protected]7fca53d42011-09-29 15:38:12250 }
[email protected]fe7074c62011-10-28 15:22:54251 UpdateAnimationState();
[email protected]710a98d2011-06-23 20:13:29252}
253
[email protected]d064ef82012-11-13 10:26:59254void LayerAnimator::StartTogether(
255 const std::vector<LayerAnimationSequence*>& animations) {
256 scoped_refptr<LayerAnimator> retain(this);
257 if (preemption_strategy_ == IMMEDIATELY_SET_NEW_TARGET) {
258 std::vector<LayerAnimationSequence*>::const_iterator iter;
259 for (iter = animations.begin(); iter != animations.end(); ++iter) {
260 StartAnimation(*iter);
261 }
262 return;
263 }
[email protected]d764fd3d2012-11-15 20:07:51264
[email protected]d064ef82012-11-13 10:26:59265 adding_animations_ = true;
[email protected]d764fd3d2012-11-15 20:07:51266 if (!is_animating()) {
[email protected]9034a282014-06-05 03:11:47267 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
268 if (collection && collection->HasActiveAnimators())
269 last_step_time_ = collection->last_tick_time();
[email protected]d764fd3d2012-11-15 20:07:51270 else
abhishek.ka7215854d2015-05-26 06:13:17271 last_step_time_ = base::TimeTicks::Now();
[email protected]d764fd3d2012-11-15 20:07:51272 }
[email protected]d064ef82012-11-13 10:26:59273
274 // Collect all the affected properties.
[email protected]e03193d2014-01-14 03:10:24275 LayerAnimationElement::AnimatableProperties animated_properties =
276 LayerAnimationElement::UNKNOWN;
277
[email protected]d064ef82012-11-13 10:26:59278 std::vector<LayerAnimationSequence*>::const_iterator iter;
[email protected]e03193d2014-01-14 03:10:24279 for (iter = animations.begin(); iter != animations.end(); ++iter)
280 animated_properties |= (*iter)->properties();
[email protected]d064ef82012-11-13 10:26:59281
282 // Starting a zero duration pause that affects all the animated properties
283 // will prevent any of the sequences from animating until there are no
284 // running animations that affect any of these properties, as well as
285 // handle preemption strategy.
286 StartAnimation(new LayerAnimationSequence(
287 LayerAnimationElement::CreatePauseElement(animated_properties,
288 base::TimeDelta())));
289
[email protected]bf912272013-02-23 01:54:16290 bool wait_for_group_start = false;
291 for (iter = animations.begin(); iter != animations.end(); ++iter)
Robert Flack763bb3a12022-08-12 17:41:17292 wait_for_group_start |=
293 delegate_ && (*iter)->IsFirstElementThreaded(delegate_);
[email protected]bf912272013-02-23 01:54:16294 int group_id = cc::AnimationIdProvider::NextGroupId();
295
[email protected]d064ef82012-11-13 10:26:59296 // These animations (provided they don't animate any common properties) will
297 // now animate together if trivially scheduled.
298 for (iter = animations.begin(); iter != animations.end(); ++iter) {
[email protected]bf912272013-02-23 01:54:16299 (*iter)->set_animation_group_id(group_id);
300 (*iter)->set_waiting_for_group_start(wait_for_group_start);
[email protected]d064ef82012-11-13 10:26:59301 ScheduleAnimation(*iter);
302 }
303
304 adding_animations_ = false;
305 UpdateAnimationState();
306}
307
308
[email protected]b4db9372011-10-24 14:44:19309void LayerAnimator::ScheduleTogether(
310 const std::vector<LayerAnimationSequence*>& animations) {
[email protected]5d86a112012-09-23 00:21:58311 scoped_refptr<LayerAnimator> retain(this);
312
[email protected]b4db9372011-10-24 14:44:19313 // Collect all the affected properties.
[email protected]e03193d2014-01-14 03:10:24314 LayerAnimationElement::AnimatableProperties animated_properties =
315 LayerAnimationElement::UNKNOWN;
316
[email protected]b4db9372011-10-24 14:44:19317 std::vector<LayerAnimationSequence*>::const_iterator iter;
[email protected]e03193d2014-01-14 03:10:24318 for (iter = animations.begin(); iter != animations.end(); ++iter)
319 animated_properties |= (*iter)->properties();
[email protected]710a98d2011-06-23 20:13:29320
[email protected]b4db9372011-10-24 14:44:19321 // Scheduling a zero duration pause that affects all the animated properties
322 // will prevent any of the sequences from animating until there are no
323 // running animations that affect any of these properties.
[email protected]e4cbcc772012-03-07 18:59:31324 ScheduleAnimation(new LayerAnimationSequence(
325 LayerAnimationElement::CreatePauseElement(animated_properties,
326 base::TimeDelta())));
[email protected]710a98d2011-06-23 20:13:29327
[email protected]bf912272013-02-23 01:54:16328 bool wait_for_group_start = false;
329 for (iter = animations.begin(); iter != animations.end(); ++iter)
Robert Flack763bb3a12022-08-12 17:41:17330 wait_for_group_start |=
331 delegate_ && (*iter)->IsFirstElementThreaded(delegate_);
[email protected]bf912272013-02-23 01:54:16332
333 int group_id = cc::AnimationIdProvider::NextGroupId();
334
[email protected]b4db9372011-10-24 14:44:19335 // These animations (provided they don't animate any common properties) will
336 // now animate together if trivially scheduled.
337 for (iter = animations.begin(); iter != animations.end(); ++iter) {
[email protected]bf912272013-02-23 01:54:16338 (*iter)->set_animation_group_id(group_id);
339 (*iter)->set_waiting_for_group_start(wait_for_group_start);
[email protected]b4db9372011-10-24 14:44:19340 ScheduleAnimation(*iter);
[email protected]710a98d2011-06-23 20:13:29341 }
[email protected]fe7074c62011-10-28 15:22:54342
343 UpdateAnimationState();
344}
345
[email protected]2a88c702012-09-04 23:15:02346void LayerAnimator::SchedulePauseForProperties(
347 base::TimeDelta duration,
[email protected]e03193d2014-01-14 03:10:24348 LayerAnimationElement::AnimatableProperties properties_to_pause) {
[email protected]2a88c702012-09-04 23:15:02349 ScheduleAnimation(new ui::LayerAnimationSequence(
350 ui::LayerAnimationElement::CreatePauseElement(
351 properties_to_pause, duration)));
352}
353
Francois Dorayeef012b62017-10-26 20:02:59354bool LayerAnimator::IsAnimatingOnePropertyOf(
355 LayerAnimationElement::AnimatableProperties properties) const {
356 for (auto& layer_animation_sequence : animation_queue_) {
357 if (layer_animation_sequence->properties() & properties)
[email protected]e876c272011-11-02 16:42:45358 return true;
[email protected]e876c272011-11-02 16:42:45359 }
360 return false;
[email protected]7fca53d42011-09-29 15:38:12361}
362
[email protected]b4db9372011-10-24 14:44:19363void LayerAnimator::StopAnimatingProperty(
364 LayerAnimationElement::AnimatableProperty property) {
[email protected]5d86a112012-09-23 00:21:58365 scoped_refptr<LayerAnimator> retain(this);
[email protected]b4db9372011-10-24 14:44:19366 while (true) {
[email protected]a48f30d2012-10-30 00:35:41367 // GetRunningAnimation purges deleted animations before searching, so we are
368 // guaranteed to find a live animation if any is returned at all.
[email protected]b4db9372011-10-24 14:44:19369 RunningAnimation* running = GetRunningAnimation(property);
370 if (!running)
371 break;
[email protected]a48f30d2012-10-30 00:35:41372 // As was mentioned above, this sequence must be alive.
373 DCHECK(running->is_sequence_alive());
[email protected]6f110e42012-12-18 00:21:14374 FinishAnimation(running->sequence(), false);
[email protected]a48f30d2012-10-30 00:35:41375 }
[email protected]b4db9372011-10-24 14:44:19376}
377
[email protected]e876c272011-11-02 16:42:45378void LayerAnimator::AddObserver(LayerAnimationObserver* observer) {
Francois Doray29ecd3aa2017-11-07 15:40:18379 if (!observers_.HasObserver(observer)) {
[email protected]e876c272011-11-02 16:42:45380 observers_.AddObserver(observer);
Francois Doray29ecd3aa2017-11-07 15:40:18381 for (auto& layer_animation_sequence : animation_queue_)
382 layer_animation_sequence->AddObserver(observer);
383 }
[email protected]e876c272011-11-02 16:42:45384}
385
386void LayerAnimator::RemoveObserver(LayerAnimationObserver* observer) {
387 observers_.RemoveObserver(observer);
[email protected]5cc8538d2011-11-07 15:24:54388 // Remove the observer from all sequences as well.
389 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
390 queue_iter != animation_queue_.end(); ++queue_iter) {
391 (*queue_iter)->RemoveObserver(observer);
392 }
[email protected]e876c272011-11-02 16:42:45393}
394
wutao4f1c0d5d2017-10-05 01:02:43395void LayerAnimator::AddOwnedObserver(
396 std::unique_ptr<ImplicitAnimationObserver> animation_observer) {
397 owned_observer_list_.push_back(std::move(animation_observer));
398}
399
400void LayerAnimator::RemoveAndDestroyOwnedObserver(
401 ImplicitAnimationObserver* animation_observer) {
Andrew Rayskiy0b0a1482024-02-27 16:07:56402 std::erase_if(owned_observer_list_,
403 [animation_observer](
404 const std::unique_ptr<ImplicitAnimationObserver>& other) {
405 return other.get() == animation_observer;
406 });
wutao4f1c0d5d2017-10-05 01:02:43407}
408
Allen Bauer8a3cd652021-09-13 22:20:03409base::CallbackListSubscription LayerAnimator::AddSequenceScheduledCallback(
410 SequenceScheduledCallback callback) {
411 return sequence_scheduled_callbacks_.Add(std::move(callback));
412}
413
[email protected]bf912272013-02-23 01:54:16414void LayerAnimator::OnThreadedAnimationStarted(
loyso79c0bfc2016-04-18 23:46:42415 base::TimeTicks monotonic_time,
416 cc::TargetProperty::Type target_property,
417 int group_id) {
[email protected]bf912272013-02-23 01:54:16418 LayerAnimationElement::AnimatableProperty property =
loyso79c0bfc2016-04-18 23:46:42419 LayerAnimationElement::ToAnimatableProperty(target_property);
[email protected]bf912272013-02-23 01:54:16420
421 RunningAnimation* running = GetRunningAnimation(property);
422 if (!running)
423 return;
424 DCHECK(running->is_sequence_alive());
425
loyso79c0bfc2016-04-18 23:46:42426 if (running->sequence()->animation_group_id() != group_id)
[email protected]bf912272013-02-23 01:54:16427 return;
428
loyso79c0bfc2016-04-18 23:46:42429 running->sequence()->OnThreadedAnimationStarted(monotonic_time,
430 target_property, group_id);
[email protected]bf912272013-02-23 01:54:16431 if (!running->sequence()->waiting_for_group_start())
432 return;
433
loyso79c0bfc2016-04-18 23:46:42434 base::TimeTicks start_time = monotonic_time;
[email protected]bf912272013-02-23 01:54:16435
436 running->sequence()->set_waiting_for_group_start(false);
437
438 // The call to GetRunningAnimation made above already purged deleted
439 // animations, so we are guaranteed that all the animations we iterate
440 // over now are alive.
jdoerriedcef4b12018-10-10 12:04:32441 for (auto iter = running_animations_.begin();
[email protected]bf912272013-02-23 01:54:16442 iter != running_animations_.end(); ++iter) {
443 // Ensure that each sequence is only Started once, regardless of the
444 // number of sequences in the group that have threaded first elements.
loyso79c0bfc2016-04-18 23:46:42445 if (((*iter).sequence()->animation_group_id() == group_id) &&
wutao914b06e62017-09-28 17:41:15446 !(*iter).sequence()->IsFirstElementThreaded(delegate_) &&
[email protected]bf912272013-02-23 01:54:16447 (*iter).sequence()->waiting_for_group_start()) {
448 (*iter).sequence()->set_start_time(start_time);
449 (*iter).sequence()->set_waiting_for_group_start(false);
450 (*iter).sequence()->Start(delegate());
451 }
452 }
453}
454
[email protected]9034a282014-06-05 03:11:47455void LayerAnimator::AddToCollection(LayerAnimatorCollection* collection) {
L. David Baron138321d2022-05-24 22:30:24456 DCHECK_EQ(collection, GetLayerAnimatorCollection());
[email protected]9034a282014-06-05 03:11:47457 if (is_animating() && !is_started_) {
458 collection->StartAnimator(this);
459 is_started_ = true;
460 }
461}
462
463void LayerAnimator::RemoveFromCollection(LayerAnimatorCollection* collection) {
L. David Baron138321d2022-05-24 22:30:24464 DCHECK_EQ(collection, GetLayerAnimatorCollection());
bruthig33b1edab2016-03-02 02:22:35465 if (is_started_) {
[email protected]9034a282014-06-05 03:11:47466 collection->StopAnimator(this);
467 is_started_ = false;
468 }
L. David Baron138321d2022-05-24 22:30:24469 DCHECK(!animation_->element_animations() ||
470 !animation_->element_animations()->HasTickingKeyframeEffect());
[email protected]9034a282014-06-05 03:11:47471}
472
[email protected]d59a3692012-04-10 20:27:31473// LayerAnimator protected -----------------------------------------------------
474
[email protected]5d86a112012-09-23 00:21:58475void LayerAnimator::ProgressAnimation(LayerAnimationSequence* sequence,
[email protected]3d75fed2012-12-15 18:47:38476 base::TimeTicks now) {
[email protected]bf912272013-02-23 01:54:16477 if (!delegate() || sequence->waiting_for_group_start())
[email protected]5d86a112012-09-23 00:21:58478 return;
479
[email protected]3d75fed2012-12-15 18:47:38480 sequence->Progress(now, delegate());
[email protected]d59a3692012-04-10 20:27:31481}
482
[email protected]a48f30d2012-10-30 00:35:41483void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence* sequence) {
[email protected]4a386e42012-12-05 01:19:30484 if (!delegate())
485 return;
486
487 sequence->ProgressToEnd(delegate());
[email protected]a48f30d2012-10-30 00:35:41488}
489
[email protected]d59a3692012-04-10 20:27:31490bool LayerAnimator::HasAnimation(LayerAnimationSequence* sequence) const {
491 for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin();
492 queue_iter != animation_queue_.end(); ++queue_iter) {
493 if ((*queue_iter).get() == sequence)
494 return true;
495 }
496 return false;
497}
498
[email protected]b4db9372011-10-24 14:44:19499// LayerAnimator private -------------------------------------------------------
500
501void LayerAnimator::Step(base::TimeTicks now) {
[email protected]e4cbcc772012-03-07 18:59:31502 TRACE_EVENT0("ui", "LayerAnimator::Step");
[email protected]5d86a112012-09-23 00:21:58503 scoped_refptr<LayerAnimator> retain(this);
[email protected]e4cbcc772012-03-07 18:59:31504
[email protected]b4db9372011-10-24 14:44:19505 last_step_time_ = now;
[email protected]1778cbc2012-09-06 04:31:19506
[email protected]a48f30d2012-10-30 00:35:41507 PurgeDeletedAnimations();
508
[email protected]f5cd9e52011-11-03 21:38:08509 // We need to make a copy of the running animations because progressing them
510 // and finishing them may indirectly affect the collection of running
511 // animations.
512 RunningAnimations running_animations_copy = running_animations_;
513 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
[email protected]a48f30d2012-10-30 00:35:41514 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
[email protected]d59a3692012-04-10 20:27:31515 continue;
516
[email protected]3d75fed2012-12-15 18:47:38517 if (running_animations_copy[i].sequence()->IsFinished(now)) {
[email protected]6f110e42012-12-18 00:21:14518 SAFE_INVOKE_VOID(FinishAnimation, running_animations_copy[i], false);
519 } else {
[email protected]3d75fed2012-12-15 18:47:38520 SAFE_INVOKE_VOID(ProgressAnimation, running_animations_copy[i], now);
[email protected]6f110e42012-12-18 00:21:14521 }
[email protected]b4db9372011-10-24 14:44:19522 }
[email protected]b4db9372011-10-24 14:44:19523}
524
[email protected]6f110e42012-12-18 00:21:14525void LayerAnimator::StopAnimatingInternal(bool abort) {
526 scoped_refptr<LayerAnimator> retain(this);
ljagielski20570982015-01-07 20:32:55527 while (is_animating() && delegate()) {
[email protected]6f110e42012-12-18 00:21:14528 // We're going to attempt to finish the first running animation. Let's
529 // ensure that it's valid.
530 PurgeDeletedAnimations();
531
532 // If we've purged all running animations, attempt to start one up.
533 if (running_animations_.empty())
534 ProcessQueue();
535
536 DCHECK(!running_animations_.empty());
537
538 // Still no luck, let's just bail and clear all animations.
539 if (running_animations_.empty()) {
540 ClearAnimationsInternal();
541 break;
542 }
543
544 SAFE_INVOKE_VOID(FinishAnimation, running_animations_[0], abort);
545 }
546}
547
[email protected]b4db9372011-10-24 14:44:19548void LayerAnimator::UpdateAnimationState() {
549 if (disable_timer_for_test_)
[email protected]7fca53d42011-09-29 15:38:12550 return;
551
[email protected]b4db9372011-10-24 14:44:19552 const bool should_start = is_animating();
[email protected]9034a282014-06-05 03:11:47553 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
554 if (collection) {
555 if (should_start && !is_started_)
556 collection->StartAnimator(this);
557 else if (!should_start && is_started_)
558 collection->StopAnimator(this);
559 is_started_ = should_start;
560 } else {
561 is_started_ = false;
562 }
[email protected]710a98d2011-06-23 20:13:29563}
564
[email protected]f5cd9e52011-11-03 21:38:08565LayerAnimationSequence* LayerAnimator::RemoveAnimation(
566 LayerAnimationSequence* sequence) {
Ian Vollick37e51bd12018-12-18 14:32:09567 std::unique_ptr<LayerAnimationSequence> to_return;
[email protected]f5cd9e52011-11-03 21:38:08568
[email protected]bf912272013-02-23 01:54:16569 bool is_running = false;
570
[email protected]f5cd9e52011-11-03 21:38:08571 // First remove from running animations
jdoerriedcef4b12018-10-10 12:04:32572 for (auto iter = running_animations_.begin();
[email protected]b4db9372011-10-24 14:44:19573 iter != running_animations_.end(); ++iter) {
[email protected]a48f30d2012-10-30 00:35:41574 if ((*iter).sequence() == sequence) {
[email protected]b4db9372011-10-24 14:44:19575 running_animations_.erase(iter);
[email protected]bf912272013-02-23 01:54:16576 is_running = true;
[email protected]b4db9372011-10-24 14:44:19577 break;
[email protected]21445e472011-10-21 20:36:32578 }
579 }
[email protected]b4db9372011-10-24 14:44:19580
581 // Then remove from the queue
582 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
583 queue_iter != animation_queue_.end(); ++queue_iter) {
Ian Vollick37e51bd12018-12-18 14:32:09584 if (queue_iter->get() == sequence) {
585 to_return = std::move(*queue_iter);
[email protected]b4db9372011-10-24 14:44:19586 animation_queue_.erase(queue_iter);
587 break;
588 }
589 }
[email protected]f5cd9e52011-11-03 21:38:08590
Elaine Chiena2c1d702021-09-08 22:50:38591 // Do not continue and attempt to start other sequences if the delegate is
592 // nullptr.
Alison Galec5ea18592024-04-16 16:08:51593 // TODO(crbug.com/40790139): Guard other uses of delegate_ in this class.
Elaine Chiena2c1d702021-09-08 22:50:38594 if (!delegate())
595 return to_return.release();
596
wutao914b06e62017-09-28 17:41:15597 if (!to_return.get() || !to_return->waiting_for_group_start() ||
598 !to_return->IsFirstElementThreaded(delegate_))
[email protected]bf912272013-02-23 01:54:16599 return to_return.release();
600
601 // The removed sequence may have been responsible for making other sequences
602 // wait for a group start. If no other sequences in the group have a
603 // threaded first element, the group no longer needs the additional wait.
604 bool is_wait_still_needed = false;
605 int group_id = to_return->animation_group_id();
606 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
607 queue_iter != animation_queue_.end(); ++queue_iter) {
608 if (((*queue_iter)->animation_group_id() == group_id) &&
wutao914b06e62017-09-28 17:41:15609 (*queue_iter)->IsFirstElementThreaded(delegate_)) {
[email protected]bf912272013-02-23 01:54:16610 is_wait_still_needed = true;
611 break;
612 }
613 }
614
615 if (is_wait_still_needed)
616 return to_return.release();
617
618 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
619 queue_iter != animation_queue_.end(); ++queue_iter) {
620 if ((*queue_iter)->animation_group_id() == group_id &&
621 (*queue_iter)->waiting_for_group_start()) {
622 (*queue_iter)->set_waiting_for_group_start(false);
623 if (is_running) {
624 (*queue_iter)->set_start_time(last_step_time_);
625 (*queue_iter)->Start(delegate());
626 }
627 }
628 }
[email protected]f5cd9e52011-11-03 21:38:08629 return to_return.release();
[email protected]0ed187e2011-10-21 20:07:42630}
631
[email protected]6f110e42012-12-18 00:21:14632void LayerAnimator::FinishAnimation(
633 LayerAnimationSequence* sequence, bool abort) {
[email protected]5d86a112012-09-23 00:21:58634 scoped_refptr<LayerAnimator> retain(this);
danakj25c52c32016-04-12 21:51:08635 std::unique_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence));
[email protected]6f110e42012-12-18 00:21:14636 if (abort)
[email protected]bf912272013-02-23 01:54:16637 sequence->Abort(delegate());
[email protected]6f110e42012-12-18 00:21:14638 else
639 ProgressAnimationToEnd(sequence);
ljagielski20570982015-01-07 20:32:55640 if (!delegate())
641 return;
[email protected]b4db9372011-10-24 14:44:19642 ProcessQueue();
643 UpdateAnimationState();
[email protected]21445e472011-10-21 20:36:32644}
[email protected]0ed187e2011-10-21 20:07:42645
[email protected]b4db9372011-10-24 14:44:19646void LayerAnimator::FinishAnyAnimationWithZeroDuration() {
[email protected]5d86a112012-09-23 00:21:58647 scoped_refptr<LayerAnimator> retain(this);
[email protected]2ddfe432011-11-07 19:26:30648 // Special case: if we've started a 0 duration animation, just finish it now
649 // and get rid of it. We need to make a copy because Progress may indirectly
650 // cause new animations to start running.
[email protected]f5cd9e52011-11-03 21:38:08651 RunningAnimations running_animations_copy = running_animations_;
652 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
[email protected]a48f30d2012-10-30 00:35:41653 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
[email protected]d59a3692012-04-10 20:27:31654 continue;
655
[email protected]3d75fed2012-12-15 18:47:38656 if (running_animations_copy[i].sequence()->IsFinished(
657 running_animations_copy[i].sequence()->start_time())) {
[email protected]a48f30d2012-10-30 00:35:41658 SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
danakj25c52c32016-04-12 21:51:08659 std::unique_ptr<LayerAnimationSequence> removed(
[email protected]a48f30d2012-10-30 00:35:41660 SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
[email protected]b4db9372011-10-24 14:44:19661 }
662 }
663 ProcessQueue();
664 UpdateAnimationState();
[email protected]21445e472011-10-21 20:36:32665}
[email protected]0ed187e2011-10-21 20:07:42666
[email protected]b4db9372011-10-24 14:44:19667void LayerAnimator::ClearAnimations() {
[email protected]5d86a112012-09-23 00:21:58668 scoped_refptr<LayerAnimator> retain(this);
669 ClearAnimationsInternal();
[email protected]b4db9372011-10-24 14:44:19670}
671
672LayerAnimator::RunningAnimation* LayerAnimator::GetRunningAnimation(
673 LayerAnimationElement::AnimatableProperty property) {
[email protected]a48f30d2012-10-30 00:35:41674 PurgeDeletedAnimations();
jdoerriedcef4b12018-10-10 12:04:32675 for (auto iter = running_animations_.begin();
[email protected]b4db9372011-10-24 14:44:19676 iter != running_animations_.end(); ++iter) {
[email protected]e03193d2014-01-14 03:10:24677 if ((*iter).sequence()->properties() & property)
[email protected]b4db9372011-10-24 14:44:19678 return &(*iter);
679 }
Bartek Nowierskieb07a5e2020-06-03 06:45:17680 return nullptr;
[email protected]b4db9372011-10-24 14:44:19681}
682
683void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence* animation) {
684 // If we don't have the animation in the queue yet, add it.
685 bool found_sequence = false;
686 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
687 queue_iter != animation_queue_.end(); ++queue_iter) {
Ian Vollick37e51bd12018-12-18 14:32:09688 if (queue_iter->get() == animation) {
[email protected]b4db9372011-10-24 14:44:19689 found_sequence = true;
690 break;
691 }
692 }
693
Ian Vollick37e51bd12018-12-18 14:32:09694 if (!found_sequence) {
695 animation_queue_.push_front(
696 std::unique_ptr<LayerAnimationSequence>(animation));
697 }
[email protected]b4db9372011-10-24 14:44:19698}
699
700void LayerAnimator::RemoveAllAnimationsWithACommonProperty(
[email protected]f5cd9e52011-11-03 21:38:08701 LayerAnimationSequence* sequence, bool abort) {
[email protected]b4db9372011-10-24 14:44:19702 // For all the running animations, if they animate the same property,
[email protected]f5cd9e52011-11-03 21:38:08703 // progress them to the end and remove them. Note, Aborting or Progressing
704 // animations may affect the collection of running animations, so we need to
705 // operate on a copy.
706 RunningAnimations running_animations_copy = running_animations_;
707 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
[email protected]a48f30d2012-10-30 00:35:41708 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
[email protected]d59a3692012-04-10 20:27:31709 continue;
710
[email protected]712f4b642013-03-14 07:09:15711 if (running_animations_copy[i].sequence()->HasConflictingProperty(
[email protected]b4db9372011-10-24 14:44:19712 sequence->properties())) {
danakj25c52c32016-04-12 21:51:08713 std::unique_ptr<LayerAnimationSequence> removed(
[email protected]a48f30d2012-10-30 00:35:41714 SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
[email protected]f5cd9e52011-11-03 21:38:08715 if (abort)
[email protected]bf912272013-02-23 01:54:16716 running_animations_copy[i].sequence()->Abort(delegate());
[email protected]f5cd9e52011-11-03 21:38:08717 else
[email protected]a48f30d2012-10-30 00:35:41718 SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
[email protected]b4db9372011-10-24 14:44:19719 }
720 }
721
[email protected]f5cd9e52011-11-03 21:38:08722 // Same for the queued animations that haven't been started. Again, we'll
723 // need to operate on a copy.
[email protected]a48f30d2012-10-30 00:35:41724 std::vector<base::WeakPtr<LayerAnimationSequence> > sequences;
[email protected]f5cd9e52011-11-03 21:38:08725 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
726 queue_iter != animation_queue_.end(); ++queue_iter)
[email protected]a48f30d2012-10-30 00:35:41727 sequences.push_back((*queue_iter)->AsWeakPtr());
[email protected]f5cd9e52011-11-03 21:38:08728
729 for (size_t i = 0; i < sequences.size(); ++i) {
[email protected]7ffde472013-06-04 06:42:19730 if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
[email protected]d59a3692012-04-10 20:27:31731 continue;
732
[email protected]712f4b642013-03-14 07:09:15733 if (sequences[i]->HasConflictingProperty(sequence->properties())) {
danakj25c52c32016-04-12 21:51:08734 std::unique_ptr<LayerAnimationSequence> removed(
[email protected]7ffde472013-06-04 06:42:19735 RemoveAnimation(sequences[i].get()));
[email protected]b4db9372011-10-24 14:44:19736 if (abort)
[email protected]bf912272013-02-23 01:54:16737 sequences[i]->Abort(delegate());
[email protected]b4db9372011-10-24 14:44:19738 else
[email protected]7ffde472013-06-04 06:42:19739 ProgressAnimationToEnd(sequences[i].get());
[email protected]b4db9372011-10-24 14:44:19740 }
741 }
742}
743
744void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence* sequence) {
[email protected]a48f30d2012-10-30 00:35:41745 // Need to detect if our sequence gets destroyed.
746 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
747 sequence->AsWeakPtr();
748
[email protected]b4db9372011-10-24 14:44:19749 const bool abort = false;
750 RemoveAllAnimationsWithACommonProperty(sequence, abort);
[email protected]7ffde472013-06-04 06:42:19751 if (!weak_sequence_ptr.get())
[email protected]a48f30d2012-10-30 00:35:41752 return;
753
[email protected]d3ba37ab2012-02-09 19:53:13754 LayerAnimationSequence* removed = RemoveAnimation(sequence);
Bartek Nowierskieb07a5e2020-06-03 06:45:17755 DCHECK(removed == nullptr || removed == sequence);
[email protected]7ffde472013-06-04 06:42:19756 if (!weak_sequence_ptr.get())
[email protected]a48f30d2012-10-30 00:35:41757 return;
758
[email protected]4a386e42012-12-05 01:19:30759 ProgressAnimationToEnd(sequence);
[email protected]7ffde472013-06-04 06:42:19760 if (!weak_sequence_ptr.get())
[email protected]a48f30d2012-10-30 00:35:41761 return;
762
763 delete sequence;
[email protected]b4db9372011-10-24 14:44:19764}
765
766void LayerAnimator::ImmediatelyAnimateToNewTarget(
767 LayerAnimationSequence* sequence) {
[email protected]a48f30d2012-10-30 00:35:41768 // Need to detect if our sequence gets destroyed.
769 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
770 sequence->AsWeakPtr();
771
[email protected]b4db9372011-10-24 14:44:19772 const bool abort = true;
773 RemoveAllAnimationsWithACommonProperty(sequence, abort);
[email protected]7ffde472013-06-04 06:42:19774 if (!weak_sequence_ptr.get())
[email protected]a48f30d2012-10-30 00:35:41775 return;
776
[email protected]b4db9372011-10-24 14:44:19777 AddToQueueIfNotPresent(sequence);
[email protected]7ffde472013-06-04 06:42:19778 if (!weak_sequence_ptr.get())
[email protected]a48f30d2012-10-30 00:35:41779 return;
780
[email protected]b4db9372011-10-24 14:44:19781 StartSequenceImmediately(sequence);
782}
783
784void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence* sequence) {
785 // It is assumed that if there was no conflicting animation, we would
786 // not have been called. No need to check for a collision; just
787 // add to the queue.
Ian Vollick37e51bd12018-12-18 14:32:09788 animation_queue_.push_back(std::unique_ptr<LayerAnimationSequence>(sequence));
[email protected]b4db9372011-10-24 14:44:19789 ProcessQueue();
790}
791
792void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence* sequence) {
[email protected]a48f30d2012-10-30 00:35:41793 // Need to detect if our sequence gets destroyed.
794 base::WeakPtr<LayerAnimationSequence> weak_sequence_ptr =
795 sequence->AsWeakPtr();
796
[email protected]b4db9372011-10-24 14:44:19797 // Remove all animations that aren't running. Note: at each iteration i is
798 // incremented or an element is removed from the queue, so
799 // animation_queue_.size() - i is always decreasing and we are always making
800 // progress towards the loop terminating.
801 for (size_t i = 0; i < animation_queue_.size();) {
[email protected]7ffde472013-06-04 06:42:19802 if (!weak_sequence_ptr.get())
[email protected]a48f30d2012-10-30 00:35:41803 break;
804
805 PurgeDeletedAnimations();
806
[email protected]b4db9372011-10-24 14:44:19807 bool is_running = false;
808 for (RunningAnimations::const_iterator iter = running_animations_.begin();
809 iter != running_animations_.end(); ++iter) {
[email protected]a48f30d2012-10-30 00:35:41810 if ((*iter).sequence() == animation_queue_[i].get()) {
[email protected]b4db9372011-10-24 14:44:19811 is_running = true;
812 break;
813 }
814 }
[email protected]a48f30d2012-10-30 00:35:41815
[email protected]b4db9372011-10-24 14:44:19816 if (!is_running)
[email protected]300548c2012-06-17 08:54:55817 delete RemoveAnimation(animation_queue_[i].get());
[email protected]b4db9372011-10-24 14:44:19818 else
819 ++i;
820 }
Ian Vollick37e51bd12018-12-18 14:32:09821 animation_queue_.push_back(std::unique_ptr<LayerAnimationSequence>(sequence));
[email protected]b4db9372011-10-24 14:44:19822 ProcessQueue();
823}
824
825void LayerAnimator::ProcessQueue() {
826 bool started_sequence = false;
827 do {
828 started_sequence = false;
[email protected]b4db9372011-10-24 14:44:19829 // Build a list of all currently animated properties.
[email protected]e03193d2014-01-14 03:10:24830 LayerAnimationElement::AnimatableProperties animated =
831 LayerAnimationElement::UNKNOWN;
[email protected]b4db9372011-10-24 14:44:19832 for (RunningAnimations::const_iterator iter = running_animations_.begin();
833 iter != running_animations_.end(); ++iter) {
[email protected]a48f30d2012-10-30 00:35:41834 if (!(*iter).is_sequence_alive())
835 continue;
[email protected]e03193d2014-01-14 03:10:24836
837 animated |= (*iter).sequence()->properties();
[email protected]b4db9372011-10-24 14:44:19838 }
839
840 // Try to find an animation that doesn't conflict with an animated
[email protected]f5cd9e52011-11-03 21:38:08841 // property or a property that will be animated before it. Note: starting
842 // the animation may indirectly cause more animations to be started, so we
843 // need to operate on a copy.
[email protected]a48f30d2012-10-30 00:35:41844 std::vector<base::WeakPtr<LayerAnimationSequence> > sequences;
[email protected]b4db9372011-10-24 14:44:19845 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
[email protected]f5cd9e52011-11-03 21:38:08846 queue_iter != animation_queue_.end(); ++queue_iter)
[email protected]a48f30d2012-10-30 00:35:41847 sequences.push_back((*queue_iter)->AsWeakPtr());
[email protected]f5cd9e52011-11-03 21:38:08848
849 for (size_t i = 0; i < sequences.size(); ++i) {
[email protected]7ffde472013-06-04 06:42:19850 if (!sequences[i].get() || !HasAnimation(sequences[i].get()))
[email protected]a48f30d2012-10-30 00:35:41851 continue;
852
[email protected]712f4b642013-03-14 07:09:15853 if (!sequences[i]->HasConflictingProperty(animated)) {
[email protected]a48f30d2012-10-30 00:35:41854 StartSequenceImmediately(sequences[i].get());
[email protected]b4db9372011-10-24 14:44:19855 started_sequence = true;
856 break;
857 }
858
859 // Animation couldn't be started. Add its properties to the collection so
860 // that we don't start a conflicting animation. For example, if our queue
861 // has the elements { {T,B}, {B} } (that is, an element that animates both
862 // the transform and the bounds followed by an element that animates the
863 // bounds), and we're currently animating the transform, we can't start
864 // the first element because it animates the transform, too. We cannot
865 // start the second element, either, because the first element animates
866 // bounds too, and needs to go first.
[email protected]e03193d2014-01-14 03:10:24867 animated |= sequences[i]->properties();
[email protected]b4db9372011-10-24 14:44:19868 }
869
870 // If we started a sequence, try again. We may be able to start several.
871 } while (started_sequence);
872}
873
874bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) {
[email protected]a48f30d2012-10-30 00:35:41875 PurgeDeletedAnimations();
876
[email protected]b4db9372011-10-24 14:44:19877 // Ensure that no one is animating one of the sequence's properties already.
878 for (RunningAnimations::const_iterator iter = running_animations_.begin();
879 iter != running_animations_.end(); ++iter) {
[email protected]712f4b642013-03-14 07:09:15880 if ((*iter).sequence()->HasConflictingProperty(sequence->properties()))
[email protected]b4db9372011-10-24 14:44:19881 return false;
882 }
883
charliea3be839702015-01-26 17:35:41884 // All clear, actually start the sequence.
[email protected]9034a282014-06-05 03:11:47885 // All LayerAnimators share the same LayerAnimatorCollection. Use the
[email protected]1778cbc2012-09-06 04:31:19886 // last_tick_time() from there to ensure animations started during the same
887 // event complete at the same time.
888 base::TimeTicks start_time;
[email protected]9034a282014-06-05 03:11:47889 LayerAnimatorCollection* collection = GetLayerAnimatorCollection();
[email protected]d064ef82012-11-13 10:26:59890 if (is_animating() || adding_animations_)
[email protected]1778cbc2012-09-06 04:31:19891 start_time = last_step_time_;
[email protected]9034a282014-06-05 03:11:47892 else if (collection && collection->HasActiveAnimators())
893 start_time = collection->last_tick_time();
[email protected]1778cbc2012-09-06 04:31:19894 else
abhishek.ka7215854d2015-05-26 06:13:17895 start_time = base::TimeTicks::Now();
[email protected]b4db9372011-10-24 14:44:19896
[email protected]bf912272013-02-23 01:54:16897 if (!sequence->animation_group_id())
898 sequence->set_animation_group_id(cc::AnimationIdProvider::NextGroupId());
bruthig4a12c2b2016-11-05 00:19:18899
[email protected]a48f30d2012-10-30 00:35:41900 running_animations_.push_back(
[email protected]3d75fed2012-12-15 18:47:38901 RunningAnimation(sequence->AsWeakPtr()));
[email protected]b4db9372011-10-24 14:44:19902
903 // Need to keep a reference to the animation.
904 AddToQueueIfNotPresent(sequence);
905
bruthig4a12c2b2016-11-05 00:19:18906 if (!sequence->waiting_for_group_start() ||
wutao914b06e62017-09-28 17:41:15907 sequence->IsFirstElementThreaded(delegate_)) {
bruthig4a12c2b2016-11-05 00:19:18908 sequence->set_start_time(start_time);
909 sequence->Start(delegate());
910 }
911
[email protected]b4db9372011-10-24 14:44:19912 // Ensure that animations get stepped at their start time.
913 Step(start_time);
914
915 return true;
[email protected]710a98d2011-06-23 20:13:29916}
917
[email protected]fe7074c62011-10-28 15:22:54918void LayerAnimator::GetTargetValue(
919 LayerAnimationElement::TargetValue* target) const {
[email protected]b1c37fc2012-03-22 03:36:13920 for (AnimationQueue::const_iterator iter = animation_queue_.begin();
921 iter != animation_queue_.end(); ++iter) {
922 (*iter)->GetTargetValue(target);
[email protected]fe7074c62011-10-28 15:22:54923 }
924}
925
[email protected]e876c272011-11-02 16:42:45926void LayerAnimator::OnScheduled(LayerAnimationSequence* sequence) {
Allen Bauer8a3cd652021-09-13 22:20:03927 sequence_scheduled_callbacks_.Notify(sequence);
dchengd38152e2016-10-13 18:21:37928 for (LayerAnimationObserver& observer : observers_)
929 sequence->AddObserver(&observer);
[email protected]e876c272011-11-02 16:42:45930 sequence->OnScheduled();
931}
932
[email protected]0d316252014-01-20 15:31:19933void LayerAnimator::SetTransitionDuration(base::TimeDelta duration) {
934 if (is_transition_duration_locked_)
935 return;
936 transition_duration_ = duration;
[email protected]9861f1752012-06-01 07:16:14937}
938
[email protected]5d86a112012-09-23 00:21:58939void LayerAnimator::ClearAnimationsInternal() {
[email protected]a48f30d2012-10-30 00:35:41940 PurgeDeletedAnimations();
941
[email protected]5d86a112012-09-23 00:21:58942 // Abort should never affect the set of running animations, but just in case
943 // clients are badly behaved, we will use a copy of the running animations.
944 RunningAnimations running_animations_copy = running_animations_;
945 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
[email protected]a48f30d2012-10-30 00:35:41946 if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
[email protected]5d86a112012-09-23 00:21:58947 continue;
948
danakj25c52c32016-04-12 21:51:08949 std::unique_ptr<LayerAnimationSequence> removed(
[email protected]a48f30d2012-10-30 00:35:41950 RemoveAnimation(running_animations_copy[i].sequence()));
[email protected]5d86a112012-09-23 00:21:58951 if (removed.get())
[email protected]bf912272013-02-23 01:54:16952 removed->Abort(delegate());
[email protected]5d86a112012-09-23 00:21:58953 }
954 // This *should* have cleared the list of running animations.
955 DCHECK(running_animations_.empty());
956 running_animations_.clear();
957 animation_queue_.clear();
958 UpdateAnimationState();
959}
960
[email protected]a48f30d2012-10-30 00:35:41961void LayerAnimator::PurgeDeletedAnimations() {
962 for (size_t i = 0; i < running_animations_.size();) {
963 if (!running_animations_[i].is_sequence_alive())
964 running_animations_.erase(running_animations_.begin() + i);
965 else
966 i++;
967 }
968}
969
[email protected]9034a282014-06-05 03:11:47970LayerAnimatorCollection* LayerAnimator::GetLayerAnimatorCollection() {
Bartek Nowierskieb07a5e2020-06-03 06:45:17971 return delegate_ ? delegate_->GetLayerAnimatorCollection() : nullptr;
[email protected]9034a282014-06-05 03:11:47972}
973
Ian Vollickba1f85922017-07-21 18:10:03974void LayerAnimator::NotifyAnimationStarted(base::TimeTicks monotonic_time,
975 int target_property,
976 int group) {
977 OnThreadedAnimationStarted(
978 monotonic_time, static_cast<cc::TargetProperty::Type>(target_property),
979 group);
loyso1fbd9f92015-12-17 07:43:13980}
981
[email protected]a48f30d2012-10-30 00:35:41982LayerAnimator::RunningAnimation::RunningAnimation(
[email protected]3d75fed2012-12-15 18:47:38983 const base::WeakPtr<LayerAnimationSequence>& sequence)
984 : sequence_(sequence) {
[email protected]a48f30d2012-10-30 00:35:41985}
986
vmpstr0ae825e72016-02-25 20:31:31987LayerAnimator::RunningAnimation::RunningAnimation(
988 const RunningAnimation& other) = default;
989
[email protected]a48f30d2012-10-30 00:35:41990LayerAnimator::RunningAnimation::~RunningAnimation() { }
991
[email protected]710a98d2011-06-23 20:13:29992} // namespace ui