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