| Index: cc/animation/layer_animation_controller.cc
|
| diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc
|
| index 08ac1d5d797ef7ea2e6d9e36b3a47789dd50a119..a026ccefa1376e0498b4637506daa451473d0a40 100644
|
| --- a/cc/animation/layer_animation_controller.cc
|
| +++ b/cc/animation/layer_animation_controller.cc
|
| @@ -11,6 +11,7 @@
|
| #include "cc/animation/keyframed_animation_curve.h"
|
| #include "cc/animation/layer_animation_value_observer.h"
|
| #include "cc/base/scoped_ptr_algorithm.h"
|
| +#include "third_party/WebKit/Source/Platform/chromium/public/WebAnimationDelegate.h"
|
| #include "ui/gfx/transform.h"
|
|
|
| namespace cc {
|
| @@ -20,7 +21,8 @@ LayerAnimationController::LayerAnimationController(int id)
|
| registrar_(0),
|
| id_(id),
|
| is_active_(false),
|
| - last_tick_time_(0) {}
|
| + last_tick_time_(0),
|
| + layer_animation_delegate_(NULL) {}
|
|
|
| LayerAnimationController::~LayerAnimationController() {
|
| if (registrar_)
|
| @@ -109,6 +111,7 @@ void LayerAnimationController::ResumeAnimations(double monotonic_time) {
|
| // thread are kept in sync.
|
| void LayerAnimationController::PushAnimationUpdatesTo(
|
| LayerAnimationController* controller_impl) {
|
| + DCHECK(this != controller_impl);
|
| if (force_sync_) {
|
| ReplaceImplThreadAnimations(controller_impl);
|
| force_sync_ = false;
|
| @@ -127,8 +130,19 @@ void LayerAnimationController::PushAnimationUpdatesTo(
|
| UpdateActivation(NormalActivation);
|
| }
|
|
|
| +void LayerAnimationController::TransferAnimationsTo(
|
| + LayerAnimationController* other_controller) {
|
| + other_controller->active_animations_.clear();
|
| + active_animations_.swap(other_controller->active_animations_);
|
| + UpdateActivation(NormalActivation);
|
| + set_force_sync();
|
| + other_controller->UpdateActivation(NormalActivation);
|
| + other_controller->set_force_sync();
|
| + other_controller->SetAnimationRegistrar(registrar_);
|
| +}
|
| +
|
| void LayerAnimationController::Animate(double monotonic_time) {
|
| - if (!HasActiveObserver())
|
| + if (!HasActiveValueObserver())
|
| return;
|
|
|
| StartAnimationsWaitingForNextTick(monotonic_time);
|
| @@ -176,7 +190,7 @@ void LayerAnimationController::AccumulatePropertyUpdates(
|
|
|
| void LayerAnimationController::UpdateState(bool start_ready_animations,
|
| AnimationEventsVector* events) {
|
| - if (!HasActiveObserver())
|
| + if (!HasActiveValueObserver())
|
| return;
|
|
|
| if (start_ready_animations)
|
| @@ -231,27 +245,13 @@ bool LayerAnimationController::HasActiveAnimation() const {
|
| bool LayerAnimationController::IsAnimatingProperty(
|
| Animation::TargetProperty target_property) const {
|
| for (size_t i = 0; i < active_animations_.size(); ++i) {
|
| - if (active_animations_[i]->run_state() != Animation::Finished &&
|
| - active_animations_[i]->run_state() != Animation::Aborted &&
|
| + if (!active_animations_[i]->is_finished() &&
|
| active_animations_[i]->target_property() == target_property)
|
| return true;
|
| }
|
| return false;
|
| }
|
|
|
| -void LayerAnimationController::OnAnimationStarted(
|
| - const AnimationEvent& event) {
|
| - for (size_t i = 0; i < active_animations_.size(); ++i) {
|
| - if (active_animations_[i]->group() == event.group_id &&
|
| - active_animations_[i]->target_property() == event.target_property &&
|
| - active_animations_[i]->needs_synchronized_start_time()) {
|
| - active_animations_[i]->set_needs_synchronized_start_time(false);
|
| - active_animations_[i]->set_start_time(event.monotonic_time);
|
| - return;
|
| - }
|
| - }
|
| -}
|
| -
|
| void LayerAnimationController::SetAnimationRegistrar(
|
| AnimationRegistrar* registrar) {
|
| if (registrar_ == registrar)
|
| @@ -267,15 +267,75 @@ void LayerAnimationController::SetAnimationRegistrar(
|
| UpdateActivation(ForceActivation);
|
| }
|
|
|
| -void LayerAnimationController::AddObserver(
|
| +void LayerAnimationController::NotifyAnimationStarted(
|
| + const AnimationEvent& event,
|
| + double wall_clock_time) {
|
| + for (size_t i = 0; i < active_animations_.size(); ++i) {
|
| + if (active_animations_[i]->group() == event.group_id &&
|
| + active_animations_[i]->target_property() == event.target_property &&
|
| + active_animations_[i]->needs_synchronized_start_time()) {
|
| + active_animations_[i]->set_needs_synchronized_start_time(false);
|
| + active_animations_[i]->set_start_time(event.monotonic_time);
|
| +
|
| + FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
|
| + OnAnimationStarted(event));
|
| + if (layer_animation_delegate_)
|
| + layer_animation_delegate_->notifyAnimationStarted(wall_clock_time);
|
| +
|
| + return;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void LayerAnimationController::NotifyAnimationFinished(
|
| + const AnimationEvent& event,
|
| + double wall_clock_time) {
|
| + for (size_t i = 0; i < active_animations_.size(); ++i) {
|
| + if (active_animations_[i]->group() == event.group_id &&
|
| + active_animations_[i]->target_property() == event.target_property) {
|
| + active_animations_[i]->set_received_finished_event(true);
|
| + if (layer_animation_delegate_)
|
| + layer_animation_delegate_->notifyAnimationFinished(wall_clock_time);
|
| +
|
| + return;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void LayerAnimationController::NotifyAnimationPropertyUpdate(
|
| + const AnimationEvent& event) {
|
| + switch (event.target_property) {
|
| + case Animation::Opacity:
|
| + NotifyObserversOpacityAnimated(event.opacity);
|
| + break;
|
| + case Animation::Transform:
|
| + NotifyObserversTransformAnimated(event.transform);
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| +}
|
| +
|
| +void LayerAnimationController::AddValueObserver(
|
| LayerAnimationValueObserver* observer) {
|
| - if (!observers_.HasObserver(observer))
|
| - observers_.AddObserver(observer);
|
| + if (!value_observers_.HasObserver(observer))
|
| + value_observers_.AddObserver(observer);
|
| }
|
|
|
| -void LayerAnimationController::RemoveObserver(
|
| +void LayerAnimationController::RemoveValueObserver(
|
| LayerAnimationValueObserver* observer) {
|
| - observers_.RemoveObserver(observer);
|
| + value_observers_.RemoveObserver(observer);
|
| +}
|
| +
|
| +void LayerAnimationController::AddEventObserver(
|
| + LayerAnimationEventObserver* observer) {
|
| + if (!event_observers_.HasObserver(observer))
|
| + event_observers_.AddObserver(observer);
|
| +}
|
| +
|
| +void LayerAnimationController::RemoveEventObserver(
|
| + LayerAnimationEventObserver* observer) {
|
| + event_observers_.RemoveObserver(observer);
|
| }
|
|
|
| void LayerAnimationController::PushNewAnimationsToImplThread(
|
| @@ -313,10 +373,13 @@ struct IsCompleted {
|
| explicit IsCompleted(const LayerAnimationController& main_thread_controller)
|
| : main_thread_controller_(main_thread_controller) {}
|
| bool operator()(Animation* animation) const {
|
| - if (animation->is_impl_only())
|
| - return false;
|
| - return !main_thread_controller_.GetAnimation(animation->group(),
|
| - animation->target_property());
|
| + if (animation->is_impl_only()) {
|
| + return (animation->run_state() == Animation::WaitingForDeletion);
|
| + } else {
|
| + return !main_thread_controller_.GetAnimation(
|
| + animation->group(),
|
| + animation->target_property());
|
| + }
|
| }
|
|
|
| private:
|
| @@ -373,8 +436,7 @@ void LayerAnimationController::StartAnimationsWaitingForTargetAvailability(
|
| TargetProperties blocked_properties;
|
| for (size_t i = 0; i < active_animations_.size(); ++i) {
|
| if (active_animations_[i]->run_state() == Animation::Starting ||
|
| - active_animations_[i]->run_state() == Animation::Running ||
|
| - active_animations_[i]->run_state() == Animation::Finished)
|
| + active_animations_[i]->run_state() == Animation::Running)
|
| blocked_properties.insert(active_animations_[i]->target_property());
|
| }
|
|
|
| @@ -441,7 +503,8 @@ void LayerAnimationController::PromoteStartedAnimations(
|
|
|
| void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) {
|
| for (size_t i = 0; i < active_animations_.size(); ++i) {
|
| - if (active_animations_[i]->IsFinishedAt(monotonic_time))
|
| + if (active_animations_[i]->IsFinishedAt(monotonic_time) &&
|
| + active_animations_[i]->run_state() != Animation::WaitingForDeletion)
|
| active_animations_[i]->SetRunState(Animation::Finished, monotonic_time);
|
| }
|
| }
|
| @@ -476,17 +539,32 @@ void LayerAnimationController::ResolveConflicts(double monotonic_time) {
|
|
|
| void LayerAnimationController::MarkAnimationsForDeletion(
|
| double monotonic_time, AnimationEventsVector* events) {
|
| + // 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 < active_animations_.size(); i++) {
|
| int group_id = active_animations_[i]->group();
|
| 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 =
|
| + events || active_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 (active_animations_[i]->is_finished() &&
|
| - active_animations_[i]->run_state() != Animation::WaitingForDeletion) {
|
| + // find out if all other animations in the same group are also finished.
|
| + if (active_animations_[i]->run_state() == Animation::Aborted ||
|
| + (active_animations_[i]->run_state() == Animation::Finished &&
|
| + animation_i_will_send_or_has_received_finish_event)) {
|
| all_anims_with_same_id_are_finished = true;
|
| for (size_t j = 0; j < active_animations_.size(); ++j) {
|
| + bool animation_j_will_send_or_has_received_finish_event =
|
| + events || active_animations_[j]->received_finished_event();
|
| if (group_id == active_animations_[j]->group() &&
|
| - !active_animations_[j]->is_finished()) {
|
| + (!active_animations_[j]->is_finished() ||
|
| + (active_animations_[j]->run_state() == Animation::Finished &&
|
| + !animation_j_will_send_or_has_received_finish_event))) {
|
| all_anims_with_same_id_are_finished = false;
|
| break;
|
| }
|
| @@ -607,20 +685,21 @@ void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
|
|
|
| void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) {
|
| FOR_EACH_OBSERVER(LayerAnimationValueObserver,
|
| - observers_,
|
| + value_observers_,
|
| OnOpacityAnimated(opacity));
|
| }
|
|
|
| void LayerAnimationController::NotifyObserversTransformAnimated(
|
| const gfx::Transform& transform) {
|
| FOR_EACH_OBSERVER(LayerAnimationValueObserver,
|
| - observers_,
|
| + value_observers_,
|
| OnTransformAnimated(transform));
|
| }
|
|
|
| -bool LayerAnimationController::HasActiveObserver() {
|
| - if (observers_.might_have_observers()) {
|
| - ObserverListBase<LayerAnimationValueObserver>::Iterator it(observers_);
|
| +bool LayerAnimationController::HasActiveValueObserver() {
|
| + if (value_observers_.might_have_observers()) {
|
| + ObserverListBase<LayerAnimationValueObserver>::Iterator it(
|
| + value_observers_);
|
| LayerAnimationValueObserver* obs;
|
| while ((obs = it.GetNext()) != NULL)
|
| if (obs->IsActive())
|
|
|