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/geometry/rect_conversions.h"
33 #include "ui/gfx/geometry/vector2d.h"
34 #include "ui/gfx/geometry/vector3d_f.h"
35 #include "ui/gfx/interpolated_transform.h"
36 #include "ui/gfx/screen.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(wm::WindowVisibilityAnimationType
)
42 DECLARE_WINDOW_PROPERTY_TYPE(wm::WindowVisibilityAnimationTransition
)
43 DECLARE_WINDOW_PROPERTY_TYPE(float)
47 const float kWindowAnimation_Vertical_TranslateY
= 15.f
;
49 // A base class for hiding animation observer which has two roles:
50 // 1) Notifies AnimationHost at the end of hiding animation.
51 // 2) Detaches the window's layers for hiding animation and deletes
52 // them upon completion of the animation. This is necessary to a)
53 // ensure that the animation continues in the event of the window being
54 // deleted, and b) to ensure that the animation is visible even if the
55 // window gets restacked below other windows when focus or activation
57 // The subclass will determine when the animation is completed.
58 class HidingWindowAnimationObserverBase
: public aura::WindowObserver
{
60 explicit HidingWindowAnimationObserverBase(aura::Window
* window
)
62 window_
->AddObserver(this);
64 ~HidingWindowAnimationObserverBase() override
{
66 window_
->RemoveObserver(this);
69 // aura::WindowObserver:
70 void OnWindowDestroying(aura::Window
* window
) override
{
71 DCHECK_EQ(window
, window_
);
75 void OnWindowDestroyed(aura::Window
* window
) override
{
76 DCHECK_EQ(window
, window_
);
80 // Detach the current layers and create new layers for |window_|.
81 // Stack the original layers above |window_| and its transient
82 // children. If the window has transient children, the original
83 // layers will be moved above the top most transient child so that
84 // activation change does not put the window above the animating
86 void DetachAndRecreateLayers() {
87 layer_owner_
= RecreateLayers(window_
);
88 if (window_
->parent()) {
89 const aura::Window::Windows
& transient_children
=
90 GetTransientChildren(window_
);
91 aura::Window::Windows::const_iterator iter
=
92 std::find(window_
->parent()->children().begin(),
93 window_
->parent()->children().end(),
95 DCHECK(iter
!= window_
->parent()->children().end());
96 aura::Window
* topmost_transient_child
= NULL
;
97 for (++iter
; iter
!= window_
->parent()->children().end(); ++iter
) {
98 if (std::find(transient_children
.begin(),
99 transient_children
.end(),
100 *iter
) != transient_children
.end()) {
101 topmost_transient_child
= *iter
;
104 if (topmost_transient_child
) {
105 window_
->parent()->layer()->StackAbove(
106 layer_owner_
->root(), topmost_transient_child
->layer());
112 // Invoked when the hiding animation is completed. It will delete
113 // 'this', and no operation should be made on this object after this
115 void OnAnimationCompleted() {
116 // Window may have been destroyed by this point.
118 aura::client::AnimationHost
* animation_host
=
119 aura::client::GetAnimationHost(window_
);
121 animation_host
->OnWindowHidingAnimationCompleted();
122 window_
->RemoveObserver(this);
128 // Invoked when the window is destroyed (or destroying).
129 void WindowInvalid() {
130 layer_owner_
->root()->SuppressPaint();
132 window_
->RemoveObserver(this);
136 aura::Window
* window_
;
138 // The owner of detached layers.
139 scoped_ptr
<ui::LayerTreeOwner
> layer_owner_
;
141 DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserverBase
);
146 DEFINE_WINDOW_PROPERTY_KEY(int,
147 kWindowVisibilityAnimationTypeKey
,
148 WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT
);
149 DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey
, 0);
150 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition
,
151 kWindowVisibilityAnimationTransitionKey
,
153 DEFINE_WINDOW_PROPERTY_KEY(float,
154 kWindowVisibilityAnimationVerticalPositionKey
,
155 kWindowAnimation_Vertical_TranslateY
);
157 // A HidingWindowAnimationObserver that deletes observer and detached
158 // layers upon the completion of the implicit animation.
159 class ImplicitHidingWindowAnimationObserver
160 : public HidingWindowAnimationObserverBase
,
161 public ui::ImplicitAnimationObserver
{
163 ImplicitHidingWindowAnimationObserver(
164 aura::Window
* window
,
165 ui::ScopedLayerAnimationSettings
* settings
);
166 ~ImplicitHidingWindowAnimationObserver() override
{}
168 // ui::ImplicitAnimationObserver:
169 void OnImplicitAnimationsCompleted() override
;
172 DISALLOW_COPY_AND_ASSIGN(ImplicitHidingWindowAnimationObserver
);
177 const int kDefaultAnimationDurationForMenuMS
= 150;
179 const float kWindowAnimation_HideOpacity
= 0.f
;
180 const float kWindowAnimation_ShowOpacity
= 1.f
;
181 const float kWindowAnimation_TranslateFactor
= 0.5f
;
182 const float kWindowAnimation_ScaleFactor
= .95f
;
184 const int kWindowAnimation_Rotate_DurationMS
= 180;
185 const int kWindowAnimation_Rotate_OpacityDurationPercent
= 90;
186 const float kWindowAnimation_Rotate_TranslateY
= -20.f
;
187 const float kWindowAnimation_Rotate_PerspectiveDepth
= 500.f
;
188 const float kWindowAnimation_Rotate_DegreesX
= 5.f
;
189 const float kWindowAnimation_Rotate_ScaleFactor
= .99f
;
191 const float kWindowAnimation_Bounce_Scale
= 1.02f
;
192 const int kWindowAnimation_Bounce_DurationMS
= 180;
193 const int kWindowAnimation_Bounce_GrowShrinkDurationPercent
= 40;
195 base::TimeDelta
GetWindowVisibilityAnimationDuration(
196 const aura::Window
& window
) {
198 window
.GetProperty(kWindowVisibilityAnimationDurationKey
);
199 if (duration
== 0 && window
.type() == ui::wm::WINDOW_TYPE_MENU
) {
200 return base::TimeDelta::FromMilliseconds(
201 kDefaultAnimationDurationForMenuMS
);
203 return base::TimeDelta::FromInternalValue(duration
);
206 // Gets/sets the WindowVisibilityAnimationType associated with a window.
207 // TODO(beng): redundant/fold into method on public api?
208 int GetWindowVisibilityAnimationType(aura::Window
* window
) {
209 int type
= window
->GetProperty(kWindowVisibilityAnimationTypeKey
);
210 if (type
== WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT
) {
211 return (window
->type() == ui::wm::WINDOW_TYPE_MENU
||
212 window
->type() == ui::wm::WINDOW_TYPE_TOOLTIP
)
213 ? WINDOW_VISIBILITY_ANIMATION_TYPE_FADE
214 : WINDOW_VISIBILITY_ANIMATION_TYPE_DROP
;
219 void GetTransformRelativeToRoot(ui::Layer
* layer
, gfx::Transform
* transform
) {
220 const ui::Layer
* root
= layer
;
221 while (root
->parent())
222 root
= root
->parent();
223 layer
->GetTargetTransformRelativeTo(root
, transform
);
226 gfx::Rect
GetLayerWorldBoundsAfterTransform(ui::Layer
* layer
,
227 const gfx::Transform
& transform
) {
228 gfx::Transform in_world
= transform
;
229 GetTransformRelativeToRoot(layer
, &in_world
);
231 gfx::RectF transformed
= layer
->bounds();
232 in_world
.TransformRect(&transformed
);
234 return gfx::ToEnclosingRect(transformed
);
237 // Augment the host window so that the enclosing bounds of the full
238 // animation will fit inside of it.
239 void AugmentWindowSize(aura::Window
* window
,
240 const gfx::Transform
& end_transform
) {
241 aura::client::AnimationHost
* animation_host
=
242 aura::client::GetAnimationHost(window
);
246 const gfx::Rect
& world_at_start
= window
->bounds();
247 gfx::Rect world_at_end
=
248 GetLayerWorldBoundsAfterTransform(window
->layer(), end_transform
);
249 gfx::Rect union_in_window_space
=
250 gfx::UnionRects(world_at_start
, world_at_end
);
252 // Calculate the top left and bottom right deltas to be added to the window
254 gfx::Vector2d
top_left_delta(world_at_start
.x() - union_in_window_space
.x(),
255 world_at_start
.y() - union_in_window_space
.y());
257 gfx::Vector2d
bottom_right_delta(
258 union_in_window_space
.x() + union_in_window_space
.width() -
259 (world_at_start
.x() + world_at_start
.width()),
260 union_in_window_space
.y() + union_in_window_space
.height() -
261 (world_at_start
.y() + world_at_start
.height()));
263 DCHECK(top_left_delta
.x() >= 0 && top_left_delta
.y() >= 0 &&
264 bottom_right_delta
.x() >= 0 && bottom_right_delta
.y() >= 0);
266 animation_host
->SetHostTransitionOffsets(top_left_delta
, bottom_right_delta
);
269 // Shows a window using an animation, animating its opacity from 0.f to 1.f,
270 // its visibility to true, and its transform from |start_transform| to
272 void AnimateShowWindowCommon(aura::Window
* window
,
273 const gfx::Transform
& start_transform
,
274 const gfx::Transform
& end_transform
) {
275 AugmentWindowSize(window
, end_transform
);
277 window
->layer()->SetOpacity(kWindowAnimation_HideOpacity
);
278 window
->layer()->SetTransform(start_transform
);
279 window
->layer()->SetVisible(true);
282 // Property sets within this scope will be implicitly animated.
283 ui::ScopedLayerAnimationSettings
settings(window
->layer()->GetAnimator());
284 base::TimeDelta duration
= GetWindowVisibilityAnimationDuration(*window
);
285 if (duration
.ToInternalValue() > 0)
286 settings
.SetTransitionDuration(duration
);
288 window
->layer()->SetTransform(end_transform
);
289 window
->layer()->SetOpacity(kWindowAnimation_ShowOpacity
);
293 // Hides a window using an animation, animating its opacity from 1.f to 0.f,
294 // its visibility to false, and its transform to |end_transform|.
295 void AnimateHideWindowCommon(aura::Window
* window
,
296 const gfx::Transform
& end_transform
) {
297 AugmentWindowSize(window
, end_transform
);
299 // Property sets within this scope will be implicitly animated.
300 ScopedHidingAnimationSettings
hiding_settings(window
);
301 base::TimeDelta duration
= GetWindowVisibilityAnimationDuration(*window
);
302 if (duration
.ToInternalValue() > 0)
303 hiding_settings
.layer_animation_settings()->SetTransitionDuration(duration
);
305 window
->layer()->SetOpacity(kWindowAnimation_HideOpacity
);
306 window
->layer()->SetTransform(end_transform
);
307 window
->layer()->SetVisible(false);
310 static gfx::Transform
GetScaleForWindow(aura::Window
* window
) {
311 gfx::Rect bounds
= window
->bounds();
312 gfx::Transform scale
= gfx::GetScaleTransform(
313 gfx::Point(kWindowAnimation_TranslateFactor
* bounds
.width(),
314 kWindowAnimation_TranslateFactor
* bounds
.height()),
315 kWindowAnimation_ScaleFactor
);
319 // Show/Hide windows using a shrink animation.
320 void AnimateShowWindow_Drop(aura::Window
* window
) {
321 AnimateShowWindowCommon(window
, GetScaleForWindow(window
), gfx::Transform());
324 void AnimateHideWindow_Drop(aura::Window
* window
) {
325 AnimateHideWindowCommon(window
, GetScaleForWindow(window
));
328 // Show/Hide windows using a vertical Glenimation.
329 void AnimateShowWindow_Vertical(aura::Window
* window
) {
330 gfx::Transform transform
;
331 transform
.Translate(0, window
->GetProperty(
332 kWindowVisibilityAnimationVerticalPositionKey
));
333 AnimateShowWindowCommon(window
, transform
, gfx::Transform());
336 void AnimateHideWindow_Vertical(aura::Window
* window
) {
337 gfx::Transform transform
;
338 transform
.Translate(0, window
->GetProperty(
339 kWindowVisibilityAnimationVerticalPositionKey
));
340 AnimateHideWindowCommon(window
, transform
);
343 // Show/Hide windows using a fade.
344 void AnimateShowWindow_Fade(aura::Window
* window
) {
345 AnimateShowWindowCommon(window
, gfx::Transform(), gfx::Transform());
348 void AnimateHideWindow_Fade(aura::Window
* window
) {
349 AnimateHideWindowCommon(window
, gfx::Transform());
352 ui::LayerAnimationElement
* CreateGrowShrinkElement(
353 aura::Window
* window
, bool grow
) {
354 scoped_ptr
<ui::InterpolatedTransform
> scale(new ui::InterpolatedScale(
355 gfx::Point3F(kWindowAnimation_Bounce_Scale
,
356 kWindowAnimation_Bounce_Scale
,
358 gfx::Point3F(1, 1, 1)));
359 scoped_ptr
<ui::InterpolatedTransform
> scale_about_pivot(
360 new ui::InterpolatedTransformAboutPivot(
361 gfx::Point(window
->bounds().width() * 0.5,
362 window
->bounds().height() * 0.5),
364 scale_about_pivot
->SetReversed(grow
);
365 scoped_ptr
<ui::LayerAnimationElement
> transition(
366 ui::LayerAnimationElement::CreateInterpolatedTransformElement(
367 scale_about_pivot
.release(),
368 base::TimeDelta::FromMilliseconds(
369 kWindowAnimation_Bounce_DurationMS
*
370 kWindowAnimation_Bounce_GrowShrinkDurationPercent
/ 100)));
371 transition
->set_tween_type(grow
? gfx::Tween::EASE_OUT
: gfx::Tween::EASE_IN
);
372 return transition
.release();
375 void AnimateBounce(aura::Window
* window
) {
376 ui::ScopedLayerAnimationSettings
scoped_settings(
377 window
->layer()->GetAnimator());
378 scoped_settings
.SetPreemptionStrategy(
379 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS
);
380 scoped_ptr
<ui::LayerAnimationSequence
> sequence(
381 new ui::LayerAnimationSequence
);
382 sequence
->AddElement(CreateGrowShrinkElement(window
, true));
383 sequence
->AddElement(ui::LayerAnimationElement::CreatePauseElement(
384 ui::LayerAnimationElement::BOUNDS
,
385 base::TimeDelta::FromMilliseconds(
386 kWindowAnimation_Bounce_DurationMS
*
387 (100 - 2 * kWindowAnimation_Bounce_GrowShrinkDurationPercent
) /
389 sequence
->AddElement(CreateGrowShrinkElement(window
, false));
390 window
->layer()->GetAnimator()->StartAnimation(sequence
.release());
393 // A HidingWindowAnimationObserver that deletes observer and detached
394 // layers when the last_sequence has been completed or aborted.
395 class RotateHidingWindowAnimationObserver
396 : public HidingWindowAnimationObserverBase
,
397 public ui::LayerAnimationObserver
{
399 explicit RotateHidingWindowAnimationObserver(aura::Window
* window
)
400 : HidingWindowAnimationObserverBase(window
) {}
401 ~RotateHidingWindowAnimationObserver() override
{}
403 // Destroys itself after |last_sequence| ends or is aborted. Does not take
404 // ownership of |last_sequence|, which should not be NULL.
405 void SetLastSequence(ui::LayerAnimationSequence
* last_sequence
) {
406 last_sequence
->AddObserver(this);
409 // ui::LayerAnimationObserver:
410 void OnLayerAnimationEnded(ui::LayerAnimationSequence
* sequence
) override
{
411 OnAnimationCompleted();
413 void OnLayerAnimationAborted(ui::LayerAnimationSequence
* sequence
) override
{
414 OnAnimationCompleted();
416 void OnLayerAnimationScheduled(
417 ui::LayerAnimationSequence
* sequence
) override
{}
420 DISALLOW_COPY_AND_ASSIGN(RotateHidingWindowAnimationObserver
);
423 void AddLayerAnimationsForRotate(aura::Window
* window
, bool show
) {
425 window
->layer()->SetOpacity(kWindowAnimation_HideOpacity
);
427 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(
428 kWindowAnimation_Rotate_DurationMS
);
430 RotateHidingWindowAnimationObserver
* observer
= NULL
;
433 observer
= new RotateHidingWindowAnimationObserver(window
);
434 window
->layer()->GetAnimator()->SchedulePauseForProperties(
435 duration
* (100 - kWindowAnimation_Rotate_OpacityDurationPercent
) / 100,
436 ui::LayerAnimationElement::OPACITY
);
438 scoped_ptr
<ui::LayerAnimationElement
> opacity(
439 ui::LayerAnimationElement::CreateOpacityElement(
440 show
? kWindowAnimation_ShowOpacity
: kWindowAnimation_HideOpacity
,
441 duration
* kWindowAnimation_Rotate_OpacityDurationPercent
/ 100));
442 opacity
->set_tween_type(gfx::Tween::EASE_IN_OUT
);
443 window
->layer()->GetAnimator()->ScheduleAnimation(
444 new ui::LayerAnimationSequence(opacity
.release()));
446 float xcenter
= window
->bounds().width() * 0.5;
448 gfx::Transform transform
;
449 transform
.Translate(xcenter
, 0);
450 transform
.ApplyPerspectiveDepth(kWindowAnimation_Rotate_PerspectiveDepth
);
451 transform
.Translate(-xcenter
, 0);
452 scoped_ptr
<ui::InterpolatedTransform
> perspective(
453 new ui::InterpolatedConstantTransform(transform
));
455 scoped_ptr
<ui::InterpolatedTransform
> scale(
456 new ui::InterpolatedScale(1, kWindowAnimation_Rotate_ScaleFactor
));
457 scoped_ptr
<ui::InterpolatedTransform
> scale_about_pivot(
458 new ui::InterpolatedTransformAboutPivot(
459 gfx::Point(xcenter
, kWindowAnimation_Rotate_TranslateY
),
462 scoped_ptr
<ui::InterpolatedTransform
> translation(
463 new ui::InterpolatedTranslation(gfx::Point(), gfx::Point(
464 0, kWindowAnimation_Rotate_TranslateY
)));
466 scoped_ptr
<ui::InterpolatedTransform
> rotation(
467 new ui::InterpolatedAxisAngleRotation(
468 gfx::Vector3dF(1, 0, 0), 0, kWindowAnimation_Rotate_DegreesX
));
470 scale_about_pivot
->SetChild(perspective
.release());
471 translation
->SetChild(scale_about_pivot
.release());
472 rotation
->SetChild(translation
.release());
473 rotation
->SetReversed(show
);
475 scoped_ptr
<ui::LayerAnimationElement
> transition(
476 ui::LayerAnimationElement::CreateInterpolatedTransformElement(
477 rotation
.release(), duration
));
478 ui::LayerAnimationSequence
* last_sequence
=
479 new ui::LayerAnimationSequence(transition
.release());
480 window
->layer()->GetAnimator()->ScheduleAnimation(last_sequence
);
483 observer
->SetLastSequence(last_sequence
);
484 observer
->DetachAndRecreateLayers();
488 void AnimateShowWindow_Rotate(aura::Window
* window
) {
489 AddLayerAnimationsForRotate(window
, true);
492 void AnimateHideWindow_Rotate(aura::Window
* window
) {
493 AddLayerAnimationsForRotate(window
, false);
496 bool AnimateShowWindow(aura::Window
* window
) {
497 if (!HasWindowVisibilityAnimationTransition(window
, ANIMATE_SHOW
)) {
498 if (HasWindowVisibilityAnimationTransition(window
, ANIMATE_HIDE
)) {
499 // Since hide animation may have changed opacity and transform,
500 // reset them to show the window.
501 window
->layer()->SetOpacity(kWindowAnimation_ShowOpacity
);
502 window
->layer()->SetTransform(gfx::Transform());
507 switch (GetWindowVisibilityAnimationType(window
)) {
508 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP
:
509 AnimateShowWindow_Drop(window
);
511 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL
:
512 AnimateShowWindow_Vertical(window
);
514 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE
:
515 AnimateShowWindow_Fade(window
);
517 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE
:
518 AnimateShowWindow_Rotate(window
);
525 bool AnimateHideWindow(aura::Window
* window
) {
526 if (!HasWindowVisibilityAnimationTransition(window
, ANIMATE_HIDE
)) {
527 if (HasWindowVisibilityAnimationTransition(window
, ANIMATE_SHOW
)) {
528 // Since show animation may have changed opacity and transform,
529 // reset them, though the change should be hidden.
530 window
->layer()->SetOpacity(kWindowAnimation_HideOpacity
);
531 window
->layer()->SetTransform(gfx::Transform());
536 switch (GetWindowVisibilityAnimationType(window
)) {
537 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP
:
538 AnimateHideWindow_Drop(window
);
540 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL
:
541 AnimateHideWindow_Vertical(window
);
543 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE
:
544 AnimateHideWindow_Fade(window
);
546 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE
:
547 AnimateHideWindow_Rotate(window
);
556 ////////////////////////////////////////////////////////////////////////////////
557 // ImplicitHidingWindowAnimationObserver
559 ImplicitHidingWindowAnimationObserver::ImplicitHidingWindowAnimationObserver(
560 aura::Window
* window
,
561 ui::ScopedLayerAnimationSettings
* settings
)
562 : HidingWindowAnimationObserverBase(window
) {
563 settings
->AddObserver(this);
566 void ImplicitHidingWindowAnimationObserver::OnImplicitAnimationsCompleted() {
567 OnAnimationCompleted();
570 ////////////////////////////////////////////////////////////////////////////////
571 // ScopedHidingAnimationSettings
573 ScopedHidingAnimationSettings::ScopedHidingAnimationSettings(
574 aura::Window
* window
)
575 : layer_animation_settings_(window
->layer()->GetAnimator()),
576 observer_(new ImplicitHidingWindowAnimationObserver(
578 &layer_animation_settings_
)) {
581 ScopedHidingAnimationSettings::~ScopedHidingAnimationSettings() {
582 observer_
->DetachAndRecreateLayers();
585 ////////////////////////////////////////////////////////////////////////////////
586 // External interface
588 void SetWindowVisibilityAnimationType(aura::Window
* window
, int type
) {
589 window
->SetProperty(kWindowVisibilityAnimationTypeKey
, type
);
592 int GetWindowVisibilityAnimationType(aura::Window
* window
) {
593 return window
->GetProperty(kWindowVisibilityAnimationTypeKey
);
596 void SetWindowVisibilityAnimationTransition(
597 aura::Window
* window
,
598 WindowVisibilityAnimationTransition transition
) {
599 window
->SetProperty(kWindowVisibilityAnimationTransitionKey
, transition
);
602 bool HasWindowVisibilityAnimationTransition(
603 aura::Window
* window
,
604 WindowVisibilityAnimationTransition transition
) {
605 WindowVisibilityAnimationTransition prop
= window
->GetProperty(
606 kWindowVisibilityAnimationTransitionKey
);
607 return (prop
& transition
) != 0;
610 void SetWindowVisibilityAnimationDuration(aura::Window
* window
,
611 const base::TimeDelta
& duration
) {
612 window
->SetProperty(kWindowVisibilityAnimationDurationKey
,
613 static_cast<int>(duration
.ToInternalValue()));
616 base::TimeDelta
GetWindowVisibilityAnimationDuration(
617 const aura::Window
& window
) {
618 return base::TimeDelta::FromInternalValue(
619 window
.GetProperty(kWindowVisibilityAnimationDurationKey
));
622 void SetWindowVisibilityAnimationVerticalPosition(aura::Window
* window
,
624 window
->SetProperty(kWindowVisibilityAnimationVerticalPositionKey
, position
);
627 bool AnimateOnChildWindowVisibilityChanged(aura::Window
* window
, bool visible
) {
628 if (WindowAnimationsDisabled(window
))
631 return AnimateShowWindow(window
);
632 // Don't start hiding the window again if it's already being hidden.
633 return window
->layer()->GetTargetOpacity() != 0.0f
&&
634 AnimateHideWindow(window
);
637 bool AnimateWindow(aura::Window
* window
, WindowAnimationType type
) {
639 case WINDOW_ANIMATION_TYPE_BOUNCE
:
640 AnimateBounce(window
);
648 bool WindowAnimationsDisabled(aura::Window
* window
) {
649 // Individual windows can choose to skip animations.
650 if (window
&& window
->GetProperty(aura::client::kAnimationsDisabledKey
))
653 // Animations can be disabled globally for testing.
654 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
655 switches::kWindowAnimationsDisabled
))
658 // Tests of animations themselves should still run even if the machine is
659 // being accessed via Remote Desktop.
660 if (ui::ScopedAnimationDurationScaleMode::duration_scale_mode() ==
661 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
)
664 // Let the user decide whether or not to play the animation.
665 return !gfx::Animation::ShouldRenderRichAnimation();