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