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.
4
5#include "ash/wm/session_state_animator.h"
6
7#include "ash/shell.h"
8#include "ash/shell_window_ids.h"
9#include "ash/wm/window_animations.h"
10#include "ui/aura/client/aura_constants.h"
11#include "ui/aura/root_window.h"
12#include "ui/compositor/layer_animation_observer.h"
13#include "ui/compositor/layer_animation_sequence.h"
14#include "ui/compositor/scoped_layer_animation_settings.h"
15#include "ui/views/widget/widget.h"
16
17namespace ash {
18namespace internal {
19
20namespace {
21
22// Slightly-smaller size that we scale the screen down to for the pre-lock and
23// pre-shutdown states.
24const float kSlowCloseSizeRatio = 0.95f;
25
26// Maximum opacity of white layer when animating pre-shutdown state.
27const float kPartialFadeRatio = 0.3f;
28
29// Minimum size. Not zero as it causes numeric issues.
30const float kMinimumScale = 1e-4f;
31
32// Returns the transform that should be applied to containers for the slow-close
33// animation.
34gfx::Transform GetSlowCloseTransform() {
35  gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size();
36  gfx::Transform transform;
37  transform.Translate(
38      floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.width() + 0.5),
39      floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.height() + 0.5));
40  transform.Scale(kSlowCloseSizeRatio, kSlowCloseSizeRatio);
41 return transform;
42}
43
44// Returns the transform that should be applied to containers for the fast-close
45// animation.
46gfx::Transform GetFastCloseTransform() {
47  gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size();
48  gfx::Transform transform;
49  transform.Translate(floor(0.5 * root_size.width() + 0.5),
50                      floor(0.5 * root_size.height() + 0.5));
51  transform.Scale(kMinimumScale, kMinimumScale);
52  return transform;
53}
54
55// Slowly shrinks |window| to a slightly-smaller size.
56void StartSlowCloseAnimationForWindow(aura::Window* window,
57                                      base::TimeDelta duration,
58                                      ui::LayerAnimationObserver* observer) {
59  ui::LayerAnimator* animator = window->layer()->GetAnimator();
60  animator->set_preemption_strategy(
61      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
62  ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
63      ui::LayerAnimationElement::CreateTransformElement(
64          GetSlowCloseTransform(),
65          duration));
66  if (observer)
67    sequence->AddObserver(observer);
68  animator->StartAnimation(sequence);
69}
70
71// Quickly undoes the effects of the slow-close animation on |window|.
72void StartUndoSlowCloseAnimationForWindow(
73    aura::Window* window,
74    base::TimeDelta duration,
75    ui::LayerAnimationObserver* observer) {
76  ui::LayerAnimator* animator = window->layer()->GetAnimator();
77  animator->set_preemption_strategy(
78      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
79  ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
80      ui::LayerAnimationElement::CreateTransformElement(
81          gfx::Transform(),
82          duration));
83  if (observer)
84    sequence->AddObserver(observer);
85  animator->StartAnimation(sequence);
86}
87
88// Quickly shrinks |window| down to a point in the center of the screen and
89// fades it out to 0 opacity.
90void StartFastCloseAnimationForWindow(aura::Window* window,
91                                      base::TimeDelta duration,
92                                      ui::LayerAnimationObserver* observer) {
93  ui::LayerAnimator* animator = window->layer()->GetAnimator();
94  animator->set_preemption_strategy(
95      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
96  animator->StartAnimation(
97      new ui::LayerAnimationSequence(
98          ui::LayerAnimationElement::CreateTransformElement(
99              GetFastCloseTransform(), duration)));
100  ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
101      ui::LayerAnimationElement::CreateOpacityElement(0.0, duration));
102  if (observer)
103    sequence->AddObserver(observer);
104  animator->StartAnimation(sequence);
105}
106
107// Fades |window| to |target_opacity| over |duration|.
108void StartPartialFadeAnimation(aura::Window* window,
109                               float target_opacity,
110                               base::TimeDelta duration,
111                               ui::LayerAnimationObserver* observer) {
112  ui::LayerAnimator* animator = window->layer()->GetAnimator();
113  animator->set_preemption_strategy(
114      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
115  ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
116      ui::LayerAnimationElement::CreateOpacityElement(
117          target_opacity, duration));
118  if (observer)
119    sequence->AddObserver(observer);
120  animator->StartAnimation(sequence);
121}
122
123// Fades |window| to |opacity| over |duration|.
124void StartOpacityAnimationForWindow(aura::Window* window,
125                                    float opacity,
126                                    base::TimeDelta duration,
127                                    ui::LayerAnimationObserver* observer) {
128  ui::LayerAnimator* animator = window->layer()->GetAnimator();
129  animator->set_preemption_strategy(
130      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
131  ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
132      ui::LayerAnimationElement::CreateOpacityElement(opacity, duration));
133  if (observer)
134    sequence->AddObserver(observer);
135  animator->StartAnimation(sequence);
136}
137
138// Makes |window| fully transparent instantaneously.
139void HideWindowImmediately(aura::Window* window,
140                           ui::LayerAnimationObserver* observer) {
141  window->layer()->SetOpacity(0.0);
142  if (observer)
143    observer->OnLayerAnimationEnded(NULL);
144}
145
146// Restores |window| to its original position and scale and full opacity
147// instantaneously.
148void RestoreWindow(aura::Window* window, ui::LayerAnimationObserver* observer) {
149  window->layer()->SetTransform(gfx::Transform());
150  window->layer()->SetOpacity(1.0);
151  if (observer)
152    observer->OnLayerAnimationEnded(NULL);
153}
154
155void HideWindow(aura::Window* window,
156                base::TimeDelta duration,
157                bool above,
158                ui::LayerAnimationObserver* observer) {
159  ui::Layer* layer = window->layer();
160  ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
161
162  settings.SetPreemptionStrategy(
163      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
164  settings.SetTransitionDuration(duration);
165
166  settings.SetTweenType(gfx::Tween::EASE_OUT);
167  SetTransformForScaleAnimation(layer,
168      above ? LAYER_SCALE_ANIMATION_ABOVE : LAYER_SCALE_ANIMATION_BELOW);
169
170  settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
171  layer->SetOpacity(0.0f);
172
173  // After the animation completes snap the transform back to the identity,
174  // otherwise any one that asks for screen bounds gets a slightly scaled
175  // version.
176  settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
177  settings.SetTransitionDuration(base::TimeDelta());
178  layer->SetTransform(gfx::Transform());
179
180  // A bit of a dirty trick: we need to catch the end of the animation we don't
181  // control. So we use two facts we know: which animator will be used and the
182  // target opacity to add "Do nothing" animation sequence.
183  // Unfortunately, we can not just use empty LayerAnimationSequence, because
184  // it does not call NotifyEnded().
185  if (observer) {
186    ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
187        ui::LayerAnimationElement::CreateOpacityElement(
188            0.0, base::TimeDelta()));
189      sequence->AddObserver(observer);
190    layer->GetAnimator()->ScheduleAnimation(sequence);
191  }
192}
193
194// Animates |window| to identity transform and full opacity over |duration|.
195void TransformWindowToBaseState(aura::Window* window,
196                                base::TimeDelta duration,
197                                ui::LayerAnimationObserver* observer) {
198  ui::Layer* layer = window->layer();
199  ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
200
201  // Animate to target values.
202  settings.SetPreemptionStrategy(
203      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
204  settings.SetTransitionDuration(duration);
205
206  settings.SetTweenType(gfx::Tween::EASE_OUT);
207  layer->SetTransform(gfx::Transform());
208
209  settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
210  layer->SetOpacity(1.0f);
211
212  // A bit of a dirty trick: we need to catch the end of the animation we don't
213  // control. So we use two facts we know: which animator will be used and the
214  // target opacity to add "Do nothing" animation sequence.
215  // Unfortunately, we can not just use empty LayerAnimationSequence, because
216  // it does not call NotifyEnded().
217  if (observer) {
218    ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
219        ui::LayerAnimationElement::CreateOpacityElement(
220            1.0, base::TimeDelta()));
221    sequence->AddObserver(observer);
222    layer->GetAnimator()->ScheduleAnimation(sequence);
223  }
224}
225
226void ShowWindow(aura::Window* window,
227                base::TimeDelta duration,
228                bool above,
229                ui::LayerAnimationObserver* observer) {
230  ui::Layer* layer = window->layer();
231  ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
232
233  // Set initial state of animation
234  settings.SetPreemptionStrategy(
235      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
236  settings.SetTransitionDuration(base::TimeDelta());
237  SetTransformForScaleAnimation(layer,
238      above ? LAYER_SCALE_ANIMATION_ABOVE : LAYER_SCALE_ANIMATION_BELOW);
239
240  TransformWindowToBaseState(window, duration, observer);
241}
242
243// Starts grayscale/brightness animation for |window| over |duration|. Target
244// value for both grayscale and brightness are specified by |target|.
245void StartGrayscaleBrightnessAnimationForWindow(
246    aura::Window* window,
247    float target,
248    base::TimeDelta duration,
249    gfx::Tween::Type tween_type,
250    ui::LayerAnimationObserver* observer) {
251  ui::LayerAnimator* animator = window->layer()->GetAnimator();
252
253  scoped_ptr<ui::LayerAnimationSequence> brightness_sequence(
254      new ui::LayerAnimationSequence());
255  scoped_ptr<ui::LayerAnimationSequence> grayscale_sequence(
256      new ui::LayerAnimationSequence());
257
258  scoped_ptr<ui::LayerAnimationElement> brightness_element(
259      ui::LayerAnimationElement::CreateBrightnessElement(
260          target, duration));
261  brightness_element->set_tween_type(tween_type);
262  brightness_sequence->AddElement(brightness_element.release());
263
264  scoped_ptr<ui::LayerAnimationElement> grayscale_element(
265      ui::LayerAnimationElement::CreateGrayscaleElement(
266          target, duration));
267  grayscale_element->set_tween_type(tween_type);
268  grayscale_sequence->AddElement(grayscale_element.release());
269
270  std::vector<ui::LayerAnimationSequence*> animations;
271  animations.push_back(brightness_sequence.release());
272  animations.push_back(grayscale_sequence.release());
273
274  if (observer)
275    animations[0]->AddObserver(observer);
276
277  animator->set_preemption_strategy(
278      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
279
280  animator->StartTogether(animations);
281}
282
283// Animation observer that will drop animated foreground once animation is
284// finished. It is used in when undoing shutdown animation.
285class CallbackAnimationObserver : public ui::LayerAnimationObserver {
286 public:
287  explicit CallbackAnimationObserver(base::Callback<void(void)> &callback)
288      : callback_(callback) {
289  }
290  virtual ~CallbackAnimationObserver() {
291  }
292
293 private:
294  // Overridden from ui::LayerAnimationObserver:
295  virtual void OnLayerAnimationEnded(ui::LayerAnimationSequence* seq)
296      OVERRIDE {
297    // Drop foreground once animation is over.
298    callback_.Run();
299    delete this;
300  }
301
302  virtual void OnLayerAnimationAborted(ui::LayerAnimationSequence* seq)
303      OVERRIDE {
304    // Drop foreground once animation is over.
305    callback_.Run();
306    delete this;
307  }
308
309  virtual void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq)
310      OVERRIDE {}
311
312  base::Callback<void(void)> callback_;
313
314  DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver);
315};
316
317
318bool IsLayerAnimated(ui::Layer* layer,
319                     SessionStateAnimator::AnimationType type) {
320  switch (type) {
321    case SessionStateAnimator::ANIMATION_PARTIAL_CLOSE:
322      if (layer->GetTargetTransform() != GetSlowCloseTransform())
323        return false;
324      break;
325    case SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE:
326      if (layer->GetTargetTransform() != gfx::Transform())
327        return false;
328      break;
329    case SessionStateAnimator::ANIMATION_FULL_CLOSE:
330      if (layer->GetTargetTransform() != GetFastCloseTransform() ||
331          layer->GetTargetOpacity() > 0.0001)
332        return false;
333      break;
334    case SessionStateAnimator::ANIMATION_FADE_IN:
335      if (layer->GetTargetOpacity() < 0.9999)
336        return false;
337      break;
338    case SessionStateAnimator::ANIMATION_FADE_OUT:
339      if (layer->GetTargetOpacity() > 0.0001)
340        return false;
341      break;
342    case SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY:
343      if (layer->GetTargetOpacity() > 0.0001)
344        return false;
345      break;
346    case SessionStateAnimator::ANIMATION_RESTORE:
347      if (layer->opacity() < 0.9999 || layer->transform() != gfx::Transform())
348        return false;
349      break;
350    case SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS:
351      if ((layer->GetTargetBrightness() < 0.9999) ||
352          (layer->GetTargetGrayscale() < 0.9999))
353        return false;
354      break;
355    case SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS:
356      if ((layer->GetTargetBrightness() > 0.0001) ||
357          (layer->GetTargetGrayscale() > 0.0001))
358        return false;
359      break;
360    case SessionStateAnimator::ANIMATION_DROP:
361    case SessionStateAnimator::ANIMATION_UNDO_LIFT:
362      //ToDo(antim) : check other effects
363      if (layer->GetTargetOpacity() < 0.9999)
364        return false;
365      break;
366      //ToDo(antim) : check other effects
367    case SessionStateAnimator::ANIMATION_LIFT:
368      if (layer->GetTargetOpacity() > 0.0001)
369        return false;
370      break;
371    case SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN:
372      //ToDo(antim) : check other effects
373      if (layer->GetTargetOpacity() < 0.9999)
374        return false;
375      break;
376      //ToDo(antim) : check other effects
377    case SessionStateAnimator::ANIMATION_LOWER_BELOW_SCREEN:
378      if (layer->GetTargetOpacity() > 0.0001)
379        return false;
380      break;
381    default:
382      NOTREACHED() << "Unhandled animation type " << type;
383      return false;
384  }
385  return true;
386}
387
388}  // namespace
389
390bool SessionStateAnimator::TestApi::ContainersAreAnimated(
391    int container_mask, AnimationType type) const {
392  aura::Window::Windows containers;
393  animator_->GetContainers(container_mask, &containers);
394  for (aura::Window::Windows::const_iterator it = containers.begin();
395       it != containers.end(); ++it) {
396    aura::Window* window = *it;
397    ui::Layer* layer = window->layer();
398    if (!IsLayerAnimated(layer, type))
399      return false;
400  }
401  return true;
402}
403
404bool SessionStateAnimator::TestApi::RootWindowIsAnimated(AnimationType type)
405    const {
406  aura::Window* root_window = Shell::GetPrimaryRootWindow();
407  ui::Layer* layer = root_window->layer();
408  return IsLayerAnimated(layer, type);
409}
410
411const int SessionStateAnimator::kAllLockScreenContainersMask =
412    SessionStateAnimator::LOCK_SCREEN_BACKGROUND |
413    SessionStateAnimator::LOCK_SCREEN_CONTAINERS |
414    SessionStateAnimator::LOCK_SCREEN_RELATED_CONTAINERS;
415
416const int SessionStateAnimator::kAllContainersMask =
417    SessionStateAnimator::kAllLockScreenContainersMask |
418    SessionStateAnimator::DESKTOP_BACKGROUND |
419    SessionStateAnimator::LAUNCHER |
420    SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS;
421
422SessionStateAnimator::SessionStateAnimator() {
423}
424
425SessionStateAnimator::~SessionStateAnimator() {
426}
427
428base::TimeDelta SessionStateAnimator::GetDuration(AnimationSpeed speed) {
429  switch (speed) {
430    case ANIMATION_SPEED_IMMEDIATE:
431      return base::TimeDelta();
432    case ANIMATION_SPEED_UNDOABLE:
433      return base::TimeDelta::FromMilliseconds(400);
434    case ANIMATION_SPEED_REVERT:
435      return base::TimeDelta::FromMilliseconds(150);
436    case ANIMATION_SPEED_FAST:
437      return base::TimeDelta::FromMilliseconds(150);
438    case ANIMATION_SPEED_SHOW_LOCK_SCREEN:
439      return base::TimeDelta::FromMilliseconds(200);
440    case ANIMATION_SPEED_MOVE_WINDOWS:
441      return base::TimeDelta::FromMilliseconds(350);
442    case ANIMATION_SPEED_UNDO_MOVE_WINDOWS:
443      return base::TimeDelta::FromMilliseconds(350);
444    case ANIMATION_SPEED_SHUTDOWN:
445      return base::TimeDelta::FromMilliseconds(1000);
446    case ANIMATION_SPEED_REVERT_SHUTDOWN:
447      return base::TimeDelta::FromMilliseconds(500);
448  }
449  // Satisfy compilers that do not understand that we will return from switch
450  // above anyway.
451  DCHECK(false) << "Unhandled animation speed " << speed;
452  return base::TimeDelta();
453}
454
455// Fills |containers| with the containers described by |container_mask|.
456void SessionStateAnimator::GetContainers(int container_mask,
457                                         aura::Window::Windows* containers) {
458  aura::Window* root_window = Shell::GetPrimaryRootWindow();
459  containers->clear();
460
461  if (container_mask & DESKTOP_BACKGROUND) {
462    containers->push_back(Shell::GetContainer(
463        root_window,
464        internal::kShellWindowId_DesktopBackgroundContainer));
465  }
466  if (container_mask & LAUNCHER) {
467    containers->push_back(Shell::GetContainer(
468        root_window,
469        internal::kShellWindowId_ShelfContainer));
470  }
471  if (container_mask & NON_LOCK_SCREEN_CONTAINERS) {
472    // TODO(antrim): Figure out a way to eliminate a need to exclude launcher
473    // in such way.
474    aura::Window* non_lock_screen_containers = Shell::GetContainer(
475        root_window,
476        internal::kShellWindowId_NonLockScreenContainersContainer);
477    aura::Window::Windows children = non_lock_screen_containers->children();
478
479    for (aura::Window::Windows::const_iterator it = children.begin();
480         it != children.end(); ++it) {
481      aura::Window* window = *it;
482      if (window->id() == internal::kShellWindowId_ShelfContainer)
483        continue;
484      containers->push_back(window);
485    }
486  }
487  if (container_mask & LOCK_SCREEN_BACKGROUND) {
488    containers->push_back(Shell::GetContainer(
489        root_window,
490        internal::kShellWindowId_LockScreenBackgroundContainer));
491  }
492  if (container_mask & LOCK_SCREEN_CONTAINERS) {
493    containers->push_back(Shell::GetContainer(
494        root_window,
495        internal::kShellWindowId_LockScreenContainersContainer));
496  }
497  if (container_mask & LOCK_SCREEN_RELATED_CONTAINERS) {
498    containers->push_back(Shell::GetContainer(
499        root_window,
500        internal::kShellWindowId_LockScreenRelatedContainersContainer));
501  }
502}
503
504void SessionStateAnimator::StartAnimation(int container_mask,
505                                          AnimationType type,
506                                          AnimationSpeed speed) {
507  aura::Window::Windows containers;
508  GetContainers(container_mask, &containers);
509  for (aura::Window::Windows::const_iterator it = containers.begin();
510       it != containers.end(); ++it) {
511    RunAnimationForWindow(*it, type, speed, NULL);
512  }
513}
514
515void SessionStateAnimator::StartAnimationWithCallback(
516    int container_mask,
517    AnimationType type,
518    AnimationSpeed speed,
519    base::Callback<void(void)>& callback) {
520  aura::Window::Windows containers;
521  GetContainers(container_mask, &containers);
522  for (aura::Window::Windows::const_iterator it = containers.begin();
523       it != containers.end(); ++it) {
524    ui::LayerAnimationObserver* observer =
525        new CallbackAnimationObserver(callback);
526    RunAnimationForWindow(*it, type, speed, observer);
527  }
528}
529
530void SessionStateAnimator::StartAnimationWithObserver(
531    int container_mask,
532    AnimationType type,
533    AnimationSpeed speed,
534    ui::LayerAnimationObserver* observer) {
535  aura::Window::Windows containers;
536  GetContainers(container_mask, &containers);
537  for (aura::Window::Windows::const_iterator it = containers.begin();
538       it != containers.end(); ++it) {
539    RunAnimationForWindow(*it, type, speed, observer);
540  }
541}
542
543void SessionStateAnimator::StartGlobalAnimation(AnimationType type,
544                                                AnimationSpeed speed) {
545  aura::Window* root_window = Shell::GetPrimaryRootWindow();
546  RunAnimationForWindow(root_window, type, speed, NULL);
547}
548
549void SessionStateAnimator::RunAnimationForWindow(
550    aura::Window* window,
551    AnimationType type,
552    AnimationSpeed speed,
553    ui::LayerAnimationObserver* observer) {
554  base::TimeDelta duration = GetDuration(speed);
555
556  switch (type) {
557    case ANIMATION_PARTIAL_CLOSE:
558      StartSlowCloseAnimationForWindow(window, duration, observer);
559      break;
560    case ANIMATION_UNDO_PARTIAL_CLOSE:
561      StartUndoSlowCloseAnimationForWindow(window, duration, observer);
562      break;
563    case ANIMATION_FULL_CLOSE:
564      StartFastCloseAnimationForWindow(window, duration, observer);
565      break;
566    case ANIMATION_FADE_IN:
567      StartOpacityAnimationForWindow(window, 1.0, duration, observer);
568      break;
569    case ANIMATION_FADE_OUT:
570      StartOpacityAnimationForWindow(window, 0.0, duration, observer);
571      break;
572    case ANIMATION_HIDE_IMMEDIATELY:
573      DCHECK_EQ(speed, ANIMATION_SPEED_IMMEDIATE);
574      HideWindowImmediately(window, observer);
575      break;
576    case ANIMATION_RESTORE:
577      DCHECK_EQ(speed, ANIMATION_SPEED_IMMEDIATE);
578      RestoreWindow(window, observer);
579      break;
580    case ANIMATION_LIFT:
581      HideWindow(window, duration, true, observer);
582      break;
583    case ANIMATION_DROP:
584      ShowWindow(window, duration, true, observer);
585      break;
586    case ANIMATION_UNDO_LIFT:
587      TransformWindowToBaseState(window, duration, observer);
588      break;
589    case ANIMATION_RAISE_TO_SCREEN:
590      ShowWindow(window, duration, false, observer);
591      break;
592    case ANIMATION_LOWER_BELOW_SCREEN:
593      HideWindow(window, duration, false, observer);
594      break;
595    case ANIMATION_PARTIAL_FADE_IN:
596      StartPartialFadeAnimation(
597          window, kPartialFadeRatio, duration, observer);
598      break;
599    case ANIMATION_UNDO_PARTIAL_FADE_IN:
600      StartPartialFadeAnimation(window, 0.0, duration, observer);
601      break;
602    case ANIMATION_FULL_FADE_IN:
603      StartPartialFadeAnimation(window, 1.0, duration, observer);
604      break;
605    case ANIMATION_GRAYSCALE_BRIGHTNESS:
606      StartGrayscaleBrightnessAnimationForWindow(
607          window, 1.0, duration, gfx::Tween::EASE_IN, observer);
608      break;
609    case ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS:
610      StartGrayscaleBrightnessAnimationForWindow(
611          window, 0.0, duration, gfx::Tween::EASE_IN_OUT, observer);
612      break;
613  }
614}
615
616}  // namespace internal
617}  // namespace ash
618