diff options
author | ajuma@chromium.org <ajuma@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-11 18:59:17 +0000 |
---|---|---|
committer | ajuma@chromium.org <ajuma@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-11 18:59:17 +0000 |
commit | 79eb14f69953b8a9a021c87ee3788c4904caf6d4 (patch) | |
tree | 37814e07db721c39dd80a365a852d40bb7b67b5f /cc/animation | |
parent | 1d93c487c97f5ca53b8004dd7842f1ee39ba8783 (diff) | |
download | chromium_src-79eb14f69953b8a9a021c87ee3788c4904caf6d4.zip chromium_src-79eb14f69953b8a9a021c87ee3788c4904caf6d4.tar.gz chromium_src-79eb14f69953b8a9a021c87ee3788c4904caf6d4.tar.bz2 |
Fix main-thread event handling for impl-only animations
Since impl-only animations have no main-thread counterpart, the
main thread (more specifically, LayerTreeHost::SetAnimationEvents,
LayerAnimationController::NotifyAnimationStarted, and
LayerAnimationController::NotifyAnimationFinished) should not
assume that incoming events will be for animations that are
running on the main thread.
BUG=196284
Review URL: https://chromiumcodereview.appspot.com/14137009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@193700 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/animation')
-rw-r--r-- | cc/animation/animation_events.cc | 23 | ||||
-rw-r--r-- | cc/animation/animation_events.h | 12 | ||||
-rw-r--r-- | cc/animation/layer_animation_controller.cc | 30 | ||||
-rw-r--r-- | cc/animation/layer_animation_controller_unittest.cc | 84 |
4 files changed, 136 insertions, 13 deletions
diff --git a/cc/animation/animation_events.cc b/cc/animation/animation_events.cc new file mode 100644 index 0000000..95b0e07 --- /dev/null +++ b/cc/animation/animation_events.cc @@ -0,0 +1,23 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/animation/animation_events.h" + +namespace cc { + +AnimationEvent::AnimationEvent(AnimationEvent::Type type, + int layer_id, + int group_id, + Animation::TargetProperty target_property, + double monotonic_time) + : type(type), + layer_id(layer_id), + group_id(group_id), + target_property(target_property), + monotonic_time(monotonic_time), + is_impl_only(false), + opacity(0.f) { +} + +} // namespace cc diff --git a/cc/animation/animation_events.h b/cc/animation/animation_events.h index b279b4b..1fd742c 100644 --- a/cc/animation/animation_events.h +++ b/cc/animation/animation_events.h @@ -8,30 +8,26 @@ #include <vector> #include "cc/animation/animation.h" +#include "cc/base/cc_export.h" #include "ui/gfx/transform.h" namespace cc { -struct AnimationEvent { +struct CC_EXPORT AnimationEvent { enum Type { Started, Finished, PropertyUpdate }; AnimationEvent(Type type, int layer_id, int group_id, Animation::TargetProperty target_property, - double monotonic_time) - : type(type), - layer_id(layer_id), - group_id(group_id), - target_property(target_property), - monotonic_time(monotonic_time), - opacity(0.f) {} + double monotonic_time); Type type; int layer_id; int group_id; Animation::TargetProperty target_property; double monotonic_time; + bool is_impl_only; float opacity; gfx::Transform transform; }; diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc index a026cce..5e20dd5 100644 --- a/cc/animation/layer_animation_controller.cc +++ b/cc/animation/layer_animation_controller.cc @@ -172,7 +172,7 @@ void LayerAnimationController::AccumulatePropertyUpdates( monotonic_time); event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue( monotonic_time); - + event.is_impl_only = true; events->push_back(event); } else if (animation->target_property() == Animation::Transform) { AnimationEvent event(AnimationEvent::PropertyUpdate, @@ -183,6 +183,7 @@ void LayerAnimationController::AccumulatePropertyUpdates( event.transform = animation->curve()->ToTransformAnimationCurve()->GetValue( monotonic_time); + event.is_impl_only = true; events->push_back(event); } } @@ -270,6 +271,15 @@ void LayerAnimationController::SetAnimationRegistrar( void LayerAnimationController::NotifyAnimationStarted( const AnimationEvent& event, double wall_clock_time) { + if (event.is_impl_only) { + FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_, + OnAnimationStarted(event)); + if (layer_animation_delegate_) + layer_animation_delegate_->notifyAnimationStarted(wall_clock_time); + + return; + } + 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 && @@ -290,6 +300,12 @@ void LayerAnimationController::NotifyAnimationStarted( void LayerAnimationController::NotifyAnimationFinished( const AnimationEvent& event, double wall_clock_time) { + if (event.is_impl_only) { + if (layer_animation_delegate_) + layer_animation_delegate_->notifyAnimationFinished(wall_clock_time); + return; + } + 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) { @@ -490,12 +506,14 @@ void LayerAnimationController::PromoteStartedAnimations( if (!active_animations_[i]->has_set_start_time()) active_animations_[i]->set_start_time(monotonic_time); if (events) { - events->push_back(AnimationEvent( + AnimationEvent started_event( AnimationEvent::Started, id_, active_animations_[i]->group(), active_animations_[i]->target_property(), - monotonic_time)); + monotonic_time); + started_event.is_impl_only = active_animations_[i]->is_impl_only(); + events->push_back(started_event); } } } @@ -577,12 +595,14 @@ void LayerAnimationController::MarkAnimationsForDeletion( for (size_t j = i; j < active_animations_.size(); j++) { if (group_id == active_animations_[j]->group()) { if (events) { - events->push_back(AnimationEvent( + AnimationEvent finished_event( AnimationEvent::Finished, id_, active_animations_[j]->group(), active_animations_[j]->target_property(), - monotonic_time)); + monotonic_time); + finished_event.is_impl_only = active_animations_[j]->is_impl_only(); + events->push_back(finished_event); } active_animations_[j]->SetRunState(Animation::WaitingForDeletion, monotonic_time); diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc index 5ef57ad..a5c815b 100644 --- a/cc/animation/layer_animation_controller_unittest.cc +++ b/cc/animation/layer_animation_controller_unittest.cc @@ -11,6 +11,7 @@ #include "cc/test/animation_test_common.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebAnimationDelegate.h" #include "ui/gfx/transform.h" namespace cc { @@ -382,6 +383,7 @@ TEST(LayerAnimationControllerTest, TrivialTransformOnImpl) { GetMostRecentPropertyUpdateEvent(events.get()); ASSERT_TRUE(start_transform_event); EXPECT_EQ(gfx::Transform(), start_transform_event->transform); + EXPECT_TRUE(start_transform_event->is_impl_only); gfx::Transform expected_transform; expected_transform.Translate(delta_x, delta_y); @@ -394,6 +396,88 @@ TEST(LayerAnimationControllerTest, TrivialTransformOnImpl) { const AnimationEvent* end_transform_event = GetMostRecentPropertyUpdateEvent(events.get()); EXPECT_EQ(expected_transform, end_transform_event->transform); + EXPECT_TRUE(end_transform_event->is_impl_only); +} + +class FakeWebAnimationDelegate : public WebKit::WebAnimationDelegate { + public: + FakeWebAnimationDelegate() + : started_(false), + finished_(false) {} + + virtual void notifyAnimationStarted(double time) OVERRIDE { + started_ = true; + } + + virtual void notifyAnimationFinished(double time) OVERRIDE { + finished_ = true; + } + + bool started() { return started_; } + + bool finished() { return finished_; } + + private: + bool started_; + bool finished_; +}; + +// Tests that impl-only animations lead to start and finished notifications +// being sent to the main thread controller's animation delegate. +TEST(LayerAnimationControllerTest, + NotificationsForImplOnlyAnimationsAreSentToMainThreadDelegate) { + FakeLayerAnimationValueObserver dummy_impl; + scoped_refptr<LayerAnimationController> controller_impl( + LayerAnimationController::Create(0)); + controller_impl->AddValueObserver(&dummy_impl); + scoped_ptr<AnimationEventsVector> events( + make_scoped_ptr(new AnimationEventsVector)); + FakeLayerAnimationValueObserver dummy; + scoped_refptr<LayerAnimationController> controller( + LayerAnimationController::Create(0)); + controller->AddValueObserver(&dummy); + FakeWebAnimationDelegate delegate; + controller->set_layer_animation_delegate(&delegate); + + scoped_ptr<Animation> to_add(CreateAnimation( + scoped_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)).Pass(), + 1, + Animation::Opacity)); + to_add->set_is_impl_only(true); + controller_impl->AddAnimation(to_add.Pass()); + + controller_impl->Animate(0.0); + controller_impl->UpdateState(true, events.get()); + + // We should receive 2 events (a started notification and a property update). + EXPECT_EQ(2u, events->size()); + EXPECT_EQ(AnimationEvent::Started, (*events)[0].type); + EXPECT_TRUE((*events)[0].is_impl_only); + EXPECT_EQ(AnimationEvent::PropertyUpdate, (*events)[1].type); + EXPECT_TRUE((*events)[1].is_impl_only); + + // Passing on the start event to the main thread controller should cause the + // delegate to get notified. + EXPECT_FALSE(delegate.started()); + controller->NotifyAnimationStarted((*events)[0], 0.0); + EXPECT_TRUE(delegate.started()); + + events.reset(new AnimationEventsVector); + controller_impl->Animate(1.0); + controller_impl->UpdateState(true, events.get()); + + // We should receive 2 events (a finished notification and a property update). + EXPECT_EQ(2u, events->size()); + EXPECT_EQ(AnimationEvent::Finished, (*events)[0].type); + EXPECT_TRUE((*events)[0].is_impl_only); + EXPECT_EQ(AnimationEvent::PropertyUpdate, (*events)[1].type); + EXPECT_TRUE((*events)[1].is_impl_only); + + // Passing on the finished event to the main thread controller should cause + // the delegate to get notified. + EXPECT_FALSE(delegate.finished()); + controller->NotifyAnimationFinished((*events)[0], 0.0); + EXPECT_TRUE(delegate.finished()); } // Tests animations that are waiting for a synchronized start time do not |