Home | History | Annotate | Download | only in corewm
      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 "ui/views/corewm/window_animations.h"
      6 
      7 #include <math.h>
      8 
      9 #include <algorithm>
     10 #include <vector>
     11 
     12 #include "base/command_line.h"
     13 #include "base/compiler_specific.h"
     14 #include "base/logging.h"
     15 #include "base/message_loop/message_loop.h"
     16 #include "base/stl_util.h"
     17 #include "base/time/time.h"
     18 #include "ui/aura/client/animation_host.h"
     19 #include "ui/aura/client/aura_constants.h"
     20 #include "ui/aura/window.h"
     21 #include "ui/aura/window_delegate.h"
     22 #include "ui/aura/window_observer.h"
     23 #include "ui/aura/window_property.h"
     24 #include "ui/compositor/compositor_observer.h"
     25 #include "ui/compositor/layer.h"
     26 #include "ui/compositor/layer_animation_observer.h"
     27 #include "ui/compositor/layer_animation_sequence.h"
     28 #include "ui/compositor/layer_animator.h"
     29 #include "ui/compositor/scoped_layer_animation_settings.h"
     30 #include "ui/gfx/interpolated_transform.h"
     31 #include "ui/gfx/rect_conversions.h"
     32 #include "ui/gfx/screen.h"
     33 #include "ui/gfx/vector3d_f.h"
     34 #include "ui/views/corewm/corewm_switches.h"
     35 #include "ui/views/corewm/window_util.h"
     36 #include "ui/views/view.h"
     37 #include "ui/views/widget/widget.h"
     38 
     39 DECLARE_WINDOW_PROPERTY_TYPE(int)
     40 DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::WindowVisibilityAnimationType)
     41 DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::WindowVisibilityAnimationTransition)
     42 DECLARE_WINDOW_PROPERTY_TYPE(float)
     43 DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(VIEWS_EXPORT, bool)
     44 
     45 using aura::Window;
     46 using base::TimeDelta;
     47 using ui::Layer;
     48 
     49 namespace views {
     50 namespace corewm {
     51 namespace {
     52 const float kWindowAnimation_Vertical_TranslateY = 15.f;
     53 }  // namespace
     54 
     55 DEFINE_WINDOW_PROPERTY_KEY(int,
     56                            kWindowVisibilityAnimationTypeKey,
     57                            WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
     58 DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0);
     59 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition,
     60                            kWindowVisibilityAnimationTransitionKey,
     61                            ANIMATE_BOTH);
     62 DEFINE_WINDOW_PROPERTY_KEY(float,
     63                            kWindowVisibilityAnimationVerticalPositionKey,
     64                            kWindowAnimation_Vertical_TranslateY);
     65 
     66 namespace {
     67 
     68 const int kDefaultAnimationDurationForMenuMS = 150;
     69 
     70 const float kWindowAnimation_HideOpacity = 0.f;
     71 const float kWindowAnimation_ShowOpacity = 1.f;
     72 const float kWindowAnimation_TranslateFactor = 0.5f;
     73 const float kWindowAnimation_ScaleFactor = .95f;
     74 
     75 const int kWindowAnimation_Rotate_DurationMS = 180;
     76 const int kWindowAnimation_Rotate_OpacityDurationPercent = 90;
     77 const float kWindowAnimation_Rotate_TranslateY = -20.f;
     78 const float kWindowAnimation_Rotate_PerspectiveDepth = 500.f;
     79 const float kWindowAnimation_Rotate_DegreesX = 5.f;
     80 const float kWindowAnimation_Rotate_ScaleFactor = .99f;
     81 
     82 const float kWindowAnimation_Bounce_Scale = 1.02f;
     83 const int kWindowAnimation_Bounce_DurationMS = 180;
     84 const int kWindowAnimation_Bounce_GrowShrinkDurationPercent = 40;
     85 
     86 base::TimeDelta GetWindowVisibilityAnimationDuration(aura::Window* window) {
     87   int duration =
     88       window->GetProperty(kWindowVisibilityAnimationDurationKey);
     89   if (duration == 0 && window->type() == aura::client::WINDOW_TYPE_MENU) {
     90     return base::TimeDelta::FromMilliseconds(
     91         kDefaultAnimationDurationForMenuMS);
     92   }
     93   return TimeDelta::FromInternalValue(duration);
     94 }
     95 
     96 // Gets/sets the WindowVisibilityAnimationType associated with a window.
     97 // TODO(beng): redundant/fold into method on public api?
     98 int GetWindowVisibilityAnimationType(aura::Window* window) {
     99   int type = window->GetProperty(kWindowVisibilityAnimationTypeKey);
    100   if (type == WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT) {
    101     return (window->type() == aura::client::WINDOW_TYPE_MENU ||
    102             window->type() == aura::client::WINDOW_TYPE_TOOLTIP) ?
    103         WINDOW_VISIBILITY_ANIMATION_TYPE_FADE :
    104         WINDOW_VISIBILITY_ANIMATION_TYPE_DROP;
    105   }
    106   return type;
    107 }
    108 
    109 // Observes a hide animation.
    110 // A window can be hidden for a variety of reasons. Sometimes, Hide() will be
    111 // called and life is simple. Sometimes, the window is actually bound to a
    112 // views::Widget and that Widget is closed, and life is a little more
    113 // complicated. When a Widget is closed the aura::Window* is actually not
    114 // destroyed immediately - it is actually just immediately hidden and then
    115 // destroyed when the stack unwinds. To handle this case, we start the hide
    116 // animation immediately when the window is hidden, then when the window is
    117 // subsequently destroyed this object acquires ownership of the window's layer,
    118 // so that it can continue animating it until the animation completes.
    119 // Regardless of whether or not the window is destroyed, this object deletes
    120 // itself when the animation completes.
    121 class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver,
    122                                       public aura::WindowObserver {
    123  public:
    124   explicit HidingWindowAnimationObserver(aura::Window* window)
    125       : window_(window) {
    126     window_->AddObserver(this);
    127   }
    128   virtual ~HidingWindowAnimationObserver() {
    129     STLDeleteElements(&layers_);
    130   }
    131 
    132  private:
    133   // Overridden from ui::ImplicitAnimationObserver:
    134   virtual void OnImplicitAnimationsCompleted() OVERRIDE {
    135     // Window may have been destroyed by this point.
    136     if (window_) {
    137       aura::client::AnimationHost* animation_host =
    138           aura::client::GetAnimationHost(window_);
    139       if (animation_host)
    140         animation_host->OnWindowHidingAnimationCompleted();
    141       window_->RemoveObserver(this);
    142     }
    143     delete this;
    144   }
    145 
    146   // Overridden from aura::WindowObserver:
    147   virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
    148     DCHECK_EQ(window, window_);
    149     DCHECK(layers_.empty());
    150     AcquireAllLayers(window_);
    151 
    152     // If the Widget has views with layers, then it is necessary to take
    153     // ownership of those layers too.
    154     views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_);
    155     const views::Widget* const_widget = widget;
    156     if (widget && const_widget->GetRootView() && widget->GetContentsView())
    157       AcquireAllViewLayers(widget->GetContentsView());
    158     window_->RemoveObserver(this);
    159     window_ = NULL;
    160   }
    161 
    162   void AcquireAllLayers(aura::Window* window) {
    163     ui::Layer* layer = window->AcquireLayer();
    164     DCHECK(layer);
    165     layers_.push_back(layer);
    166     for (aura::Window::Windows::const_iterator it = window->children().begin();
    167          it != window->children().end();
    168          ++it)
    169       AcquireAllLayers(*it);
    170   }
    171 
    172   void AcquireAllViewLayers(views::View* view) {
    173     for (int i = 0; i < view->child_count(); ++i)
    174       AcquireAllViewLayers(view->child_at(i));
    175     if (view->layer()) {
    176       ui::Layer* layer = view->RecreateLayer();
    177       if (layer) {
    178         layer->SuppressPaint();
    179         layers_.push_back(layer);
    180       }
    181     }
    182   }
    183 
    184   aura::Window* window_;
    185   std::vector<ui::Layer*> layers_;
    186 
    187   DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver);
    188 };
    189 
    190 void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) {
    191   const Layer* root = layer;
    192   while (root->parent())
    193     root = root->parent();
    194   layer->GetTargetTransformRelativeTo(root, transform);
    195 }
    196 
    197 gfx::Rect GetLayerWorldBoundsAfterTransform(ui::Layer* layer,
    198                                             const gfx::Transform& transform) {
    199   gfx::Transform in_world = transform;
    200   GetTransformRelativeToRoot(layer, &in_world);
    201 
    202   gfx::RectF transformed = layer->bounds();
    203   in_world.TransformRect(&transformed);
    204 
    205   return gfx::ToEnclosingRect(transformed);
    206 }
    207 
    208 // Augment the host window so that the enclosing bounds of the full
    209 // animation will fit inside of it.
    210 void AugmentWindowSize(aura::Window* window,
    211                        const gfx::Transform& start_transform,
    212                        const gfx::Transform& end_transform) {
    213   aura::client::AnimationHost* animation_host =
    214       aura::client::GetAnimationHost(window);
    215   if (!animation_host)
    216     return;
    217 
    218   gfx::Rect world_at_start =
    219       GetLayerWorldBoundsAfterTransform(window->layer(), start_transform);
    220   gfx::Rect world_at_end =
    221       GetLayerWorldBoundsAfterTransform(window->layer(), end_transform);
    222   gfx::Rect union_in_window_space =
    223       gfx::UnionRects(world_at_start, world_at_end);
    224   gfx::Rect current_bounds = window->bounds();
    225   gfx::Rect result(union_in_window_space.x() - current_bounds.x(),
    226                    union_in_window_space.y() - current_bounds.y(),
    227                    union_in_window_space.width() - current_bounds.width(),
    228                    union_in_window_space.height() - current_bounds.height());
    229   animation_host->SetHostTransitionBounds(result);
    230 }
    231 
    232 // Shows a window using an animation, animating its opacity from 0.f to 1.f,
    233 // its visibility to true, and its transform from |start_transform| to
    234 // |end_transform|.
    235 void AnimateShowWindowCommon(aura::Window* window,
    236                              const gfx::Transform& start_transform,
    237                              const gfx::Transform& end_transform) {
    238   window->layer()->set_delegate(window);
    239 
    240   AugmentWindowSize(window, start_transform, end_transform);
    241 
    242   window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
    243   window->layer()->SetTransform(start_transform);
    244   window->layer()->SetVisible(true);
    245 
    246   {
    247     // Property sets within this scope will be implicitly animated.
    248     ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
    249     base::TimeDelta duration = GetWindowVisibilityAnimationDuration(window);
    250     if (duration.ToInternalValue() > 0)
    251       settings.SetTransitionDuration(duration);
    252 
    253     window->layer()->SetTransform(end_transform);
    254     window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
    255   }
    256 }
    257 
    258 // Hides a window using an animation, animating its opacity from 1.f to 0.f,
    259 // its visibility to false, and its transform to |end_transform|.
    260 void AnimateHideWindowCommon(aura::Window* window,
    261                              const gfx::Transform& end_transform) {
    262   AugmentWindowSize(window, gfx::Transform(), end_transform);
    263   window->layer()->set_delegate(NULL);
    264 
    265   // Property sets within this scope will be implicitly animated.
    266   ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
    267   settings.AddObserver(new HidingWindowAnimationObserver(window));
    268 
    269   base::TimeDelta duration = GetWindowVisibilityAnimationDuration(window);
    270   if (duration.ToInternalValue() > 0)
    271     settings.SetTransitionDuration(duration);
    272 
    273   window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
    274   window->layer()->SetTransform(end_transform);
    275   window->layer()->SetVisible(false);
    276 }
    277 
    278 static gfx::Transform GetScaleForWindow(aura::Window* window) {
    279   gfx::Rect bounds = window->bounds();
    280   gfx::Transform scale = gfx::GetScaleTransform(
    281       gfx::Point(kWindowAnimation_TranslateFactor * bounds.width(),
    282                  kWindowAnimation_TranslateFactor * bounds.height()),
    283       kWindowAnimation_ScaleFactor);
    284   return scale;
    285 }
    286 
    287 // Show/Hide windows using a shrink animation.
    288 void AnimateShowWindow_Drop(aura::Window* window) {
    289   AnimateShowWindowCommon(window, GetScaleForWindow(window), gfx::Transform());
    290 }
    291 
    292 void AnimateHideWindow_Drop(aura::Window* window) {
    293   AnimateHideWindowCommon(window, GetScaleForWindow(window));
    294 }
    295 
    296 // Show/Hide windows using a vertical Glenimation.
    297 void AnimateShowWindow_Vertical(aura::Window* window) {
    298   gfx::Transform transform;
    299   transform.Translate(0, window->GetProperty(
    300       kWindowVisibilityAnimationVerticalPositionKey));
    301   AnimateShowWindowCommon(window, transform, gfx::Transform());
    302 }
    303 
    304 void AnimateHideWindow_Vertical(aura::Window* window) {
    305   gfx::Transform transform;
    306   transform.Translate(0, window->GetProperty(
    307       kWindowVisibilityAnimationVerticalPositionKey));
    308   AnimateHideWindowCommon(window, transform);
    309 }
    310 
    311 // Show/Hide windows using a fade.
    312 void AnimateShowWindow_Fade(aura::Window* window) {
    313   AnimateShowWindowCommon(window, gfx::Transform(), gfx::Transform());
    314 }
    315 
    316 void AnimateHideWindow_Fade(aura::Window* window) {
    317   AnimateHideWindowCommon(window, gfx::Transform());
    318 }
    319 
    320 ui::LayerAnimationElement* CreateGrowShrinkElement(
    321     aura::Window* window, bool grow) {
    322   scoped_ptr<ui::InterpolatedTransform> scale(new ui::InterpolatedScale(
    323       gfx::Point3F(kWindowAnimation_Bounce_Scale,
    324                    kWindowAnimation_Bounce_Scale,
    325                    1),
    326       gfx::Point3F(1, 1, 1)));
    327   scoped_ptr<ui::InterpolatedTransform> scale_about_pivot(
    328       new ui::InterpolatedTransformAboutPivot(
    329           gfx::Point(window->bounds().width() * 0.5,
    330                      window->bounds().height() * 0.5),
    331           scale.release()));
    332   scale_about_pivot->SetReversed(grow);
    333   scoped_ptr<ui::LayerAnimationElement> transition(
    334       ui::LayerAnimationElement::CreateInterpolatedTransformElement(
    335           scale_about_pivot.release(),
    336           base::TimeDelta::FromMilliseconds(
    337               kWindowAnimation_Bounce_DurationMS *
    338                   kWindowAnimation_Bounce_GrowShrinkDurationPercent / 100)));
    339   transition->set_tween_type(grow ? ui::Tween::EASE_OUT : ui::Tween::EASE_IN);
    340   return transition.release();
    341 }
    342 
    343 void AnimateBounce(aura::Window* window) {
    344   ui::ScopedLayerAnimationSettings scoped_settings(
    345       window->layer()->GetAnimator());
    346   scoped_settings.SetPreemptionStrategy(
    347       ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
    348   window->layer()->set_delegate(window);
    349   scoped_ptr<ui::LayerAnimationSequence> sequence(
    350       new ui::LayerAnimationSequence);
    351   sequence->AddElement(CreateGrowShrinkElement(window, true));
    352   ui::LayerAnimationElement::AnimatableProperties paused_properties;
    353   paused_properties.insert(ui::LayerAnimationElement::BOUNDS);
    354   sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement(
    355       paused_properties,
    356       base::TimeDelta::FromMilliseconds(
    357         kWindowAnimation_Bounce_DurationMS *
    358             (100 - 2 * kWindowAnimation_Bounce_GrowShrinkDurationPercent) /
    359             100)));
    360   sequence->AddElement(CreateGrowShrinkElement(window, false));
    361   window->layer()->GetAnimator()->StartAnimation(sequence.release());
    362 }
    363 
    364 void AddLayerAnimationsForRotate(aura::Window* window, bool show) {
    365   window->layer()->set_delegate(window);
    366   if (show)
    367     window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
    368 
    369   base::TimeDelta duration = base::TimeDelta::FromMilliseconds(
    370       kWindowAnimation_Rotate_DurationMS);
    371 
    372   if (!show) {
    373     new HidingWindowAnimationObserver(window);
    374     window->layer()->GetAnimator()->SchedulePauseForProperties(
    375         duration * (100 - kWindowAnimation_Rotate_OpacityDurationPercent) / 100,
    376         ui::LayerAnimationElement::OPACITY,
    377         -1);
    378   }
    379   scoped_ptr<ui::LayerAnimationElement> opacity(
    380       ui::LayerAnimationElement::CreateOpacityElement(
    381           show ? kWindowAnimation_ShowOpacity : kWindowAnimation_HideOpacity,
    382           duration * kWindowAnimation_Rotate_OpacityDurationPercent / 100));
    383   opacity->set_tween_type(ui::Tween::EASE_IN_OUT);
    384   window->layer()->GetAnimator()->ScheduleAnimation(
    385       new ui::LayerAnimationSequence(opacity.release()));
    386 
    387   float xcenter = window->bounds().width() * 0.5;
    388 
    389   gfx::Transform transform;
    390   transform.Translate(xcenter, 0);
    391   transform.ApplyPerspectiveDepth(kWindowAnimation_Rotate_PerspectiveDepth);
    392   transform.Translate(-xcenter, 0);
    393   scoped_ptr<ui::InterpolatedTransform> perspective(
    394       new ui::InterpolatedConstantTransform(transform));
    395 
    396   scoped_ptr<ui::InterpolatedTransform> scale(
    397       new ui::InterpolatedScale(1, kWindowAnimation_Rotate_ScaleFactor));
    398   scoped_ptr<ui::InterpolatedTransform> scale_about_pivot(
    399       new ui::InterpolatedTransformAboutPivot(
    400           gfx::Point(xcenter, kWindowAnimation_Rotate_TranslateY),
    401           scale.release()));
    402 
    403   scoped_ptr<ui::InterpolatedTransform> translation(
    404       new ui::InterpolatedTranslation(gfx::Point(), gfx::Point(
    405           0, kWindowAnimation_Rotate_TranslateY)));
    406 
    407   scoped_ptr<ui::InterpolatedTransform> rotation(
    408       new ui::InterpolatedAxisAngleRotation(
    409           gfx::Vector3dF(1, 0, 0), 0, kWindowAnimation_Rotate_DegreesX));
    410 
    411   scale_about_pivot->SetChild(perspective.release());
    412   translation->SetChild(scale_about_pivot.release());
    413   rotation->SetChild(translation.release());
    414   rotation->SetReversed(show);
    415 
    416   scoped_ptr<ui::LayerAnimationElement> transition(
    417       ui::LayerAnimationElement::CreateInterpolatedTransformElement(
    418           rotation.release(), duration));
    419 
    420   window->layer()->GetAnimator()->ScheduleAnimation(
    421       new ui::LayerAnimationSequence(transition.release()));
    422 }
    423 
    424 void AnimateShowWindow_Rotate(aura::Window* window) {
    425   AddLayerAnimationsForRotate(window, true);
    426 }
    427 
    428 void AnimateHideWindow_Rotate(aura::Window* window) {
    429   AddLayerAnimationsForRotate(window, false);
    430 }
    431 
    432 bool AnimateShowWindow(aura::Window* window) {
    433   if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW)) {
    434     if (HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) {
    435       // Since hide animation may have changed opacity and transform,
    436       // reset them to show the window.
    437       window->layer()->set_delegate(window);
    438       window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
    439       window->layer()->SetTransform(gfx::Transform());
    440     }
    441     return false;
    442   }
    443 
    444   switch (GetWindowVisibilityAnimationType(window)) {
    445     case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP:
    446       AnimateShowWindow_Drop(window);
    447       return true;
    448     case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL:
    449       AnimateShowWindow_Vertical(window);
    450       return true;
    451     case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE:
    452       AnimateShowWindow_Fade(window);
    453       return true;
    454     case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE:
    455       AnimateShowWindow_Rotate(window);
    456       return true;
    457     default:
    458       return false;
    459   }
    460 }
    461 
    462 bool AnimateHideWindow(aura::Window* window) {
    463   if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) {
    464     if (HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW)) {
    465       // Since show animation may have changed opacity and transform,
    466       // reset them, though the change should be hidden.
    467       window->layer()->set_delegate(NULL);
    468       window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
    469       window->layer()->SetTransform(gfx::Transform());
    470     }
    471     return false;
    472   }
    473 
    474   switch (GetWindowVisibilityAnimationType(window)) {
    475     case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP:
    476       AnimateHideWindow_Drop(window);
    477       return true;
    478     case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL:
    479       AnimateHideWindow_Vertical(window);
    480       return true;
    481     case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE:
    482       AnimateHideWindow_Fade(window);
    483       return true;
    484     case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE:
    485       AnimateHideWindow_Rotate(window);
    486       return true;
    487     default:
    488       return false;
    489   }
    490 }
    491 
    492 }  // namespace
    493 
    494 ////////////////////////////////////////////////////////////////////////////////
    495 // External interface
    496 
    497 void SetWindowVisibilityAnimationType(aura::Window* window, int type) {
    498   window->SetProperty(kWindowVisibilityAnimationTypeKey, type);
    499 }
    500 
    501 int GetWindowVisibilityAnimationType(aura::Window* window) {
    502   return window->GetProperty(kWindowVisibilityAnimationTypeKey);
    503 }
    504 
    505 void SetWindowVisibilityAnimationTransition(
    506     aura::Window* window,
    507     WindowVisibilityAnimationTransition transition) {
    508   window->SetProperty(kWindowVisibilityAnimationTransitionKey, transition);
    509 }
    510 
    511 bool HasWindowVisibilityAnimationTransition(
    512     aura::Window* window,
    513     WindowVisibilityAnimationTransition transition) {
    514   WindowVisibilityAnimationTransition prop = window->GetProperty(
    515       kWindowVisibilityAnimationTransitionKey);
    516   return (prop & transition) != 0;
    517 }
    518 
    519 void SetWindowVisibilityAnimationDuration(aura::Window* window,
    520                                           const TimeDelta& duration) {
    521   window->SetProperty(kWindowVisibilityAnimationDurationKey,
    522                       static_cast<int>(duration.ToInternalValue()));
    523 }
    524 
    525 void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window,
    526                                                   float position) {
    527   window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position);
    528 }
    529 
    530 ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver(
    531     aura::Window* window) {
    532   return new HidingWindowAnimationObserver(window);
    533 }
    534 
    535 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
    536   if (WindowAnimationsDisabled(window))
    537     return false;
    538   if (visible)
    539     return AnimateShowWindow(window);
    540   // Don't start hiding the window again if it's already being hidden.
    541   return window->layer()->GetTargetOpacity() != 0.0f &&
    542       AnimateHideWindow(window);
    543 }
    544 
    545 bool AnimateWindow(aura::Window* window, WindowAnimationType type) {
    546   switch (type) {
    547   case WINDOW_ANIMATION_TYPE_BOUNCE:
    548     AnimateBounce(window);
    549     return true;
    550   default:
    551     NOTREACHED();
    552     return false;
    553   }
    554 }
    555 
    556 bool WindowAnimationsDisabled(aura::Window* window) {
    557   return (window &&
    558           window->GetProperty(aura::client::kAnimationsDisabledKey)) ||
    559       CommandLine::ForCurrentProcess()->HasSwitch(
    560           switches::kWindowAnimationsDisabled);
    561 }
    562 
    563 }  // namespace corewm
    564 }  // namespace views
    565