Home | History | Annotate | Download | only in wm
      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/window_event_dispatcher.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 
     17 namespace ash {
     18 namespace {
     19 
     20 // Slightly-smaller size that we scale the screen down to for the pre-lock and
     21 // pre-shutdown states.
     22 const float kSlowCloseSizeRatio = 0.95f;
     23 
     24 // Maximum opacity of white layer when animating pre-shutdown state.
     25 const float kPartialFadeRatio = 0.3f;
     26 
     27 // Minimum size. Not zero as it causes numeric issues.
     28 const float kMinimumScale = 1e-4f;
     29 
     30 // Returns the transform that should be applied to containers for the slow-close
     31 // animation.
     32 gfx::Transform GetSlowCloseTransform() {
     33   gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size();
     34   gfx::Transform transform;
     35   transform.Translate(
     36       floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.width() + 0.5),
     37       floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.height() + 0.5));
     38   transform.Scale(kSlowCloseSizeRatio, kSlowCloseSizeRatio);
     39  return transform;
     40 }
     41 
     42 // Returns the transform that should be applied to containers for the fast-close
     43 // animation.
     44 gfx::Transform GetFastCloseTransform() {
     45   gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size();
     46   gfx::Transform transform;
     47   transform.Translate(floor(0.5 * root_size.width() + 0.5),
     48                       floor(0.5 * root_size.height() + 0.5));
     49   transform.Scale(kMinimumScale, kMinimumScale);
     50   return transform;
     51 }
     52 
     53 // Slowly shrinks |window| to a slightly-smaller size.
     54 void StartSlowCloseAnimationForWindow(aura::Window* window,
     55                                       base::TimeDelta duration,
     56                                       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(),
     63           duration));
     64   if (observer)
     65     sequence->AddObserver(observer);
     66   animator->StartAnimation(sequence);
     67 }
     68 
     69 // Quickly undoes the effects of the slow-close animation on |window|.
     70 void StartUndoSlowCloseAnimationForWindow(
     71     aura::Window* window,
     72     base::TimeDelta duration,
     73     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(),
     80           duration));
     81   if (observer)
     82     sequence->AddObserver(observer);
     83   animator->StartAnimation(sequence);
     84 }
     85 
     86 // Quickly shrinks |window| down to a point in the center of the screen and
     87 // fades it out to 0 opacity.
     88 void StartFastCloseAnimationForWindow(aura::Window* window,
     89                                       base::TimeDelta duration,
     90                                       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(
     97               GetFastCloseTransform(), duration)));
     98   ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence(
     99       ui::LayerAnimationElement::CreateOpacityElement(0.0, duration));
    100   if (observer)
    101     sequence->AddObserver(observer);
    102   animator->StartAnimation(sequence);
    103 }
    104 
    105 // Fades |window| to |target_opacity| over |duration|.
    106 void StartPartialFadeAnimation(aura::Window* window,
    107                                float target_opacity,
    108                                base::TimeDelta duration,
    109                                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(
    115           target_opacity, duration));
    116   if (observer)
    117     sequence->AddObserver(observer);
    118   animator->StartAnimation(sequence);
    119 }
    120 
    121 // Fades |window| to |opacity| over |duration|.
    122 void StartOpacityAnimationForWindow(aura::Window* window,
    123                                     float opacity,
    124                                     base::TimeDelta duration,
    125                                     ui::LayerAnimationObserver* observer) {
    126   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(
    130       ui::LayerAnimationElement::CreateOpacityElement(opacity, duration));
    131   if (observer)
    132     sequence->AddObserver(observer);
    133   animator->StartAnimation(sequence);
    134 }
    135 
    136 // Makes |window| fully transparent instantaneously.
    137 void 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.
    146 void 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 
    153 void HideWindow(aura::Window* window,
    154                 base::TimeDelta duration,
    155                 bool above,
    156                 ui::LayerAnimationObserver* observer) {
    157   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 
    164   settings.SetTweenType(gfx::Tween::EASE_OUT);
    165   SetTransformForScaleAnimation(layer,
    166       above ? LAYER_SCALE_ANIMATION_ABOVE : LAYER_SCALE_ANIMATION_BELOW);
    167 
    168   settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
    169   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 
    178   // 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().
    183   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|.
    193 void 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 
    204   settings.SetTweenType(gfx::Tween::EASE_OUT);
    205   layer->SetTransform(gfx::Transform());
    206 
    207   settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
    208   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()));
    219     sequence->AddObserver(observer);
    220     layer->GetAnimator()->ScheduleAnimation(sequence);
    221   }
    222 }
    223 
    224 void ShowWindow(aura::Window* window,
    225                 base::TimeDelta duration,
    226                 bool above,
    227                 ui::LayerAnimationObserver* observer) {
    228   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|.
    243 void StartGrayscaleBrightnessAnimationForWindow(
    244     aura::Window* window,
    245     float target,
    246     base::TimeDelta duration,
    247     gfx::Tween::Type tween_type,
    248     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 
    272   if (observer)
    273     animations[0]->AddObserver(observer);
    274 
    275   animator->set_preemption_strategy(
    276       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
    277 
    278   animator->StartTogether(animations);
    279 }
    280 
    281 // Animation observer that will drop animated foreground once animation is
    282 // finished. It is used in when undoing shutdown animation.
    283 class 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 
    315 
    316 bool 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 
    386 }  // namespace
    387 
    388 bool 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();
    396     if (!IsLayerAnimated(layer, type))
    397       return false;
    398   }
    399   return true;
    400 }
    401 
    402 bool SessionStateAnimator::TestApi::RootWindowIsAnimated(AnimationType type)
    403     const {
    404   aura::Window* root_window = Shell::GetPrimaryRootWindow();
    405   ui::Layer* layer = root_window->layer();
    406   return IsLayerAnimated(layer, type);
    407 }
    408 
    409 const int SessionStateAnimator::kAllLockScreenContainersMask =
    410     SessionStateAnimator::LOCK_SCREEN_BACKGROUND |
    411     SessionStateAnimator::LOCK_SCREEN_CONTAINERS |
    412     SessionStateAnimator::LOCK_SCREEN_RELATED_CONTAINERS;
    413 
    414 const int SessionStateAnimator::kAllContainersMask =
    415     SessionStateAnimator::kAllLockScreenContainersMask |
    416     SessionStateAnimator::DESKTOP_BACKGROUND |
    417     SessionStateAnimator::LAUNCHER |
    418     SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS;
    419 
    420 SessionStateAnimator::SessionStateAnimator() {
    421 }
    422 
    423 SessionStateAnimator::~SessionStateAnimator() {
    424 }
    425 
    426 base::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 
    453 // Fills |containers| with the containers described by |container_mask|.
    454 void SessionStateAnimator::GetContainers(int container_mask,
    455                                          aura::Window::Windows* containers) {
    456   aura::Window* root_window = Shell::GetPrimaryRootWindow();
    457   containers->clear();
    458 
    459   if (container_mask & DESKTOP_BACKGROUND) {
    460     containers->push_back(Shell::GetContainer(
    461         root_window, kShellWindowId_DesktopBackgroundContainer));
    462   }
    463   if (container_mask & LAUNCHER) {
    464     containers->push_back(
    465         Shell::GetContainer(root_window, kShellWindowId_ShelfContainer));
    466   }
    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(
    471         root_window, kShellWindowId_NonLockScreenContainersContainer);
    472     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;
    477       if (window->id() == kShellWindowId_ShelfContainer)
    478         continue;
    479       containers->push_back(window);
    480     }
    481   }
    482   if (container_mask & LOCK_SCREEN_BACKGROUND) {
    483     containers->push_back(Shell::GetContainer(
    484         root_window, kShellWindowId_LockScreenBackgroundContainer));
    485   }
    486   if (container_mask & LOCK_SCREEN_CONTAINERS) {
    487     containers->push_back(Shell::GetContainer(
    488         root_window, kShellWindowId_LockScreenContainersContainer));
    489   }
    490   if (container_mask & LOCK_SCREEN_RELATED_CONTAINERS) {
    491     containers->push_back(Shell::GetContainer(
    492         root_window, kShellWindowId_LockScreenRelatedContainersContainer));
    493   }
    494 }
    495 
    496 void SessionStateAnimator::StartAnimation(int container_mask,
    497                                           AnimationType type,
    498                                           AnimationSpeed speed) {
    499   aura::Window::Windows containers;
    500   GetContainers(container_mask, &containers);
    501   for (aura::Window::Windows::const_iterator it = containers.begin();
    502        it != containers.end(); ++it) {
    503     RunAnimationForWindow(*it, type, speed, NULL);
    504   }
    505 }
    506 
    507 void SessionStateAnimator::StartAnimationWithCallback(
    508     int container_mask,
    509     AnimationType type,
    510     AnimationSpeed speed,
    511     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);
    518     RunAnimationForWindow(*it, type, speed, observer);
    519   }
    520 }
    521 
    522 void 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 
    535 void SessionStateAnimator::StartGlobalAnimation(AnimationType type,
    536                                                 AnimationSpeed speed) {
    537   aura::Window* root_window = Shell::GetPrimaryRootWindow();
    538   RunAnimationForWindow(root_window, type, speed, NULL);
    539 }
    540 
    541 void SessionStateAnimator::RunAnimationForWindow(
    542     aura::Window* window,
    543     AnimationType type,
    544     AnimationSpeed speed,
    545     ui::LayerAnimationObserver* observer) {
    546   base::TimeDelta duration = GetDuration(speed);
    547 
    548   switch (type) {
    549     case ANIMATION_PARTIAL_CLOSE:
    550       StartSlowCloseAnimationForWindow(window, duration, observer);
    551       break;
    552     case ANIMATION_UNDO_PARTIAL_CLOSE:
    553       StartUndoSlowCloseAnimationForWindow(window, duration, observer);
    554       break;
    555     case ANIMATION_FULL_CLOSE:
    556       StartFastCloseAnimationForWindow(window, duration, observer);
    557       break;
    558     case ANIMATION_FADE_IN:
    559       StartOpacityAnimationForWindow(window, 1.0, duration, observer);
    560       break;
    561     case ANIMATION_FADE_OUT:
    562       StartOpacityAnimationForWindow(window, 0.0, duration, observer);
    563       break;
    564     case ANIMATION_HIDE_IMMEDIATELY:
    565       DCHECK_EQ(speed, ANIMATION_SPEED_IMMEDIATE);
    566       HideWindowImmediately(window, observer);
    567       break;
    568     case ANIMATION_RESTORE:
    569       DCHECK_EQ(speed, ANIMATION_SPEED_IMMEDIATE);
    570       RestoreWindow(window, observer);
    571       break;
    572     case ANIMATION_LIFT:
    573       HideWindow(window, duration, true, observer);
    574       break;
    575     case ANIMATION_DROP:
    576       ShowWindow(window, duration, true, observer);
    577       break;
    578     case ANIMATION_UNDO_LIFT:
    579       TransformWindowToBaseState(window, duration, observer);
    580       break;
    581     case ANIMATION_RAISE_TO_SCREEN:
    582       ShowWindow(window, duration, false, observer);
    583       break;
    584     case ANIMATION_LOWER_BELOW_SCREEN:
    585       HideWindow(window, duration, false, observer);
    586       break;
    587     case ANIMATION_PARTIAL_FADE_IN:
    588       StartPartialFadeAnimation(
    589           window, kPartialFadeRatio, duration, observer);
    590       break;
    591     case ANIMATION_UNDO_PARTIAL_FADE_IN:
    592       StartPartialFadeAnimation(window, 0.0, duration, observer);
    593       break;
    594     case ANIMATION_FULL_FADE_IN:
    595       StartPartialFadeAnimation(window, 1.0, duration, observer);
    596       break;
    597     case ANIMATION_GRAYSCALE_BRIGHTNESS:
    598       StartGrayscaleBrightnessAnimationForWindow(
    599           window, 1.0, duration, gfx::Tween::EASE_IN, observer);
    600       break;
    601     case ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS:
    602       StartGrayscaleBrightnessAnimationForWindow(
    603           window, 0.0, duration, gfx::Tween::EASE_IN_OUT, observer);
    604       break;
    605   }
    606 }
    607 
    608 }  // namespace ash
    609