blob: 9900275af8a0bf2032bf10661ecf48fdc58c6add [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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/session_state_animator.h"
6
7#include "ash/shell.h"
8#include "ash/shell_window_ids.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00009#include "ash/wm/window_animations.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010#include "ui/aura/client/aura_constants.h"
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000011#include "ui/aura/window_event_dispatcher.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000012#include "ui/compositor/layer_animation_observer.h"
13#include "ui/compositor/layer_animation_sequence.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000014#include "ui/compositor/scoped_layer_animation_settings.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000015#include "ui/views/widget/widget.h"
16
17namespace ash {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000018namespace {
19
Torne (Richard Coles)58218062012-11-14 11:43:16 +000020// Slightly-smaller size that we scale the screen down to for the pre-lock and
21// pre-shutdown states.
22const float kSlowCloseSizeRatio = 0.95f;
23
24// Maximum opacity of white layer when animating pre-shutdown state.
25const float kPartialFadeRatio = 0.3f;
26
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000027// Minimum size. Not zero as it causes numeric issues.
28const float kMinimumScale = 1e-4f;
29
Torne (Richard Coles)58218062012-11-14 11:43:16 +000030// Returns the transform that should be applied to containers for the slow-close
31// animation.
32gfx::Transform GetSlowCloseTransform() {
33 gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size();
34 gfx::Transform transform;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000035 transform.Translate(
Torne (Richard Coles)58218062012-11-14 11:43:16 +000036 floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.width() + 0.5),
37 floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.height() + 0.5));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000038 transform.Scale(kSlowCloseSizeRatio, kSlowCloseSizeRatio);
39 return transform;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000040}
41
42// Returns the transform that should be applied to containers for the fast-close
43// animation.
44gfx::Transform GetFastCloseTransform() {
45 gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size();
46 gfx::Transform transform;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000047 transform.Translate(floor(0.5 * root_size.width() + 0.5),
48 floor(0.5 * root_size.height() + 0.5));
49 transform.Scale(kMinimumScale, kMinimumScale);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000050 return transform;
51}
52
53// Slowly shrinks |window| to a slightly-smaller size.
54void StartSlowCloseAnimationForWindow(aura::Window* window,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000055 base::TimeDelta duration,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000056 ui::LayerAnimationObserver* observer) {
57 ui::LayerAnimator* animator = window->layer()->GetAnimator();
58 animator->set_preemption_strategy(
59 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
60 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
61 ui::LayerAnimationElement::CreateTransformElement(
62 GetSlowCloseTransform(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000063 duration));
Torne (Richard Coles)58218062012-11-14 11:43:16 +000064 if (observer)
65 sequence->AddObserver(observer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000066 animator->StartAnimation(sequence);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000067}
68
69// Quickly undoes the effects of the slow-close animation on |window|.
70void StartUndoSlowCloseAnimationForWindow(
71 aura::Window* window,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000072 base::TimeDelta duration,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000073 ui::LayerAnimationObserver* observer) {
74 ui::LayerAnimator* animator = window->layer()->GetAnimator();
75 animator->set_preemption_strategy(
76 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
77 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
78 ui::LayerAnimationElement::CreateTransformElement(
79 gfx::Transform(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000080 duration));
Torne (Richard Coles)58218062012-11-14 11:43:16 +000081 if (observer)
82 sequence->AddObserver(observer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000083 animator->StartAnimation(sequence);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000084}
85
86// Quickly shrinks |window| down to a point in the center of the screen and
87// fades it out to 0 opacity.
88void StartFastCloseAnimationForWindow(aura::Window* window,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000089 base::TimeDelta duration,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000090 ui::LayerAnimationObserver* observer) {
91 ui::LayerAnimator* animator = window->layer()->GetAnimator();
92 animator->set_preemption_strategy(
93 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
94 animator->StartAnimation(
95 new ui::LayerAnimationSequence(
96 ui::LayerAnimationElement::CreateTransformElement(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000097 GetFastCloseTransform(), duration)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +000098 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000099 ui::LayerAnimationElement::CreateOpacityElement(0.0, duration));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000100 if (observer)
101 sequence->AddObserver(observer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000102 animator->StartAnimation(sequence);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000103}
104
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000105// Fades |window| to |target_opacity| over |duration|.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000106void StartPartialFadeAnimation(aura::Window* window,
107 float target_opacity,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000108 base::TimeDelta duration,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000109 ui::LayerAnimationObserver* observer) {
110 ui::LayerAnimator* animator = window->layer()->GetAnimator();
111 animator->set_preemption_strategy(
112 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
113 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
114 ui::LayerAnimationElement::CreateOpacityElement(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000115 target_opacity, duration));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000116 if (observer)
117 sequence->AddObserver(observer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000118 animator->StartAnimation(sequence);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000119}
120
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000121// Fades |window| to |opacity| over |duration|.
122void StartOpacityAnimationForWindow(aura::Window* window,
123 float opacity,
124 base::TimeDelta duration,
125 ui::LayerAnimationObserver* observer) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000126 ui::LayerAnimator* animator = window->layer()->GetAnimator();
127 animator->set_preemption_strategy(
128 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
129 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000130 ui::LayerAnimationElement::CreateOpacityElement(opacity, duration));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000131 if (observer)
132 sequence->AddObserver(observer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000133 animator->StartAnimation(sequence);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000134}
135
136// Makes |window| fully transparent instantaneously.
137void HideWindowImmediately(aura::Window* window,
138 ui::LayerAnimationObserver* observer) {
139 window->layer()->SetOpacity(0.0);
140 if (observer)
141 observer->OnLayerAnimationEnded(NULL);
142}
143
144// Restores |window| to its original position and scale and full opacity
145// instantaneously.
146void RestoreWindow(aura::Window* window, ui::LayerAnimationObserver* observer) {
147 window->layer()->SetTransform(gfx::Transform());
148 window->layer()->SetOpacity(1.0);
149 if (observer)
150 observer->OnLayerAnimationEnded(NULL);
151}
152
153void HideWindow(aura::Window* window,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000154 base::TimeDelta duration,
155 bool above,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000156 ui::LayerAnimationObserver* observer) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000157 ui::Layer* layer = window->layer();
158 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
159
160 settings.SetPreemptionStrategy(
161 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
162 settings.SetTransitionDuration(duration);
163
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100164 settings.SetTweenType(gfx::Tween::EASE_OUT);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000165 SetTransformForScaleAnimation(layer,
166 above ? LAYER_SCALE_ANIMATION_ABOVE : LAYER_SCALE_ANIMATION_BELOW);
167
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100168 settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000169 layer->SetOpacity(0.0f);
170
171 // After the animation completes snap the transform back to the identity,
172 // otherwise any one that asks for screen bounds gets a slightly scaled
173 // version.
174 settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
175 settings.SetTransitionDuration(base::TimeDelta());
176 layer->SetTransform(gfx::Transform());
177
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000178 // A bit of a dirty trick: we need to catch the end of the animation we don't
179 // control. So we use two facts we know: which animator will be used and the
180 // target opacity to add "Do nothing" animation sequence.
181 // Unfortunately, we can not just use empty LayerAnimationSequence, because
182 // it does not call NotifyEnded().
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000183 if (observer) {
184 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
185 ui::LayerAnimationElement::CreateOpacityElement(
186 0.0, base::TimeDelta()));
187 sequence->AddObserver(observer);
188 layer->GetAnimator()->ScheduleAnimation(sequence);
189 }
190}
191
192// Animates |window| to identity transform and full opacity over |duration|.
193void TransformWindowToBaseState(aura::Window* window,
194 base::TimeDelta duration,
195 ui::LayerAnimationObserver* observer) {
196 ui::Layer* layer = window->layer();
197 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
198
199 // Animate to target values.
200 settings.SetPreemptionStrategy(
201 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
202 settings.SetTransitionDuration(duration);
203
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100204 settings.SetTweenType(gfx::Tween::EASE_OUT);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000205 layer->SetTransform(gfx::Transform());
206
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100207 settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000208 layer->SetOpacity(1.0f);
209
210 // A bit of a dirty trick: we need to catch the end of the animation we don't
211 // control. So we use two facts we know: which animator will be used and the
212 // target opacity to add "Do nothing" animation sequence.
213 // Unfortunately, we can not just use empty LayerAnimationSequence, because
214 // it does not call NotifyEnded().
215 if (observer) {
216 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
217 ui::LayerAnimationElement::CreateOpacityElement(
218 1.0, base::TimeDelta()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000219 sequence->AddObserver(observer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000220 layer->GetAnimator()->ScheduleAnimation(sequence);
221 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000222}
223
224void ShowWindow(aura::Window* window,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000225 base::TimeDelta duration,
226 bool above,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000227 ui::LayerAnimationObserver* observer) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000228 ui::Layer* layer = window->layer();
229 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
230
231 // Set initial state of animation
232 settings.SetPreemptionStrategy(
233 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
234 settings.SetTransitionDuration(base::TimeDelta());
235 SetTransformForScaleAnimation(layer,
236 above ? LAYER_SCALE_ANIMATION_ABOVE : LAYER_SCALE_ANIMATION_BELOW);
237
238 TransformWindowToBaseState(window, duration, observer);
239}
240
241// Starts grayscale/brightness animation for |window| over |duration|. Target
242// value for both grayscale and brightness are specified by |target|.
243void StartGrayscaleBrightnessAnimationForWindow(
244 aura::Window* window,
245 float target,
246 base::TimeDelta duration,
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100247 gfx::Tween::Type tween_type,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000248 ui::LayerAnimationObserver* observer) {
249 ui::LayerAnimator* animator = window->layer()->GetAnimator();
250
251 scoped_ptr<ui::LayerAnimationSequence> brightness_sequence(
252 new ui::LayerAnimationSequence());
253 scoped_ptr<ui::LayerAnimationSequence> grayscale_sequence(
254 new ui::LayerAnimationSequence());
255
256 scoped_ptr<ui::LayerAnimationElement> brightness_element(
257 ui::LayerAnimationElement::CreateBrightnessElement(
258 target, duration));
259 brightness_element->set_tween_type(tween_type);
260 brightness_sequence->AddElement(brightness_element.release());
261
262 scoped_ptr<ui::LayerAnimationElement> grayscale_element(
263 ui::LayerAnimationElement::CreateGrayscaleElement(
264 target, duration));
265 grayscale_element->set_tween_type(tween_type);
266 grayscale_sequence->AddElement(grayscale_element.release());
267
268 std::vector<ui::LayerAnimationSequence*> animations;
269 animations.push_back(brightness_sequence.release());
270 animations.push_back(grayscale_sequence.release());
271
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000272 if (observer)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000273 animations[0]->AddObserver(observer);
274
275 animator->set_preemption_strategy(
276 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
277
278 animator->StartTogether(animations);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000279}
280
281// Animation observer that will drop animated foreground once animation is
282// finished. It is used in when undoing shutdown animation.
283class CallbackAnimationObserver : public ui::LayerAnimationObserver {
284 public:
285 explicit CallbackAnimationObserver(base::Callback<void(void)> &callback)
286 : callback_(callback) {
287 }
288 virtual ~CallbackAnimationObserver() {
289 }
290
291 private:
292 // Overridden from ui::LayerAnimationObserver:
293 virtual void OnLayerAnimationEnded(ui::LayerAnimationSequence* seq)
294 OVERRIDE {
295 // Drop foreground once animation is over.
296 callback_.Run();
297 delete this;
298 }
299
300 virtual void OnLayerAnimationAborted(ui::LayerAnimationSequence* seq)
301 OVERRIDE {
302 // Drop foreground once animation is over.
303 callback_.Run();
304 delete this;
305 }
306
307 virtual void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq)
308 OVERRIDE {}
309
310 base::Callback<void(void)> callback_;
311
312 DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver);
313};
314
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000315
316bool IsLayerAnimated(ui::Layer* layer,
317 SessionStateAnimator::AnimationType type) {
318 switch (type) {
319 case SessionStateAnimator::ANIMATION_PARTIAL_CLOSE:
320 if (layer->GetTargetTransform() != GetSlowCloseTransform())
321 return false;
322 break;
323 case SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE:
324 if (layer->GetTargetTransform() != gfx::Transform())
325 return false;
326 break;
327 case SessionStateAnimator::ANIMATION_FULL_CLOSE:
328 if (layer->GetTargetTransform() != GetFastCloseTransform() ||
329 layer->GetTargetOpacity() > 0.0001)
330 return false;
331 break;
332 case SessionStateAnimator::ANIMATION_FADE_IN:
333 if (layer->GetTargetOpacity() < 0.9999)
334 return false;
335 break;
336 case SessionStateAnimator::ANIMATION_FADE_OUT:
337 if (layer->GetTargetOpacity() > 0.0001)
338 return false;
339 break;
340 case SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY:
341 if (layer->GetTargetOpacity() > 0.0001)
342 return false;
343 break;
344 case SessionStateAnimator::ANIMATION_RESTORE:
345 if (layer->opacity() < 0.9999 || layer->transform() != gfx::Transform())
346 return false;
347 break;
348 case SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS:
349 if ((layer->GetTargetBrightness() < 0.9999) ||
350 (layer->GetTargetGrayscale() < 0.9999))
351 return false;
352 break;
353 case SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS:
354 if ((layer->GetTargetBrightness() > 0.0001) ||
355 (layer->GetTargetGrayscale() > 0.0001))
356 return false;
357 break;
358 case SessionStateAnimator::ANIMATION_DROP:
359 case SessionStateAnimator::ANIMATION_UNDO_LIFT:
360 //ToDo(antim) : check other effects
361 if (layer->GetTargetOpacity() < 0.9999)
362 return false;
363 break;
364 //ToDo(antim) : check other effects
365 case SessionStateAnimator::ANIMATION_LIFT:
366 if (layer->GetTargetOpacity() > 0.0001)
367 return false;
368 break;
369 case SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN:
370 //ToDo(antim) : check other effects
371 if (layer->GetTargetOpacity() < 0.9999)
372 return false;
373 break;
374 //ToDo(antim) : check other effects
375 case SessionStateAnimator::ANIMATION_LOWER_BELOW_SCREEN:
376 if (layer->GetTargetOpacity() > 0.0001)
377 return false;
378 break;
379 default:
380 NOTREACHED() << "Unhandled animation type " << type;
381 return false;
382 }
383 return true;
384}
385
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000386} // namespace
387
388bool SessionStateAnimator::TestApi::ContainersAreAnimated(
389 int container_mask, AnimationType type) const {
390 aura::Window::Windows containers;
391 animator_->GetContainers(container_mask, &containers);
392 for (aura::Window::Windows::const_iterator it = containers.begin();
393 it != containers.end(); ++it) {
394 aura::Window* window = *it;
395 ui::Layer* layer = window->layer();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000396 if (!IsLayerAnimated(layer, type))
397 return false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000398 }
399 return true;
400}
401
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000402bool SessionStateAnimator::TestApi::RootWindowIsAnimated(AnimationType type)
403 const {
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000404 aura::Window* root_window = Shell::GetPrimaryRootWindow();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000405 ui::Layer* layer = root_window->layer();
406 return IsLayerAnimated(layer, type);
407}
408
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000409const int SessionStateAnimator::kAllLockScreenContainersMask =
410 SessionStateAnimator::LOCK_SCREEN_BACKGROUND |
411 SessionStateAnimator::LOCK_SCREEN_CONTAINERS |
412 SessionStateAnimator::LOCK_SCREEN_RELATED_CONTAINERS;
413
414const int SessionStateAnimator::kAllContainersMask =
415 SessionStateAnimator::kAllLockScreenContainersMask |
416 SessionStateAnimator::DESKTOP_BACKGROUND |
417 SessionStateAnimator::LAUNCHER |
418 SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS;
419
420SessionStateAnimator::SessionStateAnimator() {
421}
422
423SessionStateAnimator::~SessionStateAnimator() {
424}
425
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000426base::TimeDelta SessionStateAnimator::GetDuration(AnimationSpeed speed) {
427 switch (speed) {
428 case ANIMATION_SPEED_IMMEDIATE:
429 return base::TimeDelta();
430 case ANIMATION_SPEED_UNDOABLE:
431 return base::TimeDelta::FromMilliseconds(400);
432 case ANIMATION_SPEED_REVERT:
433 return base::TimeDelta::FromMilliseconds(150);
434 case ANIMATION_SPEED_FAST:
435 return base::TimeDelta::FromMilliseconds(150);
436 case ANIMATION_SPEED_SHOW_LOCK_SCREEN:
437 return base::TimeDelta::FromMilliseconds(200);
438 case ANIMATION_SPEED_MOVE_WINDOWS:
439 return base::TimeDelta::FromMilliseconds(350);
440 case ANIMATION_SPEED_UNDO_MOVE_WINDOWS:
441 return base::TimeDelta::FromMilliseconds(350);
442 case ANIMATION_SPEED_SHUTDOWN:
443 return base::TimeDelta::FromMilliseconds(1000);
444 case ANIMATION_SPEED_REVERT_SHUTDOWN:
445 return base::TimeDelta::FromMilliseconds(500);
446 }
447 // Satisfy compilers that do not understand that we will return from switch
448 // above anyway.
449 DCHECK(false) << "Unhandled animation speed " << speed;
450 return base::TimeDelta();
451}
452
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000453// Fills |containers| with the containers described by |container_mask|.
454void SessionStateAnimator::GetContainers(int container_mask,
455 aura::Window::Windows* containers) {
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000456 aura::Window* root_window = Shell::GetPrimaryRootWindow();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000457 containers->clear();
458
459 if (container_mask & DESKTOP_BACKGROUND) {
460 containers->push_back(Shell::GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +0100461 root_window, kShellWindowId_DesktopBackgroundContainer));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000462 }
463 if (container_mask & LAUNCHER) {
Ben Murdochc5cede92014-04-10 11:22:14 +0100464 containers->push_back(
465 Shell::GetContainer(root_window, kShellWindowId_ShelfContainer));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000466 }
467 if (container_mask & NON_LOCK_SCREEN_CONTAINERS) {
468 // TODO(antrim): Figure out a way to eliminate a need to exclude launcher
469 // in such way.
470 aura::Window* non_lock_screen_containers = Shell::GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +0100471 root_window, kShellWindowId_NonLockScreenContainersContainer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000472 aura::Window::Windows children = non_lock_screen_containers->children();
473
474 for (aura::Window::Windows::const_iterator it = children.begin();
475 it != children.end(); ++it) {
476 aura::Window* window = *it;
Ben Murdochc5cede92014-04-10 11:22:14 +0100477 if (window->id() == kShellWindowId_ShelfContainer)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000478 continue;
479 containers->push_back(window);
480 }
481 }
482 if (container_mask & LOCK_SCREEN_BACKGROUND) {
483 containers->push_back(Shell::GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +0100484 root_window, kShellWindowId_LockScreenBackgroundContainer));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000485 }
486 if (container_mask & LOCK_SCREEN_CONTAINERS) {
487 containers->push_back(Shell::GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +0100488 root_window, kShellWindowId_LockScreenContainersContainer));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000489 }
490 if (container_mask & LOCK_SCREEN_RELATED_CONTAINERS) {
491 containers->push_back(Shell::GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +0100492 root_window, kShellWindowId_LockScreenRelatedContainersContainer));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000493 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000494}
495
496void SessionStateAnimator::StartAnimation(int container_mask,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000497 AnimationType type,
498 AnimationSpeed speed) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000499 aura::Window::Windows containers;
500 GetContainers(container_mask, &containers);
501 for (aura::Window::Windows::const_iterator it = containers.begin();
502 it != containers.end(); ++it) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000503 RunAnimationForWindow(*it, type, speed, NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000504 }
505}
506
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000507void SessionStateAnimator::StartAnimationWithCallback(
508 int container_mask,
509 AnimationType type,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000510 AnimationSpeed speed,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000511 base::Callback<void(void)>& callback) {
512 aura::Window::Windows containers;
513 GetContainers(container_mask, &containers);
514 for (aura::Window::Windows::const_iterator it = containers.begin();
515 it != containers.end(); ++it) {
516 ui::LayerAnimationObserver* observer =
517 new CallbackAnimationObserver(callback);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000518 RunAnimationForWindow(*it, type, speed, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000519 }
520}
521
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000522void SessionStateAnimator::StartAnimationWithObserver(
523 int container_mask,
524 AnimationType type,
525 AnimationSpeed speed,
526 ui::LayerAnimationObserver* observer) {
527 aura::Window::Windows containers;
528 GetContainers(container_mask, &containers);
529 for (aura::Window::Windows::const_iterator it = containers.begin();
530 it != containers.end(); ++it) {
531 RunAnimationForWindow(*it, type, speed, observer);
532 }
533}
534
535void SessionStateAnimator::StartGlobalAnimation(AnimationType type,
536 AnimationSpeed speed) {
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000537 aura::Window* root_window = Shell::GetPrimaryRootWindow();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000538 RunAnimationForWindow(root_window, type, speed, NULL);
539}
540
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000541void SessionStateAnimator::RunAnimationForWindow(
542 aura::Window* window,
543 AnimationType type,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000544 AnimationSpeed speed,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000545 ui::LayerAnimationObserver* observer) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000546 base::TimeDelta duration = GetDuration(speed);
547
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000548 switch (type) {
549 case ANIMATION_PARTIAL_CLOSE:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000550 StartSlowCloseAnimationForWindow(window, duration, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000551 break;
552 case ANIMATION_UNDO_PARTIAL_CLOSE:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000553 StartUndoSlowCloseAnimationForWindow(window, duration, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000554 break;
555 case ANIMATION_FULL_CLOSE:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000556 StartFastCloseAnimationForWindow(window, duration, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000557 break;
558 case ANIMATION_FADE_IN:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000559 StartOpacityAnimationForWindow(window, 1.0, duration, observer);
560 break;
561 case ANIMATION_FADE_OUT:
562 StartOpacityAnimationForWindow(window, 0.0, duration, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000563 break;
564 case ANIMATION_HIDE_IMMEDIATELY:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000565 DCHECK_EQ(speed, ANIMATION_SPEED_IMMEDIATE);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000566 HideWindowImmediately(window, observer);
567 break;
568 case ANIMATION_RESTORE:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000569 DCHECK_EQ(speed, ANIMATION_SPEED_IMMEDIATE);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000570 RestoreWindow(window, observer);
571 break;
572 case ANIMATION_LIFT:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000573 HideWindow(window, duration, true, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000574 break;
575 case ANIMATION_DROP:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000576 ShowWindow(window, duration, true, observer);
577 break;
578 case ANIMATION_UNDO_LIFT:
579 TransformWindowToBaseState(window, duration, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000580 break;
581 case ANIMATION_RAISE_TO_SCREEN:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000582 ShowWindow(window, duration, false, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000583 break;
584 case ANIMATION_LOWER_BELOW_SCREEN:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000585 HideWindow(window, duration, false, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000586 break;
587 case ANIMATION_PARTIAL_FADE_IN:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000588 StartPartialFadeAnimation(
589 window, kPartialFadeRatio, duration, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000590 break;
591 case ANIMATION_UNDO_PARTIAL_FADE_IN:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000592 StartPartialFadeAnimation(window, 0.0, duration, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000593 break;
594 case ANIMATION_FULL_FADE_IN:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000595 StartPartialFadeAnimation(window, 1.0, duration, observer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000596 break;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000597 case ANIMATION_GRAYSCALE_BRIGHTNESS:
598 StartGrayscaleBrightnessAnimationForWindow(
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100599 window, 1.0, duration, gfx::Tween::EASE_IN, observer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000600 break;
601 case ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS:
602 StartGrayscaleBrightnessAnimationForWindow(
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100603 window, 0.0, duration, gfx::Tween::EASE_IN_OUT, observer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000604 break;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000605 }
606}
607
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000608} // namespace ash