blob: 0e1a4d8b24d3553cb1b3c08093f60230dc0f8ad9 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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)a3f6a492013-12-18 16:25:09 +00009#include "ash/wm/window_state.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010#include "ash/wm/workspace_controller.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010011#include "base/time/time.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000012#include "ui/aura/test/test_windows.h"
13#include "ui/aura/window.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000014#include "ui/compositor/layer.h"
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +000015#include "ui/compositor/layer_animation_observer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000016#include "ui/compositor/layer_animator.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000017#include "ui/compositor/scoped_animation_duration_scale_mode.h"
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +000018#include "ui/compositor/scoped_layer_animation_settings.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000019
20using aura::Window;
21using ui::Layer;
22
23namespace ash {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000024class WindowAnimationsTest : public ash::test::AshTestBase {
25 public:
26 WindowAnimationsTest() {}
27
28 virtual void TearDown() OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000029 AshTestBase::TearDown();
30 }
31
32 private:
33 DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest);
34};
35
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +000036// Listens to animation scheduled notifications. Remembers the transition
37// duration of the first sequence.
38class 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)58218062012-11-14 11:43:16 +000067TEST_F(WindowAnimationsTest, HideShowBrightnessGrayscaleAnimation) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000068 scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
Torne (Richard Coles)58218062012-11-14 11:43:16 +000069 window->Show();
70 EXPECT_TRUE(window->layer()->visible());
71
72 // Hiding.
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000073 ::wm::SetWindowVisibilityAnimationType(
Torne (Richard Coles)58218062012-11-14 11:43:16 +000074 window.get(),
75 WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000076 AnimateOnChildWindowVisibilityChanged(window.get(), false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000077 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)a1401312014-03-18 10:20:56 +000082 ::wm::SetWindowVisibilityAnimationType(
Torne (Richard Coles)58218062012-11-14 11:43:16 +000083 window.get(),
84 WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000085 AnimateOnChildWindowVisibilityChanged(window.get(), true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000086 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)46d4c2b2014-06-09 12:00:27 +010091 window->layer()->GetAnimator()->Step(base::TimeTicks::Now() +
92 base::TimeDelta::FromSeconds(5));
Torne (Richard Coles)58218062012-11-14 11:43:16 +000093 EXPECT_EQ(0.0f, window->layer()->GetTargetBrightness());
94 EXPECT_EQ(0.0f, window->layer()->GetTargetGrayscale());
95 EXPECT_TRUE(window->layer()->visible());
96}
97
98TEST_F(WindowAnimationsTest, LayerTargetVisibility) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000099 scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000100
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)a1401312014-03-18 10:20:56 +0000110namespace wm {
111
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000112TEST_F(WindowAnimationsTest, CrossFadeToBounds) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000113 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
114 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000115
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000116 scoped_ptr<Window> window(CreateTestWindowInShellWithId(0));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000117 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)a1401312014-03-18 10:20:56 +0000124 GetWindowState(window.get())->SetBoundsDirectCrossFade(
125 gfx::Rect(0, 0, 640, 480));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000126 // 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)2a99a7e2013-03-28 15:31:22 +0000132 grow_transform.Translate(-5.f, -10.f);
133 grow_transform.Scale(640.f / 320.f, 480.f / 240.f);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000134 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)46d4c2b2014-06-09 12:00:27 +0100140 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)58218062012-11-14 11:43:16 +0000144
145 // Cross fade to a smaller size, as in a restore animation.
146 old_layer = window->layer();
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000147 GetWindowState(window.get())->SetBoundsDirectCrossFade(
148 gfx::Rect(5, 10, 320, 240));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000149 // 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)2a99a7e2013-03-28 15:31:22 +0000155 shrink_transform.Translate(5.f, 10.f);
156 shrink_transform.Scale(320.f / 640.f, 240.f / 480.f);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000157 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)46d4c2b2014-06-09 12:00:27 +0100162 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)58218062012-11-14 11:43:16 +0000166}
167
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000168} // namespace wm
169
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000170TEST_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)23730a62014-03-21 14:25:57 +0000200 // Update layer as minimizing will replace the window's layer.
201 layer = window->layer();
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000202 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)23730a62014-03-21 14:25:57 +0000222 layer = window->layer();
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000223 // 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)23730a62014-03-21 14:25:57 +0000231 layer = window->layer();
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000232 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)58218062012-11-14 11:43:16 +0000246} // namespace ash