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

Side by Side Diff: ui/views/corewm/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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/corewm/window_animations.h" 5 #include "ui/views/corewm/window_animations.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/message_loop/message_loop.h" 15 #include "base/message_loop/message_loop.h"
16 #include "base/stl_util.h" 16 #include "base/stl_util.h"
17 #include "base/time/time.h" 17 #include "base/time/time.h"
18 #include "ui/aura/client/animation_host.h" 18 #include "ui/aura/client/animation_host.h"
19 #include "ui/aura/client/aura_constants.h" 19 #include "ui/aura/client/aura_constants.h"
20 #include "ui/aura/window.h" 20 #include "ui/aura/window.h"
21 #include "ui/aura/window_delegate.h" 21 #include "ui/aura/window_delegate.h"
22 #include "ui/aura/window_observer.h" 22 #include "ui/aura/window_observer.h"
23 #include "ui/aura/window_property.h" 23 #include "ui/aura/window_property.h"
24 #include "ui/compositor/compositor_observer.h" 24 #include "ui/compositor/compositor_observer.h"
25 #include "ui/compositor/layer.h" 25 #include "ui/compositor/layer.h"
26 #include "ui/compositor/layer_animation_observer.h" 26 #include "ui/compositor/layer_animation_observer.h"
27 #include "ui/compositor/layer_animation_sequence.h" 27 #include "ui/compositor/layer_animation_sequence.h"
28 #include "ui/compositor/layer_animator.h" 28 #include "ui/compositor/layer_animator.h"
29 #include "ui/compositor/layer_tree_owner.h"
29 #include "ui/compositor/scoped_layer_animation_settings.h" 30 #include "ui/compositor/scoped_layer_animation_settings.h"
30 #include "ui/gfx/animation/animation.h" 31 #include "ui/gfx/animation/animation.h"
31 #include "ui/gfx/interpolated_transform.h" 32 #include "ui/gfx/interpolated_transform.h"
32 #include "ui/gfx/rect_conversions.h" 33 #include "ui/gfx/rect_conversions.h"
33 #include "ui/gfx/screen.h" 34 #include "ui/gfx/screen.h"
34 #include "ui/gfx/vector2d.h" 35 #include "ui/gfx/vector2d.h"
35 #include "ui/gfx/vector3d_f.h" 36 #include "ui/gfx/vector3d_f.h"
36 #include "ui/views/corewm/corewm_switches.h" 37 #include "ui/views/corewm/corewm_switches.h"
37 #include "ui/views/corewm/window_util.h" 38 #include "ui/views/corewm/window_util.h"
38 39
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 int type = window->GetProperty(kWindowVisibilityAnimationTypeKey); 101 int type = window->GetProperty(kWindowVisibilityAnimationTypeKey);
101 if (type == WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT) { 102 if (type == WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT) {
102 return (window->type() == ui::wm::WINDOW_TYPE_MENU || 103 return (window->type() == ui::wm::WINDOW_TYPE_MENU ||
103 window->type() == ui::wm::WINDOW_TYPE_TOOLTIP) 104 window->type() == ui::wm::WINDOW_TYPE_TOOLTIP)
104 ? WINDOW_VISIBILITY_ANIMATION_TYPE_FADE 105 ? WINDOW_VISIBILITY_ANIMATION_TYPE_FADE
105 : WINDOW_VISIBILITY_ANIMATION_TYPE_DROP; 106 : WINDOW_VISIBILITY_ANIMATION_TYPE_DROP;
106 } 107 }
107 return type; 108 return type;
108 } 109 }
109 110
110 // Observes a hide animation. 111 // A base class for hiding animation observer. This calls
111 // A window can be hidden for a variety of reasons. Sometimes, Hide() will be 112 // AnimationHost::OnWindowHidingAnimationCompleted upon completion.
112 // called and life is simple. Sometimes, the window is actually bound to a
113 // views::Widget and that Widget is closed, and life is a little more
114 // complicated. When a Widget is closed the aura::Window* is actually not
115 // destroyed immediately - it is actually just immediately hidden and then
116 // destroyed when the stack unwinds. To handle this case, we start the hide
117 // animation immediately when the window is hidden, then when the window is
118 // subsequently destroyed this object acquires ownership of the window's layer,
119 // so that it can continue animating it until the animation completes.
120 // Regardless of whether or not the window is destroyed, this object deletes
121 // itself when the animation completes.
122 class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver, 113 class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver,
123 public aura::WindowObserver { 114 public aura::WindowObserver {
124 public: 115 public:
125 explicit HidingWindowAnimationObserver(aura::Window* window) 116 HidingWindowAnimationObserver(aura::Window* window,
117 ui::ScopedLayerAnimationSettings* settings)
126 : window_(window) { 118 : window_(window) {
127 window_->AddObserver(this); 119 window->AddObserver(this);
128 } 120 if (settings)
129 virtual ~HidingWindowAnimationObserver() { 121 settings->AddObserver(this);
130 STLDeleteElements(&layers_);
131 } 122 }
132 123
133 private: 124 virtual ~HidingWindowAnimationObserver() {
134 // Overridden from ui::ImplicitAnimationObserver: 125 }
126
135 virtual void OnImplicitAnimationsCompleted() OVERRIDE { 127 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
136 // Window may have been destroyed by this point. 128 // Window may have been destroyed by this point.
137 if (window_) { 129 if (window_) {
138 aura::client::AnimationHost* animation_host = 130 aura::client::AnimationHost* animation_host =
139 aura::client::GetAnimationHost(window_); 131 aura::client::GetAnimationHost(window_);
140 if (animation_host) 132 if (animation_host)
141 animation_host->OnWindowHidingAnimationCompleted(); 133 animation_host->OnWindowHidingAnimationCompleted();
142 window_->RemoveObserver(this); 134 window_->RemoveObserver(this);
143 } 135 }
144 delete this; 136 delete this;
145 } 137 }
146 138
139 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
140 DCHECK_EQ(window, window_);
141 window_->RemoveObserver(this);
142 window_ = NULL;
143 }
144
145 protected:
146 aura::Window* window_;
147
148 private:
149 DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver);
150 };
151
152 // A window can be hidden for a variety of reasons. Sometimes, Hide() will be
153 // called and life is simple. Sometimes, the window is actually bound to a
154 // views::Widget and that Widget is closed, and life is a little more
155 // complicated. When a Widget is closed the aura::Window* is actually not
156 // destroyed immediately - it is actually just immediately hidden and then
157 // destroyed when the stack unwinds. To handle this case, we start the hide
158 // animation immediately when the window is hidden, then when the window is
159 // subsequently destroyed this object acquires ownership of the window's layer,
160 // so that it can continue animating it until the animation completes.
161 // Regardless of whether or not the window is destroyed, this object deletes
162 // itself when the animation completes.
163 class DetachLayersWhenDestroyedAnimationObserver
164 : public HidingWindowAnimationObserver {
165 public:
166 DetachLayersWhenDestroyedAnimationObserver(
167 aura::Window* window,
168 ui::ScopedLayerAnimationSettings* settings)
169 : HidingWindowAnimationObserver(window, settings) {
170 }
171
172 virtual ~DetachLayersWhenDestroyedAnimationObserver() {
173 STLDeleteElements(&layers_);
174 }
175
176 private:
147 // Overridden from aura::WindowObserver: 177 // Overridden from aura::WindowObserver:
148 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { 178 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
149 DCHECK_EQ(window, window_); 179 DCHECK_EQ(window, window_);
150 DCHECK(layers_.empty()); 180 DCHECK(layers_.empty());
151 AcquireAllLayers(window_->layer()); 181 AcquireAllLayers(window_->layer());
152 window_->RemoveObserver(this); 182 HidingWindowAnimationObserver::OnWindowDestroying(window);
153 window_ = NULL;
154 } 183 }
155 184
156 void AcquireAllLayers(ui::Layer* layer) { 185 void AcquireAllLayers(ui::Layer* layer) {
157 if (layer->owner()) { 186 if (layer->owner()) {
158 ui::Layer* released = layer->owner()->AcquireLayer(); 187 ui::Layer* released = layer->owner()->AcquireLayer();
159 DCHECK_EQ(layer, released); 188 CHECK_EQ(layer, released);
160 layers_.push_back(released); 189 layers_.push_back(released);
161 } 190 }
162 std::vector<Layer*>::const_iterator it = layer->children().begin(); 191 std::vector<ui::Layer*>::const_iterator it = layer->children().begin();
163 for (; it != layer->children().end(); ++it) 192 for (; it != layer->children().end(); ++it)
164 AcquireAllLayers(*it); 193 AcquireAllLayers(*it);
165 } 194 }
166 195
167 aura::Window* window_;
168 std::vector<ui::Layer*> layers_; 196 std::vector<ui::Layer*> layers_;
sky 2014/03/11 19:16:23 Used a ScopedVector here?
169 197
170 DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver); 198 DISALLOW_COPY_AND_ASSIGN(DetachLayersWhenDestroyedAnimationObserver);
171 }; 199 };
172 200
173 void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) { 201 void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) {
174 const Layer* root = layer; 202 const Layer* root = layer;
175 while (root->parent()) 203 while (root->parent())
176 root = root->parent(); 204 root = root->parent();
177 layer->GetTargetTransformRelativeTo(root, transform); 205 layer->GetTargetTransformRelativeTo(root, transform);
178 } 206 }
179 207
180 gfx::Rect GetLayerWorldBoundsAfterTransform(ui::Layer* layer, 208 gfx::Rect GetLayerWorldBoundsAfterTransform(ui::Layer* layer,
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 276
249 // Hides a window using an animation, animating its opacity from 1.f to 0.f, 277 // Hides a window using an animation, animating its opacity from 1.f to 0.f,
250 // its visibility to false, and its transform to |end_transform|. 278 // its visibility to false, and its transform to |end_transform|.
251 void AnimateHideWindowCommon(aura::Window* window, 279 void AnimateHideWindowCommon(aura::Window* window,
252 const gfx::Transform& end_transform) { 280 const gfx::Transform& end_transform) {
253 AugmentWindowSize(window, end_transform); 281 AugmentWindowSize(window, end_transform);
254 window->layer()->set_delegate(NULL); 282 window->layer()->set_delegate(NULL);
255 283
256 // Property sets within this scope will be implicitly animated. 284 // Property sets within this scope will be implicitly animated.
257 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); 285 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
258 settings.AddObserver(new HidingWindowAnimationObserver(window)); 286 scoped_ptr<LayerDetacherForHidingAnimation> detacher =
287 DetachAndRecreateLayersForHidingAnimation(window, &settings);
259 288
260 base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window); 289 base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window);
261 if (duration.ToInternalValue() > 0) 290 if (duration.ToInternalValue() > 0)
262 settings.SetTransitionDuration(duration); 291 settings.SetTransitionDuration(duration);
263 292
264 window->layer()->SetOpacity(kWindowAnimation_HideOpacity); 293 window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
265 window->layer()->SetTransform(end_transform); 294 window->layer()->SetTransform(end_transform);
266 window->layer()->SetVisible(false); 295 window->layer()->SetVisible(false);
267 } 296 }
268 297
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 } 380 }
352 381
353 void AddLayerAnimationsForRotate(aura::Window* window, bool show) { 382 void AddLayerAnimationsForRotate(aura::Window* window, bool show) {
354 window->layer()->set_delegate(window); 383 window->layer()->set_delegate(window);
355 if (show) 384 if (show)
356 window->layer()->SetOpacity(kWindowAnimation_HideOpacity); 385 window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
357 386
358 base::TimeDelta duration = base::TimeDelta::FromMilliseconds( 387 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(
359 kWindowAnimation_Rotate_DurationMS); 388 kWindowAnimation_Rotate_DurationMS);
360 389
390 scoped_ptr<LayerDetacherForHidingAnimation> layer_detacher;
361 if (!show) { 391 if (!show) {
362 new HidingWindowAnimationObserver(window); 392 // TODO(oshima): Fix observer leak.
393 layer_detacher =
394 DetachAndRecreateLayersForHidingAnimation(window, NULL).Pass();
363 window->layer()->GetAnimator()->SchedulePauseForProperties( 395 window->layer()->GetAnimator()->SchedulePauseForProperties(
364 duration * (100 - kWindowAnimation_Rotate_OpacityDurationPercent) / 100, 396 duration * (100 - kWindowAnimation_Rotate_OpacityDurationPercent) / 100,
365 ui::LayerAnimationElement::OPACITY); 397 ui::LayerAnimationElement::OPACITY);
366 } 398 }
367 scoped_ptr<ui::LayerAnimationElement> opacity( 399 scoped_ptr<ui::LayerAnimationElement> opacity(
368 ui::LayerAnimationElement::CreateOpacityElement( 400 ui::LayerAnimationElement::CreateOpacityElement(
369 show ? kWindowAnimation_ShowOpacity : kWindowAnimation_HideOpacity, 401 show ? kWindowAnimation_ShowOpacity : kWindowAnimation_HideOpacity,
370 duration * kWindowAnimation_Rotate_OpacityDurationPercent / 100)); 402 duration * kWindowAnimation_Rotate_OpacityDurationPercent / 100));
371 opacity->set_tween_type(gfx::Tween::EASE_IN_OUT); 403 opacity->set_tween_type(gfx::Tween::EASE_IN_OUT);
372 window->layer()->GetAnimator()->ScheduleAnimation( 404 window->layer()->GetAnimator()->ScheduleAnimation(
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE: 504 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE:
473 AnimateHideWindow_Rotate(window); 505 AnimateHideWindow_Rotate(window);
474 return true; 506 return true;
475 default: 507 default:
476 return false; 508 return false;
477 } 509 }
478 } 510 }
479 511
480 } // namespace 512 } // namespace
481 513
514 // When hiding an active window, the animating layer can be hidden by
515 // new active window's layer. This class detaches the layers for
516 // hiding animation, creates new layers for the window and stacks them
517 // above the window and its transient children so that the layer for
518 // new active window will not hide the hiding animation.
519 class DetachAndRecreateLayersAnimationObserver
520 : HidingWindowAnimationObserver {
521 public:
522 DetachAndRecreateLayersAnimationObserver(
523 aura::Window* window,
524 ui::ScopedLayerAnimationSettings* settings)
525 : HidingWindowAnimationObserver(window, settings) {
526 }
527
528 virtual ~DetachAndRecreateLayersAnimationObserver() {
529 }
530
531 void DetachAndRecreateLayers() {
532 layer_owner_ = RecreateLayers(window_);
533 // If the window has transient children, move above the top most
534 // transient child so that activation change does not put the
535 // window above the animating layer.
536 if(window_->parent()) {
537 const aura::Window::Windows& transient_children =
538 GetTransientChildren(window_);
539 aura::Window::Windows::const_iterator iter =
540 std::find(window_->parent()->children().begin(),
541 window_->parent()->children().end(),
542 window_);
543 DCHECK(iter != window_->parent()->children().end());
544 aura::Window* topmost_transient_child = NULL;
545 for (++iter; iter != window_->parent()->children().end(); ++iter) {
546 if (std::find(transient_children.begin(),
547 transient_children.end(),
548 *iter) !=
549 transient_children.end()) {
550 topmost_transient_child = *iter;
551 }
552 }
553 if (topmost_transient_child) {
554 window_->parent()->layer()->StackAbove(
555 layer_owner_->root(), topmost_transient_child->layer());
556 }
557 }
558 // Make the new layer invisible immediately.
559 window_->layer()->SetVisible(false);
560 window_->layer()->SetOpacity(0);
sky 2014/03/11 19:16:23 These two calls make me nervous. I think they shou
561 }
562
563 private:
564 scoped_ptr<ui::LayerTreeOwner> layer_owner_;
565
566 DISALLOW_COPY_AND_ASSIGN(DetachAndRecreateLayersAnimationObserver);
567 };
568
569 LayerDetacherForHidingAnimation::LayerDetacherForHidingAnimation(
570 aura::Window* window,
571 ui::ScopedLayerAnimationSettings* settings)
572 : observer_(
573 new DetachAndRecreateLayersAnimationObserver(window, settings)) {
574 }
575
576 LayerDetacherForHidingAnimation::~LayerDetacherForHidingAnimation() {
577 observer_->DetachAndRecreateLayers();
578 }
579
482 //////////////////////////////////////////////////////////////////////////////// 580 ////////////////////////////////////////////////////////////////////////////////
483 // External interface 581 // External interface
484 582
485 void SetWindowVisibilityAnimationType(aura::Window* window, int type) { 583 void SetWindowVisibilityAnimationType(aura::Window* window, int type) {
486 window->SetProperty(kWindowVisibilityAnimationTypeKey, type); 584 window->SetProperty(kWindowVisibilityAnimationTypeKey, type);
487 } 585 }
488 586
489 int GetWindowVisibilityAnimationType(aura::Window* window) { 587 int GetWindowVisibilityAnimationType(aura::Window* window) {
490 return window->GetProperty(kWindowVisibilityAnimationTypeKey); 588 return window->GetProperty(kWindowVisibilityAnimationTypeKey);
491 } 589 }
(...skipping 22 matching lines...) Expand all
514 const aura::Window& window) { 612 const aura::Window& window) {
515 return base::TimeDelta::FromInternalValue( 613 return base::TimeDelta::FromInternalValue(
516 window.GetProperty(kWindowVisibilityAnimationDurationKey)); 614 window.GetProperty(kWindowVisibilityAnimationDurationKey));
517 } 615 }
518 616
519 void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window, 617 void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window,
520 float position) { 618 float position) {
521 window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position); 619 window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position);
522 } 620 }
523 621
524 ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver( 622 scoped_ptr<LayerDetacherForHidingAnimation>
525 aura::Window* window) { 623 DetachAndRecreateLayersForHidingAnimation(
526 return new HidingWindowAnimationObserver(window); 624 aura::Window* window,
625 ui::ScopedLayerAnimationSettings* settings) {
626 return scoped_ptr<LayerDetacherForHidingAnimation>(
627 new LayerDetacherForHidingAnimation(window, settings)).Pass();
628 }
629
630 void DetachLayersForHidingAnimationWhenDestroyed(
631 aura::Window* window,
632 ui::ScopedLayerAnimationSettings* settings) {
633 new DetachLayersWhenDestroyedAnimationObserver(window, settings);
527 } 634 }
528 635
529 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) { 636 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
530 if (WindowAnimationsDisabled(window)) 637 if (WindowAnimationsDisabled(window))
531 return false; 638 return false;
532 if (visible) 639 if (visible)
533 return AnimateShowWindow(window); 640 return AnimateShowWindow(window);
534 // Don't start hiding the window again if it's already being hidden. 641 // Don't start hiding the window again if it's already being hidden.
535 return window->layer()->GetTargetOpacity() != 0.0f && 642 return window->layer()->GetTargetOpacity() != 0.0f &&
536 AnimateHideWindow(window); 643 AnimateHideWindow(window);
(...skipping 12 matching lines...) Expand all
549 656
550 bool WindowAnimationsDisabled(aura::Window* window) { 657 bool WindowAnimationsDisabled(aura::Window* window) {
551 return (!gfx::Animation::ShouldRenderRichAnimation() || (window && 658 return (!gfx::Animation::ShouldRenderRichAnimation() || (window &&
552 window->GetProperty(aura::client::kAnimationsDisabledKey)) || 659 window->GetProperty(aura::client::kAnimationsDisabledKey)) ||
553 CommandLine::ForCurrentProcess()->HasSwitch( 660 CommandLine::ForCurrentProcess()->HasSwitch(
554 switches::kWindowAnimationsDisabled)); 661 switches::kWindowAnimationsDisabled));
555 } 662 }
556 663
557 } // namespace corewm 664 } // namespace corewm
558 } // namespace views 665 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698