Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / wm / core / window_animations_unittest.cc
blobef642c00b71cd9a43bfe69046c1701ff11870e0a
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.
5 #include "ui/wm/core/window_animations.h"
7 #include "base/time/time.h"
8 #include "ui/aura/test/aura_test_base.h"
9 #include "ui/aura/test/test_windows.h"
10 #include "ui/aura/window.h"
11 #include "ui/compositor/layer.h"
12 #include "ui/compositor/layer_animator.h"
13 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
14 #include "ui/gfx/animation/animation_container_element.h"
15 #include "ui/gfx/geometry/vector2d.h"
16 #include "ui/wm/core/transient_window_manager.h"
17 #include "ui/wm/core/transient_window_stacking_client.h"
18 #include "ui/wm/core/window_util.h"
19 #include "ui/wm/public/animation_host.h"
21 using aura::Window;
22 using ui::Layer;
24 namespace wm {
25 namespace {
27 template<typename T>int GetZPosition(const T* child) {
28 const T* parent = child->parent();
29 const std::vector<T*> children = parent->children();
30 typename std::vector<T*>::const_iterator iter =
31 std::find(children.begin(), children.end(), child);
32 DCHECK(iter != children.end());
33 return iter - children.begin();
36 int GetWindowZPosition(const aura::Window* child) {
37 return GetZPosition<aura::Window>(child);
40 int GetLayerZPosition(const ui::Layer* child) {
41 return GetZPosition<ui::Layer>(child);
44 } // namespace
46 class WindowAnimationsTest : public aura::test::AuraTestBase {
47 public:
48 WindowAnimationsTest() {}
50 void TearDown() override { AuraTestBase::TearDown(); }
52 private:
53 DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest);
56 TEST_F(WindowAnimationsTest, LayerTargetVisibility) {
57 scoped_ptr<aura::Window> window(
58 aura::test::CreateTestWindowWithId(0, NULL));
60 // Layer target visibility changes according to Show/Hide.
61 window->Show();
62 EXPECT_TRUE(window->layer()->GetTargetVisibility());
63 window->Hide();
64 EXPECT_FALSE(window->layer()->GetTargetVisibility());
65 window->Show();
66 EXPECT_TRUE(window->layer()->GetTargetVisibility());
69 TEST_F(WindowAnimationsTest, LayerTargetVisibility_AnimateShow) {
70 // Tests if opacity and transform are reset when only show animation is
71 // enabled. See also LayerTargetVisibility_AnimateHide.
72 // Since the window is not visible after Hide() is called, opacity and
73 // transform shouldn't matter in case of ANIMATE_SHOW, but we reset them
74 // to keep consistency.
76 scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL));
77 SetWindowVisibilityAnimationTransition(window.get(), ANIMATE_SHOW);
79 // Layer target visibility and opacity change according to Show/Hide.
80 window->Show();
81 AnimateOnChildWindowVisibilityChanged(window.get(), true);
82 EXPECT_TRUE(window->layer()->GetTargetVisibility());
83 EXPECT_EQ(1, window->layer()->opacity());
85 window->Hide();
86 AnimateOnChildWindowVisibilityChanged(window.get(), false);
87 EXPECT_FALSE(window->layer()->GetTargetVisibility());
88 EXPECT_EQ(0, window->layer()->opacity());
89 EXPECT_EQ(gfx::Transform(), window->layer()->transform());
91 window->Show();
92 AnimateOnChildWindowVisibilityChanged(window.get(), true);
93 EXPECT_TRUE(window->layer()->GetTargetVisibility());
94 EXPECT_EQ(1, window->layer()->opacity());
97 TEST_F(WindowAnimationsTest, LayerTargetVisibility_AnimateHide) {
98 // Tests if opacity and transform are reset when only hide animation is
99 // enabled. Hide animation changes opacity and transform in addition to
100 // visibility, so we need to reset not only visibility but also opacity
101 // and transform to show the window.
103 scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL));
104 SetWindowVisibilityAnimationTransition(window.get(), ANIMATE_HIDE);
106 // Layer target visibility and opacity change according to Show/Hide.
107 window->Show();
108 AnimateOnChildWindowVisibilityChanged(window.get(), true);
109 EXPECT_TRUE(window->layer()->GetTargetVisibility());
110 EXPECT_EQ(1, window->layer()->opacity());
111 EXPECT_EQ(gfx::Transform(), window->layer()->transform());
113 window->Hide();
114 AnimateOnChildWindowVisibilityChanged(window.get(), false);
115 EXPECT_FALSE(window->layer()->GetTargetVisibility());
116 EXPECT_EQ(0, window->layer()->opacity());
118 window->Show();
119 AnimateOnChildWindowVisibilityChanged(window.get(), true);
120 EXPECT_TRUE(window->layer()->GetTargetVisibility());
121 EXPECT_EQ(1, window->layer()->opacity());
122 EXPECT_EQ(gfx::Transform(), window->layer()->transform());
125 TEST_F(WindowAnimationsTest, HideAnimationDetachLayers) {
126 scoped_ptr<aura::Window> parent(aura::test::CreateTestWindowWithId(0, NULL));
128 scoped_ptr<aura::Window> other(
129 aura::test::CreateTestWindowWithId(1, parent.get()));
131 scoped_ptr<aura::Window> animating_window(
132 aura::test::CreateTestWindowWithId(2, parent.get()));
133 SetWindowVisibilityAnimationTransition(animating_window.get(), ANIMATE_HIDE);
135 EXPECT_EQ(0, GetWindowZPosition(other.get()));
136 EXPECT_EQ(1, GetWindowZPosition(animating_window.get()));
137 EXPECT_EQ(0, GetLayerZPosition(other->layer()));
138 EXPECT_EQ(1, GetLayerZPosition(animating_window->layer()));
141 ui::ScopedAnimationDurationScaleMode scale_mode(
142 ui::ScopedAnimationDurationScaleMode::FAST_DURATION);
143 ui::Layer* animating_layer = animating_window->layer();
145 animating_window->Hide();
146 EXPECT_TRUE(AnimateOnChildWindowVisibilityChanged(
147 animating_window.get(), false));
148 EXPECT_TRUE(animating_layer->GetAnimator()->is_animating());
149 EXPECT_FALSE(animating_layer->delegate());
151 // Make sure the Hide animation create another layer, and both are in
152 // the parent layer.
153 EXPECT_NE(animating_window->layer(), animating_layer);
154 EXPECT_TRUE(
155 std::find(parent->layer()->children().begin(),
156 parent->layer()->children().end(),
157 animating_layer) !=
158 parent->layer()->children().end());
159 EXPECT_TRUE(
160 std::find(parent->layer()->children().begin(),
161 parent->layer()->children().end(),
162 animating_window->layer()) !=
163 parent->layer()->children().end());
164 // Current layer must be already hidden.
165 EXPECT_FALSE(animating_window->layer()->visible());
167 EXPECT_EQ(1, GetWindowZPosition(animating_window.get()));
168 EXPECT_EQ(1, GetLayerZPosition(animating_window->layer()));
169 EXPECT_EQ(2, GetLayerZPosition(animating_layer));
171 parent->StackChildAtTop(other.get());
172 EXPECT_EQ(0, GetWindowZPosition(animating_window.get()));
173 EXPECT_EQ(1, GetWindowZPosition(other.get()));
175 EXPECT_EQ(0, GetLayerZPosition(animating_window->layer()));
176 EXPECT_EQ(1, GetLayerZPosition(other->layer()));
177 // Make sure the animating layer is on top.
178 EXPECT_EQ(2, GetLayerZPosition(animating_layer));
180 // Animating layer must be gone
181 animating_layer->GetAnimator()->StopAnimating();
182 EXPECT_TRUE(
183 std::find(parent->layer()->children().begin(),
184 parent->layer()->children().end(),
185 animating_layer) ==
186 parent->layer()->children().end());
190 TEST_F(WindowAnimationsTest, HideAnimationDetachLayersWithTransientChildren) {
191 TransientWindowStackingClient transient_stacking_client;
193 scoped_ptr<aura::Window> parent(aura::test::CreateTestWindowWithId(0, NULL));
195 scoped_ptr<aura::Window> other(
196 aura::test::CreateTestWindowWithId(1, parent.get()));
198 scoped_ptr<aura::Window> animating_window(
199 aura::test::CreateTestWindowWithId(2, parent.get()));
200 SetWindowVisibilityAnimationTransition(animating_window.get(), ANIMATE_HIDE);
202 scoped_ptr<aura::Window> transient1(
203 aura::test::CreateTestWindowWithId(3, parent.get()));
204 scoped_ptr<aura::Window> transient2(
205 aura::test::CreateTestWindowWithId(4, parent.get()));
207 TransientWindowManager::Get(animating_window.get());
208 AddTransientChild(animating_window.get(), transient1.get());
209 AddTransientChild(animating_window.get(), transient2.get());
211 EXPECT_EQ(0, GetWindowZPosition(other.get()));
212 EXPECT_EQ(1, GetWindowZPosition(animating_window.get()));
213 EXPECT_EQ(2, GetWindowZPosition(transient1.get()));
214 EXPECT_EQ(3, GetWindowZPosition(transient2.get()));
217 ui::ScopedAnimationDurationScaleMode scale_mode(
218 ui::ScopedAnimationDurationScaleMode::FAST_DURATION);
219 ui::Layer* animating_layer = animating_window->layer();
221 animating_window->Hide();
222 EXPECT_TRUE(AnimateOnChildWindowVisibilityChanged(
223 animating_window.get(), false));
224 EXPECT_TRUE(animating_layer->GetAnimator()->is_animating());
225 EXPECT_FALSE(animating_layer->delegate());
227 EXPECT_EQ(1, GetWindowZPosition(animating_window.get()));
228 EXPECT_EQ(2, GetWindowZPosition(transient1.get()));
229 EXPECT_EQ(3, GetWindowZPosition(transient2.get()));
231 EXPECT_EQ(1, GetLayerZPosition(animating_window->layer()));
232 EXPECT_EQ(2, GetLayerZPosition(transient1->layer()));
233 EXPECT_EQ(3, GetLayerZPosition(transient2->layer()));
234 EXPECT_EQ(4, GetLayerZPosition(animating_layer));
236 parent->StackChildAtTop(other.get());
238 EXPECT_EQ(0, GetWindowZPosition(animating_window.get()));
239 EXPECT_EQ(1, GetWindowZPosition(transient1.get()));
240 EXPECT_EQ(2, GetWindowZPosition(transient2.get()));
241 EXPECT_EQ(3, GetWindowZPosition(other.get()));
243 EXPECT_EQ(0, GetLayerZPosition(animating_window->layer()));
244 EXPECT_EQ(1, GetLayerZPosition(transient1->layer()));
245 EXPECT_EQ(2, GetLayerZPosition(transient2->layer()));
246 EXPECT_EQ(3, GetLayerZPosition(other->layer()));
247 // Make sure the animating layer is on top of all windows.
248 EXPECT_EQ(4, GetLayerZPosition(animating_layer));
252 // A simple AnimationHost implementation for the NotifyHideCompleted test.
253 class NotifyHideCompletedAnimationHost : public aura::client::AnimationHost {
254 public:
255 NotifyHideCompletedAnimationHost() : hide_completed_(false) {}
256 ~NotifyHideCompletedAnimationHost() override {}
258 // Overridden from TestWindowDelegate:
259 void OnWindowHidingAnimationCompleted() override { hide_completed_ = true; }
261 void SetHostTransitionOffsets(const gfx::Vector2d& top_left,
262 const gfx::Vector2d& bottom_right) override {}
264 bool hide_completed() const { return hide_completed_; }
266 private:
267 bool hide_completed_;
269 DISALLOW_COPY_AND_ASSIGN(NotifyHideCompletedAnimationHost);
272 TEST_F(WindowAnimationsTest, NotifyHideCompleted) {
273 NotifyHideCompletedAnimationHost animation_host;
274 scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL));
275 aura::client::SetAnimationHost(window.get(), &animation_host);
276 wm::SetWindowVisibilityAnimationType(
277 window.get(), WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
278 AnimateOnChildWindowVisibilityChanged(window.get(), true);
279 EXPECT_TRUE(window->layer()->visible());
281 EXPECT_FALSE(animation_host.hide_completed());
282 AnimateOnChildWindowVisibilityChanged(window.get(), false);
283 EXPECT_TRUE(animation_host.hide_completed());
286 // The rotation animation for hiding a window should not leak the animation
287 // observer.
288 TEST_F(WindowAnimationsTest, RotateHideNoLeak) {
289 ui::ScopedAnimationDurationScaleMode scale_mode(
290 ui::ScopedAnimationDurationScaleMode::FAST_DURATION);
292 scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL));
293 ui::Layer* animating_layer = window->layer();
294 wm::SetWindowVisibilityAnimationType(window.get(),
295 WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE);
297 AnimateOnChildWindowVisibilityChanged(window.get(), true);
298 AnimateOnChildWindowVisibilityChanged(window.get(), false);
300 animating_layer->GetAnimator()->StopAnimating();
303 // The rotation animation for hiding a window should not crash when terminated
304 // by LayerAnimator::StopAnimating().
305 TEST_F(WindowAnimationsTest, RotateHideNoCrash) {
306 ui::ScopedAnimationDurationScaleMode scale_mode(
307 ui::ScopedAnimationDurationScaleMode::FAST_DURATION);
309 scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL));
310 ui::Layer* animating_layer = window->layer();
311 wm::SetWindowVisibilityAnimationType(window.get(),
312 WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE);
313 AnimateOnChildWindowVisibilityChanged(window.get(), true);
314 window->layer()->GetAnimator()->Step(base::TimeTicks::Now() +
315 base::TimeDelta::FromSeconds(5));
316 AnimateOnChildWindowVisibilityChanged(window.get(), false);
317 animating_layer->GetAnimator()->StopAnimating();
320 } // namespace wm