Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Side by Side Diff: ash/display/display_animator.cc

Issue 1594683002: Introduce DisplayConfigurationController (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@issue_576375_display1b1
Patch Set: Rebase Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ash/display/display_animator.h ('k') | ash/display/display_animator_chromeos.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 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/display/display_animator.h"
6
7 #include "ash/shell.h"
8 #include "ash/shell_window_ids.h"
9 #include "base/bind.h"
10 #include "base/stl_util.h"
11 #include "base/time/time.h"
12 #include "ui/aura/window.h"
13 #include "ui/aura/window_event_dispatcher.h"
14 #include "ui/compositor/layer.h"
15 #include "ui/compositor/layer_animation_observer.h"
16 #include "ui/compositor/layer_animation_sequence.h"
17 #include "ui/compositor/layer_animator.h"
18 #include "ui/compositor/scoped_layer_animation_settings.h"
19
20 namespace ash {
21 namespace {
22
23 const int kFadingAnimationDurationInMS = 200;
24 const int kFadingTimeoutDurationInSeconds = 10;
25
26 // CallbackRunningObserver accepts multiple layer animations and
27 // runs the specified |callback| when all of the animations have finished.
28 class CallbackRunningObserver {
29 public:
30 CallbackRunningObserver(base::Closure callback)
31 : completed_counter_(0), animation_aborted_(false), callback_(callback) {}
32
33 void AddNewAnimator(ui::LayerAnimator* animator) {
34 Observer* observer = new Observer(animator, this);
35 animator->AddObserver(observer);
36 observer_list_.push_back(observer);
37 }
38
39 private:
40 void OnSingleTaskCompleted() {
41 completed_counter_++;
42 if (completed_counter_ >= observer_list_.size()) {
43 base::MessageLoopForUI::current()->DeleteSoon(FROM_HERE, this);
44 if (!animation_aborted_)
45 base::MessageLoopForUI::current()->PostTask(FROM_HERE, callback_);
46 }
47 }
48
49 void OnSingleTaskAborted() {
50 animation_aborted_ = true;
51 OnSingleTaskCompleted();
52 }
53
54 // The actual observer to listen each animation completion.
55 class Observer : public ui::LayerAnimationObserver {
56 public:
57 Observer(ui::LayerAnimator* animator, CallbackRunningObserver* observer)
58 : animator_(animator), observer_(observer) {}
59
60 protected:
61 // ui::LayerAnimationObserver overrides:
62 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {
63 animator_->RemoveObserver(this);
64 observer_->OnSingleTaskCompleted();
65 }
66 void OnLayerAnimationAborted(
67 ui::LayerAnimationSequence* sequence) override {
68 animator_->RemoveObserver(this);
69 observer_->OnSingleTaskAborted();
70 }
71 void OnLayerAnimationScheduled(
72 ui::LayerAnimationSequence* sequence) override {}
73 bool RequiresNotificationWhenAnimatorDestroyed() const override {
74 return true;
75 }
76
77 private:
78 ui::LayerAnimator* animator_;
79 CallbackRunningObserver* observer_;
80
81 DISALLOW_COPY_AND_ASSIGN(Observer);
82 };
83
84 size_t completed_counter_;
85 bool animation_aborted_;
86 ScopedVector<Observer> observer_list_;
87 base::Closure callback_;
88
89 DISALLOW_COPY_AND_ASSIGN(CallbackRunningObserver);
90 };
91
92 } // namespace
93
94 DisplayAnimator::DisplayAnimator() : weak_ptr_factory_(this) {}
95
96 DisplayAnimator::~DisplayAnimator() {
97 ClearHidingLayers();
98 }
99
100 void DisplayAnimator::StartFadeOutAnimation(base::Closure callback) {
101 CallbackRunningObserver* observer = new CallbackRunningObserver(callback);
102 ClearHidingLayers();
103
104 // Make the fade-out animation for all root windows. Instead of actually
105 // hiding the root windows, we put a black layer over a root window for
106 // safety. These layers remain to hide root windows and will be deleted
107 // after the animation of OnDisplayModeChanged().
108 for (aura::Window* root_window : Shell::GetInstance()->GetAllRootWindows()) {
109 ui::Layer* hiding_layer = new ui::Layer(ui::LAYER_SOLID_COLOR);
110 hiding_layer->SetColor(SK_ColorBLACK);
111 hiding_layer->SetBounds(root_window->bounds());
112 ui::Layer* parent = ash::Shell::GetContainer(
113 root_window, ash::kShellWindowId_OverlayContainer)
114 ->layer();
115 parent->Add(hiding_layer);
116
117 hiding_layer->SetOpacity(0.0);
118
119 ui::ScopedLayerAnimationSettings settings(hiding_layer->GetAnimator());
120 settings.SetTransitionDuration(
121 base::TimeDelta::FromMilliseconds(kFadingAnimationDurationInMS));
122 observer->AddNewAnimator(hiding_layer->GetAnimator());
123 hiding_layer->SetOpacity(1.0f);
124 hiding_layer->SetVisible(true);
125 hiding_layers_[root_window] = hiding_layer;
126 }
127
128 // In case that OnDisplayModeChanged() isn't called or its animator is
129 // canceled due to some unknown errors, we set a timer to clear these
130 // hiding layers.
131 timer_.reset(new base::OneShotTimer());
132 timer_->Start(FROM_HERE,
133 base::TimeDelta::FromSeconds(kFadingTimeoutDurationInSeconds),
134 this, &DisplayAnimator::ClearHidingLayers);
135 }
136
137 void DisplayAnimator::StartFadeInAnimation() {
138 // We want to make sure clearing all of hiding layers after the animation
139 // finished. Note that this callback can be canceled, but the cancel only
140 // happens when the next animation is scheduled. Thus the hiding layers
141 // should be deleted eventually.
142 CallbackRunningObserver* observer = new CallbackRunningObserver(base::Bind(
143 &DisplayAnimator::ClearHidingLayers, weak_ptr_factory_.GetWeakPtr()));
144
145 // Ensure that layers are not animating.
146 for (std::map<aura::Window*, ui::Layer*>::value_type& e : hiding_layers_) {
147 ui::LayerAnimator* animator = e.second->GetAnimator();
148 if (animator->is_animating())
149 animator->StopAnimating();
150 }
151
152 // Schedules the fade-in effect for all root windows. Because we put the
153 // black layers for fade-out, here we actually turn those black layers
154 // invisible.
155 for (aura::Window* root_window : Shell::GetInstance()->GetAllRootWindows()) {
156 ui::Layer* hiding_layer = nullptr;
157 if (hiding_layers_.find(root_window) == hiding_layers_.end()) {
158 // In case of the transition from mirroring->non-mirroring, new root
159 // windows appear and we do not have the black layers for them. Thus
160 // we need to create the layer and make it visible.
161 hiding_layer = new ui::Layer(ui::LAYER_SOLID_COLOR);
162 hiding_layer->SetColor(SK_ColorBLACK);
163 hiding_layer->SetBounds(root_window->bounds());
164 ui::Layer* parent = ash::Shell::GetContainer(
165 root_window, ash::kShellWindowId_OverlayContainer)
166 ->layer();
167 parent->Add(hiding_layer);
168 hiding_layer->SetOpacity(1.0f);
169 hiding_layer->SetVisible(true);
170 hiding_layers_[root_window] = hiding_layer;
171 } else {
172 hiding_layer = hiding_layers_[root_window];
173 if (hiding_layer->bounds() != root_window->bounds())
174 hiding_layer->SetBounds(root_window->bounds());
175 }
176
177 ui::ScopedLayerAnimationSettings settings(hiding_layer->GetAnimator());
178 settings.SetTransitionDuration(
179 base::TimeDelta::FromMilliseconds(kFadingAnimationDurationInMS));
180 observer->AddNewAnimator(hiding_layer->GetAnimator());
181 hiding_layer->SetOpacity(0.0f);
182 hiding_layer->SetVisible(false);
183 }
184 }
185
186 void DisplayAnimator::OnDisplayModeChanged(
187 const ui::DisplayConfigurator::DisplayStateList& displays) {
188 if (!hiding_layers_.empty())
189 StartFadeInAnimation();
190 }
191
192 void DisplayAnimator::OnDisplayModeChangeFailed(
193 const ui::DisplayConfigurator::DisplayStateList& displays,
194 ui::MultipleDisplayState failed_new_state) {
195 if (!hiding_layers_.empty())
196 StartFadeInAnimation();
197 }
198
199 void DisplayAnimator::ClearHidingLayers() {
200 if (timer_) {
201 timer_->Stop();
202 timer_.reset();
203 }
204 STLDeleteContainerPairSecondPointers(hiding_layers_.begin(),
205 hiding_layers_.end());
206 hiding_layers_.clear();
207 }
208
209 } // namespace ash
OLDNEW
« no previous file with comments | « ash/display/display_animator.h ('k') | ash/display/display_animator_chromeos.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698