15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_animations.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell_window_ids.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/test/ash_test_base.h"
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ash/wm/window_state.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/workspace_controller.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/test/test_windows.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/compositor/layer_animation_observer.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer_animator.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/scoped_animation_duration_scale_mode.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using aura::Window;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ui::Layer;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WindowAnimationsTest : public ash::test::AshTestBase {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowAnimationsTest() {}
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AshTestBase::TearDown();
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Listens to animation scheduled notifications. Remembers the transition
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// duration of the first sequence.
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MinimizeAnimationObserver : public ui::LayerAnimationObserver {
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  explicit MinimizeAnimationObserver(ui::LayerAnimator* animator)
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : animator_(animator) {
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    animator_->AddObserver(this);
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // RemoveObserver is called when the first animation is scheduled and so
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // there should be no need for now to remove it in destructor.
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  };
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::TimeDelta duration() { return duration_; }
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) protected:
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // ui::LayerAnimationObserver:
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnLayerAnimationScheduled(
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ui::LayerAnimationSequence* sequence) OVERRIDE {
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    duration_ = animator_->GetTransitionDuration();
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    animator_->RemoveObserver(this);
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnLayerAnimationEnded(
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ui::LayerAnimationSequence* sequence) OVERRIDE {}
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void OnLayerAnimationAborted(
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ui::LayerAnimationSequence* sequence) OVERRIDE {}
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ui::LayerAnimator* animator_;
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::TimeDelta duration_;
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MinimizeAnimationObserver);
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(WindowAnimationsTest, HideShowBrightnessGrayscaleAnimation) {
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::ScopedAnimationDurationScaleMode test_duration_mode(
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->Show();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window->layer()->visible());
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Hiding.
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ::wm::SetWindowVisibilityAnimationType(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window.get(),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AnimateOnChildWindowVisibilityChanged(window.get(), false);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0.0f, window->layer()->GetTargetOpacity());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(window->layer()->GetTargetVisibility());
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(window->layer()->visible());
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Showing.
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ::wm::SetWindowVisibilityAnimationType(
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window.get(),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AnimateOnChildWindowVisibilityChanged(window.get(), true);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0.0f, window->layer()->GetTargetBrightness());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0.0f, window->layer()->GetTargetGrayscale());
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window->layer()->visible());
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stays shown.
9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  window->layer()->GetAnimator()->Step(base::TimeTicks::Now() +
9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                       base::TimeDelta::FromSeconds(5));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0.0f, window->layer()->GetTargetBrightness());
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0.0f, window->layer()->GetTargetGrayscale());
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window->layer()->visible());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(WindowAnimationsTest, LayerTargetVisibility) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Layer target visibility changes according to Show/Hide.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->Show();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window->layer()->GetTargetVisibility());
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->Hide();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(window->layer()->GetTargetVisibility());
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->Show();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(window->layer()->GetTargetVisibility());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace wm {
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(WindowAnimationsTest, CrossFadeToBounds) {
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::ScopedAnimationDurationScaleMode test_duration_mode(
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Window> window(CreateTestWindowInShellWithId(0));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->SetBounds(gfx::Rect(5, 10, 320, 240));
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->Show();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Layer* old_layer = window->layer();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, old_layer->GetTargetOpacity());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cross fade to a larger size, as in a maximize animation.
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GetWindowState(window.get())->SetBoundsDirectCrossFade(
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      gfx::Rect(0, 0, 640, 480));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Window's layer has been replaced.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(old_layer, window->layer());
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Original layer stays opaque and stretches to new size.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, old_layer->GetTargetOpacity());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("5,10 320x240", old_layer->bounds().ToString());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform grow_transform;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grow_transform.Translate(-5.f, -10.f);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grow_transform.Scale(640.f / 320.f, 480.f / 240.f);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(grow_transform, old_layer->GetTargetTransform());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // New layer animates in to the identity transform.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity());
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(gfx::Transform(), window->layer()->GetTargetTransform());
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run the animations to completion.
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  old_layer->GetAnimator()->Step(base::TimeTicks::Now() +
14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 base::TimeDelta::FromSeconds(1));
14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  window->layer()->GetAnimator()->Step(base::TimeTicks::Now() +
14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                       base::TimeDelta::FromSeconds(1));
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cross fade to a smaller size, as in a restore animation.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  old_layer = window->layer();
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GetWindowState(window.get())->SetBoundsDirectCrossFade(
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      gfx::Rect(5, 10, 320, 240));
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Again, window layer has been replaced.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(old_layer, window->layer());
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Original layer fades out and stretches down to new size.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0.0f, old_layer->GetTargetOpacity());
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("0,0 640x480", old_layer->bounds().ToString());
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform shrink_transform;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  shrink_transform.Translate(5.f, 10.f);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  shrink_transform.Scale(320.f / 640.f, 240.f / 480.f);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(shrink_transform, old_layer->GetTargetTransform());
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // New layer animates in to the identity transform.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(gfx::Transform(), window->layer()->GetTargetTransform());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  old_layer->GetAnimator()->Step(base::TimeTicks::Now() +
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 base::TimeDelta::FromSeconds(1));
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  window->layer()->GetAnimator()->Step(base::TimeTicks::Now() +
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                       base::TimeDelta::FromSeconds(1));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace wm
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(WindowAnimationsTest, LockAnimationDuration) {
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::ScopedAnimationDurationScaleMode test_duration_mode(
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<Window> window(CreateTestWindowInShellWithId(0));
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Layer* layer = window->layer();
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  window->SetBounds(gfx::Rect(5, 10, 320, 240));
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  window->Show();
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Test that it is possible to override transition duration when it is not
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // locked.
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  {
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ui::ScopedLayerAnimationSettings settings1(layer->GetAnimator());
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000));
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    {
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ui::ScopedLayerAnimationSettings settings2(layer->GetAnimator());
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // Duration is not locked so it gets overridden.
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      settings2.SetTransitionDuration(base::TimeDelta::FromMilliseconds(50));
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      wm::GetWindowState(window.get())->Minimize();
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      EXPECT_TRUE(layer->GetAnimator()->is_animating());
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // Expect duration from the inner scope
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      EXPECT_EQ(50,
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                layer->GetAnimator()->GetTransitionDuration().InMilliseconds());
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    window->Show();
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    layer->GetAnimator()->StopAnimating();
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Test that it is possible to lock transition duration
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  {
20323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // Update layer as minimizing will replace the window's layer.
20423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    layer = window->layer();
205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ui::ScopedLayerAnimationSettings settings1(layer->GetAnimator());
206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000));
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Duration is locked in outer scope.
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    settings1.LockTransitionDuration();
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    {
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ui::ScopedLayerAnimationSettings settings2(layer->GetAnimator());
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // Transition duration setting is ignored.
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      settings2.SetTransitionDuration(base::TimeDelta::FromMilliseconds(50));
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      wm::GetWindowState(window.get())->Minimize();
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      EXPECT_TRUE(layer->GetAnimator()->is_animating());
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // Expect duration from the outer scope
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      EXPECT_EQ(1000,
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                layer->GetAnimator()->GetTransitionDuration().InMilliseconds());
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    window->Show();
220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    layer->GetAnimator()->StopAnimating();
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Test that duration respects default.
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  {
22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    layer = window->layer();
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Query default duration.
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    MinimizeAnimationObserver observer(layer->GetAnimator());
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    wm::GetWindowState(window.get())->Minimize();
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    EXPECT_TRUE(layer->GetAnimator()->is_animating());
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::TimeDelta default_duration(observer.duration());
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    window->Show();
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    layer->GetAnimator()->StopAnimating();
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    layer = window->layer();
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    settings.LockTransitionDuration();
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Setting transition duration is ignored since duration is locked
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000));
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    wm::GetWindowState(window.get())->Minimize();
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    EXPECT_TRUE(layer->GetAnimator()->is_animating());
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Expect default duration (200ms for stock ash minimizing animation).
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    EXPECT_EQ(default_duration.InMilliseconds(),
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              layer->GetAnimator()->GetTransitionDuration().InMilliseconds());
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    window->Show();
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    layer->GetAnimator()->StopAnimating();
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
250