• 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 #include "ui/gfx/animation/animation_container_element.h"
20 
21 using aura::Window;
22 using ui::Layer;
23 
24 namespace ash {
25 namespace internal {
26 
27 class WindowAnimationsTest : public ash::test::AshTestBase {
28  public:
WindowAnimationsTest()29   WindowAnimationsTest() {}
30 
TearDown()31   virtual void TearDown() OVERRIDE {
32     AshTestBase::TearDown();
33   }
34 
35  private:
36   DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest);
37 };
38 
39 // Listens to animation scheduled notifications. Remembers the transition
40 // duration of the first sequence.
41 class MinimizeAnimationObserver : public ui::LayerAnimationObserver {
42  public:
MinimizeAnimationObserver(ui::LayerAnimator * animator)43   explicit MinimizeAnimationObserver(ui::LayerAnimator* animator)
44       : animator_(animator) {
45     animator_->AddObserver(this);
46     // RemoveObserver is called when the first animation is scheduled and so
47     // there should be no need for now to remove it in destructor.
48   };
duration()49   base::TimeDelta duration() { return duration_; }
50 
51  protected:
52   // ui::LayerAnimationObserver:
OnLayerAnimationScheduled(ui::LayerAnimationSequence * sequence)53   virtual void OnLayerAnimationScheduled(
54       ui::LayerAnimationSequence* sequence) OVERRIDE {
55     duration_ = animator_->GetTransitionDuration();
56     animator_->RemoveObserver(this);
57   }
OnLayerAnimationEnded(ui::LayerAnimationSequence * sequence)58   virtual void OnLayerAnimationEnded(
59       ui::LayerAnimationSequence* sequence) OVERRIDE {}
OnLayerAnimationAborted(ui::LayerAnimationSequence * sequence)60   virtual void OnLayerAnimationAborted(
61       ui::LayerAnimationSequence* sequence) OVERRIDE {}
62 
63  private:
64   ui::LayerAnimator* animator_;
65   base::TimeDelta duration_;
66 
67   DISALLOW_COPY_AND_ASSIGN(MinimizeAnimationObserver);
68 };
69 
TEST_F(WindowAnimationsTest,HideShowBrightnessGrayscaleAnimation)70 TEST_F(WindowAnimationsTest, HideShowBrightnessGrayscaleAnimation) {
71   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
72   window->Show();
73   EXPECT_TRUE(window->layer()->visible());
74 
75   // Hiding.
76   views::corewm::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   views::corewm::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   gfx::AnimationContainerElement* element =
95       static_cast<gfx::AnimationContainerElement*>(
96       window->layer()->GetAnimator());
97   element->Step(base::TimeTicks::Now() +
98                 base::TimeDelta::FromSeconds(5));
99   EXPECT_EQ(0.0f, window->layer()->GetTargetBrightness());
100   EXPECT_EQ(0.0f, window->layer()->GetTargetGrayscale());
101   EXPECT_TRUE(window->layer()->visible());
102 }
103 
TEST_F(WindowAnimationsTest,LayerTargetVisibility)104 TEST_F(WindowAnimationsTest, LayerTargetVisibility) {
105   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
106 
107   // Layer target visibility changes according to Show/Hide.
108   window->Show();
109   EXPECT_TRUE(window->layer()->GetTargetVisibility());
110   window->Hide();
111   EXPECT_FALSE(window->layer()->GetTargetVisibility());
112   window->Show();
113   EXPECT_TRUE(window->layer()->GetTargetVisibility());
114 }
115 
TEST_F(WindowAnimationsTest,CrossFadeToBounds)116 TEST_F(WindowAnimationsTest, CrossFadeToBounds) {
117   ui::ScopedAnimationDurationScaleMode normal_duration_mode(
118       ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
119 
120   scoped_ptr<Window> window(CreateTestWindowInShellWithId(0));
121   window->SetBounds(gfx::Rect(5, 10, 320, 240));
122   window->Show();
123 
124   Layer* old_layer = window->layer();
125   EXPECT_EQ(1.0f, old_layer->GetTargetOpacity());
126 
127   // Cross fade to a larger size, as in a maximize animation.
128   CrossFadeToBounds(window.get(), 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   static_cast<gfx::AnimationContainerElement*>(old_layer->GetAnimator())->Step(
144       base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1));
145   static_cast<gfx::AnimationContainerElement*>(window->layer()->GetAnimator())->
146       Step(base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1));
147 
148   // Cross fade to a smaller size, as in a restore animation.
149   old_layer = window->layer();
150   CrossFadeToBounds(window.get(), gfx::Rect(5, 10, 320, 240));
151   // Again, window layer has been replaced.
152   EXPECT_NE(old_layer, window->layer());
153   // Original layer fades out and stretches down to new size.
154   EXPECT_EQ(0.0f, old_layer->GetTargetOpacity());
155   EXPECT_EQ("0,0 640x480", old_layer->bounds().ToString());
156   gfx::Transform shrink_transform;
157   shrink_transform.Translate(5.f, 10.f);
158   shrink_transform.Scale(320.f / 640.f, 240.f / 480.f);
159   EXPECT_EQ(shrink_transform, old_layer->GetTargetTransform());
160   // New layer animates in to the identity transform.
161   EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity());
162   EXPECT_EQ(gfx::Transform(), window->layer()->GetTargetTransform());
163 
164   static_cast<gfx::AnimationContainerElement*>(old_layer->GetAnimator())->Step(
165       base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1));
166   static_cast<gfx::AnimationContainerElement*>(window->layer()->GetAnimator())->
167       Step(base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1));
168 }
169 
TEST_F(WindowAnimationsTest,LockAnimationDuration)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   {
200     ui::ScopedLayerAnimationSettings settings1(layer->GetAnimator());
201     settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000));
202     // Duration is locked in outer scope.
203     settings1.LockTransitionDuration();
204     {
205       ui::ScopedLayerAnimationSettings settings2(layer->GetAnimator());
206       // Transition duration setting is ignored.
207       settings2.SetTransitionDuration(base::TimeDelta::FromMilliseconds(50));
208       wm::GetWindowState(window.get())->Minimize();
209       EXPECT_TRUE(layer->GetAnimator()->is_animating());
210       // Expect duration from the outer scope
211       EXPECT_EQ(1000,
212                 layer->GetAnimator()->GetTransitionDuration().InMilliseconds());
213     }
214     window->Show();
215     layer->GetAnimator()->StopAnimating();
216   }
217 
218   // Test that duration respects default.
219   {
220     // Query default duration.
221     MinimizeAnimationObserver observer(layer->GetAnimator());
222     wm::GetWindowState(window.get())->Minimize();
223     EXPECT_TRUE(layer->GetAnimator()->is_animating());
224     base::TimeDelta default_duration(observer.duration());
225     window->Show();
226     layer->GetAnimator()->StopAnimating();
227 
228     ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
229     settings.LockTransitionDuration();
230     // Setting transition duration is ignored since duration is locked
231     settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000));
232     wm::GetWindowState(window.get())->Minimize();
233     EXPECT_TRUE(layer->GetAnimator()->is_animating());
234     // Expect default duration (200ms for stock ash minimizing animation).
235     EXPECT_EQ(default_duration.InMilliseconds(),
236               layer->GetAnimator()->GetTransitionDuration().InMilliseconds());
237     window->Show();
238     layer->GetAnimator()->StopAnimating();
239   }
240 }
241 
242 }  // namespace internal
243 }  // namespace ash
244