Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "ash/wm/window_animations.h" |
| 6 | |
| 7 | #include "ash/shell_window_ids.h" |
| 8 | #include "ash/test/ash_test_base.h" |
Torne (Richard Coles) | a3f6a49 | 2013-12-18 16:25:09 +0000 | [diff] [blame] | 9 | #include "ash/wm/window_state.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 10 | #include "ash/wm/workspace_controller.h" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 11 | #include "base/time/time.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 12 | #include "ui/aura/test/test_windows.h" |
| 13 | #include "ui/aura/window.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 14 | #include "ui/compositor/layer.h" |
Torne (Richard Coles) | a3f6a49 | 2013-12-18 16:25:09 +0000 | [diff] [blame] | 15 | #include "ui/compositor/layer_animation_observer.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 16 | #include "ui/compositor/layer_animator.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 17 | #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
Torne (Richard Coles) | a3f6a49 | 2013-12-18 16:25:09 +0000 | [diff] [blame] | 18 | #include "ui/compositor/scoped_layer_animation_settings.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 19 | |
| 20 | using aura::Window; |
| 21 | using ui::Layer; |
| 22 | |
| 23 | namespace ash { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 24 | class WindowAnimationsTest : public ash::test::AshTestBase { |
| 25 | public: |
| 26 | WindowAnimationsTest() {} |
| 27 | |
| 28 | virtual void TearDown() OVERRIDE { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 29 | AshTestBase::TearDown(); |
| 30 | } |
| 31 | |
| 32 | private: |
| 33 | DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest); |
| 34 | }; |
| 35 | |
Torne (Richard Coles) | a3f6a49 | 2013-12-18 16:25:09 +0000 | [diff] [blame] | 36 | // Listens to animation scheduled notifications. Remembers the transition |
| 37 | // duration of the first sequence. |
| 38 | class MinimizeAnimationObserver : public ui::LayerAnimationObserver { |
| 39 | public: |
| 40 | explicit MinimizeAnimationObserver(ui::LayerAnimator* animator) |
| 41 | : animator_(animator) { |
| 42 | animator_->AddObserver(this); |
| 43 | // RemoveObserver is called when the first animation is scheduled and so |
| 44 | // there should be no need for now to remove it in destructor. |
| 45 | }; |
| 46 | base::TimeDelta duration() { return duration_; } |
| 47 | |
| 48 | protected: |
| 49 | // ui::LayerAnimationObserver: |
| 50 | virtual void OnLayerAnimationScheduled( |
| 51 | ui::LayerAnimationSequence* sequence) OVERRIDE { |
| 52 | duration_ = animator_->GetTransitionDuration(); |
| 53 | animator_->RemoveObserver(this); |
| 54 | } |
| 55 | virtual void OnLayerAnimationEnded( |
| 56 | ui::LayerAnimationSequence* sequence) OVERRIDE {} |
| 57 | virtual void OnLayerAnimationAborted( |
| 58 | ui::LayerAnimationSequence* sequence) OVERRIDE {} |
| 59 | |
| 60 | private: |
| 61 | ui::LayerAnimator* animator_; |
| 62 | base::TimeDelta duration_; |
| 63 | |
| 64 | DISALLOW_COPY_AND_ASSIGN(MinimizeAnimationObserver); |
| 65 | }; |
| 66 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 67 | TEST_F(WindowAnimationsTest, HideShowBrightnessGrayscaleAnimation) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 68 | scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 69 | window->Show(); |
| 70 | EXPECT_TRUE(window->layer()->visible()); |
| 71 | |
| 72 | // Hiding. |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 73 | ::wm::SetWindowVisibilityAnimationType( |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 74 | window.get(), |
| 75 | WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 76 | AnimateOnChildWindowVisibilityChanged(window.get(), false); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 77 | EXPECT_EQ(0.0f, window->layer()->GetTargetOpacity()); |
| 78 | EXPECT_FALSE(window->layer()->GetTargetVisibility()); |
| 79 | EXPECT_FALSE(window->layer()->visible()); |
| 80 | |
| 81 | // Showing. |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 82 | ::wm::SetWindowVisibilityAnimationType( |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 83 | window.get(), |
| 84 | WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 85 | AnimateOnChildWindowVisibilityChanged(window.get(), true); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 86 | EXPECT_EQ(0.0f, window->layer()->GetTargetBrightness()); |
| 87 | EXPECT_EQ(0.0f, window->layer()->GetTargetGrayscale()); |
| 88 | EXPECT_TRUE(window->layer()->visible()); |
| 89 | |
| 90 | // Stays shown. |
Torne (Richard Coles) | 46d4c2b | 2014-06-09 12:00:27 +0100 | [diff] [blame^] | 91 | window->layer()->GetAnimator()->Step(base::TimeTicks::Now() + |
| 92 | base::TimeDelta::FromSeconds(5)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 93 | EXPECT_EQ(0.0f, window->layer()->GetTargetBrightness()); |
| 94 | EXPECT_EQ(0.0f, window->layer()->GetTargetGrayscale()); |
| 95 | EXPECT_TRUE(window->layer()->visible()); |
| 96 | } |
| 97 | |
| 98 | TEST_F(WindowAnimationsTest, LayerTargetVisibility) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 99 | scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 100 | |
| 101 | // Layer target visibility changes according to Show/Hide. |
| 102 | window->Show(); |
| 103 | EXPECT_TRUE(window->layer()->GetTargetVisibility()); |
| 104 | window->Hide(); |
| 105 | EXPECT_FALSE(window->layer()->GetTargetVisibility()); |
| 106 | window->Show(); |
| 107 | EXPECT_TRUE(window->layer()->GetTargetVisibility()); |
| 108 | } |
| 109 | |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 110 | namespace wm { |
| 111 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 112 | TEST_F(WindowAnimationsTest, CrossFadeToBounds) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 113 | ui::ScopedAnimationDurationScaleMode normal_duration_mode( |
| 114 | ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 115 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 116 | scoped_ptr<Window> window(CreateTestWindowInShellWithId(0)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 117 | window->SetBounds(gfx::Rect(5, 10, 320, 240)); |
| 118 | window->Show(); |
| 119 | |
| 120 | Layer* old_layer = window->layer(); |
| 121 | EXPECT_EQ(1.0f, old_layer->GetTargetOpacity()); |
| 122 | |
| 123 | // Cross fade to a larger size, as in a maximize animation. |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 124 | GetWindowState(window.get())->SetBoundsDirectCrossFade( |
| 125 | gfx::Rect(0, 0, 640, 480)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 126 | // Window's layer has been replaced. |
| 127 | EXPECT_NE(old_layer, window->layer()); |
| 128 | // Original layer stays opaque and stretches to new size. |
| 129 | EXPECT_EQ(1.0f, old_layer->GetTargetOpacity()); |
| 130 | EXPECT_EQ("5,10 320x240", old_layer->bounds().ToString()); |
| 131 | gfx::Transform grow_transform; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 132 | grow_transform.Translate(-5.f, -10.f); |
| 133 | grow_transform.Scale(640.f / 320.f, 480.f / 240.f); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 134 | EXPECT_EQ(grow_transform, old_layer->GetTargetTransform()); |
| 135 | // New layer animates in to the identity transform. |
| 136 | EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity()); |
| 137 | EXPECT_EQ(gfx::Transform(), window->layer()->GetTargetTransform()); |
| 138 | |
| 139 | // Run the animations to completion. |
Torne (Richard Coles) | 46d4c2b | 2014-06-09 12:00:27 +0100 | [diff] [blame^] | 140 | old_layer->GetAnimator()->Step(base::TimeTicks::Now() + |
| 141 | base::TimeDelta::FromSeconds(1)); |
| 142 | window->layer()->GetAnimator()->Step(base::TimeTicks::Now() + |
| 143 | base::TimeDelta::FromSeconds(1)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 144 | |
| 145 | // Cross fade to a smaller size, as in a restore animation. |
| 146 | old_layer = window->layer(); |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 147 | GetWindowState(window.get())->SetBoundsDirectCrossFade( |
| 148 | gfx::Rect(5, 10, 320, 240)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 149 | // Again, window layer has been replaced. |
| 150 | EXPECT_NE(old_layer, window->layer()); |
| 151 | // Original layer fades out and stretches down to new size. |
| 152 | EXPECT_EQ(0.0f, old_layer->GetTargetOpacity()); |
| 153 | EXPECT_EQ("0,0 640x480", old_layer->bounds().ToString()); |
| 154 | gfx::Transform shrink_transform; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 155 | shrink_transform.Translate(5.f, 10.f); |
| 156 | shrink_transform.Scale(320.f / 640.f, 240.f / 480.f); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 157 | EXPECT_EQ(shrink_transform, old_layer->GetTargetTransform()); |
| 158 | // New layer animates in to the identity transform. |
| 159 | EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity()); |
| 160 | EXPECT_EQ(gfx::Transform(), window->layer()->GetTargetTransform()); |
| 161 | |
Torne (Richard Coles) | 46d4c2b | 2014-06-09 12:00:27 +0100 | [diff] [blame^] | 162 | old_layer->GetAnimator()->Step(base::TimeTicks::Now() + |
| 163 | base::TimeDelta::FromSeconds(1)); |
| 164 | window->layer()->GetAnimator()->Step(base::TimeTicks::Now() + |
| 165 | base::TimeDelta::FromSeconds(1)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 166 | } |
| 167 | |
Torne (Richard Coles) | a140131 | 2014-03-18 10:20:56 +0000 | [diff] [blame] | 168 | } // namespace wm |
| 169 | |
Torne (Richard Coles) | a3f6a49 | 2013-12-18 16:25:09 +0000 | [diff] [blame] | 170 | TEST_F(WindowAnimationsTest, LockAnimationDuration) { |
| 171 | ui::ScopedAnimationDurationScaleMode normal_duration_mode( |
| 172 | ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); |
| 173 | |
| 174 | scoped_ptr<Window> window(CreateTestWindowInShellWithId(0)); |
| 175 | Layer* layer = window->layer(); |
| 176 | window->SetBounds(gfx::Rect(5, 10, 320, 240)); |
| 177 | window->Show(); |
| 178 | |
| 179 | // Test that it is possible to override transition duration when it is not |
| 180 | // locked. |
| 181 | { |
| 182 | ui::ScopedLayerAnimationSettings settings1(layer->GetAnimator()); |
| 183 | settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000)); |
| 184 | { |
| 185 | ui::ScopedLayerAnimationSettings settings2(layer->GetAnimator()); |
| 186 | // Duration is not locked so it gets overridden. |
| 187 | settings2.SetTransitionDuration(base::TimeDelta::FromMilliseconds(50)); |
| 188 | wm::GetWindowState(window.get())->Minimize(); |
| 189 | EXPECT_TRUE(layer->GetAnimator()->is_animating()); |
| 190 | // Expect duration from the inner scope |
| 191 | EXPECT_EQ(50, |
| 192 | layer->GetAnimator()->GetTransitionDuration().InMilliseconds()); |
| 193 | } |
| 194 | window->Show(); |
| 195 | layer->GetAnimator()->StopAnimating(); |
| 196 | } |
| 197 | |
| 198 | // Test that it is possible to lock transition duration |
| 199 | { |
Torne (Richard Coles) | 23730a6 | 2014-03-21 14:25:57 +0000 | [diff] [blame] | 200 | // Update layer as minimizing will replace the window's layer. |
| 201 | layer = window->layer(); |
Torne (Richard Coles) | a3f6a49 | 2013-12-18 16:25:09 +0000 | [diff] [blame] | 202 | ui::ScopedLayerAnimationSettings settings1(layer->GetAnimator()); |
| 203 | settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000)); |
| 204 | // Duration is locked in outer scope. |
| 205 | settings1.LockTransitionDuration(); |
| 206 | { |
| 207 | ui::ScopedLayerAnimationSettings settings2(layer->GetAnimator()); |
| 208 | // Transition duration setting is ignored. |
| 209 | settings2.SetTransitionDuration(base::TimeDelta::FromMilliseconds(50)); |
| 210 | wm::GetWindowState(window.get())->Minimize(); |
| 211 | EXPECT_TRUE(layer->GetAnimator()->is_animating()); |
| 212 | // Expect duration from the outer scope |
| 213 | EXPECT_EQ(1000, |
| 214 | layer->GetAnimator()->GetTransitionDuration().InMilliseconds()); |
| 215 | } |
| 216 | window->Show(); |
| 217 | layer->GetAnimator()->StopAnimating(); |
| 218 | } |
| 219 | |
| 220 | // Test that duration respects default. |
| 221 | { |
Torne (Richard Coles) | 23730a6 | 2014-03-21 14:25:57 +0000 | [diff] [blame] | 222 | layer = window->layer(); |
Torne (Richard Coles) | a3f6a49 | 2013-12-18 16:25:09 +0000 | [diff] [blame] | 223 | // Query default duration. |
| 224 | MinimizeAnimationObserver observer(layer->GetAnimator()); |
| 225 | wm::GetWindowState(window.get())->Minimize(); |
| 226 | EXPECT_TRUE(layer->GetAnimator()->is_animating()); |
| 227 | base::TimeDelta default_duration(observer.duration()); |
| 228 | window->Show(); |
| 229 | layer->GetAnimator()->StopAnimating(); |
| 230 | |
Torne (Richard Coles) | 23730a6 | 2014-03-21 14:25:57 +0000 | [diff] [blame] | 231 | layer = window->layer(); |
Torne (Richard Coles) | a3f6a49 | 2013-12-18 16:25:09 +0000 | [diff] [blame] | 232 | ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); |
| 233 | settings.LockTransitionDuration(); |
| 234 | // Setting transition duration is ignored since duration is locked |
| 235 | settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000)); |
| 236 | wm::GetWindowState(window.get())->Minimize(); |
| 237 | EXPECT_TRUE(layer->GetAnimator()->is_animating()); |
| 238 | // Expect default duration (200ms for stock ash minimizing animation). |
| 239 | EXPECT_EQ(default_duration.InMilliseconds(), |
| 240 | layer->GetAnimator()->GetTransitionDuration().InMilliseconds()); |
| 241 | window->Show(); |
| 242 | layer->GetAnimator()->StopAnimating(); |
| 243 | } |
| 244 | } |
| 245 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 246 | } // namespace ash |