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

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>
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 int type = window->GetProperty(kWindowVisibilityAnimationTypeKey); 100 int type = window->GetProperty(kWindowVisibilityAnimationTypeKey);
101 if (type == WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT) { 101 if (type == WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT) {
102 return (window->type() == ui::wm::WINDOW_TYPE_MENU || 102 return (window->type() == ui::wm::WINDOW_TYPE_MENU ||
103 window->type() == ui::wm::WINDOW_TYPE_TOOLTIP) 103 window->type() == ui::wm::WINDOW_TYPE_TOOLTIP)
104 ? WINDOW_VISIBILITY_ANIMATION_TYPE_FADE 104 ? WINDOW_VISIBILITY_ANIMATION_TYPE_FADE
105 : WINDOW_VISIBILITY_ANIMATION_TYPE_DROP; 105 : WINDOW_VISIBILITY_ANIMATION_TYPE_DROP;
106 } 106 }
107 return type; 107 return type;
108 } 108 }
109 109
110 // Observes a hide animation. 110 // A base class for hiding animation observer. This calls
111 // A window can be hidden for a variety of reasons. Sometimes, Hide() will be 111 // 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, 112 class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver,
123 public aura::WindowObserver { 113 public aura::WindowObserver {
124 public: 114 public:
125 explicit HidingWindowAnimationObserver(aura::Window* window) 115 HidingWindowAnimationObserver(aura::Window* window,
116 ui::ScopedLayerAnimationSettings* settings)
126 : window_(window) { 117 : window_(window) {
127 window_->AddObserver(this); 118 window->AddObserver(this);
128 } 119 if (settings)
129 virtual ~HidingWindowAnimationObserver() { 120 settings->AddObserver(this);
130 STLDeleteElements(&layers_);
131 } 121 }
132 122
133 private: 123 virtual ~HidingWindowAnimationObserver() {
134 // Overridden from ui::ImplicitAnimationObserver: 124 }
125
135 virtual void OnImplicitAnimationsCompleted() OVERRIDE { 126 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
136 // Window may have been destroyed by this point. 127 // Window may have been destroyed by this point.
137 if (window_) { 128 if (window_) {
138 aura::client::AnimationHost* animation_host = 129 aura::client::AnimationHost* animation_host =
139 aura::client::GetAnimationHost(window_); 130 aura::client::GetAnimationHost(window_);
140 if (animation_host) 131 if (animation_host)
141 animation_host->OnWindowHidingAnimationCompleted(); 132 animation_host->OnWindowHidingAnimationCompleted();
142 window_->RemoveObserver(this); 133 window_->RemoveObserver(this);
143 } 134 }
144 delete this; 135 delete this;
145 } 136 }
146 137
138 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
139 DCHECK_EQ(window, window_);
140 window_->RemoveObserver(this);
141 window_ = NULL;
142 }
143
144 protected:
145 aura::Window* window_;
146
147 private:
148 DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver);
149 };
150
151 // A window can be hidden for a variety of reasons. Sometimes, Hide() will be
152 // called and life is simple. Sometimes, the window is actually bound to a
153 // views::Widget and that Widget is closed, and life is a little more
154 // complicated. When a Widget is closed the aura::Window* is actually not
155 // destroyed immediately - it is actually just immediately hidden and then
156 // destroyed when the stack unwinds. To handle this case, we start the hide
157 // animation immediately when the window is hidden, then when the window is
158 // subsequently destroyed this object acquires ownership of the window's layer,
159 // so that it can continue animating it until the animation completes.
160 // Regardless of whether or not the window is destroyed, this object deletes
161 // itself when the animation completes.
162 class DetachLayersWhenDestroyedAnimationObserver
163 : public HidingWindowAnimationObserver {
164 public:
165 DetachLayersWhenDestroyedAnimationObserver(
166 aura::Window* window,
167 ui::ScopedLayerAnimationSettings* settings)
168 : HidingWindowAnimationObserver(window, settings) {
169 }
170
171 virtual ~DetachLayersWhenDestroyedAnimationObserver() {
172 STLDeleteElements(&layers_);
173 }
174
175 private:
147 // Overridden from aura::WindowObserver: 176 // Overridden from aura::WindowObserver:
148 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { 177 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
149 DCHECK_EQ(window, window_); 178 DCHECK_EQ(window, window_);
150 DCHECK(layers_.empty()); 179 DCHECK(layers_.empty());
151 AcquireAllLayers(window_->layer()); 180 AcquireAllLayers(window_->layer());
152 window_->RemoveObserver(this); 181 HidingWindowAnimationObserver::OnWindowDestroying(window);
153 window_ = NULL;
154 } 182 }
155 183
156 void AcquireAllLayers(ui::Layer* layer) { 184 void AcquireAllLayers(ui::Layer* layer) {
157 if (layer->owner()) { 185 if (layer->owner()) {
158 ui::Layer* released = layer->owner()->AcquireLayer(); 186 ui::Layer* released = layer->owner()->AcquireLayer();
159 DCHECK_EQ(layer, released); 187 CHECK_EQ(layer, released);
160 layers_.push_back(released); 188 layers_.push_back(released);
161 } 189 }
162 std::vector<Layer*>::const_iterator it = layer->children().begin(); 190 std::vector<ui::Layer*>::const_iterator it = layer->children().begin();
163 for (; it != layer->children().end(); ++it) 191 for (; it != layer->children().end(); ++it)
164 AcquireAllLayers(*it); 192 AcquireAllLayers(*it);
165 } 193 }
166 194
167 aura::Window* window_;
168 std::vector<ui::Layer*> layers_; 195 std::vector<ui::Layer*> layers_;
169 196
170 DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver); 197 DISALLOW_COPY_AND_ASSIGN(DetachLayersWhenDestroyedAnimationObserver);
198 };
199
200 // When hiding an active window, the animating layer can be hidden by
201 // new active window's layer. This class detaches the layers for
202 // hiding animation, creates new layers for the window and stacks them
203 // above the window and its transient children so that the layer for
204 // new active window will not hide the hiding animation.
205 class DetachAndRecreateLayersAnimationObserver
206 : HidingWindowAnimationObserver {
207 public:
208 DetachAndRecreateLayersAnimationObserver(
209 aura::Window* window,
210 ui::ScopedLayerAnimationSettings* settings)
211 : HidingWindowAnimationObserver(window, settings) {
212 }
213
214 virtual ~DetachAndRecreateLayersAnimationObserver() {
215 DeepDeleteLayers(layer_);
216 }
217
218 void DetachAndRecreateLayers() {
219 layer_ = RecreateWindowLayers(window_, true);
220 // If the window has transient children, move above the top most
221 // transient child so that activation change does not put the
222 // window above the animating layer.
223 if(window_->parent()) {
224 const aura::Window::Windows& transient_children =
225 GetTransientChildren(window_);
226 aura::Window::Windows::const_iterator iter =
227 std::find(window_->parent()->children().begin(),
228 window_->parent()->children().end(),
229 window_);
230 DCHECK(iter != window_->parent()->children().end());
231 aura::Window* topmost_transient_child = NULL;
232 for (++iter; iter != window_->parent()->children().end(); ++iter) {
233 if (std::find(transient_children.begin(),
234 transient_children.end(),
235 *iter) !=
236 transient_children.end()) {
237 topmost_transient_child = *iter;
238 }
239 }
240 if (topmost_transient_child) {
241 window_->parent()->layer()->StackAbove(
242 layer_, topmost_transient_child->layer());
243 }
244 }
245 // Make the new layer invisible immediately.
246 window_->layer()->SetVisible(false);
247 window_->layer()->SetOpacity(0);
248 }
249
250 private:
251 ui::Layer* layer_;
252
253 DISALLOW_COPY_AND_ASSIGN(DetachAndRecreateLayersAnimationObserver);
171 }; 254 };
172 255
173 void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) { 256 void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) {
174 const Layer* root = layer; 257 const Layer* root = layer;
175 while (root->parent()) 258 while (root->parent())
176 root = root->parent(); 259 root = root->parent();
177 layer->GetTargetTransformRelativeTo(root, transform); 260 layer->GetTargetTransformRelativeTo(root, transform);
178 } 261 }
179 262
180 gfx::Rect GetLayerWorldBoundsAfterTransform(ui::Layer* layer, 263 gfx::Rect GetLayerWorldBoundsAfterTransform(ui::Layer* layer,
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 331
249 // Hides a window using an animation, animating its opacity from 1.f to 0.f, 332 // 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|. 333 // its visibility to false, and its transform to |end_transform|.
251 void AnimateHideWindowCommon(aura::Window* window, 334 void AnimateHideWindowCommon(aura::Window* window,
252 const gfx::Transform& end_transform) { 335 const gfx::Transform& end_transform) {
253 AugmentWindowSize(window, end_transform); 336 AugmentWindowSize(window, end_transform);
254 window->layer()->set_delegate(NULL); 337 window->layer()->set_delegate(NULL);
255 338
256 // Property sets within this scope will be implicitly animated. 339 // Property sets within this scope will be implicitly animated.
257 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); 340 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
258 settings.AddObserver(new HidingWindowAnimationObserver(window)); 341 scoped_ptr<LayerDetacherForHidingAnimation> detacher =
342 DetachAndRecreateLayersForHidingAnimation(window, &settings);
259 343
260 base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window); 344 base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window);
261 if (duration.ToInternalValue() > 0) 345 if (duration.ToInternalValue() > 0)
262 settings.SetTransitionDuration(duration); 346 settings.SetTransitionDuration(duration);
263 347
264 window->layer()->SetOpacity(kWindowAnimation_HideOpacity); 348 window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
265 window->layer()->SetTransform(end_transform); 349 window->layer()->SetTransform(end_transform);
266 window->layer()->SetVisible(false); 350 window->layer()->SetVisible(false);
267 } 351 }
268 352
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 } 435 }
352 436
353 void AddLayerAnimationsForRotate(aura::Window* window, bool show) { 437 void AddLayerAnimationsForRotate(aura::Window* window, bool show) {
354 window->layer()->set_delegate(window); 438 window->layer()->set_delegate(window);
355 if (show) 439 if (show)
356 window->layer()->SetOpacity(kWindowAnimation_HideOpacity); 440 window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
357 441
358 base::TimeDelta duration = base::TimeDelta::FromMilliseconds( 442 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(
359 kWindowAnimation_Rotate_DurationMS); 443 kWindowAnimation_Rotate_DurationMS);
360 444
445 scoped_ptr<LayerDetacherForHidingAnimation> layer_detacher;
361 if (!show) { 446 if (!show) {
362 new HidingWindowAnimationObserver(window); 447 // TODO(oshima): Fix observer leak.
448 layer_detacher =
449 DetachAndRecreateLayersForHidingAnimation(window, NULL).Pass();
363 window->layer()->GetAnimator()->SchedulePauseForProperties( 450 window->layer()->GetAnimator()->SchedulePauseForProperties(
364 duration * (100 - kWindowAnimation_Rotate_OpacityDurationPercent) / 100, 451 duration * (100 - kWindowAnimation_Rotate_OpacityDurationPercent) / 100,
365 ui::LayerAnimationElement::OPACITY); 452 ui::LayerAnimationElement::OPACITY);
366 } 453 }
367 scoped_ptr<ui::LayerAnimationElement> opacity( 454 scoped_ptr<ui::LayerAnimationElement> opacity(
368 ui::LayerAnimationElement::CreateOpacityElement( 455 ui::LayerAnimationElement::CreateOpacityElement(
369 show ? kWindowAnimation_ShowOpacity : kWindowAnimation_HideOpacity, 456 show ? kWindowAnimation_ShowOpacity : kWindowAnimation_HideOpacity,
370 duration * kWindowAnimation_Rotate_OpacityDurationPercent / 100)); 457 duration * kWindowAnimation_Rotate_OpacityDurationPercent / 100));
371 opacity->set_tween_type(gfx::Tween::EASE_IN_OUT); 458 opacity->set_tween_type(gfx::Tween::EASE_IN_OUT);
372 window->layer()->GetAnimator()->ScheduleAnimation( 459 window->layer()->GetAnimator()->ScheduleAnimation(
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 AnimateHideWindow_Fade(window); 557 AnimateHideWindow_Fade(window);
471 return true; 558 return true;
472 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE: 559 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE:
473 AnimateHideWindow_Rotate(window); 560 AnimateHideWindow_Rotate(window);
474 return true; 561 return true;
475 default: 562 default:
476 return false; 563 return false;
477 } 564 }
478 } 565 }
479 566
567 // Refer to the description of LayerDetacherForHidingAnimation in
568 // window_animations.h for details.
569 class LayerDetacherForHidingAnimationImpl
570 : public LayerDetacherForHidingAnimation {
571 public:
572 LayerDetacherForHidingAnimationImpl(
573 aura::Window* window,
574 ui::ScopedLayerAnimationSettings* settings)
575 : observer_(
576 new DetachAndRecreateLayersAnimationObserver(window, settings)) {
577 }
578
579 virtual ~LayerDetacherForHidingAnimationImpl() {
580 observer_->DetachAndRecreateLayers();
581 }
582
583 private:
584 DetachAndRecreateLayersAnimationObserver* observer_;
585
586 DISALLOW_COPY_AND_ASSIGN(LayerDetacherForHidingAnimationImpl);
587 };
588
480 } // namespace 589 } // namespace
481 590
482 //////////////////////////////////////////////////////////////////////////////// 591 ////////////////////////////////////////////////////////////////////////////////
483 // External interface 592 // External interface
484 593
485 void SetWindowVisibilityAnimationType(aura::Window* window, int type) { 594 void SetWindowVisibilityAnimationType(aura::Window* window, int type) {
486 window->SetProperty(kWindowVisibilityAnimationTypeKey, type); 595 window->SetProperty(kWindowVisibilityAnimationTypeKey, type);
487 } 596 }
488 597
489 int GetWindowVisibilityAnimationType(aura::Window* window) { 598 int GetWindowVisibilityAnimationType(aura::Window* window) {
(...skipping 24 matching lines...) Expand all
514 const aura::Window& window) { 623 const aura::Window& window) {
515 return base::TimeDelta::FromInternalValue( 624 return base::TimeDelta::FromInternalValue(
516 window.GetProperty(kWindowVisibilityAnimationDurationKey)); 625 window.GetProperty(kWindowVisibilityAnimationDurationKey));
517 } 626 }
518 627
519 void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window, 628 void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window,
520 float position) { 629 float position) {
521 window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position); 630 window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position);
522 } 631 }
523 632
524 ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver( 633 scoped_ptr<LayerDetacherForHidingAnimation>
525 aura::Window* window) { 634 DetachAndRecreateLayersForHidingAnimation(
526 return new HidingWindowAnimationObserver(window); 635 aura::Window* window,
636 ui::ScopedLayerAnimationSettings* settings) {
637 return scoped_ptr<LayerDetacherForHidingAnimation>(
638 new LayerDetacherForHidingAnimationImpl(window, settings)).Pass();
639 }
640
641 void DetachLayersForHidingAnimationWhenDestroyed(
642 aura::Window* window,
643 ui::ScopedLayerAnimationSettings* settings) {
644 new DetachLayersWhenDestroyedAnimationObserver(window, settings);
527 } 645 }
528 646
529 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) { 647 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
530 if (WindowAnimationsDisabled(window)) 648 if (WindowAnimationsDisabled(window))
531 return false; 649 return false;
532 if (visible) 650 if (visible)
533 return AnimateShowWindow(window); 651 return AnimateShowWindow(window);
534 // Don't start hiding the window again if it's already being hidden. 652 // Don't start hiding the window again if it's already being hidden.
535 return window->layer()->GetTargetOpacity() != 0.0f && 653 return window->layer()->GetTargetOpacity() != 0.0f &&
536 AnimateHideWindow(window); 654 AnimateHideWindow(window);
(...skipping 12 matching lines...) Expand all
549 667
550 bool WindowAnimationsDisabled(aura::Window* window) { 668 bool WindowAnimationsDisabled(aura::Window* window) {
551 return (!gfx::Animation::ShouldRenderRichAnimation() || (window && 669 return (!gfx::Animation::ShouldRenderRichAnimation() || (window &&
552 window->GetProperty(aura::client::kAnimationsDisabledKey)) || 670 window->GetProperty(aura::client::kAnimationsDisabledKey)) ||
553 CommandLine::ForCurrentProcess()->HasSwitch( 671 CommandLine::ForCurrentProcess()->HasSwitch(
554 switches::kWindowAnimationsDisabled)); 672 switches::kWindowAnimationsDisabled));
555 } 673 }
556 674
557 } // namespace corewm 675 } // namespace corewm
558 } // namespace views 676 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698