• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetWindowVisibilityAnimationDuration(aura::Window * window)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?
GetWindowVisibilityAnimationType(aura::Window * window)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:
HidingWindowAnimationObserver(aura::Window * window)125   explicit HidingWindowAnimationObserver(aura::Window* window)
126       : window_(window) {
127     window_->AddObserver(this);
128   }
~HidingWindowAnimationObserver()129   virtual ~HidingWindowAnimationObserver() {
130     STLDeleteElements(&layers_);
131   }
132 
133  private:
134   // Overridden from ui::ImplicitAnimationObserver:
OnImplicitAnimationsCompleted()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:
OnWindowDestroying(aura::Window * window)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 
AcquireAllLayers(aura::Window * window)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 
AcquireAllViewLayers(views::View * view)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 
GetTransformRelativeToRoot(ui::Layer * layer,gfx::Transform * transform)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 
GetLayerWorldBoundsAfterTransform(ui::Layer * layer,const gfx::Transform & transform)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.
AugmentWindowSize(aura::Window * window,const gfx::Transform & end_transform)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|.
AnimateShowWindowCommon(aura::Window * window,const gfx::Transform & start_transform,const gfx::Transform & 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|.
AnimateHideWindowCommon(aura::Window * window,const gfx::Transform & 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 
GetScaleForWindow(aura::Window * window)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.
AnimateShowWindow_Drop(aura::Window * window)297 void AnimateShowWindow_Drop(aura::Window* window) {
298   AnimateShowWindowCommon(window, GetScaleForWindow(window), gfx::Transform());
299 }
300 
AnimateHideWindow_Drop(aura::Window * window)301 void AnimateHideWindow_Drop(aura::Window* window) {
302   AnimateHideWindowCommon(window, GetScaleForWindow(window));
303 }
304 
305 // Show/Hide windows using a vertical Glenimation.
AnimateShowWindow_Vertical(aura::Window * window)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 
AnimateHideWindow_Vertical(aura::Window * window)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.
AnimateShowWindow_Fade(aura::Window * window)321 void AnimateShowWindow_Fade(aura::Window* window) {
322   AnimateShowWindowCommon(window, gfx::Transform(), gfx::Transform());
323 }
324 
AnimateHideWindow_Fade(aura::Window * window)325 void AnimateHideWindow_Fade(aura::Window* window) {
326   AnimateHideWindowCommon(window, gfx::Transform());
327 }
328 
CreateGrowShrinkElement(aura::Window * window,bool grow)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 
AnimateBounce(aura::Window * window)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 
AddLayerAnimationsForRotate(aura::Window * window,bool show)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 
AnimateShowWindow_Rotate(aura::Window * window)433 void AnimateShowWindow_Rotate(aura::Window* window) {
434   AddLayerAnimationsForRotate(window, true);
435 }
436 
AnimateHideWindow_Rotate(aura::Window * window)437 void AnimateHideWindow_Rotate(aura::Window* window) {
438   AddLayerAnimationsForRotate(window, false);
439 }
440 
AnimateShowWindow(aura::Window * window)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 
AnimateHideWindow(aura::Window * window)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 
SetWindowVisibilityAnimationType(aura::Window * window,int type)506 void SetWindowVisibilityAnimationType(aura::Window* window, int type) {
507   window->SetProperty(kWindowVisibilityAnimationTypeKey, type);
508 }
509 
GetWindowVisibilityAnimationType(aura::Window * window)510 int GetWindowVisibilityAnimationType(aura::Window* window) {
511   return window->GetProperty(kWindowVisibilityAnimationTypeKey);
512 }
513 
SetWindowVisibilityAnimationTransition(aura::Window * window,WindowVisibilityAnimationTransition transition)514 void SetWindowVisibilityAnimationTransition(
515     aura::Window* window,
516     WindowVisibilityAnimationTransition transition) {
517   window->SetProperty(kWindowVisibilityAnimationTransitionKey, transition);
518 }
519 
HasWindowVisibilityAnimationTransition(aura::Window * window,WindowVisibilityAnimationTransition transition)520 bool HasWindowVisibilityAnimationTransition(
521     aura::Window* window,
522     WindowVisibilityAnimationTransition transition) {
523   WindowVisibilityAnimationTransition prop = window->GetProperty(
524       kWindowVisibilityAnimationTransitionKey);
525   return (prop & transition) != 0;
526 }
527 
SetWindowVisibilityAnimationDuration(aura::Window * window,const TimeDelta & duration)528 void SetWindowVisibilityAnimationDuration(aura::Window* window,
529                                           const TimeDelta& duration) {
530   window->SetProperty(kWindowVisibilityAnimationDurationKey,
531                       static_cast<int>(duration.ToInternalValue()));
532 }
533 
SetWindowVisibilityAnimationVerticalPosition(aura::Window * window,float position)534 void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window,
535                                                   float position) {
536   window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position);
537 }
538 
CreateHidingWindowAnimationObserver(aura::Window * window)539 ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver(
540     aura::Window* window) {
541   return new HidingWindowAnimationObserver(window);
542 }
543 
AnimateOnChildWindowVisibilityChanged(aura::Window * window,bool visible)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 
AnimateWindow(aura::Window * window,WindowAnimationType type)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 
WindowAnimationsDisabled(aura::Window * window)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