15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_animations.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/screen_util.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shelf/shelf.h"
14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ash/shelf/shelf_layout_manager.h"
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ash/shelf/shelf_widget.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_util.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ash/wm/workspace_controller.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/message_loop/message_loop.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/aura_constants.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window_observer.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window_property.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/compositor_observer.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer_animation_observer.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer_animation_sequence.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer_animator.h"
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/layer_tree_owner.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/interpolated_transform.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/vector3d_f.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_util.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kLayerAnimationsForMinimizeDurationMS = 200;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Durations for the cross-fade animation, in milliseconds.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const float kCrossFadeDurationMinMs = 200.f;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const float kCrossFadeDurationMaxMs = 400.f;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Durations for the brightness/grayscale fade animation, in milliseconds.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kBrightnessGrayscaleFadeDurationMs = 1000;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Brightness/grayscale values for hide/show window animations.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const float kWindowAnimation_HideBrightnessGrayscale = 1.f;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const float kWindowAnimation_ShowBrightnessGrayscale = 0.f;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const float kWindowAnimation_HideOpacity = 0.f;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const float kWindowAnimation_ShowOpacity = 1.f;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Scales for AshWindow above/below current workspace.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kLayerScaleAboveSize = 1.1f;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kLayerScaleBelowSize = .9f;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 Round64(float f) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<int64>(f + 0.5f);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::TimeDelta GetCrossFadeDuration(aura::Window* window,
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     const gfx::Rect& old_bounds,
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     const gfx::Rect& new_bounds) {
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (::wm::WindowAnimationsDisabled(window))
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return base::TimeDelta();
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int old_area = old_bounds.width() * old_bounds.height();
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int new_area = new_bounds.width() * new_bounds.height();
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int max_area = std::max(old_area, new_area);
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Avoid divide by zero.
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (max_area == 0)
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return base::TimeDelta::FromMilliseconds(kCrossFadeDurationMS);
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int delta_area = std::abs(old_area - new_area);
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If the area didn't change, the animation is instantaneous.
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (delta_area == 0)
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return base::TimeDelta::FromMilliseconds(kCrossFadeDurationMS);
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  float factor =
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      static_cast<float>(delta_area) / static_cast<float>(max_area);
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const float kRange = kCrossFadeDurationMaxMs - kCrossFadeDurationMinMs;
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return base::TimeDelta::FromMilliseconds(
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Round64(kCrossFadeDurationMinMs + (factor * kRange)));
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst int kCrossFadeDurationMS = 200;
972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddLayerAnimationsForMinimize(aura::Window* window, bool show) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Recalculate the transform at restore time since the launcher item may have
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // moved while the window was minimized.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect bounds = window->bounds();
102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  gfx::Rect target_bounds = GetMinimizeAnimationTargetBoundsInScreen(window);
103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  target_bounds =
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ScreenUtil::ConvertRectFromScreen(window->parent(), target_bounds);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  float scale_x = static_cast<float>(target_bounds.width()) / bounds.width();
107ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  float scale_y = static_cast<float>(target_bounds.height()) / bounds.height();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::InterpolatedTransform> scale(
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ui::InterpolatedScale(gfx::Point3F(1, 1, 1),
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                gfx::Point3F(scale_x, scale_y, 1)));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::InterpolatedTransform> translation(
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ui::InterpolatedTranslation(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          gfx::Point(),
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          gfx::Point(target_bounds.x() - bounds.x(),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     target_bounds.y() - bounds.y())));
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scale->SetChild(translation.release());
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scale->SetReversed(show);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::TimeDelta duration = window->layer()->GetAnimator()->
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      GetTransitionDuration();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ui::LayerAnimationElement> transition(
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::LayerAnimationElement::CreateInterpolatedTransformElement(
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          scale.release(), duration));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transition->set_tween_type(
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      show ? gfx::Tween::EASE_IN : gfx::Tween::EASE_IN_OUT);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->layer()->GetAnimator()->ScheduleAnimation(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ui::LayerAnimationSequence(transition.release()));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When hiding a window, turn off blending until the animation is 3 / 4 done
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to save bandwidth and reduce jank.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!show) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->layer()->GetAnimator()->SchedulePauseForProperties(
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        (duration * 3) / 4, ui::LayerAnimationElement::OPACITY);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Fade in and out quickly when the window is small to reduce jank.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float opacity = show ? 1.0f : 0.0f;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->layer()->GetAnimator()->ScheduleAnimation(
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ui::LayerAnimationSequence(
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ui::LayerAnimationElement::CreateOpacityElement(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              opacity, duration / 4)));
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Reset the transform to identity when the minimize animation is completed.
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window->layer()->GetAnimator()->ScheduleAnimation(
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new ui::LayerAnimationSequence(
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          ui::LayerAnimationElement::CreateTransformElement(
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              gfx::Transform(),
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              base::TimeDelta())));
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AnimateShowWindow_Minimize(aura::Window* window) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::TimeDelta duration = base::TimeDelta::FromMilliseconds(
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      kLayerAnimationsForMinimizeDurationMS);
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  settings.SetTransitionDuration(duration);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddLayerAnimationsForMinimize(window, true);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now that the window has been restored, we need to clear its animation style
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to default so that normal animation applies.
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ::wm::SetWindowVisibilityAnimationType(
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      window, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AnimateHideWindow_Minimize(aura::Window* window) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Property sets within this scope will be implicitly animated.
17323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ::wm::ScopedHidingAnimationSettings hiding_settings(window);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta duration = base::TimeDelta::FromMilliseconds(
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kLayerAnimationsForMinimizeDurationMS);
17623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  hiding_settings.layer_animation_settings()->SetTransitionDuration(duration);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->layer()->SetVisible(false);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddLayerAnimationsForMinimize(window, false);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AnimateShowHideWindowCommon_BrightnessGrayscale(aura::Window* window,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     bool show) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float start_value, end_value;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (show) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    start_value = kWindowAnimation_HideBrightnessGrayscale;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    end_value = kWindowAnimation_ShowBrightnessGrayscale;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    start_value = kWindowAnimation_ShowBrightnessGrayscale;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    end_value = kWindowAnimation_HideBrightnessGrayscale;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->layer()->SetLayerBrightness(start_value);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->layer()->SetLayerGrayscale(start_value);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (show) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->layer()->SetVisible(true);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta duration =
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kBrightnessGrayscaleFadeDurationMs);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (show) {
20423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
20523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    window->layer()->GetAnimator()->
20623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        ScheduleTogether(
20723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            CreateBrightnessGrayscaleAnimationSequence(end_value, duration));
20823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
20923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ::wm::ScopedHidingAnimationSettings hiding_settings(window);
21023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    window->layer()->GetAnimator()->
21123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        ScheduleTogether(
21223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            CreateBrightnessGrayscaleAnimationSequence(end_value, duration));
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window->layer()->SetVisible(false);
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AnimateShowWindow_BrightnessGrayscale(aura::Window* window) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnimateShowHideWindowCommon_BrightnessGrayscale(window, true);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AnimateHideWindow_BrightnessGrayscale(aura::Window* window) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnimateShowHideWindowCommon_BrightnessGrayscale(window, false);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AnimateShowWindow(aura::Window* window) {
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!::wm::HasWindowVisibilityAnimationTransition(
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          window, ::wm::ANIMATE_SHOW)) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (::wm::GetWindowVisibilityAnimationType(window)) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE:
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AnimateShowWindow_Minimize(window);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE:
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AnimateShowWindow_BrightnessGrayscale(window);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AnimateHideWindow(aura::Window* window) {
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!::wm::HasWindowVisibilityAnimationTransition(
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          window, ::wm::ANIMATE_HIDE)) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (::wm::GetWindowVisibilityAnimationType(window)) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE:
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AnimateHideWindow_Minimize(window);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE:
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AnimateHideWindow_BrightnessGrayscale(window);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Observer for a window cross-fade animation. If either the window closes or
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the layer's animation completes or compositing is aborted due to GPU crash,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it deletes the layer and removes itself as an observer.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CrossFadeObserver : public ui::CompositorObserver,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          public aura::WindowObserver,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          public ui::ImplicitAnimationObserver {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Observes |window| for destruction, but does not take ownership.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Takes ownership of |layer| and its child layers.
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CrossFadeObserver(aura::Window* window,
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    scoped_ptr<ui::LayerTreeOwner> layer_owner)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : window_(window),
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        layer_owner_(layer_owner.Pass()) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_->AddObserver(this);
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    layer_owner_->root()->GetCompositor()->AddObserver(this);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~CrossFadeObserver() {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_->RemoveObserver(this);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_ = NULL;
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    layer_owner_->root()->GetCompositor()->RemoveObserver(this);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ui::CompositorObserver overrides:
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCompositingStarted(ui::Compositor* compositor,
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    base::TimeTicks start_time) OVERRIDE {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Triggers OnImplicitAnimationsCompleted() to be called and deletes us.
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    layer_owner_->root()->GetAnimator()->StopAnimating();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnCompositingLockStateChanged(
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::Compositor* compositor) OVERRIDE {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // aura::WindowObserver overrides:
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Triggers OnImplicitAnimationsCompleted() to be called and deletes us.
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    layer_owner_->root()->GetAnimator()->StopAnimating();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
307effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                              aura::Window* new_root) OVERRIDE {
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    layer_owner_->root()->GetAnimator()->StopAnimating();
310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ui::ImplicitAnimationObserver overrides:
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnImplicitAnimationsCompleted() OVERRIDE {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::Window* window_;  // not owned
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<ui::LayerTreeOwner> layer_owner_;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CrossFadeObserver);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::TimeDelta CrossFadeAnimation(
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    aura::Window* window,
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<ui::LayerTreeOwner> old_layer_owner,
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    gfx::Tween::Type tween_type) {
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(old_layer_owner->root());
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const gfx::Rect old_bounds(old_layer_owner->root()->bounds());
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect new_bounds(window->bounds());
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool old_on_top = (old_bounds.width() > new_bounds.width());
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shorten the animation if there's not much visual movement.
334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const base::TimeDelta duration = GetCrossFadeDuration(window,
335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                        old_bounds, new_bounds);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Scale up the old layer while translating to new position.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ui::Layer* old_layer = old_layer_owner->root();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_layer->GetAnimator()->StopAnimating();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::ScopedLayerAnimationSettings settings(old_layer->GetAnimator());
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Animation observer owns the old layer and deletes itself.
344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    settings.AddObserver(new CrossFadeObserver(window, old_layer_owner.Pass()));
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings.SetTransitionDuration(duration);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings.SetTweenType(tween_type);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Transform out_transform;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float scale_x = static_cast<float>(new_bounds.width()) /
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<float>(old_bounds.width());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float scale_y = static_cast<float>(new_bounds.height()) /
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<float>(old_bounds.height());
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out_transform.Translate(new_bounds.x() - old_bounds.x(),
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            new_bounds.y() - old_bounds.y());
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out_transform.Scale(scale_x, scale_y);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_layer->SetTransform(out_transform);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (old_on_top) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The old layer is on top, and should fade out.  The new layer below will
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // stay opaque to block the desktop.
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      old_layer->SetOpacity(kWindowAnimation_HideOpacity);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In tests |old_layer| is deleted here, as animations have zero duration.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    old_layer = NULL;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the new layer's current transform, such that the user sees a scaled
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // version of the window with the original bounds at the original position.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform in_transform;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const float scale_x = static_cast<float>(old_bounds.width()) /
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<float>(new_bounds.width());
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const float scale_y = static_cast<float>(old_bounds.height()) /
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<float>(new_bounds.height());
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  in_transform.Translate(old_bounds.x() - new_bounds.x(),
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               old_bounds.y() - new_bounds.y());
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  in_transform.Scale(scale_x, scale_y);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window->layer()->SetTransform(in_transform);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!old_on_top) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The new layer is on top and should fade in.  The old layer below will
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // stay opaque and block the desktop.
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Animate the new layer to the identity transform, so the window goes to
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // its newly set bounds.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings.SetTransitionDuration(duration);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings.SetTweenType(tween_type);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window->layer()->SetTransform(gfx::Transform());
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!old_on_top) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // New layer is on top, fade it in.
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return duration;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (::wm::WindowAnimationsDisabled(window))
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Attempt to run CoreWm supplied animation types.
401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (::wm::AnimateOnChildWindowVisibilityChanged(window, visible))
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Otherwise try to run an Ash-specific animation.
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (visible)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AnimateShowWindow(window);
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't start hiding the window again if it's already being hidden.
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return window->layer()->GetTargetOpacity() != 0.0f &&
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      AnimateHideWindow(window);
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::vector<ui::LayerAnimationSequence*>
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CreateBrightnessGrayscaleAnimationSequence(float target_value,
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           base::TimeDelta duration) {
415d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  gfx::Tween::Type animation_type = gfx::Tween::EASE_OUT;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::LayerAnimationSequence> brightness_sequence(
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::LayerAnimationSequence());
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::LayerAnimationSequence> grayscale_sequence(
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ui::LayerAnimationSequence());
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::LayerAnimationElement> brightness_element(
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::LayerAnimationElement::CreateBrightnessElement(
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          target_value, duration));
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  brightness_element->set_tween_type(animation_type);
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  brightness_sequence->AddElement(brightness_element.release());
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ui::LayerAnimationElement> grayscale_element(
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::LayerAnimationElement::CreateGrayscaleElement(
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          target_value, duration));
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grayscale_element->set_tween_type(animation_type);
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  grayscale_sequence->AddElement(grayscale_element.release());
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<ui::LayerAnimationSequence*> animations;
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  animations.push_back(brightness_sequence.release());
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  animations.push_back(grayscale_sequence.release());
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return animations;
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns scale related to the specified AshWindowScaleType.
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetTransformForScaleAnimation(ui::Layer* layer,
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   LayerScaleAnimationDirection type) {
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const float scale =
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      type == LAYER_SCALE_ANIMATION_ABOVE ? kLayerScaleAboveSize :
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kLayerScaleBelowSize;
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform transform;
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.Translate(-layer->bounds().width() * (scale - 1.0f) / 2,
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      -layer->bounds().height() * (scale - 1.0f) / 2);
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform.Scale(scale, scale);
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  layer->SetTransform(transform);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
453ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochgfx::Rect GetMinimizeAnimationTargetBoundsInScreen(aura::Window* window) {
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Shelf* shelf = Shelf::ForWindow(window);
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Shelf is created lazily and can be NULL.
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!shelf)
457ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return gfx::Rect();
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect item_rect = shelf->GetScreenBoundsOfItemIconForWindow(window);
459ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
460ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // The launcher item is visible and has an icon.
461ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!item_rect.IsEmpty())
462ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return item_rect;
463ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
464ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // If both the icon width and height are 0, then there is no icon in the
465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // launcher for |window|. If the launcher is auto hidden, one of the height or
466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // width will be 0 but the position in the launcher and the major dimension
467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // are still reported correctly and the window can be animated to the launcher
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // item's light bar.
469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ShelfLayoutManager* layout_manager = ShelfLayoutManager::ForShelf(window);
470ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (item_rect.width() != 0 || item_rect.height() != 0) {
471ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (layout_manager->visibility_state() == SHELF_AUTO_HIDE) {
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gfx::Rect shelf_bounds = shelf->shelf_widget()->GetWindowBoundsInScreen();
473ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      switch (layout_manager->GetAlignment()) {
474ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        case SHELF_ALIGNMENT_BOTTOM:
475ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          item_rect.set_y(shelf_bounds.y());
476ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          break;
477ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        case SHELF_ALIGNMENT_LEFT:
478ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          item_rect.set_x(shelf_bounds.right());
479ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          break;
480ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        case SHELF_ALIGNMENT_RIGHT:
481ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          item_rect.set_x(shelf_bounds.x());
482ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          break;
483ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        case SHELF_ALIGNMENT_TOP:
484ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          item_rect.set_y(shelf_bounds.bottom());
485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          break;
486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      }
487ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      return item_rect;
488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
489ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
490ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Coming here, there is no visible icon of that shelf item and we zoom back
492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // to the location of the application launcher (which is fixed as first item
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // of the shelf).
494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  gfx::Rect work_area =
495ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      Shell::GetScreen()->GetDisplayNearestWindow(window).work_area();
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int ltr_adjusted_x = base::i18n::IsRTL() ? work_area.right() : work_area.x();
497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  switch (layout_manager->GetAlignment()) {
498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SHELF_ALIGNMENT_BOTTOM:
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return gfx::Rect(ltr_adjusted_x, work_area.bottom(), 0, 0);
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SHELF_ALIGNMENT_TOP:
501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return gfx::Rect(ltr_adjusted_x, work_area.y(), 0, 0);
502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SHELF_ALIGNMENT_LEFT:
503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return gfx::Rect(work_area.x(), work_area.y(), 0, 0);
504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SHELF_ALIGNMENT_RIGHT:
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return gfx::Rect(work_area.right(), work_area.y(), 0, 0);
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTREACHED();
508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return gfx::Rect();
509ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
510ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
512