window_animations.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_animations.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <math.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/animation_host.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/aura_constants.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window_delegate.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window_observer.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window_property.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/compositor_observer.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/layer.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/layer_animation_observer.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/layer_animation_sequence.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/layer_animator.h"
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/compositor/layer_tree_owner.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/animation/animation.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/interpolated_transform.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect_conversions.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/screen.h"
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/gfx/vector2d.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/vector3d_f.h"
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_util.h"
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/wm_core_switches.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DECLARE_WINDOW_PROPERTY_TYPE(int)
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)DECLARE_WINDOW_PROPERTY_TYPE(wm::WindowVisibilityAnimationType)
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)DECLARE_WINDOW_PROPERTY_TYPE(wm::WindowVisibilityAnimationTransition)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DECLARE_WINDOW_PROPERTY_TYPE(float)
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(WM_CORE_EXPORT, bool)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace wm {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kWindowAnimation_Vertical_TranslateY = 15.f;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_WINDOW_PROPERTY_KEY(int,
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           kWindowVisibilityAnimationTypeKey,
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0);
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition,
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           kWindowVisibilityAnimationTransitionKey,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           ANIMATE_BOTH);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_WINDOW_PROPERTY_KEY(float,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           kWindowVisibilityAnimationVerticalPositionKey,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           kWindowAnimation_Vertical_TranslateY);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// An AnimationObserer which has two roles:
6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// 1) Notifies AnimationHost at the end of hiding animation.
6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// 2) Detaches the window's layers for hiding animation and deletes
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// them upon completion of the animation. This is necessary to a)
6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// ensure that the animation continues in the event of the window being
6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// deleted, and b) to ensure that the animation is visible even if the
6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// window gets restacked below other windows when focus or activation
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// changes.
7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver,
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                      public aura::WindowObserver {
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public:
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  HidingWindowAnimationObserver(aura::Window* window,
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                ui::ScopedLayerAnimationSettings* settings);
7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual ~HidingWindowAnimationObserver() {}
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // ui::ImplicitAnimationObserver:
7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual void OnImplicitAnimationsCompleted() OVERRIDE;
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // aura::WindowObserver:
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Detach the current layers and create new layers for |window_|.
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Stack the original layers above |window_| and its transient
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // children.  If the window has transient children, the original
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // layers will be moved above the top most transient child so that
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // activation change does not put the window above the animating
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // layer.
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  void DetachAndRecreateLayers();
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private:
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  aura::Window* window_;
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // The owner of detached layers.
9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<ui::LayerTreeOwner> layer_owner_;
9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver);
9823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)};
9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kDefaultAnimationDurationForMenuMS = 150;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kWindowAnimation_HideOpacity = 0.f;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kWindowAnimation_ShowOpacity = 1.f;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kWindowAnimation_TranslateFactor = 0.5f;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kWindowAnimation_ScaleFactor = .95f;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kWindowAnimation_Rotate_DurationMS = 180;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kWindowAnimation_Rotate_OpacityDurationPercent = 90;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kWindowAnimation_Rotate_TranslateY = -20.f;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kWindowAnimation_Rotate_PerspectiveDepth = 500.f;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kWindowAnimation_Rotate_DegreesX = 5.f;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kWindowAnimation_Rotate_ScaleFactor = .99f;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kWindowAnimation_Bounce_Scale = 1.02f;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kWindowAnimation_Bounce_DurationMS = 180;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kWindowAnimation_Bounce_GrowShrinkDurationPercent = 40;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::TimeDelta GetWindowVisibilityAnimationDuration(
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const aura::Window& window) {
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int duration =
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      window.GetProperty(kWindowVisibilityAnimationDurationKey);
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (duration == 0 && window.type() == ui::wm::WINDOW_TYPE_MENU) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::TimeDelta::FromMilliseconds(
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kDefaultAnimationDurationForMenuMS);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return base::TimeDelta::FromInternalValue(duration);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Gets/sets the WindowVisibilityAnimationType associated with a window.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(beng): redundant/fold into method on public api?
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetWindowVisibilityAnimationType(aura::Window* window) {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int type = window->GetProperty(kWindowVisibilityAnimationTypeKey);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (type == WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT) {
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return (window->type() == ui::wm::WINDOW_TYPE_MENU ||
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            window->type() == ui::wm::WINDOW_TYPE_TOOLTIP)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               ? WINDOW_VISIBILITY_ANIMATION_TYPE_FADE
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               : WINDOW_VISIBILITY_ANIMATION_TYPE_DROP;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return type;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) {
14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const ui::Layer* root = layer;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (root->parent())
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    root = root->parent();
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  layer->GetTargetTransformRelativeTo(root, transform);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect GetLayerWorldBoundsAfterTransform(ui::Layer* layer,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const gfx::Transform& transform) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform in_world = transform;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetTransformRelativeToRoot(layer, &in_world);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::RectF transformed = layer->bounds();
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  in_world.TransformRect(&transformed);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::ToEnclosingRect(transformed);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Augment the host window so that the enclosing bounds of the full
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// animation will fit inside of it.
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AugmentWindowSize(aura::Window* window,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const gfx::Transform& end_transform) {
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::client::AnimationHost* animation_host =
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      aura::client::GetAnimationHost(window);
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!animation_host)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const gfx::Rect& world_at_start = window->bounds();
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect world_at_end =
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetLayerWorldBoundsAfterTransform(window->layer(), end_transform);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect union_in_window_space =
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::UnionRects(world_at_start, world_at_end);
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Calculate the top left and bottom right deltas to be added to the window
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // bounds.
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gfx::Vector2d top_left_delta(world_at_start.x() - union_in_window_space.x(),
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               world_at_start.y() - union_in_window_space.y());
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gfx::Vector2d bottom_right_delta(
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      union_in_window_space.x() + union_in_window_space.width() -
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          (world_at_start.x() + world_at_start.width()),
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      union_in_window_space.y() + union_in_window_space.height() -
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          (world_at_start.y() + world_at_start.height()));
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(top_left_delta.x() >= 0 && top_left_delta.y() >= 0 &&
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         bottom_right_delta.x() >= 0 && bottom_right_delta.y() >= 0);
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  animation_host->SetHostTransitionOffsets(top_left_delta, bottom_right_delta);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Shows a window using an animation, animating its opacity from 0.f to 1.f,
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// its visibility to true, and its transform from |start_transform| to
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |end_transform|.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateShowWindowCommon(aura::Window* window,
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const gfx::Transform& start_transform,
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const gfx::Transform& end_transform) {
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AugmentWindowSize(window, end_transform);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->layer()->SetTransform(start_transform);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->layer()->SetVisible(true);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Property sets within this scope will be implicitly animated.
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (duration.ToInternalValue() > 0)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      settings.SetTransitionDuration(duration);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window->layer()->SetTransform(end_transform);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Hides a window using an animation, animating its opacity from 1.f to 0.f,
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// its visibility to false, and its transform to |end_transform|.
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateHideWindowCommon(aura::Window* window,
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const gfx::Transform& end_transform) {
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AugmentWindowSize(window, end_transform);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Property sets within this scope will be implicitly animated.
22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ScopedHidingAnimationSettings hiding_settings(window);
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (duration.ToInternalValue() > 0)
22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    hiding_settings.layer_animation_settings()->SetTransitionDuration(duration);
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->layer()->SetTransform(end_transform);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->layer()->SetVisible(false);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static gfx::Transform GetScaleForWindow(aura::Window* window) {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect bounds = window->bounds();
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform scale = gfx::GetScaleTransform(
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Point(kWindowAnimation_TranslateFactor * bounds.width(),
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 kWindowAnimation_TranslateFactor * bounds.height()),
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kWindowAnimation_ScaleFactor);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return scale;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Show/Hide windows using a shrink animation.
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateShowWindow_Drop(aura::Window* window) {
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AnimateShowWindowCommon(window, GetScaleForWindow(window), gfx::Transform());
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateHideWindow_Drop(aura::Window* window) {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AnimateHideWindowCommon(window, GetScaleForWindow(window));
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Show/Hide windows using a vertical Glenimation.
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateShowWindow_Vertical(aura::Window* window) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform transform;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.Translate(0, window->GetProperty(
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kWindowVisibilityAnimationVerticalPositionKey));
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AnimateShowWindowCommon(window, transform, gfx::Transform());
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateHideWindow_Vertical(aura::Window* window) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform transform;
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.Translate(0, window->GetProperty(
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kWindowVisibilityAnimationVerticalPositionKey));
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AnimateHideWindowCommon(window, transform);
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Show/Hide windows using a fade.
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateShowWindow_Fade(aura::Window* window) {
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AnimateShowWindowCommon(window, gfx::Transform(), gfx::Transform());
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateHideWindow_Fade(aura::Window* window) {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AnimateHideWindowCommon(window, gfx::Transform());
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ui::LayerAnimationElement* CreateGrowShrinkElement(
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    aura::Window* window, bool grow) {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::InterpolatedTransform> scale(new ui::InterpolatedScale(
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Point3F(kWindowAnimation_Bounce_Scale,
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   kWindowAnimation_Bounce_Scale,
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   1),
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Point3F(1, 1, 1)));
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::InterpolatedTransform> scale_about_pivot(
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::InterpolatedTransformAboutPivot(
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          gfx::Point(window->bounds().width() * 0.5,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     window->bounds().height() * 0.5),
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          scale.release()));
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scale_about_pivot->SetReversed(grow);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::LayerAnimationElement> transition(
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::LayerAnimationElement::CreateInterpolatedTransformElement(
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          scale_about_pivot.release(),
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeDelta::FromMilliseconds(
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              kWindowAnimation_Bounce_DurationMS *
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  kWindowAnimation_Bounce_GrowShrinkDurationPercent / 100)));
296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  transition->set_tween_type(grow ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN);
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return transition.release();
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateBounce(aura::Window* window) {
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::ScopedLayerAnimationSettings scoped_settings(
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      window->layer()->GetAnimator());
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_settings.SetPreemptionStrategy(
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::LayerAnimationSequence> sequence(
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::LayerAnimationSequence);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sequence->AddElement(CreateGrowShrinkElement(window, true));
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement(
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ui::LayerAnimationElement::BOUNDS,
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        kWindowAnimation_Bounce_DurationMS *
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            (100 - 2 * kWindowAnimation_Bounce_GrowShrinkDurationPercent) /
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            100)));
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sequence->AddElement(CreateGrowShrinkElement(window, false));
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->layer()->GetAnimator()->StartAnimation(sequence.release());
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AddLayerAnimationsForRotate(aura::Window* window, bool show) {
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (show)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta duration = base::TimeDelta::FromMilliseconds(
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kWindowAnimation_Rotate_DurationMS);
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  HidingWindowAnimationObserver* observer = NULL;
32623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!show) {
32823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // TODO(oshima): Fix observer leak.
32923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    observer = new HidingWindowAnimationObserver(window, NULL);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window->layer()->GetAnimator()->SchedulePauseForProperties(
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        duration * (100 - kWindowAnimation_Rotate_OpacityDurationPercent) / 100,
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ui::LayerAnimationElement::OPACITY);
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::LayerAnimationElement> opacity(
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::LayerAnimationElement::CreateOpacityElement(
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          show ? kWindowAnimation_ShowOpacity : kWindowAnimation_HideOpacity,
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          duration * kWindowAnimation_Rotate_OpacityDurationPercent / 100));
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  opacity->set_tween_type(gfx::Tween::EASE_IN_OUT);
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->layer()->GetAnimator()->ScheduleAnimation(
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::LayerAnimationSequence(opacity.release()));
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float xcenter = window->bounds().width() * 0.5;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform transform;
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.Translate(xcenter, 0);
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.ApplyPerspectiveDepth(kWindowAnimation_Rotate_PerspectiveDepth);
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.Translate(-xcenter, 0);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::InterpolatedTransform> perspective(
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::InterpolatedConstantTransform(transform));
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::InterpolatedTransform> scale(
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::InterpolatedScale(1, kWindowAnimation_Rotate_ScaleFactor));
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::InterpolatedTransform> scale_about_pivot(
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::InterpolatedTransformAboutPivot(
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          gfx::Point(xcenter, kWindowAnimation_Rotate_TranslateY),
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          scale.release()));
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::InterpolatedTransform> translation(
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::InterpolatedTranslation(gfx::Point(), gfx::Point(
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          0, kWindowAnimation_Rotate_TranslateY)));
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::InterpolatedTransform> rotation(
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::InterpolatedAxisAngleRotation(
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          gfx::Vector3dF(1, 0, 0), 0, kWindowAnimation_Rotate_DegreesX));
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scale_about_pivot->SetChild(perspective.release());
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  translation->SetChild(scale_about_pivot.release());
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rotation->SetChild(translation.release());
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rotation->SetReversed(show);
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::LayerAnimationElement> transition(
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::LayerAnimationElement::CreateInterpolatedTransformElement(
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          rotation.release(), duration));
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->layer()->GetAnimator()->ScheduleAnimation(
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::LayerAnimationSequence(transition.release()));
37723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (observer)
37823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    observer->DetachAndRecreateLayers();
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateShowWindow_Rotate(aura::Window* window) {
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddLayerAnimationsForRotate(window, true);
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AnimateHideWindow_Rotate(aura::Window* window) {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddLayerAnimationsForRotate(window, false);
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AnimateShowWindow(aura::Window* window) {
39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW)) {
39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) {
39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Since hide animation may have changed opacity and transform,
39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // reset them to show the window.
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      window->layer()->SetTransform(gfx::Transform());
39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (GetWindowVisibilityAnimationType(window)) {
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP:
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AnimateShowWindow_Drop(window);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL:
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AnimateShowWindow_Vertical(window);
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE:
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AnimateShowWindow_Fade(window);
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE:
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AnimateShowWindow_Rotate(window);
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AnimateHideWindow(aura::Window* window) {
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) {
42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW)) {
42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Since show animation may have changed opacity and transform,
42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // reset them, though the change should be hidden.
42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      window->layer()->SetTransform(gfx::Transform());
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (GetWindowVisibilityAnimationType(window)) {
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP:
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AnimateHideWindow_Drop(window);
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL:
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AnimateHideWindow_Vertical(window);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE:
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AnimateHideWindow_Fade(window);
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE:
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AnimateHideWindow_Rotate(window);
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
45023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// HidingWindowAnimationObserver
45123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
45223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)HidingWindowAnimationObserver::HidingWindowAnimationObserver(
45323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    aura::Window* window,
45423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ui::ScopedLayerAnimationSettings* settings)
45523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : window_(window) {
45623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  window->AddObserver(this);
45723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (settings)
45823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    settings->AddObserver(this);
45923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
46023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
46123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void HidingWindowAnimationObserver::OnImplicitAnimationsCompleted() {
46223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Window may have been destroyed by this point.
46323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (window_) {
46423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    aura::client::AnimationHost* animation_host =
46523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        aura::client::GetAnimationHost(window_);
46623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (animation_host)
46723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      animation_host->OnWindowHidingAnimationCompleted();
46823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    window_->RemoveObserver(this);
46923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
47023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  delete this;
47123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
47223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
47323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void HidingWindowAnimationObserver::OnWindowDestroying(aura::Window* window) {
47423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK_EQ(window, window_);
47523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  window_->RemoveObserver(this);
47623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  window_ = NULL;
47723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
47823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
47923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void HidingWindowAnimationObserver::DetachAndRecreateLayers() {
48023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  layer_owner_ = RecreateLayers(window_);
48123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (window_->parent()) {
48223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const aura::Window::Windows& transient_children =
48323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        GetTransientChildren(window_);
48423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    aura::Window::Windows::const_iterator iter =
48523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        std::find(window_->parent()->children().begin(),
48623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                  window_->parent()->children().end(),
48723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                  window_);
48823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DCHECK(iter != window_->parent()->children().end());
48923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    aura::Window* topmost_transient_child = NULL;
49023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    for (++iter; iter != window_->parent()->children().end(); ++iter) {
49123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (std::find(transient_children.begin(),
49223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                    transient_children.end(),
49323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                    *iter) !=
49423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          transient_children.end()) {
49523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        topmost_transient_child = *iter;
49623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      }
49723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
49823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (topmost_transient_child) {
49923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      window_->parent()->layer()->StackAbove(
50023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          layer_owner_->root(), topmost_transient_child->layer());
50123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
50223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
50323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
50423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // TODO(sky): The recreated layer should have the target visibility of
50523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // the original layer.
50623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Make the new layer invisible immediately.
50723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  window_->layer()->SetVisible(false);
50823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  window_->layer()->SetOpacity(0);
50923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
51023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
51123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
51223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// ScopedHidingAnimationSettings
51323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
51423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ScopedHidingAnimationSettings::ScopedHidingAnimationSettings(
51523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    aura::Window* window)
51623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : layer_animation_settings_(window->layer()->GetAnimator()),
51723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      observer_(new HidingWindowAnimationObserver(
51823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          window, &layer_animation_settings_)) {
51923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
52023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
52123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ScopedHidingAnimationSettings::~ScopedHidingAnimationSettings() {
52223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  observer_->DetachAndRecreateLayers();
52323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
52423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
52523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// External interface
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetWindowVisibilityAnimationType(aura::Window* window, int type) {
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->SetProperty(kWindowVisibilityAnimationTypeKey, type);
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetWindowVisibilityAnimationType(aura::Window* window) {
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return window->GetProperty(kWindowVisibilityAnimationTypeKey);
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetWindowVisibilityAnimationTransition(
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    aura::Window* window,
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WindowVisibilityAnimationTransition transition) {
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->SetProperty(kWindowVisibilityAnimationTransitionKey, transition);
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HasWindowVisibilityAnimationTransition(
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    aura::Window* window,
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WindowVisibilityAnimationTransition transition) {
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WindowVisibilityAnimationTransition prop = window->GetProperty(
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kWindowVisibilityAnimationTransitionKey);
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (prop & transition) != 0;
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetWindowVisibilityAnimationDuration(aura::Window* window,
55123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                          const base::TimeDelta& duration) {
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->SetProperty(kWindowVisibilityAnimationDurationKey,
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      static_cast<int>(duration.ToInternalValue()));
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::TimeDelta GetWindowVisibilityAnimationDuration(
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const aura::Window& window) {
5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::TimeDelta::FromInternalValue(
5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      window.GetProperty(kWindowVisibilityAnimationDurationKey));
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window,
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  float position) {
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position);
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (WindowAnimationsDisabled(window))
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (visible)
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return AnimateShowWindow(window);
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't start hiding the window again if it's already being hidden.
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return window->layer()->GetTargetOpacity() != 0.0f &&
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AnimateHideWindow(window);
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AnimateWindow(aura::Window* window, WindowAnimationType type) {
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  case WINDOW_ANIMATION_TYPE_BOUNCE:
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AnimateBounce(window);
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  default:
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WindowAnimationsDisabled(aura::Window* window) {
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return (!gfx::Animation::ShouldRenderRichAnimation() || (window &&
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          window->GetProperty(aura::client::kAnimationsDisabledKey)) ||
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CommandLine::ForCurrentProcess()->HasSwitch(
5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          switches::kWindowAnimationsDisabled));
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
595a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace wm
596