1 // Copyright 2018 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/overview/delayed_animation_observer_impl.h"
6 
7 #include <memory>
8 #include <utility>
9 #include <vector>
10 
11 #include "ash/test/ash_test_base.h"
12 #include "ash/wm/overview/overview_delegate.h"
13 #include "base/containers/unique_ptr_adapters.h"
14 #include "base/test/task_environment.h"
15 #include "ui/aura/window.h"
16 #include "ui/compositor/scoped_layer_animation_settings.h"
17 #include "ui/gfx/transform.h"
18 
19 namespace ash {
20 
21 namespace {
22 
23 class TestOverviewDelegate : public OverviewDelegate {
24  public:
25   TestOverviewDelegate() = default;
26 
27   ~TestOverviewDelegate() override = default;
28 
29   // OverviewDelegate:
AddExitAnimationObserver(std::unique_ptr<DelayedAnimationObserver> animation_observer)30   void AddExitAnimationObserver(
31       std::unique_ptr<DelayedAnimationObserver> animation_observer) override {
32     animation_observer->SetOwner(this);
33     exit_observers_.push_back(std::move(animation_observer));
34   }
RemoveAndDestroyExitAnimationObserver(DelayedAnimationObserver * animation_observer)35   void RemoveAndDestroyExitAnimationObserver(
36       DelayedAnimationObserver* animation_observer) override {
37     base::EraseIf(exit_observers_, base::MatchesUniquePtr(animation_observer));
38   }
AddEnterAnimationObserver(std::unique_ptr<DelayedAnimationObserver> animation_observer)39   void AddEnterAnimationObserver(
40       std::unique_ptr<DelayedAnimationObserver> animation_observer) override {
41     animation_observer->SetOwner(this);
42     enter_observers_.push_back(std::move(animation_observer));
43   }
RemoveAndDestroyEnterAnimationObserver(DelayedAnimationObserver * animation_observer)44   void RemoveAndDestroyEnterAnimationObserver(
45       DelayedAnimationObserver* animation_observer) override {
46     base::EraseIf(enter_observers_, base::MatchesUniquePtr(animation_observer));
47   }
48 
num_exit_observers() const49   size_t num_exit_observers() const { return exit_observers_.size(); }
num_enter_observers() const50   size_t num_enter_observers() const { return enter_observers_.size(); }
51 
52  private:
53   std::vector<std::unique_ptr<DelayedAnimationObserver>> exit_observers_;
54   std::vector<std::unique_ptr<DelayedAnimationObserver>> enter_observers_;
55 
56   DISALLOW_COPY_AND_ASSIGN(TestOverviewDelegate);
57 };
58 
59 }  // namespace
60 
61 class ForceDelayObserverTest : public AshTestBase {
62  public:
ForceDelayObserverTest()63   ForceDelayObserverTest()
64       : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
65   ~ForceDelayObserverTest() override = default;
66 
67  private:
68   DISALLOW_COPY_AND_ASSIGN(ForceDelayObserverTest);
69 };
70 
TEST_F(ForceDelayObserverTest,Basic)71 TEST_F(ForceDelayObserverTest, Basic) {
72   TestOverviewDelegate delegate;
73 
74   auto observer = std::make_unique<ForceDelayObserver>(
75       base::TimeDelta::FromMilliseconds(100));
76   delegate.AddEnterAnimationObserver(std::move(observer));
77   EXPECT_EQ(1u, delegate.num_enter_observers());
78 
79   task_environment()->FastForwardBy(base::TimeDelta::FromMilliseconds(50));
80   base::RunLoop().RunUntilIdle();
81   EXPECT_EQ(1u, delegate.num_enter_observers());
82   task_environment()->FastForwardBy(base::TimeDelta::FromMilliseconds(55));
83   base::RunLoop().RunUntilIdle();
84   EXPECT_EQ(0u, delegate.num_enter_observers());
85 }
86 
87 using EnterAnimationObserverTest = AshTestBase;
88 
89 // Tests that adding a EnterAnimationObserver works as intended.
TEST_F(EnterAnimationObserverTest,Basic)90 TEST_F(EnterAnimationObserverTest, Basic) {
91   TestOverviewDelegate delegate;
92   std::unique_ptr<aura::Window> window = CreateTestWindow();
93 
94   {
95     ui::ScopedLayerAnimationSettings animation_settings(
96         window->layer()->GetAnimator());
97     animation_settings.SetTransitionDuration(
98         base::TimeDelta::FromMilliseconds(1000));
99     animation_settings.SetPreemptionStrategy(
100         ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
101 
102     auto observer = std::make_unique<EnterAnimationObserver>();
103     animation_settings.AddObserver(observer.get());
104     delegate.AddEnterAnimationObserver(std::move(observer));
105     window->SetTransform(gfx::Transform(1.f, 0.f, 0.f, 1.f, 100.f, 0.f));
106     EXPECT_EQ(0u, delegate.num_exit_observers());
107     EXPECT_EQ(1u, delegate.num_enter_observers());
108   }
109 
110   // Tests that when done animating, the observer count is zero.
111   window->layer()->GetAnimator()->StopAnimating();
112   EXPECT_EQ(0u, delegate.num_enter_observers());
113 }
114 
115 using ExitAnimationObserverTest = AshTestBase;
116 
117 // Tests that adding a ExitAnimationObserver works as intended.
TEST_F(ExitAnimationObserverTest,Basic)118 TEST_F(ExitAnimationObserverTest, Basic) {
119   TestOverviewDelegate delegate;
120   std::unique_ptr<aura::Window> window = CreateTestWindow();
121 
122   {
123     ui::ScopedLayerAnimationSettings animation_settings(
124         window->layer()->GetAnimator());
125     animation_settings.SetTransitionDuration(
126         base::TimeDelta::FromMilliseconds(1000));
127     animation_settings.SetPreemptionStrategy(
128         ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
129 
130     auto observer = std::make_unique<ExitAnimationObserver>();
131     animation_settings.AddObserver(observer.get());
132     delegate.AddExitAnimationObserver(std::move(observer));
133     window->SetTransform(gfx::Transform(1.f, 0.f, 0.f, 1.f, 100.f, 0.f));
134     EXPECT_EQ(1u, delegate.num_exit_observers());
135     EXPECT_EQ(0u, delegate.num_enter_observers());
136   }
137 
138   // Tests that when done animating, the observer count is zero.
139   window->layer()->GetAnimator()->StopAnimating();
140   EXPECT_EQ(0u, delegate.num_exit_observers());
141 }
142 
143 }  // namespace ash
144