diff options
27 files changed, 303 insertions, 257 deletions
diff --git a/ash/app_list/app_list.cc b/ash/app_list/app_list.cc index c439bbb..ad9fd01 100644 --- a/ash/app_list/app_list.cc +++ b/ash/app_list/app_list.cc @@ -87,7 +87,6 @@ void AppList::SetWidget(views::Widget* widget) { if (is_visible_) { widget_ = widget; - widget_->AddObserver(this); GetLayer(widget_)->GetAnimator()->AddObserver(this); Shell::GetInstance()->AddRootWindowEventFilter(this); @@ -119,13 +118,19 @@ void AppList::ScheduleAnimation() { return; ui::Layer* layer = GetLayer(widget_); + + // Stop observing previous animation. + StopObservingImplicitAnimations(); + ui::ScopedLayerAnimationSettings app_list_animation(layer->GetAnimator()); + app_list_animation.AddObserver(this); layer->SetBounds(GetPreferredBounds(is_visible_)); layer->SetOpacity(is_visible_ ? 1.0 : 0.0); ui::Layer* default_container_layer = default_container->layer(); ui::ScopedLayerAnimationSettings default_container_animation( default_container_layer->GetAnimator()); + app_list_animation.AddObserver(this); default_container_layer->SetOpacity(is_visible_ ? 0.0 : 1.0); } @@ -159,22 +164,13 @@ ui::GestureStatus AppList::PreHandleGestureEvent( } //////////////////////////////////////////////////////////////////////////////// -// AppList, ui::LayerAnimationObserver implementation: +// AppList, ui::ImplicitAnimationObserver implementation: -void AppList::OnLayerAnimationEnded( - const ui::LayerAnimationSequence* sequence) { +void AppList::OnImplicitAnimationsCompleted() { if (!is_visible_ ) widget_->Close(); } -void AppList::OnLayerAnimationAborted( - const ui::LayerAnimationSequence* sequence) { -} - -void AppList::OnLayerAnimationScheduled( - const ui::LayerAnimationSequence* sequence) { -} - //////////////////////////////////////////////////////////////////////////////// // AppList, views::Widget::Observer implementation: diff --git a/ash/app_list/app_list.h b/ash/app_list/app_list.h index 77b2ecd..b499498 100644 --- a/ash/app_list/app_list.h +++ b/ash/app_list/app_list.h @@ -20,7 +20,7 @@ namespace internal { // While the UI is visible, it monitors things such as app list widget's // activation state and desktop mouse click to auto dismiss the UI. class AppList : public aura::EventFilter, - public ui::LayerAnimationObserver, + public ui::ImplicitAnimationObserver, public views::Widget::Observer { public: AppList(); @@ -54,13 +54,8 @@ class AppList : public aura::EventFilter, aura::Window* target, aura::GestureEvent* event) OVERRIDE; - // ui::LayerAnimationObserver overrides: - virtual void OnLayerAnimationEnded( - const ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationAborted( - const ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationScheduled( - const ui::LayerAnimationSequence* sequence) OVERRIDE; + // ui::ImplicitAnimationObserver overrides: + virtual void OnImplicitAnimationsCompleted() OVERRIDE; // views::Widget::Observer overrides: virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE; diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc index 2e43ea3..255b0e2 100644 --- a/ash/drag_drop/drag_drop_controller.cc +++ b/ash/drag_drop/drag_drop_controller.cc @@ -28,7 +28,7 @@ namespace { const gfx::Point kDragDropWidgetOffset(0, 0); const base::TimeDelta kDragDropAnimationDuration = base::TimeDelta::FromMilliseconds(250); -} +} // namespace //////////////////////////////////////////////////////////////////////////////// // DragDropController, public: @@ -47,11 +47,8 @@ DragDropController::DragDropController() DragDropController::~DragDropController() { Shell::GetInstance()->RemoveRootWindowEventFilter(this); Cleanup(); - if (drag_image_.get()) { - aura::Window* window = drag_image_->GetWidget()->GetNativeView(); - window->layer()->GetAnimator()->RemoveObserver(this); + if (drag_image_.get()) drag_image_.reset(); - } } int DragDropController::StartDragAndDrop(const ui::OSExchangeData& data, @@ -206,14 +203,7 @@ ui::GestureStatus DragDropController::PreHandleGestureEvent( //////////////////////////////////////////////////////////////////////////////// // DragDropController, private: -void DragDropController::OnLayerAnimationEnded( - const ui::LayerAnimationSequence* sequence) { - DCHECK(drag_image_.get()); - drag_image_.reset(); -} - -void DragDropController::OnLayerAnimationAborted( - const ui::LayerAnimationSequence* sequence) { +void DragDropController::OnImplicitAnimationsCompleted() { DCHECK(drag_image_.get()); drag_image_.reset(); } @@ -223,9 +213,13 @@ void DragDropController::StartCanceledAnimation() { ui::LayerAnimator* animator = window->layer()->GetAnimator(); animator->set_preemption_strategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - animator->AddObserver(this); + + // Stop waiting for any as yet unfinished implicit animations. + StopObservingImplicitAnimations(); + ui::ScopedLayerAnimationSettings animation_setter(animator); animation_setter.SetTransitionDuration(kDragDropAnimationDuration); + animation_setter.AddObserver(this); window->SetBounds(gfx::Rect(drag_start_location_, window->bounds().size())); } diff --git a/ash/drag_drop/drag_drop_controller.h b/ash/drag_drop/drag_drop_controller.h index 0f9b257..9272257 100644 --- a/ash/drag_drop/drag_drop_controller.h +++ b/ash/drag_drop/drag_drop_controller.h @@ -36,8 +36,8 @@ class DragImageView; class ASH_EXPORT DragDropController : public aura::client::DragDropClient, public aura::EventFilter, - public ui::LayerAnimationObserver { - public: + public ui::ImplicitAnimationObserver { +public: DragDropController(); virtual ~DragDropController(); @@ -69,13 +69,8 @@ class ASH_EXPORT DragDropController private: friend class ash::test::DragDropControllerTest; - // Overridden from ui::LayerAnimationObserver: - virtual void OnLayerAnimationEnded( - const ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationAborted( - const ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationScheduled( - const ui::LayerAnimationSequence* sequence) OVERRIDE {} + // Implementation of ImplicitAnimationObserver + virtual void OnImplicitAnimationsCompleted() OVERRIDE; // Helper method to start drag widget flying back animation. void StartCanceledAnimation(); diff --git a/ash/test/aura_shell_test_base.cc b/ash/test/aura_shell_test_base.cc index b6011de..1486f1c 100644 --- a/ash/test/aura_shell_test_base.cc +++ b/ash/test/aura_shell_test_base.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -6,6 +6,7 @@ #include "ash/shell.h" #include "ash/test/test_shell_delegate.h" +#include "ui/gfx/compositor/layer_animator.h" namespace ash { namespace test { @@ -21,6 +22,9 @@ void AuraShellTestBase::SetUp() { // Creates Shell and hook with Desktop. ash::Shell::CreateInstance(new TestShellDelegate); + + // Disable animations during tests. + ui::LayerAnimator::set_disable_animations_for_test(true); } void AuraShellTestBase::TearDown() { diff --git a/ash/wm/compact_layout_manager.cc b/ash/wm/compact_layout_manager.cc index 105d04c..2be9525 100644 --- a/ash/wm/compact_layout_manager.cc +++ b/ash/wm/compact_layout_manager.cc @@ -140,20 +140,11 @@ void CompactLayoutManager::OnWindowStackingChanged(aura::Window* window) { ///////////////////////////////////////////////////////////////////////////// // CompactLayoutManager, AnimationDelegate overrides: -void CompactLayoutManager::OnLayerAnimationEnded( - const ui::LayerAnimationSequence* animation) { +void CompactLayoutManager::OnImplicitAnimationsCompleted() { if (!GetDefaultContainerLayer()->GetAnimator()->is_animating()) HideWindows(); } -void CompactLayoutManager::OnLayerAnimationScheduled( - const ui::LayerAnimationSequence* animation) { -} - -void CompactLayoutManager::OnLayerAnimationAborted( - const ui::LayerAnimationSequence* animation) { -} - ////////////////////////////////////////////////////////////////////////////// // CompactLayoutManager, private: diff --git a/ash/wm/compact_layout_manager.h b/ash/wm/compact_layout_manager.h index 8b4f241..9f9843a 100644 --- a/ash/wm/compact_layout_manager.h +++ b/ash/wm/compact_layout_manager.h @@ -25,7 +25,7 @@ namespace internal { // maximized, fill the screen, and only one tabbed browser window is visible at // a time. The status area appears in the top-right corner of the screen. class ASH_EXPORT CompactLayoutManager : public BaseLayoutManager, - public ui::LayerAnimationObserver { + public ui::ImplicitAnimationObserver { public: CompactLayoutManager(); virtual ~CompactLayoutManager(); @@ -48,13 +48,8 @@ class ASH_EXPORT CompactLayoutManager : public BaseLayoutManager, void* old) OVERRIDE; virtual void OnWindowStackingChanged(aura::Window* window) OVERRIDE; - // ui::LayerAnimationObserver: - virtual void OnLayerAnimationEnded( - const ui::LayerAnimationSequence* animation) OVERRIDE; - virtual void OnLayerAnimationScheduled( - const ui::LayerAnimationSequence* animation) OVERRIDE; - virtual void OnLayerAnimationAborted( - const ui::LayerAnimationSequence* animation) OVERRIDE; + // ui::OnImplicitAnimationsCompleted: + virtual void OnImplicitAnimationsCompleted() OVERRIDE; private: FRIEND_TEST_ALL_PREFIXES(CompactLayoutManagerTransitionTest, diff --git a/ash/wm/shelf_layout_manager.cc b/ash/wm/shelf_layout_manager.cc index 1283fe5..c747c0f 100644 --- a/ash/wm/shelf_layout_manager.cc +++ b/ash/wm/shelf_layout_manager.cc @@ -10,6 +10,7 @@ #include "ui/aura/root_window.h" #include "ui/aura/screen_aura.h" #include "ui/gfx/compositor/layer.h" +#include "ui/gfx/compositor/layer_animation_observer.h" #include "ui/gfx/compositor/layer_animator.h" #include "ui/gfx/compositor/scoped_layer_animation_settings.h" #include "ui/views/widget/widget.h" @@ -30,8 +31,7 @@ ui::Layer* GetLayer(views::Widget* widget) { ShelfLayoutManager::ShelfLayoutManager(views::Widget* launcher, views::Widget* status) - : animating_(false), - in_layout_(false), + : in_layout_(false), visible_(true), max_height_(-1), launcher_(launcher), @@ -39,11 +39,9 @@ ShelfLayoutManager::ShelfLayoutManager(views::Widget* launcher, gfx::Rect launcher_bounds = launcher->GetWindowScreenBounds(); gfx::Rect status_bounds = status->GetWindowScreenBounds(); max_height_ = std::max(launcher_bounds.height(), status_bounds.height()); - GetLayer(launcher)->GetAnimator()->AddObserver(this); } ShelfLayoutManager::~ShelfLayoutManager() { - GetLayer(launcher_)->GetAnimator()->RemoveObserver(this); // Without a shelf we don't need special insets anymore. aura::RootWindow::GetInstance()-> screen()->set_work_area_insets(gfx::Insets()); @@ -66,19 +64,36 @@ void ShelfLayoutManager::LayoutShelf() { } void ShelfLayoutManager::SetVisible(bool visible) { - bool current_visibility = animating_ ? !visible_ : visible_; + ui::Layer* launcher_layer = GetLayer(launcher_); + ui::Layer* status_layer = GetLayer(status_); + + // TODO(vollick): once visibility is animatable, use GetTargetVisibility. + bool current_visibility = visible_ && + launcher_layer->GetTargetOpacity() > 0.0f && + status_layer->GetTargetOpacity() > 0.0f; + if (visible == current_visibility) return; // Nothing changed. StopAnimating(); + visible_ = visible; TargetBounds target_bounds; float target_opacity = visible ? 1.0f : 0.0f; CalculateTargetBounds(visible, &target_bounds); - AnimateWidgetTo(launcher_, target_bounds.launcher_bounds, target_opacity); - AnimateWidgetTo(status_, target_bounds.status_bounds, target_opacity); - animating_ = true; - // |visible_| is updated once the animation completes. + + ui::ScopedLayerAnimationSettings launcher_animation_setter( + launcher_layer->GetAnimator()); + ui::ScopedLayerAnimationSettings status_animation_setter( + status_layer->GetAnimator()); + + launcher_animation_setter.AddObserver(this); + status_animation_setter.AddObserver(this); + + launcher_layer->SetBounds(target_bounds.launcher_bounds); + launcher_layer->SetOpacity(target_opacity); + status_layer->SetBounds(target_bounds.status_bounds); + status_layer->SetOpacity(target_opacity); } //////////////////////////////////////////////////////////////////////////////// @@ -109,10 +124,7 @@ void ShelfLayoutManager::SetChildBounds(aura::Window* child, // ShelfLayoutManager, private: void ShelfLayoutManager::StopAnimating() { - if (animating_) { - animating_ = false; - visible_ = !visible_; - } + StopObservingImplicitAnimations(); GetLayer(launcher_)->GetAnimator()->StopAnimating(); GetLayer(status_)->GetAnimator()->StopAnimating(); } @@ -135,23 +147,7 @@ void ShelfLayoutManager::CalculateTargetBounds(bool visible, target_bounds->work_area_insets = gfx::Insets(0, 0, max_height_, 0); } -void ShelfLayoutManager::AnimateWidgetTo(views::Widget* widget, - const gfx::Rect& target_bounds, - float target_opacity) { - ui::Layer* layer = GetLayer(widget); - ui::ScopedLayerAnimationSettings animation_setter(layer->GetAnimator()); - // Don't go through the widget, otherwise we end up back in SetChildBounds and - // cancel the animation/layout. - layer->SetBounds(target_bounds); - layer->SetOpacity(target_opacity); -} - -void ShelfLayoutManager::OnLayerAnimationEnded( - const ui::LayerAnimationSequence* sequence) { - if (!animating_) - return; - animating_ = false; - visible_ = !visible_; +void ShelfLayoutManager::OnImplicitAnimationsCompleted() { TargetBounds target_bounds; CalculateTargetBounds(visible_, &target_bounds); aura::RootWindow::GetInstance()->screen()->set_work_area_insets( diff --git a/ash/wm/shelf_layout_manager.h b/ash/wm/shelf_layout_manager.h index 3c35389..8d69cc6 100644 --- a/ash/wm/shelf_layout_manager.h +++ b/ash/wm/shelf_layout_manager.h @@ -28,7 +28,7 @@ namespace internal { // To respond to bounds changes in the status area StatusAreaLayoutManager works // closely with ShelfLayoutManager. class ASH_EXPORT ShelfLayoutManager : public aura::LayoutManager, - public ui::LayerAnimationObserver { + public ui::ImplicitAnimationObserver { public: ShelfLayoutManager(views::Widget* launcher, views::Widget* status); virtual ~ShelfLayoutManager(); @@ -41,7 +41,7 @@ class ASH_EXPORT ShelfLayoutManager : public aura::LayoutManager, // Sets the visibility of the shelf to |visible|. void SetVisible(bool visible); - bool visible() const { return animating_ ? !visible_ : visible_; } + bool visible() const { return visible_; } views::Widget* launcher() { return launcher_; } views::Widget* status() { return status_; } @@ -72,21 +72,8 @@ class ASH_EXPORT ShelfLayoutManager : public aura::LayoutManager, void CalculateTargetBounds(bool visible, TargetBounds* target_bounds); - // Animates |widget| to the specified bounds and opacity. - void AnimateWidgetTo(views::Widget* widget, - const gfx::Rect& target_bounds, - float target_opacity); - - // LayerAnimationObserver overrides: - virtual void OnLayerAnimationEnded( - const ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationAborted( - const ui::LayerAnimationSequence* sequence) OVERRIDE {} - virtual void OnLayerAnimationScheduled( - const ui::LayerAnimationSequence* sequence) OVERRIDE {} - - // Are we animating? - bool animating_; + // Implementation of ImplicitAnimationObserver + virtual void OnImplicitAnimationsCompleted() OVERRIDE; // True when inside LayoutShelf method. Used to prevent calling LayoutShelf // again from SetChildBounds(). diff --git a/ash/wm/system_modal_container_layout_manager.cc b/ash/wm/system_modal_container_layout_manager.cc index 6fdd910..e337a57 100644 --- a/ash/wm/system_modal_container_layout_manager.cc +++ b/ash/wm/system_modal_container_layout_manager.cc @@ -122,22 +122,14 @@ void SystemModalContainerLayoutManager::OnWindowPropertyChanged( } //////////////////////////////////////////////////////////////////////////////// -// SystemModalContainerLayoutManager, ui::LayerAnimationObserver implementation: +// SystemModalContainerLayoutManager, +// ui::ImplicitAnimationObserver implementation: -void SystemModalContainerLayoutManager::OnLayerAnimationEnded( - const ui::LayerAnimationSequence* sequence) { +void SystemModalContainerLayoutManager::OnImplicitAnimationsCompleted() { if (modal_screen_ && !modal_screen_->GetNativeView()->layer()->ShouldDraw()) DestroyModalScreen(); } -void SystemModalContainerLayoutManager::OnLayerAnimationAborted( - const ui::LayerAnimationSequence* sequence) { -} - -void SystemModalContainerLayoutManager::OnLayerAnimationScheduled( - const ui::LayerAnimationSequence* sequence) { -} - //////////////////////////////////////////////////////////////////////////////// // SystemModalContainerLayoutManager, // SystemModalContainerEventFilter::Delegate implementation: @@ -186,27 +178,33 @@ void SystemModalContainerLayoutManager::CreateModalScreen() { "SystemModalContainerLayoutManager.ModalScreen"); modal_screen_->SetContentsView(new ScreenView); modal_screen_->GetNativeView()->layer()->SetOpacity(0.0f); - modal_screen_->GetNativeView()->layer()->GetAnimator()->AddObserver(this); Shell::GetInstance()->AddRootWindowEventFilter(modality_filter_.get()); + StopObservingImplicitAnimations(); + ui::ScopedLayerAnimationSettings settings( modal_screen_->GetNativeView()->layer()->GetAnimator()); + settings.AddObserver(this); modal_screen_->Show(); modal_screen_->GetNativeView()->layer()->SetOpacity(0.5f); container_->StackChildAtTop(modal_screen_->GetNativeView()); } void SystemModalContainerLayoutManager::DestroyModalScreen() { - modal_screen_->GetNativeView()->layer()->GetAnimator()->RemoveObserver(this); + // Stop observing the modal screen's animations. + StopObservingImplicitAnimations(); modal_screen_->Close(); modal_screen_ = NULL; } void SystemModalContainerLayoutManager::HideModalScreen() { + StopObservingImplicitAnimations(); + Shell::GetInstance()->RemoveRootWindowEventFilter(modality_filter_.get()); ui::ScopedLayerAnimationSettings settings( modal_screen_->GetNativeView()->layer()->GetAnimator()); + settings.AddObserver(this); modal_screen_->GetNativeView()->layer()->SetOpacity(0.0f); } diff --git a/ash/wm/system_modal_container_layout_manager.h b/ash/wm/system_modal_container_layout_manager.h index c713500..309d0f07 100644 --- a/ash/wm/system_modal_container_layout_manager.h +++ b/ash/wm/system_modal_container_layout_manager.h @@ -35,7 +35,7 @@ namespace internal { class ASH_EXPORT SystemModalContainerLayoutManager : public aura::LayoutManager, public aura::WindowObserver, - public ui::LayerAnimationObserver, + public ui::ImplicitAnimationObserver, public SystemModalContainerEventFilterDelegate { public: explicit SystemModalContainerLayoutManager(aura::Window* container); @@ -55,13 +55,8 @@ class ASH_EXPORT SystemModalContainerLayoutManager const char* key, void* old) OVERRIDE; - // Overridden from ui::LayerAnimationObserver: - virtual void OnLayerAnimationEnded( - const ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationAborted( - const ui::LayerAnimationSequence* sequence) OVERRIDE; - virtual void OnLayerAnimationScheduled( - const ui::LayerAnimationSequence* sequence) OVERRIDE; + // Overridden from ui::ImplicitAnimationObserver: + virtual void OnImplicitAnimationsCompleted() OVERRIDE; // Overridden from SystemModalContainerEventFilterDelegate: virtual bool CanWindowReceiveEvents(aura::Window* window) OVERRIDE; diff --git a/ash/wm/system_modal_container_layout_manager_unittest.cc b/ash/wm/system_modal_container_layout_manager_unittest.cc index 04198ea..e3be65d 100644 --- a/ash/wm/system_modal_container_layout_manager_unittest.cc +++ b/ash/wm/system_modal_container_layout_manager_unittest.cc @@ -168,10 +168,8 @@ TEST_F(SystemModalContainerLayoutManagerTest, ModalTransient) { // Tests that we can activate an unrelated window after a modal window is closed // for a window. -// TODO(beng): This test is disabled pending a solution re: visibility & target -// visibility. TEST_F(SystemModalContainerLayoutManagerTest, - DISABLED_CanActivateAfterEndModalSession) { + CanActivateAfterEndModalSession) { scoped_ptr<aura::Window> unrelated(TestWindow::OpenTestWindow(NULL, false)); unrelated->SetBounds(gfx::Rect(100, 100, 50, 50)); scoped_ptr<aura::Window> parent(TestWindow::OpenTestWindow(NULL, false)); @@ -191,6 +189,8 @@ TEST_F(SystemModalContainerLayoutManagerTest, // Now close the transient. transient.reset(); + MessageLoopForUI::current()->RunAllPending(); + // parent should now be active again. EXPECT_TRUE(IsActiveWindow(parent.get())); diff --git a/ash/wm/visibility_controller_unittest.cc b/ash/wm/visibility_controller_unittest.cc index aaa15a5..9fb1024 100644 --- a/ash/wm/visibility_controller_unittest.cc +++ b/ash/wm/visibility_controller_unittest.cc @@ -8,6 +8,7 @@ #include "ui/aura/test/test_windows.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/window.h" +#include "ui/gfx/compositor/layer_animator.h" namespace ash { namespace internal { @@ -17,6 +18,9 @@ typedef test::AuraShellTestBase VisibilityControllerTest; // Hiding a window in an animatable container should not hide the window's layer // immediately. TEST_F(VisibilityControllerTest, AnimateHideDoesntHideWindowLayer) { + // We cannot disable animations for this test. + ui::LayerAnimator::set_disable_animations_for_test(false); + scoped_ptr<aura::Window> container( aura::test::CreateTestWindowWithId(-1, NULL)); SetChildWindowVisibilityChangesAnimated(container.get()); diff --git a/ash/wm/window_animations.cc b/ash/wm/window_animations.cc index 8b8c0b1..5c4c3a4 100644 --- a/ash/wm/window_animations.cc +++ b/ash/wm/window_animations.cc @@ -171,7 +171,8 @@ void AnimateHideWindowCommon(aura::Window* window, // Property sets within this scope will be implicitly animated. ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - settings.AddImplicitObserver(new HidingWindowAnimationObserver(window)); + settings.AddObserver(new HidingWindowAnimationObserver(window)); + int duration = window->GetIntProperty(internal::kWindowVisibilityAnimationDurationKey); if (duration > 0) { diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index b2f380e..0b4baa3 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -676,16 +676,16 @@ internal::FocusManager* RootWindow::GetFocusManager() { } void RootWindow::OnLayerAnimationEnded( - const ui::LayerAnimationSequence* animation) { + ui::LayerAnimationSequence* animation) { OnHostResized(host_->GetSize()); } void RootWindow::OnLayerAnimationScheduled( - const ui::LayerAnimationSequence* animation) { + ui::LayerAnimationSequence* animation) { } void RootWindow::OnLayerAnimationAborted( - const ui::LayerAnimationSequence* animation) { + ui::LayerAnimationSequence* animation) { } void RootWindow::SetFocusedWindow(Window* focused_window) { diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index ec0f09f..4f5bd4f 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -219,11 +219,11 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // Overridden from ui::LayerAnimationObserver: virtual void OnLayerAnimationEnded( - const ui::LayerAnimationSequence* animation) OVERRIDE; + ui::LayerAnimationSequence* animation) OVERRIDE; virtual void OnLayerAnimationScheduled( - const ui::LayerAnimationSequence* animation) OVERRIDE; + ui::LayerAnimationSequence* animation) OVERRIDE; virtual void OnLayerAnimationAborted( - const ui::LayerAnimationSequence* animation) OVERRIDE; + ui::LayerAnimationSequence* animation) OVERRIDE; // Overridden from FocusManager: virtual void SetFocusedWindow(Window* window) OVERRIDE; diff --git a/ui/aura/test/aura_test_base.cc b/ui/aura/test/aura_test_base.cc index 70d33f5..3e1e95f 100644 --- a/ui/aura/test/aura_test_base.cc +++ b/ui/aura/test/aura_test_base.cc @@ -9,6 +9,7 @@ #endif #include "ui/aura/root_window.h" +#include "ui/gfx/compositor/layer_animator.h" namespace aura { namespace test { @@ -22,6 +23,9 @@ AuraTestBase::AuraTestBase() RootWindow::GetInstance()->Show(); RootWindow::GetInstance()->SetHostSize(gfx::Size(600, 600)); + + // Disable animations during tests. + ui::LayerAnimator::set_disable_animations_for_test(true); } AuraTestBase::~AuraTestBase() { diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index 1e59c2d..78b9142 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -933,6 +933,9 @@ TEST_F(WindowTest, Property) { } TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) { + // We cannot short-circuit animations in this test. + ui::LayerAnimator::set_disable_animations_for_test(false); + scoped_ptr<Window> w1( CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), NULL)); @@ -966,7 +969,7 @@ TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) { // Confirm that the target bounds are reached. base::TimeTicks start_time = - w1->layer()->GetAnimator()->get_last_step_time_for_test(); + w1->layer()->GetAnimator()->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); diff --git a/ui/gfx/compositor/layer_animation_observer.cc b/ui/gfx/compositor/layer_animation_observer.cc index 23217a5..a477bde 100644 --- a/ui/gfx/compositor/layer_animation_observer.cc +++ b/ui/gfx/compositor/layer_animation_observer.cc @@ -11,14 +11,26 @@ namespace ui { //////////////////////////////////////////////////////////////////////////////// // LayerAnimationObserver +LayerAnimationObserver::LayerAnimationObserver() { +} + +LayerAnimationObserver::~LayerAnimationObserver() { + StopObserving(); +} + bool LayerAnimationObserver::RequiresNotificationWhenAnimatorDestroyed() const { return false; } -LayerAnimationObserver::LayerAnimationObserver() { +void LayerAnimationObserver::OnAttachedToSequence( + LayerAnimationSequence* sequence) { } -LayerAnimationObserver::~LayerAnimationObserver() { +void LayerAnimationObserver::OnDetachedFromSequence( + LayerAnimationSequence* sequence) { +} + +void LayerAnimationObserver::StopObserving() { while (!attached_sequences_.empty()) { LayerAnimationSequence* sequence = *attached_sequences_.begin(); sequence->RemoveObserver(this); @@ -29,20 +41,21 @@ void LayerAnimationObserver::AttachedToSequence( LayerAnimationSequence* sequence) { DCHECK(attached_sequences_.find(sequence) == attached_sequences_.end()); attached_sequences_.insert(sequence); + OnAttachedToSequence(sequence); } void LayerAnimationObserver::DetachedFromSequence( LayerAnimationSequence* sequence) { if (attached_sequences_.find(sequence) != attached_sequences_.end()) attached_sequences_.erase(sequence); + OnDetachedFromSequence(sequence); } //////////////////////////////////////////////////////////////////////////////// // ImplicitAnimationObserver ImplicitAnimationObserver::ImplicitAnimationObserver() - : active_(false), - animation_count_(0) { + : active_(false) { } ImplicitAnimationObserver::~ImplicitAnimationObserver() {} @@ -52,26 +65,44 @@ void ImplicitAnimationObserver::SetActive(bool active) { CheckCompleted(); } +void ImplicitAnimationObserver::StopObservingImplicitAnimations() { + SetActive(false); + StopObserving(); +} + void ImplicitAnimationObserver::OnLayerAnimationEnded( - const LayerAnimationSequence* sequence) { - animation_count_--; + LayerAnimationSequence* sequence) { + sequence->RemoveObserver(this); + DCHECK(attached_sequences().find(sequence) == attached_sequences().end()); CheckCompleted(); } void ImplicitAnimationObserver::OnLayerAnimationAborted( - const LayerAnimationSequence* sequence) { - animation_count_--; + LayerAnimationSequence* sequence) { + sequence->RemoveObserver(this); + DCHECK(attached_sequences().find(sequence) == attached_sequences().end()); CheckCompleted(); } void ImplicitAnimationObserver::OnLayerAnimationScheduled( - const LayerAnimationSequence* sequence) { - animation_count_++; + LayerAnimationSequence* sequence) { +} + +void ImplicitAnimationObserver::OnAttachedToSequence( + LayerAnimationSequence* sequence) { +} + +void ImplicitAnimationObserver::OnDetachedFromSequence( + LayerAnimationSequence* sequence) { + DCHECK(attached_sequences().find(sequence) == attached_sequences().end()); + CheckCompleted(); } void ImplicitAnimationObserver::CheckCompleted() { - if (active_ && animation_count_ == 0) + if (active_ && attached_sequences().empty()) { OnImplicitAnimationsCompleted(); + active_ = false; + } } } // namespace ui diff --git a/ui/gfx/compositor/layer_animation_observer.h b/ui/gfx/compositor/layer_animation_observer.h index c35dc60..a2eb911 100644 --- a/ui/gfx/compositor/layer_animation_observer.h +++ b/ui/gfx/compositor/layer_animation_observer.h @@ -16,22 +16,29 @@ namespace ui { class LayerAnimationSequence; class ScopedLayerAnimationSettings; +class ImplicitAnimationObserver; // LayerAnimationObservers are notified when animations complete. class COMPOSITOR_EXPORT LayerAnimationObserver { public: // Called when the |sequence| ends. Not called if |sequence| is aborted. virtual void OnLayerAnimationEnded( - const LayerAnimationSequence* sequence) = 0; + LayerAnimationSequence* sequence) = 0; // Called if |sequence| is aborted for any reason. Should never do anything // that may cause another animation to be started. virtual void OnLayerAnimationAborted( - const LayerAnimationSequence* sequence) = 0; + LayerAnimationSequence* sequence) = 0; // Called when the animation is scheduled. virtual void OnLayerAnimationScheduled( - const LayerAnimationSequence* sequence) = 0; + LayerAnimationSequence* sequence) = 0; + + protected: + typedef std::set<LayerAnimationSequence*> AttachedSequences; + + LayerAnimationObserver(); + virtual ~LayerAnimationObserver(); // If the animator is destroyed during an animation, the animations are // aborted. The resulting NotifyAborted notifications will NOT be sent to @@ -40,9 +47,18 @@ class COMPOSITOR_EXPORT LayerAnimationObserver { // OBSERVER WHEN YOU ARE DESTROYED. virtual bool RequiresNotificationWhenAnimatorDestroyed() const; - protected: - LayerAnimationObserver(); - virtual ~LayerAnimationObserver(); + // Called when |this| is added to |sequence|'s observer list. + virtual void OnAttachedToSequence(LayerAnimationSequence* sequence); + + // Called when |this| is removed to |sequence|'s observer list. + virtual void OnDetachedFromSequence(LayerAnimationSequence* sequence); + + // Detaches this observer from all sequences it is currently observing. + void StopObserving(); + + const AttachedSequences& attached_sequences() const { + return attached_sequences_; + } private: friend class LayerAnimationSequence; @@ -53,7 +69,7 @@ class COMPOSITOR_EXPORT LayerAnimationObserver { // Called when |this| is removed to |sequence|'s observer list. void DetachedFromSequence(LayerAnimationSequence* sequence); - std::set<LayerAnimationSequence*> attached_sequences_; + AttachedSequences attached_sequences_; }; // An implicit animation observer is intended to be used in conjunction with a @@ -67,29 +83,33 @@ class COMPOSITOR_EXPORT ImplicitAnimationObserver virtual void OnImplicitAnimationsCompleted() = 0; + protected: + // Deactivates the observer and clears the collection of animations it is + // waiting for. + void StopObservingImplicitAnimations(); + private: friend class ScopedLayerAnimationSettings; - // OnImplicitAnimationsCompleted is not fired unless the observer is active. - bool active() const { return active_; } - void SetActive(bool active); - // LayerAnimationObserver implementation virtual void OnLayerAnimationEnded( - const LayerAnimationSequence* sequence) OVERRIDE; + LayerAnimationSequence* sequence) OVERRIDE; virtual void OnLayerAnimationAborted( - const LayerAnimationSequence* sequence) OVERRIDE; + LayerAnimationSequence* sequence) OVERRIDE; virtual void OnLayerAnimationScheduled( - const LayerAnimationSequence* sequence) OVERRIDE; + LayerAnimationSequence* sequence) OVERRIDE; + virtual void OnAttachedToSequence( + LayerAnimationSequence* sequence) OVERRIDE; + virtual void OnDetachedFromSequence( + LayerAnimationSequence* sequence) OVERRIDE; + + // OnImplicitAnimationsCompleted is not fired unless the observer is active. + bool active() const { return active_; } + void SetActive(bool active); void CheckCompleted(); bool active_; - - // This tracks the number of scheduled animations that have yet to complete. - // If this value is zero, and the observer is active, then - // OnImplicitAnimationsCompleted is fired. - size_t animation_count_; }; } // namespace ui diff --git a/ui/gfx/compositor/layer_animator.cc b/ui/gfx/compositor/layer_animator.cc index 82aa949..f98904c 100644 --- a/ui/gfx/compositor/layer_animator.cc +++ b/ui/gfx/compositor/layer_animator.cc @@ -45,6 +45,9 @@ LayerAnimator::~LayerAnimator() { } // static +bool LayerAnimator::disable_animations_for_test_ = false; + +// static LayerAnimator* LayerAnimator::CreateDefaultAnimator() { return new LayerAnimator(base::TimeDelta::FromMilliseconds(0)); } @@ -55,9 +58,12 @@ LayerAnimator* LayerAnimator::CreateImplicitAnimator() { } void LayerAnimator::SetTransform(const Transform& transform) { + base::TimeDelta duration = transition_duration_; + if (disable_animations_for_test_) + duration = base::TimeDelta(); StartAnimation(new LayerAnimationSequence( LayerAnimationElement::CreateTransformElement( - transform, transition_duration_))); + transform, duration))); } Transform LayerAnimator::GetTargetTransform() const { @@ -67,9 +73,12 @@ Transform LayerAnimator::GetTargetTransform() const { } void LayerAnimator::SetBounds(const gfx::Rect& bounds) { + base::TimeDelta duration = transition_duration_; + if (disable_animations_for_test_) + duration = base::TimeDelta(); StartAnimation(new LayerAnimationSequence( LayerAnimationElement::CreateBoundsElement( - bounds, transition_duration_))); + bounds, duration))); } gfx::Rect LayerAnimator::GetTargetBounds() const { @@ -79,9 +88,12 @@ gfx::Rect LayerAnimator::GetTargetBounds() const { } void LayerAnimator::SetOpacity(float opacity) { + base::TimeDelta duration = transition_duration_; + if (disable_animations_for_test_) + duration = base::TimeDelta(); StartAnimation(new LayerAnimationSequence( LayerAnimationElement::CreateOpacityElement( - opacity, transition_duration_))); + opacity, duration))); } float LayerAnimator::GetTargetOpacity() const { diff --git a/ui/gfx/compositor/layer_animator.h b/ui/gfx/compositor/layer_animator.h index 60ee25a..2231f57 100644 --- a/ui/gfx/compositor/layer_animator.h +++ b/ui/gfx/compositor/layer_animator.h @@ -33,6 +33,8 @@ class Transform; // When a property of layer needs to be changed it is set by way of // LayerAnimator. This enables LayerAnimator to animate property changes. +// NB: during many tests, set_disable_animations_for_test is used and causes +// all animations to complete immediately. class COMPOSITOR_EXPORT LayerAnimator : public AnimationContainerElement { public: enum PreemptionStrategy { @@ -108,17 +110,22 @@ class COMPOSITOR_EXPORT LayerAnimator : public AnimationContainerElement { // Stops all animation and clears any queued animations. void StopAnimating(); - // For testing purposes only. - void set_disable_timer_for_test(bool enabled) { - disable_timer_for_test_ = enabled; - } - base::TimeTicks get_last_step_time_for_test() { return last_step_time_; } - // These functions are used for adding or removing observers from the observer // list. The observers are notified when animations end. void AddObserver(LayerAnimationObserver* observer); void RemoveObserver(LayerAnimationObserver* observer); + // For testing purposes only. + void set_disable_timer_for_test(bool disable_timer) { + disable_timer_for_test_ = disable_timer; + } + base::TimeTicks last_step_time() const { return last_step_time_; } + + // When set to true, all animations complete immediately. + static void set_disable_animations_for_test(bool disable_animations) { + disable_animations_for_test_ = disable_animations; + } + protected: LayerAnimationDelegate* delegate() { return delegate_; } const LayerAnimationDelegate* delegate() const { return delegate_; } @@ -233,6 +240,9 @@ class COMPOSITOR_EXPORT LayerAnimator : public AnimationContainerElement { // and allows for manual stepping. bool disable_timer_for_test_; + // This causes all animations to complete immediately. + static bool disable_animations_for_test_; + // Observers are notified when layer animations end, are scheduled or are // aborted. ObserverList<LayerAnimationObserver> observers_; diff --git a/ui/gfx/compositor/layer_animator_unittest.cc b/ui/gfx/compositor/layer_animator_unittest.cc index cad4a6b..09d1c66 100644 --- a/ui/gfx/compositor/layer_animator_unittest.cc +++ b/ui/gfx/compositor/layer_animator_unittest.cc @@ -133,7 +133,7 @@ TEST(LayerAnimatorTest, ScheduleAnimationThatCanRunImmediately) { EXPECT_TRUE(animator->is_animating()); EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); @@ -181,7 +181,7 @@ TEST(LayerAnimatorTest, ScheduleTwoAnimationsThatCanRunImmediately) { EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); @@ -224,7 +224,7 @@ TEST(LayerAnimatorTest, ScheduleTwoAnimationsOnSameProperty) { EXPECT_TRUE(animator->is_animating()); EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); @@ -292,7 +292,7 @@ TEST(LayerAnimatorTest, ScheduleBlockedAnimation) { EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); @@ -364,7 +364,7 @@ TEST(LayerAnimatorTest, ScheduleTogether) { EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); CheckApproximatelyEqual(delegate.GetBoundsForAnimation(), start_bounds); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); @@ -403,7 +403,7 @@ TEST(LayerAnimatorTest, StartAnimationThatCanRunImmediately) { EXPECT_TRUE(animator->is_animating()); EXPECT_FLOAT_EQ(delegate.GetOpacityForAnimation(), start_opacity); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); @@ -467,7 +467,7 @@ TEST(LayerAnimatorTest, PreemptByImmediatelyAnimatingToNewTarget) { new LayerAnimationSequence( LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); @@ -518,7 +518,7 @@ TEST(LayerAnimatorTest, PreemptEnqueueNewAnimation) { new LayerAnimationSequence( LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); @@ -571,7 +571,7 @@ TEST(LayerAnimatorTest, PreemptyByReplacingQueuedAnimations) { new LayerAnimationSequence( LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); @@ -630,7 +630,7 @@ TEST(LayerAnimatorTest, CyclicSequences) { animator->StartAnimation(sequence.release()); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); @@ -687,7 +687,7 @@ TEST(LayerAnimatorTest, AddObserverExplicit) { EXPECT_EQ(observer.last_scheduled_sequence(), sequence); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); @@ -704,45 +704,6 @@ TEST(LayerAnimatorTest, AddObserverExplicit) { EXPECT_EQ(observer.last_aborted_sequence(), sequence); } -TEST(LayerAnimatorTest, AddObserverImplicit) { - scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); - AnimationContainerElement* element = animator.get(); - animator->set_disable_timer_for_test(true); - TestLayerAnimationObserver observer; - TestLayerAnimationDelegate delegate; - animator->SetDelegate(&delegate); - animator->AddObserver(&observer); - - // Should end a sequence with the default animator. - EXPECT_TRUE(!observer.last_ended_sequence()); - animator->SetOpacity(1.0f); - base::TimeTicks start_time = base::TimeTicks::Now(); - element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); - EXPECT_TRUE(observer.last_ended_sequence()); - - TestLayerAnimationObserver scoped_observer; - { - ScopedLayerAnimationSettings settings(animator.get()); - settings.AddObserver(&scoped_observer); - for (int i = 0; i < 2; ++i) { - // reset the observer - scoped_observer = TestLayerAnimationObserver(); - EXPECT_TRUE(!scoped_observer.last_ended_sequence()); - animator->SetOpacity(1.0f); - start_time = animator->get_last_step_time_for_test(); - element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); - EXPECT_FALSE(!scoped_observer.last_ended_sequence()); - } - } - - scoped_observer = TestLayerAnimationObserver(); - EXPECT_TRUE(!scoped_observer.last_ended_sequence()); - animator->SetOpacity(1.0f); - start_time = base::TimeTicks::Now(); - element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); - EXPECT_TRUE(!scoped_observer.last_ended_sequence()); -} - // Tests that an observer added to a scoped settings object is still notified // when the object goes out of scope. TEST(LayerAnimatorTest, ImplicitAnimationObservers) { @@ -758,12 +719,12 @@ TEST(LayerAnimatorTest, ImplicitAnimationObservers) { { ScopedLayerAnimationSettings settings(animator.get()); - settings.AddImplicitObserver(&observer); + settings.AddObserver(&observer); animator->SetOpacity(0.0f); } EXPECT_FALSE(observer.animations_completed()); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); EXPECT_TRUE(observer.animations_completed()); EXPECT_FLOAT_EQ(0.0f, delegate.GetOpacityForAnimation()); @@ -783,7 +744,7 @@ TEST(LayerAnimatorTest, InterruptedImplicitAnimationObservers) { { ScopedLayerAnimationSettings settings(animator.get()); - settings.AddImplicitObserver(&observer); + settings.AddObserver(&observer); animator->SetOpacity(0.0f); } @@ -822,7 +783,7 @@ TEST(LayerAnimatorTest, RemoveObserverShouldRemoveFromSequences) { // This should stop the observer from observing sequence. animator->RemoveObserver(&removed_observer); - base::TimeTicks start_time = animator->get_last_step_time_for_test(); + base::TimeTicks start_time = animator->last_step_time(); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); @@ -858,6 +819,70 @@ TEST(LayerAnimatorTest, ObserverReleasedBeforeAnimationSequenceEnds) { EXPECT_EQ(static_cast<size_t>(0), sequence->observers_.size()); } +TEST(LayerAnimatorTest, ObserverAttachedAfterAnimationStarted) { + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); + AnimationContainerElement* element = animator.get(); + animator->set_disable_timer_for_test(true); + + TestImplicitAnimationObserver observer; + TestLayerAnimationDelegate delegate; + animator->SetDelegate(&delegate); + + delegate.SetOpacityFromAnimation(0.0f); + + { + ScopedLayerAnimationSettings setter(animator.get()); + + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + LayerAnimationSequence* sequence = new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement(1.0f, delta)); + + animator->StartAnimation(sequence); + base::TimeTicks start_time = animator->last_step_time(); + element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); + + setter.AddObserver(&observer); + + // Start observing an in-flight animation. + sequence->AddObserver(&observer); + + element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); + } + + EXPECT_TRUE(observer.animations_completed()); +} + +TEST(LayerAnimatorTest, ObserverDetachedBeforeAnimationFinished) { + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); + AnimationContainerElement* element = animator.get(); + animator->set_disable_timer_for_test(true); + + TestImplicitAnimationObserver observer; + TestLayerAnimationDelegate delegate; + animator->SetDelegate(&delegate); + + delegate.SetOpacityFromAnimation(0.0f); + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + LayerAnimationSequence* sequence = new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement(1.0f, delta)); + + { + ScopedLayerAnimationSettings setter(animator.get()); + setter.AddObserver(&observer); + + animator->StartAnimation(sequence); + base::TimeTicks start_time = animator->last_step_time(); + element->Step(start_time + base::TimeDelta::FromMilliseconds(500)); + } + + EXPECT_FALSE(observer.animations_completed()); + + // Stop observing an in-flight animation. + sequence->RemoveObserver(&observer); + + EXPECT_TRUE(observer.animations_completed()); +} + // Check that setting a property during an animation with a default animator // cancels the original animation. TEST(LayerAnimatorTest, SettingPropertyDuringAnAnimation) { diff --git a/ui/gfx/compositor/scoped_layer_animation_settings.cc b/ui/gfx/compositor/scoped_layer_animation_settings.cc index 874b927..7a7dbc1 100644 --- a/ui/gfx/compositor/scoped_layer_animation_settings.cc +++ b/ui/gfx/compositor/scoped_layer_animation_settings.cc @@ -26,27 +26,19 @@ ScopedLayerAnimationSettings::ScopedLayerAnimationSettings( ScopedLayerAnimationSettings::~ScopedLayerAnimationSettings() { animator_->transition_duration_ = old_transition_duration_; - for (std::set<LayerAnimationObserver*>::const_iterator i = - observers_.begin(); i != observers_.end(); ++i) - animator_->observers_.RemoveObserver(*i); - for (std::set<ImplicitAnimationObserver*>::const_iterator i = - implicit_observers_.begin(); i != implicit_observers_.end(); ++i) - (*i)->SetActive(true); + observers_.begin(); i != observers_.end(); ++i) { + animator_->observers_.RemoveObserver(*i); + (*i)->SetActive(true); + } } void ScopedLayerAnimationSettings::AddObserver( - LayerAnimationObserver* observer) { + ImplicitAnimationObserver* observer) { observers_.insert(observer); animator_->AddObserver(observer); } -void ScopedLayerAnimationSettings::AddImplicitObserver( - ImplicitAnimationObserver* observer) { - implicit_observers_.insert(observer); - AddObserver(observer); -} - void ScopedLayerAnimationSettings::SetTransitionDuration( base::TimeDelta duration) { animator_->transition_duration_ = duration; diff --git a/ui/gfx/compositor/scoped_layer_animation_settings.h b/ui/gfx/compositor/scoped_layer_animation_settings.h index 2f90055..dce64ef 100644 --- a/ui/gfx/compositor/scoped_layer_animation_settings.h +++ b/ui/gfx/compositor/scoped_layer_animation_settings.h @@ -27,15 +27,13 @@ class COMPOSITOR_EXPORT ScopedLayerAnimationSettings { explicit ScopedLayerAnimationSettings(LayerAnimator* animator); virtual ~ScopedLayerAnimationSettings(); - void AddObserver(LayerAnimationObserver* observer); - void AddImplicitObserver(ImplicitAnimationObserver* observer); + void AddObserver(ImplicitAnimationObserver* observer); void SetTransitionDuration(base::TimeDelta duration); private: LayerAnimator* animator_; base::TimeDelta old_transition_duration_; - std::set<LayerAnimationObserver*> observers_; - std::set<ImplicitAnimationObserver*> implicit_observers_; + std::set<ImplicitAnimationObserver*> observers_; DISALLOW_COPY_AND_ASSIGN(ScopedLayerAnimationSettings); }; diff --git a/ui/gfx/compositor/test/test_layer_animation_observer.cc b/ui/gfx/compositor/test/test_layer_animation_observer.cc index fe515d3..2afcb1b 100644 --- a/ui/gfx/compositor/test/test_layer_animation_observer.cc +++ b/ui/gfx/compositor/test/test_layer_animation_observer.cc @@ -19,17 +19,17 @@ TestLayerAnimationObserver::~TestLayerAnimationObserver() { } void TestLayerAnimationObserver::OnLayerAnimationEnded( - const LayerAnimationSequence* sequence) { + LayerAnimationSequence* sequence) { last_ended_sequence_ = sequence; } void TestLayerAnimationObserver::OnLayerAnimationAborted( - const LayerAnimationSequence* sequence) { + LayerAnimationSequence* sequence) { last_aborted_sequence_ = sequence; } void TestLayerAnimationObserver::OnLayerAnimationScheduled( - const LayerAnimationSequence* sequence) { + LayerAnimationSequence* sequence) { last_scheduled_sequence_ = sequence; } diff --git a/ui/gfx/compositor/test/test_layer_animation_observer.h b/ui/gfx/compositor/test/test_layer_animation_observer.h index b90a9dc..44a7119 100644 --- a/ui/gfx/compositor/test/test_layer_animation_observer.h +++ b/ui/gfx/compositor/test/test_layer_animation_observer.h @@ -21,13 +21,13 @@ class TestLayerAnimationObserver : public LayerAnimationObserver { virtual ~TestLayerAnimationObserver(); virtual void OnLayerAnimationEnded( - const LayerAnimationSequence* sequence) OVERRIDE; + LayerAnimationSequence* sequence) OVERRIDE; virtual void OnLayerAnimationAborted( - const LayerAnimationSequence* sequence) OVERRIDE; + LayerAnimationSequence* sequence) OVERRIDE; virtual void OnLayerAnimationScheduled( - const LayerAnimationSequence* sequence) OVERRIDE; + LayerAnimationSequence* sequence) OVERRIDE; virtual bool RequiresNotificationWhenAnimatorDestroyed() const OVERRIDE; |