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