Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(991)

Unified Diff: ui/wm/core/window_animations.cc

Issue 180273025: Keep dedicated layers for hiding animation (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/wm/core/window_animations.h ('k') | ui/wm/core/window_animations_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 =
sky 2014/03/13 22:34:05 Why isn't this a member?
+ 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;
« no previous file with comments | « ui/wm/core/window_animations.h ('k') | ui/wm/core/window_animations_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698