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