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

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

Powered by Google App Engine
This is Rietveld 408576698