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.
5 #include "ui/wm/core/window_animations.h"
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/aura_constants.h"
19 #include "ui/aura/window.h"
20 #include "ui/aura/window_delegate.h"
21 #include "ui/aura/window_observer.h"
22 #include "ui/aura/window_property.h"
23 #include "ui/compositor/compositor_observer.h"
24 #include "ui/compositor/layer.h"
25 #include "ui/compositor/layer_animation_observer.h"
26 #include "ui/compositor/layer_animation_sequence.h"
27 #include "ui/compositor/layer_animator.h"
28 #include "ui/compositor/layer_tree_owner.h"
29 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
30 #include "ui/compositor/scoped_layer_animation_settings.h"
31 #include "ui/gfx/animation/animation.h"
32 #include "ui/gfx/interpolated_transform.h"
33 #include "ui/gfx/rect_conversions.h"
34 #include "ui/gfx/screen.h"
35 #include "ui/gfx/vector2d.h"
36 #include "ui/gfx/vector3d_f.h"
37 #include "ui/wm/core/window_util.h"
38 #include "ui/wm/core/wm_core_switches.h"
39 #include "ui/wm/public/animation_host.h"
41 DECLARE_WINDOW_PROPERTY_TYPE(int)
42 DECLARE_WINDOW_PROPERTY_TYPE(wm::WindowVisibilityAnimationType
)
43 DECLARE_WINDOW_PROPERTY_TYPE(wm::WindowVisibilityAnimationTransition
)
44 DECLARE_WINDOW_PROPERTY_TYPE(float)
45 DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(WM_EXPORT
, bool)
49 const float kWindowAnimation_Vertical_TranslateY
= 15.f
;
51 // A base class for hiding animation observer which has two roles:
52 // 1) Notifies AnimationHost at the end of hiding animation.
53 // 2) Detaches the window's layers for hiding animation and deletes
54 // them upon completion of the animation. This is necessary to a)
55 // ensure that the animation continues in the event of the window being
56 // deleted, and b) to ensure that the animation is visible even if the
57 // window gets restacked below other windows when focus or activation
59 // The subclass will determine when the animation is completed.
60 class HidingWindowAnimationObserverBase
: public aura::WindowObserver
{
62 explicit HidingWindowAnimationObserverBase(aura::Window
* window
)
64 window_
->AddObserver(this);
66 virtual ~HidingWindowAnimationObserverBase() {
68 window_
->RemoveObserver(this);
71 // aura::WindowObserver:
72 virtual void OnWindowDestroying(aura::Window
* window
) OVERRIDE
{
73 DCHECK_EQ(window
, window_
);
77 virtual void OnWindowDestroyed(aura::Window
* window
) OVERRIDE
{
78 DCHECK_EQ(window
, window_
);
82 // Detach the current layers and create new layers for |window_|.
83 // Stack the original layers above |window_| and its transient
84 // children. If the window has transient children, the original
85 // layers will be moved above the top most transient child so that
86 // activation change does not put the window above the animating
88 void DetachAndRecreateLayers() {
89 layer_owner_
= RecreateLayers(window_
);
90 if (window_
->parent()) {
91 const aura::Window::Windows
& transient_children
=
92 GetTransientChildren(window_
);
93 aura::Window::Windows::const_iterator iter
=
94 std::find(window_
->parent()->children().begin(),
95 window_
->parent()->children().end(),
97 DCHECK(iter
!= window_
->parent()->children().end());
98 aura::Window
* topmost_transient_child
= NULL
;
99 for (++iter
; iter
!= window_
->parent()->children().end(); ++iter
) {
100 if (std::find(transient_children
.begin(),
101 transient_children
.end(),
102 *iter
) != transient_children
.end()) {
103 topmost_transient_child
= *iter
;
106 if (topmost_transient_child
) {
107 window_
->parent()->layer()->StackAbove(
108 layer_owner_
->root(), topmost_transient_child
->layer());
114 // Invoked when the hiding animation is completed. It will delete
115 // 'this', and no operation should be made on this object after this
117 void OnAnimationCompleted() {
118 // Window may have been destroyed by this point.
120 aura::client::AnimationHost
* animation_host
=
121 aura::client::GetAnimationHost(window_
);
123 animation_host
->OnWindowHidingAnimationCompleted();
124 window_
->RemoveObserver(this);
130 // Invoked when the window is destroyed (or destroying).
131 void WindowInvalid() {
132 layer_owner_
->root()->SuppressPaint();
134 window_
->RemoveObserver(this);
138 aura::Window
* window_
;
140 // The owner of detached layers.
141 scoped_ptr
<ui::LayerTreeOwner
> layer_owner_
;
143 DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserverBase
);
148 DEFINE_WINDOW_PROPERTY_KEY(int,
149 kWindowVisibilityAnimationTypeKey
,
150 WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT
);
151 DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey
, 0);
152 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition
,
153 kWindowVisibilityAnimationTransitionKey
,
155 DEFINE_WINDOW_PROPERTY_KEY(float,
156 kWindowVisibilityAnimationVerticalPositionKey
,
157 kWindowAnimation_Vertical_TranslateY
);
159 // A HidingWindowAnimationObserver that deletes observer and detached
160 // layers upon the completion of the implicit animation.
161 class ImplicitHidingWindowAnimationObserver
162 : public HidingWindowAnimationObserverBase
,
163 public ui::ImplicitAnimationObserver
{
165 ImplicitHidingWindowAnimationObserver(
166 aura::Window
* window
,
167 ui::ScopedLayerAnimationSettings
* settings
);
168 virtual ~ImplicitHidingWindowAnimationObserver() {}
170 // ui::ImplicitAnimationObserver:
171 virtual void OnImplicitAnimationsCompleted() OVERRIDE
;
174 DISALLOW_COPY_AND_ASSIGN(ImplicitHidingWindowAnimationObserver
);
179 const int kDefaultAnimationDurationForMenuMS
= 150;
181 const float kWindowAnimation_HideOpacity
= 0.f
;
182 const float kWindowAnimation_ShowOpacity
= 1.f
;
183 const float kWindowAnimation_TranslateFactor
= 0.5f
;
184 const float kWindowAnimation_ScaleFactor
= .95f
;
186 const int kWindowAnimation_Rotate_DurationMS
= 180;
187 const int kWindowAnimation_Rotate_OpacityDurationPercent
= 90;
188 const float kWindowAnimation_Rotate_TranslateY
= -20.f
;
189 const float kWindowAnimation_Rotate_PerspectiveDepth
= 500.f
;
190 const float kWindowAnimation_Rotate_DegreesX
= 5.f
;
191 const float kWindowAnimation_Rotate_ScaleFactor
= .99f
;
193 const float kWindowAnimation_Bounce_Scale
= 1.02f
;
194 const int kWindowAnimation_Bounce_DurationMS
= 180;
195 const int kWindowAnimation_Bounce_GrowShrinkDurationPercent
= 40;
197 base::TimeDelta
GetWindowVisibilityAnimationDuration(
198 const aura::Window
& window
) {
200 window
.GetProperty(kWindowVisibilityAnimationDurationKey
);
201 if (duration
== 0 && window
.type() == ui::wm::WINDOW_TYPE_MENU
) {
202 return base::TimeDelta::FromMilliseconds(
203 kDefaultAnimationDurationForMenuMS
);
205 return base::TimeDelta::FromInternalValue(duration
);
208 // Gets/sets the WindowVisibilityAnimationType associated with a window.
209 // TODO(beng): redundant/fold into method on public api?
210 int GetWindowVisibilityAnimationType(aura::Window
* window
) {
211 int type
= window
->GetProperty(kWindowVisibilityAnimationTypeKey
);
212 if (type
== WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT
) {
213 return (window
->type() == ui::wm::WINDOW_TYPE_MENU
||
214 window
->type() == ui::wm::WINDOW_TYPE_TOOLTIP
)
215 ? WINDOW_VISIBILITY_ANIMATION_TYPE_FADE
216 : WINDOW_VISIBILITY_ANIMATION_TYPE_DROP
;
221 void GetTransformRelativeToRoot(ui::Layer
* layer
, gfx::Transform
* transform
) {
222 const ui::Layer
* root
= layer
;
223 while (root
->parent())
224 root
= root
->parent();
225 layer
->GetTargetTransformRelativeTo(root
, transform
);
228 gfx::Rect
GetLayerWorldBoundsAfterTransform(ui::Layer
* layer
,
229 const gfx::Transform
& transform
) {
230 gfx::Transform in_world
= transform
;
231 GetTransformRelativeToRoot(layer
, &in_world
);
233 gfx::RectF transformed
= layer
->bounds();
234 in_world
.TransformRect(&transformed
);
236 return gfx::ToEnclosingRect(transformed
);
239 // Augment the host window so that the enclosing bounds of the full
240 // animation will fit inside of it.
241 void AugmentWindowSize(aura::Window
* window
,
242 const gfx::Transform
& end_transform
) {
243 aura::client::AnimationHost
* animation_host
=
244 aura::client::GetAnimationHost(window
);
248 const gfx::Rect
& world_at_start
= window
->bounds();
249 gfx::Rect world_at_end
=
250 GetLayerWorldBoundsAfterTransform(window
->layer(), end_transform
);
251 gfx::Rect union_in_window_space
=
252 gfx::UnionRects(world_at_start
, world_at_end
);
254 // Calculate the top left and bottom right deltas to be added to the window
256 gfx::Vector2d
top_left_delta(world_at_start
.x() - union_in_window_space
.x(),
257 world_at_start
.y() - union_in_window_space
.y());
259 gfx::Vector2d
bottom_right_delta(
260 union_in_window_space
.x() + union_in_window_space
.width() -
261 (world_at_start
.x() + world_at_start
.width()),
262 union_in_window_space
.y() + union_in_window_space
.height() -
263 (world_at_start
.y() + world_at_start
.height()));
265 DCHECK(top_left_delta
.x() >= 0 && top_left_delta
.y() >= 0 &&
266 bottom_right_delta
.x() >= 0 && bottom_right_delta
.y() >= 0);
268 animation_host
->SetHostTransitionOffsets(top_left_delta
, bottom_right_delta
);
271 // Shows a window using an animation, animating its opacity from 0.f to 1.f,
272 // its visibility to true, and its transform from |start_transform| to
274 void AnimateShowWindowCommon(aura::Window
* window
,
275 const gfx::Transform
& start_transform
,
276 const gfx::Transform
& end_transform
) {
277 AugmentWindowSize(window
, end_transform
);
279 window
->layer()->SetOpacity(kWindowAnimation_HideOpacity
);
280 window
->layer()->SetTransform(start_transform
);
281 window
->layer()->SetVisible(true);
284 // Property sets within this scope will be implicitly animated.
285 ui::ScopedLayerAnimationSettings
settings(window
->layer()->GetAnimator());
286 base::TimeDelta duration
= GetWindowVisibilityAnimationDuration(*window
);
287 if (duration
.ToInternalValue() > 0)
288 settings
.SetTransitionDuration(duration
);
290 window
->layer()->SetTransform(end_transform
);
291 window
->layer()->SetOpacity(kWindowAnimation_ShowOpacity
);
295 // Hides a window using an animation, animating its opacity from 1.f to 0.f,
296 // its visibility to false, and its transform to |end_transform|.
297 void AnimateHideWindowCommon(aura::Window
* window
,
298 const gfx::Transform
& end_transform
) {
299 AugmentWindowSize(window
, end_transform
);
301 // Property sets within this scope will be implicitly animated.
302 ScopedHidingAnimationSettings
hiding_settings(window
);
303 base::TimeDelta duration
= GetWindowVisibilityAnimationDuration(*window
);
304 if (duration
.ToInternalValue() > 0)
305 hiding_settings
.layer_animation_settings()->SetTransitionDuration(duration
);
307 window
->layer()->SetOpacity(kWindowAnimation_HideOpacity
);
308 window
->layer()->SetTransform(end_transform
);
309 window
->layer()->SetVisible(false);
312 static gfx::Transform
GetScaleForWindow(aura::Window
* window
) {
313 gfx::Rect bounds
= window
->bounds();
314 gfx::Transform scale
= gfx::GetScaleTransform(
315 gfx::Point(kWindowAnimation_TranslateFactor
* bounds
.width(),
316 kWindowAnimation_TranslateFactor
* bounds
.height()),
317 kWindowAnimation_ScaleFactor
);
321 // Show/Hide windows using a shrink animation.
322 void AnimateShowWindow_Drop(aura::Window
* window
) {
323 AnimateShowWindowCommon(window
, GetScaleForWindow(window
), gfx::Transform());
326 void AnimateHideWindow_Drop(aura::Window
* window
) {
327 AnimateHideWindowCommon(window
, GetScaleForWindow(window
));
330 // Show/Hide windows using a vertical Glenimation.
331 void AnimateShowWindow_Vertical(aura::Window
* window
) {
332 gfx::Transform transform
;
333 transform
.Translate(0, window
->GetProperty(
334 kWindowVisibilityAnimationVerticalPositionKey
));
335 AnimateShowWindowCommon(window
, transform
, gfx::Transform());
338 void AnimateHideWindow_Vertical(aura::Window
* window
) {
339 gfx::Transform transform
;
340 transform
.Translate(0, window
->GetProperty(
341 kWindowVisibilityAnimationVerticalPositionKey
));
342 AnimateHideWindowCommon(window
, transform
);
345 // Show/Hide windows using a fade.
346 void AnimateShowWindow_Fade(aura::Window
* window
) {
347 AnimateShowWindowCommon(window
, gfx::Transform(), gfx::Transform());
350 void AnimateHideWindow_Fade(aura::Window
* window
) {
351 AnimateHideWindowCommon(window
, gfx::Transform());
354 ui::LayerAnimationElement
* CreateGrowShrinkElement(
355 aura::Window
* window
, bool grow
) {
356 scoped_ptr
<ui::InterpolatedTransform
> scale(new ui::InterpolatedScale(
357 gfx::Point3F(kWindowAnimation_Bounce_Scale
,
358 kWindowAnimation_Bounce_Scale
,
360 gfx::Point3F(1, 1, 1)));
361 scoped_ptr
<ui::InterpolatedTransform
> scale_about_pivot(
362 new ui::InterpolatedTransformAboutPivot(
363 gfx::Point(window
->bounds().width() * 0.5,
364 window
->bounds().height() * 0.5),
366 scale_about_pivot
->SetReversed(grow
);
367 scoped_ptr
<ui::LayerAnimationElement
> transition(
368 ui::LayerAnimationElement::CreateInterpolatedTransformElement(
369 scale_about_pivot
.release(),
370 base::TimeDelta::FromMilliseconds(
371 kWindowAnimation_Bounce_DurationMS
*
372 kWindowAnimation_Bounce_GrowShrinkDurationPercent
/ 100)));
373 transition
->set_tween_type(grow
? gfx::Tween::EASE_OUT
: gfx::Tween::EASE_IN
);
374 return transition
.release();
377 void AnimateBounce(aura::Window
* window
) {
378 ui::ScopedLayerAnimationSettings
scoped_settings(
379 window
->layer()->GetAnimator());
380 scoped_settings
.SetPreemptionStrategy(
381 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS
);
382 scoped_ptr
<ui::LayerAnimationSequence
> sequence(
383 new ui::LayerAnimationSequence
);
384 sequence
->AddElement(CreateGrowShrinkElement(window
, true));
385 sequence
->AddElement(ui::LayerAnimationElement::CreatePauseElement(
386 ui::LayerAnimationElement::BOUNDS
,
387 base::TimeDelta::FromMilliseconds(
388 kWindowAnimation_Bounce_DurationMS
*
389 (100 - 2 * kWindowAnimation_Bounce_GrowShrinkDurationPercent
) /
391 sequence
->AddElement(CreateGrowShrinkElement(window
, false));
392 window
->layer()->GetAnimator()->StartAnimation(sequence
.release());
395 // A HidingWindowAnimationObserver that deletes observer and detached
396 // layers when the last_sequence has been completed or aborted.
397 class RotateHidingWindowAnimationObserver
398 : public HidingWindowAnimationObserverBase
,
399 public ui::LayerAnimationObserver
{
401 explicit RotateHidingWindowAnimationObserver(aura::Window
* window
)
402 : HidingWindowAnimationObserverBase(window
) {}
403 virtual ~RotateHidingWindowAnimationObserver() {}
405 // Destroys itself after |last_sequence| ends or is aborted. Does not take
406 // ownership of |last_sequence|, which should not be NULL.
407 void SetLastSequence(ui::LayerAnimationSequence
* last_sequence
) {
408 last_sequence
->AddObserver(this);
411 // ui::LayerAnimationObserver:
412 virtual void OnLayerAnimationEnded(
413 ui::LayerAnimationSequence
* sequence
) OVERRIDE
{
414 OnAnimationCompleted();
416 virtual void OnLayerAnimationAborted(
417 ui::LayerAnimationSequence
* sequence
) OVERRIDE
{
418 OnAnimationCompleted();
420 virtual void OnLayerAnimationScheduled(
421 ui::LayerAnimationSequence
* sequence
) OVERRIDE
{}
424 DISALLOW_COPY_AND_ASSIGN(RotateHidingWindowAnimationObserver
);
427 void AddLayerAnimationsForRotate(aura::Window
* window
, bool show
) {
429 window
->layer()->SetOpacity(kWindowAnimation_HideOpacity
);
431 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(
432 kWindowAnimation_Rotate_DurationMS
);
434 RotateHidingWindowAnimationObserver
* observer
= NULL
;
437 observer
= new RotateHidingWindowAnimationObserver(window
);
438 window
->layer()->GetAnimator()->SchedulePauseForProperties(
439 duration
* (100 - kWindowAnimation_Rotate_OpacityDurationPercent
) / 100,
440 ui::LayerAnimationElement::OPACITY
);
442 scoped_ptr
<ui::LayerAnimationElement
> opacity(
443 ui::LayerAnimationElement::CreateOpacityElement(
444 show
? kWindowAnimation_ShowOpacity
: kWindowAnimation_HideOpacity
,
445 duration
* kWindowAnimation_Rotate_OpacityDurationPercent
/ 100));
446 opacity
->set_tween_type(gfx::Tween::EASE_IN_OUT
);
447 window
->layer()->GetAnimator()->ScheduleAnimation(
448 new ui::LayerAnimationSequence(opacity
.release()));
450 float xcenter
= window
->bounds().width() * 0.5;
452 gfx::Transform transform
;
453 transform
.Translate(xcenter
, 0);
454 transform
.ApplyPerspectiveDepth(kWindowAnimation_Rotate_PerspectiveDepth
);
455 transform
.Translate(-xcenter
, 0);
456 scoped_ptr
<ui::InterpolatedTransform
> perspective(
457 new ui::InterpolatedConstantTransform(transform
));
459 scoped_ptr
<ui::InterpolatedTransform
> scale(
460 new ui::InterpolatedScale(1, kWindowAnimation_Rotate_ScaleFactor
));
461 scoped_ptr
<ui::InterpolatedTransform
> scale_about_pivot(
462 new ui::InterpolatedTransformAboutPivot(
463 gfx::Point(xcenter
, kWindowAnimation_Rotate_TranslateY
),
466 scoped_ptr
<ui::InterpolatedTransform
> translation(
467 new ui::InterpolatedTranslation(gfx::Point(), gfx::Point(
468 0, kWindowAnimation_Rotate_TranslateY
)));
470 scoped_ptr
<ui::InterpolatedTransform
> rotation(
471 new ui::InterpolatedAxisAngleRotation(
472 gfx::Vector3dF(1, 0, 0), 0, kWindowAnimation_Rotate_DegreesX
));
474 scale_about_pivot
->SetChild(perspective
.release());
475 translation
->SetChild(scale_about_pivot
.release());
476 rotation
->SetChild(translation
.release());
477 rotation
->SetReversed(show
);
479 scoped_ptr
<ui::LayerAnimationElement
> transition(
480 ui::LayerAnimationElement::CreateInterpolatedTransformElement(
481 rotation
.release(), duration
));
482 ui::LayerAnimationSequence
* last_sequence
=
483 new ui::LayerAnimationSequence(transition
.release());
484 window
->layer()->GetAnimator()->ScheduleAnimation(last_sequence
);
487 observer
->SetLastSequence(last_sequence
);
488 observer
->DetachAndRecreateLayers();
492 void AnimateShowWindow_Rotate(aura::Window
* window
) {
493 AddLayerAnimationsForRotate(window
, true);
496 void AnimateHideWindow_Rotate(aura::Window
* window
) {
497 AddLayerAnimationsForRotate(window
, false);
500 bool AnimateShowWindow(aura::Window
* window
) {
501 if (!HasWindowVisibilityAnimationTransition(window
, ANIMATE_SHOW
)) {
502 if (HasWindowVisibilityAnimationTransition(window
, ANIMATE_HIDE
)) {
503 // Since hide animation may have changed opacity and transform,
504 // reset them to show the window.
505 window
->layer()->SetOpacity(kWindowAnimation_ShowOpacity
);
506 window
->layer()->SetTransform(gfx::Transform());
511 switch (GetWindowVisibilityAnimationType(window
)) {
512 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP
:
513 AnimateShowWindow_Drop(window
);
515 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL
:
516 AnimateShowWindow_Vertical(window
);
518 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE
:
519 AnimateShowWindow_Fade(window
);
521 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE
:
522 AnimateShowWindow_Rotate(window
);
529 bool AnimateHideWindow(aura::Window
* window
) {
530 if (!HasWindowVisibilityAnimationTransition(window
, ANIMATE_HIDE
)) {
531 if (HasWindowVisibilityAnimationTransition(window
, ANIMATE_SHOW
)) {
532 // Since show animation may have changed opacity and transform,
533 // reset them, though the change should be hidden.
534 window
->layer()->SetOpacity(kWindowAnimation_HideOpacity
);
535 window
->layer()->SetTransform(gfx::Transform());
540 switch (GetWindowVisibilityAnimationType(window
)) {
541 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP
:
542 AnimateHideWindow_Drop(window
);
544 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL
:
545 AnimateHideWindow_Vertical(window
);
547 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE
:
548 AnimateHideWindow_Fade(window
);
550 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE
:
551 AnimateHideWindow_Rotate(window
);
560 ////////////////////////////////////////////////////////////////////////////////
561 // ImplicitHidingWindowAnimationObserver
563 ImplicitHidingWindowAnimationObserver::ImplicitHidingWindowAnimationObserver(
564 aura::Window
* window
,
565 ui::ScopedLayerAnimationSettings
* settings
)
566 : HidingWindowAnimationObserverBase(window
) {
567 settings
->AddObserver(this);
570 void ImplicitHidingWindowAnimationObserver::OnImplicitAnimationsCompleted() {
571 OnAnimationCompleted();
574 ////////////////////////////////////////////////////////////////////////////////
575 // ScopedHidingAnimationSettings
577 ScopedHidingAnimationSettings::ScopedHidingAnimationSettings(
578 aura::Window
* window
)
579 : layer_animation_settings_(window
->layer()->GetAnimator()),
580 observer_(new ImplicitHidingWindowAnimationObserver(
582 &layer_animation_settings_
)) {
585 ScopedHidingAnimationSettings::~ScopedHidingAnimationSettings() {
586 observer_
->DetachAndRecreateLayers();
589 ////////////////////////////////////////////////////////////////////////////////
590 // External interface
592 void SetWindowVisibilityAnimationType(aura::Window
* window
, int type
) {
593 window
->SetProperty(kWindowVisibilityAnimationTypeKey
, type
);
596 int GetWindowVisibilityAnimationType(aura::Window
* window
) {
597 return window
->GetProperty(kWindowVisibilityAnimationTypeKey
);
600 void SetWindowVisibilityAnimationTransition(
601 aura::Window
* window
,
602 WindowVisibilityAnimationTransition transition
) {
603 window
->SetProperty(kWindowVisibilityAnimationTransitionKey
, transition
);
606 bool HasWindowVisibilityAnimationTransition(
607 aura::Window
* window
,
608 WindowVisibilityAnimationTransition transition
) {
609 WindowVisibilityAnimationTransition prop
= window
->GetProperty(
610 kWindowVisibilityAnimationTransitionKey
);
611 return (prop
& transition
) != 0;
614 void SetWindowVisibilityAnimationDuration(aura::Window
* window
,
615 const base::TimeDelta
& duration
) {
616 window
->SetProperty(kWindowVisibilityAnimationDurationKey
,
617 static_cast<int>(duration
.ToInternalValue()));
620 base::TimeDelta
GetWindowVisibilityAnimationDuration(
621 const aura::Window
& window
) {
622 return base::TimeDelta::FromInternalValue(
623 window
.GetProperty(kWindowVisibilityAnimationDurationKey
));
626 void SetWindowVisibilityAnimationVerticalPosition(aura::Window
* window
,
628 window
->SetProperty(kWindowVisibilityAnimationVerticalPositionKey
, position
);
631 bool AnimateOnChildWindowVisibilityChanged(aura::Window
* window
, bool visible
) {
632 if (WindowAnimationsDisabled(window
))
635 return AnimateShowWindow(window
);
636 // Don't start hiding the window again if it's already being hidden.
637 return window
->layer()->GetTargetOpacity() != 0.0f
&&
638 AnimateHideWindow(window
);
641 bool AnimateWindow(aura::Window
* window
, WindowAnimationType type
) {
643 case WINDOW_ANIMATION_TYPE_BOUNCE
:
644 AnimateBounce(window
);
652 bool WindowAnimationsDisabled(aura::Window
* window
) {
653 // Individual windows can choose to skip animations.
654 if (window
&& window
->GetProperty(aura::client::kAnimationsDisabledKey
))
657 // Animations can be disabled globally for testing.
658 if (CommandLine::ForCurrentProcess()->HasSwitch(
659 switches::kWindowAnimationsDisabled
))
662 // Tests of animations themselves should still run even if the machine is
663 // being accessed via Remote Desktop.
664 if (ui::ScopedAnimationDurationScaleMode::duration_scale_mode() ==
665 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
)
668 // Let the user decide whether or not to play the animation.
669 return !gfx::Animation::ShouldRenderRichAnimation();