| Index: ui/wm/core/window_animations.cc
|
| diff --git a/ui/wm/core/window_animations.cc b/ui/wm/core/window_animations.cc
|
| index feccce36c3a3ebb5a0f258bd29866c949b16ca2f..b113ede442d05431670ee4c5dc7f0499e651af7f 100644
|
| --- a/ui/wm/core/window_animations.cc
|
| +++ b/ui/wm/core/window_animations.cc
|
| @@ -26,6 +26,7 @@
|
| #include "ui/compositor/layer_animation_observer.h"
|
| #include "ui/compositor/layer_animation_sequence.h"
|
| #include "ui/compositor/layer_animator.h"
|
| +#include "ui/compositor/layer_tree_owner.h"
|
| #include "ui/compositor/scoped_layer_animation_settings.h"
|
| #include "ui/gfx/animation/animation.h"
|
| #include "ui/gfx/interpolated_transform.h"
|
| @@ -42,10 +43,6 @@ DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::WindowVisibilityAnimationTransition)
|
| DECLARE_WINDOW_PROPERTY_TYPE(float)
|
| DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(WM_CORE_EXPORT, bool)
|
|
|
| -using aura::Window;
|
| -using base::TimeDelta;
|
| -using ui::Layer;
|
| -
|
| namespace views {
|
| namespace corewm {
|
| namespace {
|
| @@ -83,6 +80,11 @@ const float kWindowAnimation_Bounce_Scale = 1.02f;
|
| const int kWindowAnimation_Bounce_DurationMS = 180;
|
| const int kWindowAnimation_Bounce_GrowShrinkDurationPercent = 40;
|
|
|
| +class HidingWindowAnimationObserver;
|
| +DEFINE_WINDOW_PROPERTY_KEY(HidingWindowAnimationObserver*,
|
| + kHidingWindowAnimationObserverKey,
|
| + NULL);
|
| +
|
| base::TimeDelta GetWindowVisibilityAnimationDuration(
|
| const aura::Window& window) {
|
| int duration =
|
| @@ -91,7 +93,7 @@ base::TimeDelta GetWindowVisibilityAnimationDuration(
|
| return base::TimeDelta::FromMilliseconds(
|
| kDefaultAnimationDurationForMenuMS);
|
| }
|
| - return TimeDelta::FromInternalValue(duration);
|
| + return base::TimeDelta::FromInternalValue(duration);
|
| }
|
|
|
| // Gets/sets the WindowVisibilityAnimationType associated with a window.
|
| @@ -119,19 +121,27 @@ int GetWindowVisibilityAnimationType(aura::Window* window) {
|
| // so that it can continue animating it until the animation completes.
|
| // Regardless of whether or not the window is destroyed, this object deletes
|
| // itself when the animation completes.
|
| +// In addition, a window being hidden can be hidden by a new focused/active
|
| +// window, in which case, a user may not see the hiding animation. This class
|
| +// also provides a method |DetachAndRecreateLayers| so that the animating
|
| +// layer can stay above the new active window while keeping the
|
| +// z-order of window and its layer in sync.
|
| class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver,
|
| public aura::WindowObserver {
|
| public:
|
| - explicit HidingWindowAnimationObserver(aura::Window* window)
|
| + HidingWindowAnimationObserver(aura::Window* window,
|
| + ui::ScopedLayerAnimationSettings* settings)
|
| : window_(window) {
|
| - window_->AddObserver(this);
|
| + window->SetProperty(kHidingWindowAnimationObserverKey, this);
|
| + window->AddObserver(this);
|
| + if (settings)
|
| + settings->AddObserver(this);
|
| }
|
| +
|
| virtual ~HidingWindowAnimationObserver() {
|
| - STLDeleteElements(&layers_);
|
| }
|
|
|
| - private:
|
| - // Overridden from ui::ImplicitAnimationObserver:
|
| + // ui::ImplicitAnimationObserver:
|
| virtual void OnImplicitAnimationsCompleted() OVERRIDE {
|
| // Window may have been destroyed by this point.
|
| if (window_) {
|
| @@ -140,15 +150,19 @@ class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver,
|
| if (animation_host)
|
| animation_host->OnWindowHidingAnimationCompleted();
|
| window_->RemoveObserver(this);
|
| + window_->ClearProperty(kHidingWindowAnimationObserverKey);
|
| }
|
| delete this;
|
| }
|
|
|
| - // Overridden from aura::WindowObserver:
|
| + // aura::WindowObserver:
|
| virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
|
| DCHECK_EQ(window, window_);
|
| DCHECK(layers_.empty());
|
| - AcquireAllLayers(window_->layer());
|
| + // No need to acquire layers if the animating layers have already
|
| + // been detached.
|
| + if (!layer_owner_)
|
| + AcquireAllLayers(window_->layer());
|
| window_->RemoveObserver(this);
|
| window_ = NULL;
|
| }
|
| @@ -159,19 +173,60 @@ class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver,
|
| DCHECK_EQ(layer, released);
|
| layers_.push_back(released);
|
| }
|
| - std::vector<Layer*>::const_iterator it = layer->children().begin();
|
| + std::vector<ui::Layer*>::const_iterator it = layer->children().begin();
|
| for (; it != layer->children().end(); ++it)
|
| AcquireAllLayers(*it);
|
| }
|
|
|
| + void DetachAndRecreateLayers() {
|
| + layer_owner_ = RecreateLayers(window_);
|
| + // If the window has transient children, move above the top most
|
| + // transient child so that activation change does not put the
|
| + // window above the animating layer.
|
| + if(window_->parent()) {
|
| + const aura::Window::Windows& transient_children =
|
| + GetTransientChildren(window_);
|
| + aura::Window::Windows::const_iterator iter =
|
| + std::find(window_->parent()->children().begin(),
|
| + window_->parent()->children().end(),
|
| + window_);
|
| + DCHECK(iter != window_->parent()->children().end());
|
| + aura::Window* topmost_transient_child = NULL;
|
| + for (++iter; iter != window_->parent()->children().end(); ++iter) {
|
| + if (std::find(transient_children.begin(),
|
| + transient_children.end(),
|
| + *iter) !=
|
| + transient_children.end()) {
|
| + topmost_transient_child = *iter;
|
| + }
|
| + }
|
| + if (topmost_transient_child) {
|
| + window_->parent()->layer()->StackAbove(
|
| + layer_owner_->root(), topmost_transient_child->layer());
|
| + }
|
| + }
|
| +
|
| + // TODO(sky): The recreated layer should have the target visibility of
|
| + // the original layer.
|
| + // Make the new layer invisible immediately.
|
| + window_->layer()->SetVisible(false);
|
| + window_->layer()->SetOpacity(0);
|
| + }
|
| +
|
| + private:
|
| aura::Window* window_;
|
| - std::vector<ui::Layer*> layers_;
|
| +
|
| + // Stores acquired layers upon deletion.
|
| + ScopedVector<ui::Layer> layers_;
|
| +
|
| + // The owner of detached layers.
|
| + scoped_ptr<ui::LayerTreeOwner> layer_owner_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver);
|
| };
|
|
|
| void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) {
|
| - const Layer* root = layer;
|
| + const ui::Layer* root = layer;
|
| while (root->parent())
|
| root = root->parent();
|
| layer->GetTargetTransformRelativeTo(root, transform);
|
| @@ -254,12 +309,12 @@ void AnimateHideWindowCommon(aura::Window* window,
|
| window->layer()->set_delegate(NULL);
|
|
|
| // Property sets within this scope will be implicitly animated.
|
| - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
|
| - settings.AddObserver(new HidingWindowAnimationObserver(window));
|
| + ScopedHidingAnimationSettings hiding_settings(window);
|
| + hiding_settings.set_ensure_visible_after_focus_lost(true);
|
|
|
| base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window);
|
| if (duration.ToInternalValue() > 0)
|
| - settings.SetTransitionDuration(duration);
|
| + hiding_settings.layer_animation_settings()->SetTransitionDuration(duration);
|
|
|
| window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
|
| window->layer()->SetTransform(end_transform);
|
| @@ -358,8 +413,11 @@ void AddLayerAnimationsForRotate(aura::Window* window, bool show) {
|
| base::TimeDelta duration = base::TimeDelta::FromMilliseconds(
|
| kWindowAnimation_Rotate_DurationMS);
|
|
|
| + HidingWindowAnimationObserver* observer = NULL;
|
| +
|
| if (!show) {
|
| - new HidingWindowAnimationObserver(window);
|
| + // TODO(oshima): Fix observer leak.
|
| + observer = new HidingWindowAnimationObserver(window, NULL);
|
| window->layer()->GetAnimator()->SchedulePauseForProperties(
|
| duration * (100 - kWindowAnimation_Rotate_OpacityDurationPercent) / 100,
|
| ui::LayerAnimationElement::OPACITY);
|
| @@ -407,6 +465,8 @@ void AddLayerAnimationsForRotate(aura::Window* window, bool show) {
|
|
|
| window->layer()->GetAnimator()->ScheduleAnimation(
|
| new ui::LayerAnimationSequence(transition.release()));
|
| + if (observer)
|
| + observer->DetachAndRecreateLayers();
|
| }
|
|
|
| void AnimateShowWindow_Rotate(aura::Window* window) {
|
| @@ -479,6 +539,22 @@ bool AnimateHideWindow(aura::Window* window) {
|
|
|
| } // namespace
|
|
|
| +ScopedHidingAnimationSettings::ScopedHidingAnimationSettings(
|
| + aura::Window* window)
|
| + : window_(window),
|
| + ensure_visibility_after_focus_lost_(false),
|
| + layer_animation_settings_(window->layer()->GetAnimator()) {
|
| + new HidingWindowAnimationObserver(window, &layer_animation_settings_);
|
| +}
|
| +
|
| +ScopedHidingAnimationSettings::~ScopedHidingAnimationSettings() {
|
| + HidingWindowAnimationObserver* observer =
|
| + window_->GetProperty(kHidingWindowAnimationObserverKey);
|
| + DCHECK(observer);
|
| + if (ensure_visibility_after_focus_lost_)
|
| + observer->DetachAndRecreateLayers();
|
| +}
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // External interface
|
|
|
| @@ -505,7 +581,7 @@ bool HasWindowVisibilityAnimationTransition(
|
| }
|
|
|
| void SetWindowVisibilityAnimationDuration(aura::Window* window,
|
| - const TimeDelta& duration) {
|
| + const base::TimeDelta& duration) {
|
| window->SetProperty(kWindowVisibilityAnimationDurationKey,
|
| static_cast<int>(duration.ToInternalValue()));
|
| }
|
| @@ -521,11 +597,6 @@ void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window,
|
| window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position);
|
| }
|
|
|
| -ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver(
|
| - aura::Window* window) {
|
| - return new HidingWindowAnimationObserver(window);
|
| -}
|
| -
|
| bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
|
| if (WindowAnimationsDisabled(window))
|
| return false;
|
|
|