Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Unified Diff: cc/animation/element_animations.cc

Issue 2335043002: CC Animation: Move animations_ from ElementAnimations to AnimationPlayer. (Closed)
Patch Set: Clean it up harder. Rework UpdateClientAnimationState. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: cc/animation/element_animations.cc
diff --git a/cc/animation/element_animations.cc b/cc/animation/element_animations.cc
index b1bd59e03a808fee891acdf2864d5f87255a83bb..35de36725d0732d55d31f11a50e2434867524243 100644
--- a/cc/animation/element_animations.cc
+++ b/cc/animation/element_animations.cc
@@ -14,7 +14,6 @@
#include "cc/animation/animation_host.h"
#include "cc/animation/animation_player.h"
#include "cc/animation/keyframed_animation_curve.h"
-#include "cc/animation/scroll_offset_animation_curve.h"
#include "cc/output/filter_operations.h"
#include "cc/trees/mutator_host_client.h"
#include "ui/gfx/geometry/box_f.h"
@@ -32,9 +31,10 @@ ElementAnimations::ElementAnimations()
is_active_(false),
has_element_in_active_list_(false),
has_element_in_pending_list_(false),
- needs_to_start_animations_(false),
scroll_offset_animation_was_interrupted_(false),
- needs_push_properties_(false) {}
+ needs_push_properties_(false) {
+ ClearNeedsUpdateImplClientState();
+}
ElementAnimations::~ElementAnimations() {}
@@ -50,7 +50,7 @@ void ElementAnimations::InitAffectedElementTypes() {
DCHECK(element_id_);
DCHECK(animation_host_);
- UpdateActivation(FORCE_ACTIVATION);
+ UpdateActivation(ActivationType::FORCE);
DCHECK(animation_host_->mutator_host_client());
if (animation_host_->mutator_host_client()->IsElementInList(
@@ -83,7 +83,7 @@ void ElementAnimations::ClearAffectedElementTypes() {
set_has_element_in_pending_list(false);
animation_host_->DidDeactivateElementAnimations(this);
- UpdateActivation(FORCE_ACTIVATION);
+ UpdateActivation(ActivationType::FORCE);
}
void ElementAnimations::ElementRegistered(ElementId element_id,
@@ -91,7 +91,7 @@ void ElementAnimations::ElementRegistered(ElementId element_id,
DCHECK_EQ(element_id_, element_id);
if (!has_element_in_any_list())
- UpdateActivation(FORCE_ACTIVATION);
+ UpdateActivation(ActivationType::FORCE);
if (list_type == ElementListType::ACTIVE)
set_has_element_in_active_list(true);
@@ -135,39 +135,56 @@ void ElementAnimations::PushPropertiesTo(
return;
needs_push_properties_ = false;
- if (!HasAnyAnimation() && !element_animations_impl->HasAnyAnimation())
- return;
- MarkAbortedAnimationsForDeletion(element_animations_impl.get());
- PurgeAnimationsMarkedForDeletion();
- PushNewAnimationsToImplThread(element_animations_impl.get());
-
- // Remove finished impl side animations only after pushing,
- // and only after the animations are deleted on the main thread
- // this insures we will never push an animation twice.
- RemoveAnimationsCompletedOnMainThread(element_animations_impl.get());
-
- PushPropertiesToImplThread(element_animations_impl.get());
- element_animations_impl->UpdateActivation(NORMAL_ACTIVATION);
- UpdateActivation(NORMAL_ACTIVATION);
+ element_animations_impl->scroll_offset_animation_was_interrupted_ =
+ scroll_offset_animation_was_interrupted_;
+ scroll_offset_animation_was_interrupted_ = false;
+
+ // Update impl client state.
+ element_animations_impl->UpdateClientAnimationState(
+ needs_update_impl_client_state_transform_,
+ needs_update_impl_client_state_opacity_,
+ needs_update_impl_client_state_filter_);
+ ClearNeedsUpdateImplClientState();
+
+ element_animations_impl->UpdateActivation(ActivationType::NORMAL);
+ UpdateActivation(ActivationType::NORMAL);
}
-void ElementAnimations::AddAnimation(std::unique_ptr<Animation> animation) {
- DCHECK(!animation->is_impl_only() ||
- animation->target_property() == TargetProperty::SCROLL_OFFSET);
- TargetProperty::Type target_property = animation->target_property();
- animations_.push_back(std::move(animation));
- needs_to_start_animations_ = true;
- UpdateActivation(NORMAL_ACTIVATION);
+void ElementAnimations::UpdateClientAnimationState(
+ TargetProperty::Type target_property) {
switch (target_property) {
case TargetProperty::TRANSFORM:
case TargetProperty::OPACITY:
case TargetProperty::FILTER:
- UpdateClientAnimationState(target_property);
+ UpdateClientAnimationStateInternal(target_property);
break;
default:
+ // Do not update for other properties.
break;
}
- SetNeedsPushProperties();
+}
+
+void ElementAnimations::UpdateClientAnimationState(bool transform,
+ bool opacity,
+ bool filter) {
+ if (transform)
+ UpdateClientAnimationStateInternal(TargetProperty::TRANSFORM);
+ if (opacity)
+ UpdateClientAnimationStateInternal(TargetProperty::OPACITY);
+ if (filter)
+ UpdateClientAnimationStateInternal(TargetProperty::FILTER);
+}
+
+void ElementAnimations::AddAnimation(std::unique_ptr<Animation> animation) {
+ // TODO(loyso): Erase this. Rewrite element_animations_unittest to use
+ // AnimationPlayer::AddAnimation.
+
+ // Add animation to the first player.
+ DCHECK(players_list_->might_have_observers());
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player = it.GetNext();
+ DCHECK(player);
+ player->AddAnimation(std::move(animation));
}
void ElementAnimations::Animate(base::TimeTicks monotonic_time) {
@@ -175,13 +192,27 @@ void ElementAnimations::Animate(base::TimeTicks monotonic_time) {
if (!has_element_in_active_list() && !has_element_in_pending_list())
return;
- if (needs_to_start_animations_)
- StartAnimations(monotonic_time);
- TickAnimations(monotonic_time);
+ {
+ // TODO(crbug.com/634916): Shouldn't manually iterate through the list if
+ // base::ObserverList has a callback mechanism.
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->needs_to_start_animations())
+ player->StartAnimations(monotonic_time);
+ }
+ }
+ {
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr)
+ player->TickAnimations(monotonic_time);
+ }
last_tick_time_ = monotonic_time;
- UpdateClientAnimationState(TargetProperty::OPACITY);
- UpdateClientAnimationState(TargetProperty::TRANSFORM);
- UpdateClientAnimationState(TargetProperty::FILTER);
+
+ UpdateClientAnimationStateInternal(TargetProperty::OPACITY);
+ UpdateClientAnimationStateInternal(TargetProperty::TRANSFORM);
+ UpdateClientAnimationStateInternal(TargetProperty::FILTER);
}
void ElementAnimations::UpdateState(bool start_ready_animations,
@@ -194,130 +225,106 @@ void ElementAnimations::UpdateState(bool start_ready_animations,
if (last_tick_time_ == base::TimeTicks())
return;
- if (start_ready_animations)
- PromoteStartedAnimations(last_tick_time_, events);
-
- MarkFinishedAnimations(last_tick_time_);
- MarkAnimationsForDeletion(last_tick_time_, events);
-
- if (needs_to_start_animations_ && start_ready_animations) {
- StartAnimations(last_tick_time_);
- PromoteStartedAnimations(last_tick_time_, events);
+ if (start_ready_animations) {
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr)
+ player->PromoteStartedAnimations(last_tick_time_, events);
+ }
+
+ {
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr)
+ player->MarkFinishedAnimations(last_tick_time_);
+ }
+ {
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr)
+ player->MarkAnimationsForDeletion(last_tick_time_, events);
+ }
+
+ if (start_ready_animations) {
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->needs_to_start_animations()) {
+ player->StartAnimations(last_tick_time_);
+ player->PromoteStartedAnimations(last_tick_time_, events);
+ }
+ }
}
- UpdateActivation(NORMAL_ACTIVATION);
+ UpdateActivation(ActivationType::NORMAL);
}
void ElementAnimations::ActivateAnimations() {
bool changed_transform_animation = false;
bool changed_opacity_animation = false;
bool changed_filter_animation = false;
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->affects_active_elements() !=
- animations_[i]->affects_pending_elements()) {
- if (animations_[i]->target_property() == TargetProperty::TRANSFORM)
- changed_transform_animation = true;
- else if (animations_[i]->target_property() == TargetProperty::OPACITY)
- changed_opacity_animation = true;
- else if (animations_[i]->target_property() == TargetProperty::FILTER)
- changed_filter_animation = true;
- }
- animations_[i]->set_affects_active_elements(
- animations_[i]->affects_pending_elements());
+
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ player->ActivateAnimations(&changed_transform_animation,
+ &changed_opacity_animation,
+ &changed_filter_animation);
}
- auto affects_no_elements = [](const std::unique_ptr<Animation>& animation) {
- return !animation->affects_active_elements() &&
- !animation->affects_pending_elements();
- };
- animations_.erase(std::remove_if(animations_.begin(), animations_.end(),
- affects_no_elements),
- animations_.end());
+
scroll_offset_animation_was_interrupted_ = false;
- UpdateActivation(NORMAL_ACTIVATION);
- if (changed_transform_animation)
- UpdateClientAnimationState(TargetProperty::TRANSFORM);
- if (changed_opacity_animation)
- UpdateClientAnimationState(TargetProperty::OPACITY);
- if (changed_filter_animation)
- UpdateClientAnimationState(TargetProperty::FILTER);
+ UpdateActivation(ActivationType::NORMAL);
+ UpdateClientAnimationState(changed_transform_animation,
+ changed_opacity_animation,
+ changed_filter_animation);
}
void ElementAnimations::NotifyAnimationStarted(const AnimationEvent& event) {
- if (event.is_impl_only) {
- NotifyPlayersAnimationStarted(event.monotonic_time, event.target_property,
- event.group_id);
- return;
- }
-
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->group() == event.group_id &&
- animations_[i]->target_property() == event.target_property &&
- animations_[i]->needs_synchronized_start_time()) {
- animations_[i]->set_needs_synchronized_start_time(false);
- if (!animations_[i]->has_set_start_time())
- animations_[i]->set_start_time(event.monotonic_time);
-
- NotifyPlayersAnimationStarted(event.monotonic_time, event.target_property,
- event.group_id);
-
- return;
- }
+ DCHECK(!event.is_impl_only);
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->NotifyAnimationStarted(event))
+ break;
}
}
void ElementAnimations::NotifyAnimationFinished(const AnimationEvent& event) {
- if (event.is_impl_only) {
- NotifyPlayersAnimationFinished(event.monotonic_time, event.target_property,
- event.group_id);
- return;
- }
-
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->group() == event.group_id &&
- animations_[i]->target_property() == event.target_property) {
- animations_[i]->set_received_finished_event(true);
- NotifyPlayersAnimationFinished(event.monotonic_time,
- event.target_property, event.group_id);
-
- return;
- }
+ DCHECK(!event.is_impl_only);
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->NotifyAnimationFinished(event))
+ break;
}
}
void ElementAnimations::NotifyAnimationTakeover(const AnimationEvent& event) {
+ DCHECK(!event.is_impl_only);
DCHECK(event.target_property == TargetProperty::SCROLL_OFFSET);
- if (!IsEmpty()) {
- std::unique_ptr<AnimationCurve> animation_curve = event.curve->Clone();
- NotifyPlayersAnimationTakeover(event.monotonic_time, event.target_property,
- event.animation_start_time,
- std::move(animation_curve));
- }
+
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr)
+ player->NotifyAnimationTakeover(event);
}
void ElementAnimations::NotifyAnimationAborted(const AnimationEvent& event) {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->group() == event.group_id &&
- animations_[i]->target_property() == event.target_property) {
- animations_[i]->SetRunState(Animation::ABORTED, event.monotonic_time);
- animations_[i]->set_received_finished_event(true);
- NotifyPlayersAnimationAborted(event.monotonic_time, event.target_property,
- event.group_id);
- break;
- }
- }
- switch (event.target_property) {
- case TargetProperty::TRANSFORM:
- case TargetProperty::OPACITY:
- case TargetProperty::FILTER:
- UpdateClientAnimationState(event.target_property);
- break;
- default:
+ DCHECK(!event.is_impl_only);
+
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->NotifyAnimationAborted(event))
break;
}
+
+ UpdateClientAnimationState(event.target_property);
}
void ElementAnimations::NotifyAnimationPropertyUpdate(
const AnimationEvent& event) {
+ DCHECK(!event.is_impl_only);
bool notify_active_elements = true;
bool notify_pending_elements = true;
switch (event.target_property) {
@@ -335,24 +342,23 @@ void ElementAnimations::NotifyAnimationPropertyUpdate(
}
bool ElementAnimations::HasFilterAnimationThatInflatesBounds() const {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (!animations_[i]->is_finished() &&
- animations_[i]->target_property() == TargetProperty::FILTER &&
- animations_[i]
- ->curve()
- ->ToFilterAnimationCurve()
- ->HasFilterThatMovesPixels())
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->HasFilterAnimationThatInflatesBounds())
return true;
}
-
return false;
}
bool ElementAnimations::HasTransformAnimationThatInflatesBounds() const {
- return IsCurrentlyAnimatingProperty(TargetProperty::TRANSFORM,
- ElementListType::ACTIVE) ||
- IsCurrentlyAnimatingProperty(TargetProperty::TRANSFORM,
- ElementListType::PENDING);
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->HasTransformAnimationThatInflatesBounds())
+ return true;
+ }
+ return false;
}
bool ElementAnimations::FilterAnimationBoundsForBox(const gfx::BoxF& box,
@@ -364,662 +370,119 @@ bool ElementAnimations::FilterAnimationBoundsForBox(const gfx::BoxF& box,
bool ElementAnimations::TransformAnimationBoundsForBox(
const gfx::BoxF& box,
gfx::BoxF* bounds) const {
- DCHECK(HasTransformAnimationThatInflatesBounds())
- << "TransformAnimationBoundsForBox will give incorrect results if there "
- << "are no transform animations affecting bounds, non-animated transform "
- << "is not known";
-
- // Compute bounds based on animations for which is_finished() is false.
- // Do nothing if there are no such animations; in this case, it is assumed
- // that callers will take care of computing bounds based on the owning layer's
- // actual transform.
*bounds = gfx::BoxF();
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->is_finished() ||
- animations_[i]->target_property() != TargetProperty::TRANSFORM)
- continue;
-
- const TransformAnimationCurve* transform_animation_curve =
- animations_[i]->curve()->ToTransformAnimationCurve();
- gfx::BoxF animation_bounds;
- bool success =
- transform_animation_curve->AnimatedBoundsForBox(box, &animation_bounds);
+
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ gfx::BoxF player_bounds;
+ bool success = player->TransformAnimationBoundsForBox(box, &player_bounds);
if (!success)
return false;
- bounds->Union(animation_bounds);
+ bounds->Union(player_bounds);
}
-
return true;
}
bool ElementAnimations::HasAnimationThatAffectsScale() const {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->is_finished() ||
- animations_[i]->target_property() != TargetProperty::TRANSFORM)
- continue;
-
- const TransformAnimationCurve* transform_animation_curve =
- animations_[i]->curve()->ToTransformAnimationCurve();
- if (transform_animation_curve->AffectsScale())
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->HasAnimationThatAffectsScale())
return true;
}
-
return false;
}
bool ElementAnimations::HasOnlyTranslationTransforms(
ElementListType list_type) const {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->is_finished() ||
- animations_[i]->target_property() != TargetProperty::TRANSFORM)
- continue;
-
- if ((list_type == ElementListType::ACTIVE &&
- !animations_[i]->affects_active_elements()) ||
- (list_type == ElementListType::PENDING &&
- !animations_[i]->affects_pending_elements()))
- continue;
-
- const TransformAnimationCurve* transform_animation_curve =
- animations_[i]->curve()->ToTransformAnimationCurve();
- if (!transform_animation_curve->IsTranslation())
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (!player->HasOnlyTranslationTransforms(list_type))
return false;
}
-
return true;
}
bool ElementAnimations::AnimationsPreserveAxisAlignment() const {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->is_finished() ||
- animations_[i]->target_property() != TargetProperty::TRANSFORM)
- continue;
-
- const TransformAnimationCurve* transform_animation_curve =
- animations_[i]->curve()->ToTransformAnimationCurve();
- if (!transform_animation_curve->PreservesAxisAlignment())
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (!player->AnimationsPreserveAxisAlignment())
return false;
}
-
return true;
}
bool ElementAnimations::AnimationStartScale(ElementListType list_type,
float* start_scale) const {
*start_scale = 0.f;
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->is_finished() ||
- animations_[i]->target_property() != TargetProperty::TRANSFORM)
- continue;
-
- if ((list_type == ElementListType::ACTIVE &&
- !animations_[i]->affects_active_elements()) ||
- (list_type == ElementListType::PENDING &&
- !animations_[i]->affects_pending_elements()))
- continue;
-
- bool forward_direction = true;
- switch (animations_[i]->direction()) {
- case Animation::Direction::NORMAL:
- case Animation::Direction::ALTERNATE_NORMAL:
- forward_direction = animations_[i]->playback_rate() >= 0.0;
- break;
- case Animation::Direction::REVERSE:
- case Animation::Direction::ALTERNATE_REVERSE:
- forward_direction = animations_[i]->playback_rate() < 0.0;
- break;
- }
- const TransformAnimationCurve* transform_animation_curve =
- animations_[i]->curve()->ToTransformAnimationCurve();
- float animation_start_scale = 0.f;
- if (!transform_animation_curve->AnimationStartScale(forward_direction,
- &animation_start_scale))
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ float player_start_scale = 0.f;
+ bool success = player->AnimationStartScale(list_type, &player_start_scale);
+ if (!success)
return false;
- *start_scale = std::max(*start_scale, animation_start_scale);
+ // Union: a maximum.
+ *start_scale = std::max(*start_scale, player_start_scale);
}
+
return true;
}
bool ElementAnimations::MaximumTargetScale(ElementListType list_type,
float* max_scale) const {
*max_scale = 0.f;
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->is_finished() ||
- animations_[i]->target_property() != TargetProperty::TRANSFORM)
- continue;
-
- if ((list_type == ElementListType::ACTIVE &&
- !animations_[i]->affects_active_elements()) ||
- (list_type == ElementListType::PENDING &&
- !animations_[i]->affects_pending_elements()))
- continue;
-
- bool forward_direction = true;
- switch (animations_[i]->direction()) {
- case Animation::Direction::NORMAL:
- case Animation::Direction::ALTERNATE_NORMAL:
- forward_direction = animations_[i]->playback_rate() >= 0.0;
- break;
- case Animation::Direction::REVERSE:
- case Animation::Direction::ALTERNATE_REVERSE:
- forward_direction = animations_[i]->playback_rate() < 0.0;
- break;
- }
- const TransformAnimationCurve* transform_animation_curve =
- animations_[i]->curve()->ToTransformAnimationCurve();
- float animation_scale = 0.f;
- if (!transform_animation_curve->MaximumTargetScale(forward_direction,
- &animation_scale))
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ float player_max_scale = 0.f;
+ bool success = player->MaximumTargetScale(list_type, &player_max_scale);
+ if (!success)
return false;
- *max_scale = std::max(*max_scale, animation_scale);
+ // Union: a maximum.
+ *max_scale = std::max(*max_scale, player_max_scale);
}
return true;
}
-void ElementAnimations::PushNewAnimationsToImplThread(
- ElementAnimations* element_animations_impl) const {
- // Any new animations owned by the main thread's ElementAnimations are cloned
- // and added to the impl thread's ElementAnimations.
- for (size_t i = 0; i < animations_.size(); ++i) {
- // If the animation is already running on the impl thread, there is no
- // need to copy it over.
- if (element_animations_impl->GetAnimationById(animations_[i]->id()))
- continue;
-
- if (animations_[i]->target_property() == TargetProperty::SCROLL_OFFSET &&
- !animations_[i]
- ->curve()
- ->ToScrollOffsetAnimationCurve()
- ->HasSetInitialValue()) {
- gfx::ScrollOffset current_scroll_offset;
- if (element_animations_impl->has_element_in_active_list()) {
- current_scroll_offset =
- element_animations_impl->ScrollOffsetForAnimation();
- } else {
- // The owning layer isn't yet in the active tree, so the main thread
- // scroll offset will be up to date.
- current_scroll_offset = ScrollOffsetForAnimation();
- }
- animations_[i]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
- current_scroll_offset);
- }
-
- // The new animation should be set to run as soon as possible.
- Animation::RunState initial_run_state =
- Animation::WAITING_FOR_TARGET_AVAILABILITY;
- std::unique_ptr<Animation> to_add(
- animations_[i]->CloneAndInitialize(initial_run_state));
- DCHECK(!to_add->needs_synchronized_start_time());
- to_add->set_affects_active_elements(false);
- element_animations_impl->AddAnimation(std::move(to_add));
- }
-}
-
-static bool IsCompleted(
- Animation* animation,
- const ElementAnimations* main_thread_element_animations) {
- if (animation->is_impl_only()) {
- return (animation->run_state() == Animation::WAITING_FOR_DELETION);
- } else {
- return !main_thread_element_animations->GetAnimationById(animation->id());
- }
-}
-
-void ElementAnimations::RemoveAnimationsCompletedOnMainThread(
- ElementAnimations* element_animations_impl) const {
- bool removed_transform_animation = false;
- bool removed_opacity_animation = false;
- bool removed_filter_animation = false;
- // Animations removed on the main thread should no longer affect pending
- // elements, and should stop affecting active elements after the next call
- // to ActivateAnimations. If already WAITING_FOR_DELETION, they can be removed
- // immediately.
- auto& animations = element_animations_impl->animations_;
- for (const auto& animation : animations) {
- if (IsCompleted(animation.get(), this)) {
- animation->set_affects_pending_elements(false);
- if (animation->target_property() == TargetProperty::TRANSFORM)
- removed_transform_animation = true;
- else if (animation->target_property() == TargetProperty::OPACITY)
- removed_opacity_animation = true;
- else if (animation->target_property() == TargetProperty::FILTER)
- removed_filter_animation = true;
- }
- }
- auto affects_active_only_and_is_waiting_for_deletion =
- [](const std::unique_ptr<Animation>& animation) {
- return animation->run_state() == Animation::WAITING_FOR_DELETION &&
- !animation->affects_pending_elements();
- };
- animations.erase(
- std::remove_if(animations.begin(), animations.end(),
- affects_active_only_and_is_waiting_for_deletion),
- animations.end());
-
- if (removed_transform_animation) {
- element_animations_impl->UpdateClientAnimationState(
- TargetProperty::TRANSFORM);
- }
- if (removed_opacity_animation) {
- element_animations_impl->UpdateClientAnimationState(
- TargetProperty::OPACITY);
- }
- if (removed_filter_animation) {
- element_animations_impl->UpdateClientAnimationState(TargetProperty::FILTER);
- }
-}
-
-void ElementAnimations::PushPropertiesToImplThread(
- ElementAnimations* element_animations_impl) {
- for (size_t i = 0; i < animations_.size(); ++i) {
- Animation* current_impl =
- element_animations_impl->GetAnimationById(animations_[i]->id());
- if (current_impl)
- animations_[i]->PushPropertiesTo(current_impl);
- }
- element_animations_impl->scroll_offset_animation_was_interrupted_ =
- scroll_offset_animation_was_interrupted_;
- scroll_offset_animation_was_interrupted_ = false;
-}
-
-void ElementAnimations::StartAnimations(base::TimeTicks monotonic_time) {
- DCHECK(needs_to_start_animations_);
- needs_to_start_animations_ = false;
- // First collect running properties affecting each type of element.
- TargetProperties blocked_properties_for_active_elements;
- TargetProperties blocked_properties_for_pending_elements;
- std::vector<size_t> animations_waiting_for_target;
-
- animations_waiting_for_target.reserve(animations_.size());
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->run_state() == Animation::STARTING ||
- animations_[i]->run_state() == Animation::RUNNING) {
- if (animations_[i]->affects_active_elements()) {
- blocked_properties_for_active_elements[animations_[i]
- ->target_property()] = true;
- }
- if (animations_[i]->affects_pending_elements()) {
- blocked_properties_for_pending_elements[animations_[i]
- ->target_property()] = true;
- }
- } else if (animations_[i]->run_state() ==
- Animation::WAITING_FOR_TARGET_AVAILABILITY) {
- animations_waiting_for_target.push_back(i);
- }
- }
-
- for (size_t i = 0; i < animations_waiting_for_target.size(); ++i) {
- // Collect all properties for animations with the same group id (they
- // should all also be in the list of animations).
- size_t animation_index = animations_waiting_for_target[i];
- Animation* animation_waiting_for_target =
- animations_[animation_index].get();
- // Check for the run state again even though the animation was waiting
- // for target because it might have changed the run state while handling
- // previous animation in this loop (if they belong to same group).
- if (animation_waiting_for_target->run_state() ==
- Animation::WAITING_FOR_TARGET_AVAILABILITY) {
- TargetProperties enqueued_properties;
- bool affects_active_elements =
- animation_waiting_for_target->affects_active_elements();
- bool affects_pending_elements =
- animation_waiting_for_target->affects_pending_elements();
- enqueued_properties[animation_waiting_for_target->target_property()] =
- true;
- for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
- if (animation_waiting_for_target->group() == animations_[j]->group()) {
- enqueued_properties[animations_[j]->target_property()] = true;
- affects_active_elements |= animations_[j]->affects_active_elements();
- affects_pending_elements |=
- animations_[j]->affects_pending_elements();
- }
- }
-
- // Check to see if intersection of the list of properties affected by
- // the group and the list of currently blocked properties is null, taking
- // into account the type(s) of elements affected by the group. In any
- // case, the group's target properties need to be added to the lists of
- // blocked properties.
- bool null_intersection = true;
- static_assert(TargetProperty::FIRST_TARGET_PROPERTY == 0,
- "TargetProperty must be 0-based enum");
- for (int property = TargetProperty::FIRST_TARGET_PROPERTY;
- property <= TargetProperty::LAST_TARGET_PROPERTY; ++property) {
- if (enqueued_properties[property]) {
- if (affects_active_elements) {
- if (blocked_properties_for_active_elements[property])
- null_intersection = false;
- else
- blocked_properties_for_active_elements[property] = true;
- }
- if (affects_pending_elements) {
- if (blocked_properties_for_pending_elements[property])
- null_intersection = false;
- else
- blocked_properties_for_pending_elements[property] = true;
- }
- }
- }
-
- // If the intersection is null, then we are free to start the animations
- // in the group.
- if (null_intersection) {
- animation_waiting_for_target->SetRunState(Animation::STARTING,
- monotonic_time);
- for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
- if (animation_waiting_for_target->group() ==
- animations_[j]->group()) {
- animations_[j]->SetRunState(Animation::STARTING, monotonic_time);
- }
- }
- } else {
- needs_to_start_animations_ = true;
- }
- }
- }
-}
-
-void ElementAnimations::PromoteStartedAnimations(base::TimeTicks monotonic_time,
- AnimationEvents* events) {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->run_state() == Animation::STARTING &&
- animations_[i]->affects_active_elements()) {
- animations_[i]->SetRunState(Animation::RUNNING, monotonic_time);
- if (!animations_[i]->has_set_start_time() &&
- !animations_[i]->needs_synchronized_start_time())
- animations_[i]->set_start_time(monotonic_time);
- if (events) {
- base::TimeTicks start_time;
- if (animations_[i]->has_set_start_time())
- start_time = animations_[i]->start_time();
- else
- start_time = monotonic_time;
- AnimationEvent started_event(
- AnimationEvent::STARTED, element_id_, animations_[i]->group(),
- animations_[i]->target_property(), start_time);
- started_event.is_impl_only = animations_[i]->is_impl_only();
- if (started_event.is_impl_only)
- NotifyAnimationStarted(started_event);
- else
- events->events_.push_back(started_event);
- }
- }
- }
-}
+void ElementAnimations::SetNeedsUpdateImplClientState(bool transform,
+ bool opacity,
+ bool filter) {
+ if (transform)
+ needs_update_impl_client_state_transform_ = true;
+ if (opacity)
+ needs_update_impl_client_state_opacity_ = true;
+ if (filter)
+ needs_update_impl_client_state_filter_ = true;
-void ElementAnimations::MarkFinishedAnimations(base::TimeTicks monotonic_time) {
- bool finished_transform_animation = false;
- bool finished_opacity_animation = false;
- bool finished_filter_animation = false;
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (!animations_[i]->is_finished() &&
- animations_[i]->IsFinishedAt(monotonic_time)) {
- animations_[i]->SetRunState(Animation::FINISHED, monotonic_time);
- if (animations_[i]->target_property() == TargetProperty::TRANSFORM)
- finished_transform_animation = true;
- else if (animations_[i]->target_property() == TargetProperty::OPACITY)
- finished_opacity_animation = true;
- else if (animations_[i]->target_property() == TargetProperty::FILTER)
- finished_filter_animation = true;
- }
- }
- if (finished_transform_animation)
- UpdateClientAnimationState(TargetProperty::TRANSFORM);
- if (finished_opacity_animation)
- UpdateClientAnimationState(TargetProperty::OPACITY);
- if (finished_filter_animation)
- UpdateClientAnimationState(TargetProperty::FILTER);
+ if (needs_update_impl_client_state_transform_ ||
+ needs_update_impl_client_state_opacity_ ||
+ needs_update_impl_client_state_filter_)
+ SetNeedsPushProperties();
}
-void ElementAnimations::MarkAnimationsForDeletion(
- base::TimeTicks monotonic_time,
- AnimationEvents* events) {
- bool marked_animations_for_deletions = false;
- std::vector<size_t> animations_with_same_group_id;
-
- animations_with_same_group_id.reserve(animations_.size());
- // Non-aborted animations are marked for deletion after a corresponding
- // AnimationEvent::FINISHED event is sent or received. This means that if
- // we don't have an events vector, we must ensure that non-aborted animations
- // have received a finished event before marking them for deletion.
- for (size_t i = 0; i < animations_.size(); i++) {
- int group_id = animations_[i]->group();
- if (animations_[i]->run_state() == Animation::ABORTED) {
- if (events && !animations_[i]->is_impl_only()) {
- AnimationEvent aborted_event(
- AnimationEvent::ABORTED, element_id_, group_id,
- animations_[i]->target_property(), monotonic_time);
- events->events_.push_back(aborted_event);
- }
- // If on the compositor or on the main thread and received finish event,
- // animation can be marked for deletion.
- if (events || animations_[i]->received_finished_event()) {
- animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION,
- monotonic_time);
- marked_animations_for_deletions = true;
- }
- continue;
- }
-
- // If running on the compositor and need to complete an aborted animation
- // on the main thread.
- if (events &&
- animations_[i]->run_state() ==
- Animation::ABORTED_BUT_NEEDS_COMPLETION) {
- AnimationEvent aborted_event(AnimationEvent::TAKEOVER, element_id_,
- group_id, animations_[i]->target_property(),
- monotonic_time);
- aborted_event.animation_start_time =
- (animations_[i]->start_time() - base::TimeTicks()).InSecondsF();
- const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
- animations_[i]->curve()->ToScrollOffsetAnimationCurve();
- aborted_event.curve = scroll_offset_animation_curve->Clone();
- // Notify the compositor that the animation is finished.
- NotifyPlayersAnimationFinished(aborted_event.monotonic_time,
- aborted_event.target_property,
- aborted_event.group_id);
- // Notify main thread.
- events->events_.push_back(aborted_event);
-
- // Remove the animation from the compositor.
- animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION,
- monotonic_time);
- marked_animations_for_deletions = true;
- continue;
- }
-
- bool all_anims_with_same_id_are_finished = false;
-
- // Since deleting an animation on the main thread leads to its deletion
- // on the impl thread, we only mark a FINISHED main thread animation for
- // deletion once it has received a FINISHED event from the impl thread.
- bool animation_i_will_send_or_has_received_finish_event =
- animations_[i]->is_controlling_instance() ||
- animations_[i]->is_impl_only() ||
- animations_[i]->received_finished_event();
- // If an animation is finished, and not already marked for deletion,
- // find out if all other animations in the same group are also finished.
- if (animations_[i]->run_state() == Animation::FINISHED &&
- animation_i_will_send_or_has_received_finish_event) {
- // Clear the animations_with_same_group_id if it was added for
- // the previous animation's iteration.
- if (animations_with_same_group_id.size() > 0)
- animations_with_same_group_id.clear();
- all_anims_with_same_id_are_finished = true;
- for (size_t j = 0; j < animations_.size(); ++j) {
- bool animation_j_will_send_or_has_received_finish_event =
- animations_[j]->is_controlling_instance() ||
- animations_[j]->is_impl_only() ||
- animations_[j]->received_finished_event();
- if (group_id == animations_[j]->group()) {
- if (!animations_[j]->is_finished() ||
- (animations_[j]->run_state() == Animation::FINISHED &&
- !animation_j_will_send_or_has_received_finish_event)) {
- all_anims_with_same_id_are_finished = false;
- break;
- } else if (j >= i &&
- animations_[j]->run_state() != Animation::ABORTED) {
- // Mark down the animations which belong to the same group
- // and is not yet aborted. If this current iteration finds that all
- // animations with same ID are finished, then the marked
- // animations below will be set to WAITING_FOR_DELETION in next
- // iteration.
- animations_with_same_group_id.push_back(j);
- }
- }
- }
- }
- if (all_anims_with_same_id_are_finished) {
- // We now need to remove all animations with the same group id as
- // group_id (and send along animation finished notifications, if
- // necessary).
- for (size_t j = 0; j < animations_with_same_group_id.size(); j++) {
- size_t animation_index = animations_with_same_group_id[j];
- if (events) {
- AnimationEvent finished_event(
- AnimationEvent::FINISHED, element_id_,
- animations_[animation_index]->group(),
- animations_[animation_index]->target_property(), monotonic_time);
- finished_event.is_impl_only =
- animations_[animation_index]->is_impl_only();
- if (finished_event.is_impl_only)
- NotifyAnimationFinished(finished_event);
- else
- events->events_.push_back(finished_event);
- }
- animations_[animation_index]->SetRunState(
- Animation::WAITING_FOR_DELETION, monotonic_time);
- }
- marked_animations_for_deletions = true;
- }
- }
- if (marked_animations_for_deletions)
- NotifyPlayersAnimationWaitingForDeletion();
+void ElementAnimations::ClearNeedsUpdateImplClientState() {
+ needs_update_impl_client_state_transform_ = false;
+ needs_update_impl_client_state_opacity_ = false;
+ needs_update_impl_client_state_filter_ = false;
}
-void ElementAnimations::MarkAbortedAnimationsForDeletion(
- ElementAnimations* element_animations_impl) const {
- bool aborted_transform_animation = false;
- bool aborted_opacity_animation = false;
- bool aborted_filter_animation = false;
- auto& animations_impl = element_animations_impl->animations_;
- for (const auto& animation_impl : animations_impl) {
- // If the animation has been aborted on the main thread, mark it for
- // deletion.
- if (Animation* animation = GetAnimationById(animation_impl->id())) {
- if (animation->run_state() == Animation::ABORTED) {
- animation_impl->SetRunState(Animation::WAITING_FOR_DELETION,
- element_animations_impl->last_tick_time_);
- animation->SetRunState(Animation::WAITING_FOR_DELETION,
- last_tick_time_);
- if (animation_impl->target_property() == TargetProperty::TRANSFORM)
- aborted_transform_animation = true;
- else if (animation_impl->target_property() == TargetProperty::OPACITY)
- aborted_opacity_animation = true;
- else if (animation_impl->target_property() == TargetProperty::FILTER)
- aborted_filter_animation = true;
- }
- }
- }
-
- if (aborted_transform_animation) {
- element_animations_impl->UpdateClientAnimationState(
- TargetProperty::TRANSFORM);
- }
- if (aborted_opacity_animation) {
- element_animations_impl->UpdateClientAnimationState(
- TargetProperty::OPACITY);
- }
- if (aborted_filter_animation) {
- element_animations_impl->UpdateClientAnimationState(TargetProperty::FILTER);
- }
-}
-
-void ElementAnimations::PurgeAnimationsMarkedForDeletion() {
- animations_.erase(
- std::remove_if(animations_.begin(), animations_.end(),
- [](const std::unique_ptr<Animation>& animation) {
- return animation->run_state() ==
- Animation::WAITING_FOR_DELETION;
- }),
- animations_.end());
-}
-
-void ElementAnimations::TickAnimations(base::TimeTicks monotonic_time) {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->run_state() == Animation::STARTING ||
- animations_[i]->run_state() == Animation::RUNNING ||
- animations_[i]->run_state() == Animation::PAUSED) {
- if (!animations_[i]->InEffect(monotonic_time))
- continue;
-
- base::TimeDelta trimmed =
- animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
-
- switch (animations_[i]->target_property()) {
- case TargetProperty::TRANSFORM: {
- const TransformAnimationCurve* transform_animation_curve =
- animations_[i]->curve()->ToTransformAnimationCurve();
- const gfx::Transform transform =
- transform_animation_curve->GetValue(trimmed);
- NotifyClientTransformAnimated(
- transform, animations_[i]->affects_active_elements(),
- animations_[i]->affects_pending_elements());
- break;
- }
-
- case TargetProperty::OPACITY: {
- const FloatAnimationCurve* float_animation_curve =
- animations_[i]->curve()->ToFloatAnimationCurve();
- const float opacity = std::max(
- std::min(float_animation_curve->GetValue(trimmed), 1.0f), 0.f);
- NotifyClientOpacityAnimated(
- opacity, animations_[i]->affects_active_elements(),
- animations_[i]->affects_pending_elements());
- break;
- }
-
- case TargetProperty::FILTER: {
- const FilterAnimationCurve* filter_animation_curve =
- animations_[i]->curve()->ToFilterAnimationCurve();
- const FilterOperations filter =
- filter_animation_curve->GetValue(trimmed);
- NotifyClientFilterAnimated(
- filter, animations_[i]->affects_active_elements(),
- animations_[i]->affects_pending_elements());
- break;
- }
-
- case TargetProperty::BACKGROUND_COLOR: {
- // Not yet implemented.
- break;
- }
-
- case TargetProperty::SCROLL_OFFSET: {
- const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
- animations_[i]->curve()->ToScrollOffsetAnimationCurve();
- const gfx::ScrollOffset scroll_offset =
- scroll_offset_animation_curve->GetValue(trimmed);
- NotifyClientScrollOffsetAnimated(
- scroll_offset, animations_[i]->affects_active_elements(),
- animations_[i]->affects_pending_elements());
- break;
- }
- }
- }
- }
-}
-
-void ElementAnimations::UpdateActivation(UpdateActivationType type) {
- bool force = type == FORCE_ACTIVATION;
+void ElementAnimations::UpdateActivation(ActivationType type) {
+ bool force = type == ActivationType::FORCE;
if (animation_host_) {
bool was_active = is_active_;
is_active_ = false;
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->run_state() != Animation::WAITING_FOR_DELETION) {
+
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->HasNonDeletedAnimation()) {
is_active_ = true;
break;
}
@@ -1036,6 +499,10 @@ void ElementAnimations::UpdateActivation(UpdateActivationType type) {
}
}
+void ElementAnimations::UpdateActivationNormal() {
+ UpdateActivation(ActivationType::NORMAL);
+}
+
void ElementAnimations::NotifyClientOpacityAnimated(
float opacity,
bool notify_active_elements,
@@ -1126,7 +593,7 @@ void ElementAnimations::NotifyClientAnimationChanged(
}
}
-void ElementAnimations::UpdateClientAnimationState(
+void ElementAnimations::UpdateClientAnimationStateInternal(
TargetProperty::Type property) {
struct PropertyAnimationState* animation_state = nullptr;
switch (property) {
@@ -1158,18 +625,23 @@ void ElementAnimations::UpdateClientAnimationState(
DCHECK(was_potentially_animating_for_pending_elements ||
!was_currently_running_animation_for_pending_elements);
- for (const auto& animation : animations_) {
- if (!animation->is_finished() && animation->target_property() == property) {
- animation_state->potentially_animating_for_active_elements |=
- animation->affects_active_elements();
- animation_state->potentially_animating_for_pending_elements |=
- animation->affects_pending_elements();
- animation_state->currently_running_for_active_elements =
- animation_state->potentially_animating_for_active_elements &&
- animation->InEffect(last_tick_time_);
- animation_state->currently_running_for_pending_elements =
- animation_state->potentially_animating_for_pending_elements &&
- animation->InEffect(last_tick_time_);
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ for (const auto& animation : player->animations()) {
+ if (!animation->is_finished() &&
+ animation->target_property() == property) {
+ animation_state->potentially_animating_for_active_elements |=
+ animation->affects_active_elements();
+ animation_state->potentially_animating_for_pending_elements |=
+ animation->affects_pending_elements();
+ animation_state->currently_running_for_active_elements =
+ animation_state->potentially_animating_for_active_elements &&
+ animation->InEffect(last_tick_time_);
+ animation_state->currently_running_for_pending_elements =
+ animation_state->potentially_animating_for_pending_elements &&
+ animation->InEffect(last_tick_time_);
+ }
}
}
@@ -1203,169 +675,116 @@ void ElementAnimations::UpdateClientAnimationState(
}
bool ElementAnimations::HasActiveAnimation() const {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (!animations_[i]->is_finished())
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->HasActiveAnimation())
return true;
}
+
return false;
}
bool ElementAnimations::HasAnyAnimation() const {
- return !animations_.empty();
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->has_any_animation())
+ return true;
+ }
+
+ return false;
}
bool ElementAnimations::IsPotentiallyAnimatingProperty(
TargetProperty::Type target_property,
ElementListType list_type) const {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (!animations_[i]->is_finished() &&
- animations_[i]->target_property() == target_property) {
- if ((list_type == ElementListType::ACTIVE &&
- animations_[i]->affects_active_elements()) ||
- (list_type == ElementListType::PENDING &&
- animations_[i]->affects_pending_elements()))
- return true;
- }
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->IsPotentiallyAnimatingProperty(target_property, list_type))
+ return true;
}
+
return false;
}
bool ElementAnimations::IsCurrentlyAnimatingProperty(
TargetProperty::Type target_property,
ElementListType list_type) const {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (!animations_[i]->is_finished() &&
- animations_[i]->InEffect(last_tick_time_) &&
- animations_[i]->target_property() == target_property) {
- if ((list_type == ElementListType::ACTIVE &&
- animations_[i]->affects_active_elements()) ||
- (list_type == ElementListType::PENDING &&
- animations_[i]->affects_pending_elements()))
- return true;
- }
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->IsCurrentlyAnimatingProperty(target_property, list_type))
+ return true;
}
+
return false;
}
-void ElementAnimations::PauseAnimation(int animation_id,
- base::TimeDelta time_offset) {
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->id() == animation_id) {
- animations_[i]->SetRunState(Animation::PAUSED,
- time_offset + animations_[i]->start_time() +
- animations_[i]->time_offset());
- }
- }
- SetNeedsPushProperties();
+void ElementAnimations::SetScrollOffsetAnimationWasInterrupted() {
+ scroll_offset_animation_was_interrupted_ = true;
}
-void ElementAnimations::RemoveAnimation(int animation_id) {
- bool removed_transform_animation = false;
- bool removed_opacity_animation = false;
- bool removed_filter_animation = false;
- // Since we want to use the animations that we're going to remove, we need to
- // use a stable_parition here instead of remove_if. Remove_if leaves the
- // removed items in an unspecified state.
- auto animations_to_remove = std::stable_partition(
- animations_.begin(), animations_.end(),
- [animation_id](const std::unique_ptr<Animation>& animation) {
- return animation->id() != animation_id;
- });
- for (auto it = animations_to_remove; it != animations_.end(); ++it) {
- if ((*it)->target_property() == TargetProperty::SCROLL_OFFSET) {
- scroll_offset_animation_was_interrupted_ = true;
- } else if ((*it)->target_property() == TargetProperty::TRANSFORM &&
- !(*it)->is_finished()) {
- removed_transform_animation = true;
- } else if ((*it)->target_property() == TargetProperty::OPACITY &&
- !(*it)->is_finished()) {
- removed_opacity_animation = true;
- } else if ((*it)->target_property() == TargetProperty::FILTER &&
- !(*it)->is_finished()) {
- removed_filter_animation = true;
- }
+bool ElementAnimations::needs_to_start_animations_for_testing() const {
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (player->needs_to_start_animations())
+ return true;
}
- animations_.erase(animations_to_remove, animations_.end());
- UpdateActivation(NORMAL_ACTIVATION);
- if (removed_transform_animation)
- UpdateClientAnimationState(TargetProperty::TRANSFORM);
- if (removed_opacity_animation)
- UpdateClientAnimationState(TargetProperty::OPACITY);
- if (removed_filter_animation)
- UpdateClientAnimationState(TargetProperty::FILTER);
+ return false;
+}
- SetNeedsPushProperties();
+void ElementAnimations::PauseAnimation(int animation_id,
+ base::TimeDelta time_offset) {
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr)
+ player->PauseAnimation(animation_id, time_offset.InSecondsF());
}
-void ElementAnimations::AbortAnimation(int animation_id) {
- if (Animation* animation = GetAnimationById(animation_id)) {
- if (!animation->is_finished()) {
- animation->SetRunState(Animation::ABORTED, last_tick_time_);
- switch (animation->target_property()) {
- case TargetProperty::TRANSFORM:
- case TargetProperty::OPACITY:
- case TargetProperty::FILTER:
- UpdateClientAnimationState(animation->target_property());
- break;
- default:
- break;
- }
- }
- }
+void ElementAnimations::RemoveAnimation(int animation_id) {
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr)
+ player->RemoveAnimation(animation_id);
+}
- SetNeedsPushProperties();
+void ElementAnimations::AbortAnimation(int animation_id) {
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr)
+ player->AbortAnimation(animation_id);
}
void ElementAnimations::AbortAnimations(TargetProperty::Type target_property,
bool needs_completion) {
- if (needs_completion)
- DCHECK(target_property == TargetProperty::SCROLL_OFFSET);
-
- bool aborted_animation = false;
- for (size_t i = 0; i < animations_.size(); ++i) {
- if (animations_[i]->target_property() == target_property &&
- !animations_[i]->is_finished()) {
- // Currently only impl-only scroll offset animations can be completed on
- // the main thread.
- if (needs_completion && animations_[i]->is_impl_only()) {
- animations_[i]->SetRunState(Animation::ABORTED_BUT_NEEDS_COMPLETION,
- last_tick_time_);
- } else {
- animations_[i]->SetRunState(Animation::ABORTED, last_tick_time_);
- }
- aborted_animation = true;
- }
- }
- if (aborted_animation) {
- switch (target_property) {
- case TargetProperty::TRANSFORM:
- case TargetProperty::OPACITY:
- case TargetProperty::FILTER:
- UpdateClientAnimationState(target_property);
- break;
- default:
- break;
- }
- }
-
- SetNeedsPushProperties();
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr)
+ player->AbortAnimations(target_property, needs_completion);
}
Animation* ElementAnimations::GetAnimation(
TargetProperty::Type target_property) const {
- for (size_t i = 0; i < animations_.size(); ++i) {
- size_t index = animations_.size() - i - 1;
- if (animations_[index]->target_property() == target_property)
- return animations_[index].get();
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (Animation* animation = player->GetAnimation(target_property))
+ return animation;
}
return nullptr;
}
Animation* ElementAnimations::GetAnimationById(int animation_id) const {
- for (size_t i = 0; i < animations_.size(); ++i)
- if (animations_[i]->id() == animation_id)
- return animations_[i].get();
+ ElementAnimations::PlayersList::Iterator it(players_list_.get());
+ AnimationPlayer* player;
+ while ((player = it.GetNext()) != nullptr) {
+ if (Animation* animation = player->GetAnimationById(animation_id))
+ return animation;
+ }
return nullptr;
}
@@ -1440,61 +859,6 @@ void ElementAnimations::IsAnimatingChanged(ElementListType list_type,
}
}
-void ElementAnimations::NotifyPlayersAnimationStarted(
- base::TimeTicks monotonic_time,
- TargetProperty::Type target_property,
- int group) {
- ElementAnimations::PlayersList::Iterator it(players_list_.get());
- AnimationPlayer* player;
- // TODO(crbug.com/634916): Shouldn't manually iterate through the list if
- // base::ObserverList has a callback mechanism.
- while ((player = it.GetNext()) != nullptr)
- player->NotifyAnimationStarted(monotonic_time, target_property, group);
-}
-
-void ElementAnimations::NotifyPlayersAnimationFinished(
- base::TimeTicks monotonic_time,
- TargetProperty::Type target_property,
- int group) {
- ElementAnimations::PlayersList::Iterator it(players_list_.get());
- AnimationPlayer* player;
- while ((player = it.GetNext()) != nullptr)
- player->NotifyAnimationFinished(monotonic_time, target_property, group);
-}
-
-void ElementAnimations::NotifyPlayersAnimationAborted(
- base::TimeTicks monotonic_time,
- TargetProperty::Type target_property,
- int group) {
- ElementAnimations::PlayersList::Iterator it(players_list_.get());
- AnimationPlayer* player;
- while ((player = it.GetNext()) != nullptr)
- player->NotifyAnimationAborted(monotonic_time, target_property, group);
-}
-
-void ElementAnimations::NotifyPlayersAnimationWaitingForDeletion() {
- ElementAnimations::PlayersList::Iterator it(players_list_.get());
- AnimationPlayer* player;
- while ((player = it.GetNext()) != nullptr)
- player->NotifyAnimationWaitingForDeletion();
-}
-
-void ElementAnimations::NotifyPlayersAnimationTakeover(
- base::TimeTicks monotonic_time,
- TargetProperty::Type target_property,
- double animation_start_time,
- std::unique_ptr<AnimationCurve> curve) {
- DCHECK(curve);
- ElementAnimations::PlayersList::Iterator it(players_list_.get());
- AnimationPlayer* player;
- while ((player = it.GetNext()) != nullptr) {
- std::unique_ptr<AnimationCurve> animation_curve = curve->Clone();
- player->NotifyAnimationTakeover(monotonic_time, target_property,
- animation_start_time,
- std::move(animation_curve));
- }
-}
-
gfx::ScrollOffset ElementAnimations::ScrollOffsetForAnimation() const {
if (animation_host()) {
DCHECK(animation_host()->mutator_host_client());

Powered by Google App Engine
This is Rietveld 408576698