Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ui / wm / core / window_animations.cc
blob82849906fc89d34cea92ef84ef2e705e9c930d31
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"
7 #include <math.h>
9 #include <algorithm>
10 #include <vector>
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)
47 namespace wm {
48 namespace {
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
58 // changes.
59 // The subclass will determine when the animation is completed.
60 class HidingWindowAnimationObserverBase : public aura::WindowObserver {
61 public:
62 explicit HidingWindowAnimationObserverBase(aura::Window* window)
63 : window_(window) {
64 window_->AddObserver(this);
66 virtual ~HidingWindowAnimationObserverBase() {
67 if (window_)
68 window_->RemoveObserver(this);
71 // aura::WindowObserver:
72 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
73 DCHECK_EQ(window, window_);
74 WindowInvalid();
77 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
78 DCHECK_EQ(window, window_);
79 WindowInvalid();
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
87 // layer.
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(),
96 window_);
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());
113 protected:
114 // Invoked when the hiding animation is completed. It will delete
115 // 'this', and no operation should be made on this object after this
116 // point.
117 void OnAnimationCompleted() {
118 // Window may have been destroyed by this point.
119 if (window_) {
120 aura::client::AnimationHost* animation_host =
121 aura::client::GetAnimationHost(window_);
122 if (animation_host)
123 animation_host->OnWindowHidingAnimationCompleted();
124 window_->RemoveObserver(this);
126 delete this;
129 private:
130 // Invoked when the window is destroyed (or destroying).
131 void WindowInvalid() {
132 layer_owner_->root()->SuppressPaint();
134 window_->RemoveObserver(this);
135 window_ = NULL;
138 aura::Window* window_;
140 // The owner of detached layers.
141 scoped_ptr<ui::LayerTreeOwner> layer_owner_;
143 DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserverBase);
146 } // namespace
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,
154 ANIMATE_BOTH);
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 {
164 public:
165 ImplicitHidingWindowAnimationObserver(
166 aura::Window* window,
167 ui::ScopedLayerAnimationSettings* settings);
168 virtual ~ImplicitHidingWindowAnimationObserver() {}
170 // ui::ImplicitAnimationObserver:
171 virtual void OnImplicitAnimationsCompleted() OVERRIDE;
173 private:
174 DISALLOW_COPY_AND_ASSIGN(ImplicitHidingWindowAnimationObserver);
177 namespace {
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) {
199 int duration =
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;
218 return type;
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);
245 if (!animation_host)
246 return;
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
255 // bounds.
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
273 // |end_transform|.
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);
318 return scale;
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),
365 scale.release()));
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) /
390 100)));
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 {
400 public:
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 {}
423 private:
424 DISALLOW_COPY_AND_ASSIGN(RotateHidingWindowAnimationObserver);
427 void AddLayerAnimationsForRotate(aura::Window* window, bool show) {
428 if (show)
429 window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
431 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(
432 kWindowAnimation_Rotate_DurationMS);
434 RotateHidingWindowAnimationObserver* observer = NULL;
436 if (!show) {
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),
464 scale.release()));
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);
486 if (observer) {
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());
508 return false;
511 switch (GetWindowVisibilityAnimationType(window)) {
512 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP:
513 AnimateShowWindow_Drop(window);
514 return true;
515 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL:
516 AnimateShowWindow_Vertical(window);
517 return true;
518 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE:
519 AnimateShowWindow_Fade(window);
520 return true;
521 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE:
522 AnimateShowWindow_Rotate(window);
523 return true;
524 default:
525 return false;
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());
537 return false;
540 switch (GetWindowVisibilityAnimationType(window)) {
541 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP:
542 AnimateHideWindow_Drop(window);
543 return true;
544 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL:
545 AnimateHideWindow_Vertical(window);
546 return true;
547 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE:
548 AnimateHideWindow_Fade(window);
549 return true;
550 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE:
551 AnimateHideWindow_Rotate(window);
552 return true;
553 default:
554 return false;
558 } // namespace
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(
581 window,
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,
627 float position) {
628 window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position);
631 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
632 if (WindowAnimationsDisabled(window))
633 return false;
634 if (visible)
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) {
642 switch (type) {
643 case WINDOW_ANIMATION_TYPE_BOUNCE:
644 AnimateBounce(window);
645 return true;
646 default:
647 NOTREACHED();
648 return false;
652 bool WindowAnimationsDisabled(aura::Window* window) {
653 // Individual windows can choose to skip animations.
654 if (window && window->GetProperty(aura::client::kAnimationsDisabledKey))
655 return true;
657 // Animations can be disabled globally for testing.
658 if (CommandLine::ForCurrentProcess()->HasSwitch(
659 switches::kWindowAnimationsDisabled))
660 return true;
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)
666 return false;
668 // Let the user decide whether or not to play the animation.
669 return !gfx::Animation::ShouldRenderRichAnimation();
672 } // namespace wm