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

Side by Side Diff: ash/wm/window_animations.cc

Issue 10444014: ash: Improved window maximize/restore animations (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix workspace mgr, remove ignore_window, cleanup Created 8 years, 6 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 "ash/wm/window_animations.h" 5 #include "ash/wm/window_animations.h"
6 6
7 #include "ash/ash_switches.h" 7 #include "ash/ash_switches.h"
8 #include "ash/launcher/launcher.h" 8 #include "ash/launcher/launcher.h"
9 #include "ash/shell.h" 9 #include "ash/shell.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/message_loop.h" 13 #include "base/message_loop.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "base/time.h" 15 #include "base/time.h"
16 #include "ui/aura/client/aura_constants.h" 16 #include "ui/aura/client/aura_constants.h"
17 #include "ui/aura/window.h" 17 #include "ui/aura/window.h"
18 #include "ui/aura/window_observer.h" 18 #include "ui/aura/window_observer.h"
19 #include "ui/aura/window_property.h" 19 #include "ui/aura/window_property.h"
20 #include "ui/compositor/compositor_observer.h"
20 #include "ui/compositor/layer.h" 21 #include "ui/compositor/layer.h"
21 #include "ui/compositor/layer_animation_observer.h" 22 #include "ui/compositor/layer_animation_observer.h"
22 #include "ui/compositor/layer_animation_sequence.h" 23 #include "ui/compositor/layer_animation_sequence.h"
23 #include "ui/compositor/layer_animator.h" 24 #include "ui/compositor/layer_animator.h"
24 #include "ui/compositor/scoped_layer_animation_settings.h" 25 #include "ui/compositor/scoped_layer_animation_settings.h"
25 #include "ui/gfx/interpolated_transform.h" 26 #include "ui/gfx/interpolated_transform.h"
26 #include "ui/gfx/screen.h" 27 #include "ui/gfx/screen.h"
27 28
28 DECLARE_WINDOW_PROPERTY_TYPE(int) 29 DECLARE_WINDOW_PROPERTY_TYPE(int)
29 DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationType) 30 DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationType)
30 DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationTransition) 31 DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationTransition)
31 32
33 using aura::Window;
32 using base::TimeDelta; 34 using base::TimeDelta;
35 using ui::Layer;
33 36
34 namespace ash { 37 namespace ash {
35 namespace internal { 38 namespace internal {
36 39
37 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationType, 40 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationType,
38 kWindowVisibilityAnimationTypeKey, 41 kWindowVisibilityAnimationTypeKey,
39 WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT); 42 WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
40 DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0); 43 DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0);
41 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition, 44 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition,
42 kWindowVisibilityAnimationTransitionKey, 45 kWindowVisibilityAnimationTransitionKey,
43 ANIMATE_BOTH); 46 ANIMATE_BOTH);
44 47
45 namespace { 48 namespace {
46 49
47 const int kDefaultAnimationDurationForMenuMS = 150; 50 const int kDefaultAnimationDurationForMenuMS = 150;
48 51
52 const int kCrossFadeAnimationDurationMs = 400;
53
49 const float kWindowAnimation_HideOpacity = 0.f; 54 const float kWindowAnimation_HideOpacity = 0.f;
50 const float kWindowAnimation_ShowOpacity = 1.f; 55 const float kWindowAnimation_ShowOpacity = 1.f;
51 const float kWindowAnimation_TranslateFactor = -0.025f; 56 const float kWindowAnimation_TranslateFactor = -0.025f;
52 const float kWindowAnimation_ScaleFactor = 1.05f; 57 const float kWindowAnimation_ScaleFactor = 1.05f;
53 const float kWindowAnimation_MinimizeRotate = -5.f; 58 const float kWindowAnimation_MinimizeRotate = -5.f;
54 59
55 const float kWindowAnimation_Vertical_TranslateY = 15.f; 60 const float kWindowAnimation_Vertical_TranslateY = 15.f;
56 61
57 // Amount windows are scaled during workspace animations. 62 // Amount windows are scaled during workspace animations.
58 const float kWorkspaceScale = .95f; 63 const float kWorkspaceScale = .95f;
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 return true; 470 return true;
466 case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE: 471 case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE:
467 AnimateHideWindow_Minimize(window); 472 AnimateHideWindow_Minimize(window);
468 return true; 473 return true;
469 default: 474 default:
470 NOTREACHED(); 475 NOTREACHED();
471 return false; 476 return false;
472 } 477 }
473 } 478 }
474 479
480 // Recreates a fresh layer for |window| and all its child windows. Does not
481 // recreate shadows or other non-window layers. Returns the old layer and its
482 // children, maintaining the hierarchy.
483 Layer* RecreateWindowLayers(Window* window) {
484 Layer* old_layer = window->RecreateLayer();
485 for (Window::Windows::const_iterator it = window->children().begin();
486 it != window->children().end();
487 ++it) {
488 aura::Window* child = *it;
489 Layer* old_child_layer = RecreateWindowLayers(child);
490 // Maintain the hierarchy of the detached layers.
491 old_layer->Add(old_child_layer);
492 }
493 return old_layer;
494 }
495
496 // Deletes |layer| and all its child layers.
497 void DeepDelete(Layer* layer) {
498 std::vector<Layer*> children = layer->children();
499 for (std::vector<Layer*>::const_iterator it = children.begin();
500 it != children.end();
501 ++it) {
502 Layer* child = *it;
503 DeepDelete(child);
504 }
505 delete layer;
506 }
507
508 // Observer for a window cross-fade animation. If either the window closes or
509 // the layer's animation completes or compositing is aborted due to GPU crash,
510 // it deletes the layer and removes itself as an observer.
511 class CrossFadeObserver : public ui::CompositorObserver,
512 public aura::WindowObserver,
513 public ui::ImplicitAnimationObserver {
514 public:
515 // Observes |window| for destruction, but does not take ownership.
516 // Takes ownership of |layer| and its child layers.
517 CrossFadeObserver(Window* window, Layer* layer)
518 : window_(window),
519 layer_(layer) {
520 window_->AddObserver(this);
521 layer_->GetCompositor()->AddObserver(this);
522 }
523 virtual ~CrossFadeObserver() {
524 Cleanup();
525 }
526
527 // ui::CompositorObserver overrides:
528 virtual void OnCompositingStarted(ui::Compositor* compositor) OVERRIDE {
529 }
530 virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE {
531 }
532 virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE {
533 // Something went wrong with compositing and our layers are now invalid.
534 if (layer_)
535 layer_->GetAnimator()->StopAnimating();
536 // Delete is scheduled in OnImplicitAnimationsCompleted().
537 Cleanup();
538 }
539
540 // aura::WindowObserver overrides:
541 virtual void OnWindowDestroying(Window* window) OVERRIDE {
542 if (layer_)
543 layer_->GetAnimator()->StopAnimating();
544 // Delete is scheduled in OnImplicitAnimationsCompleted().
545 Cleanup();
546 }
547
548 // ui::ImplicitAnimationObserver overrides:
549 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
550 // ImplicitAnimationObserver's base class uses the object after calling
551 // this function, so we cannot delete |this|.
552 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
553 }
554
555 private:
556 // Can be called multiple times if the window is closed or the compositor
557 // fails in the middle of the animation.
558 void Cleanup() {
559 if (window_) {
560 window_->RemoveObserver(this);
561 window_ = NULL;
562 }
563 if (layer_) {
564 layer_->GetCompositor()->RemoveObserver(this);
565 DeepDelete(layer_);
566 layer_ = NULL;
567 }
568 }
569
570 Window* window_; // not owned
571 Layer* layer_; // owned
572
573 DISALLOW_COPY_AND_ASSIGN(CrossFadeObserver);
574 };
575
475 } // namespace 576 } // namespace
476 } // namespace internal 577 } // namespace internal
477 578
478 //////////////////////////////////////////////////////////////////////////////// 579 ////////////////////////////////////////////////////////////////////////////////
479 // External interface 580 // External interface
480 581
481 void SetWindowVisibilityAnimationType(aura::Window* window, 582 void SetWindowVisibilityAnimationType(aura::Window* window,
482 WindowVisibilityAnimationType type) { 583 WindowVisibilityAnimationType type) {
483 window->SetProperty(internal::kWindowVisibilityAnimationTypeKey, type); 584 window->SetProperty(internal::kWindowVisibilityAnimationTypeKey, type);
484 } 585 }
(...skipping 16 matching lines...) Expand all
501 static_cast<int>(duration.ToInternalValue())); 602 static_cast<int>(duration.ToInternalValue()));
502 } 603 }
503 604
504 ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver( 605 ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver(
505 aura::Window* window) { 606 aura::Window* window) {
506 return new internal::HidingWindowAnimationObserver(window); 607 return new internal::HidingWindowAnimationObserver(window);
507 } 608 }
508 609
509 namespace internal { 610 namespace internal {
510 611
612 void CrossFadeToBounds(aura::Window* window, const gfx::Rect& new_bounds) {
613 DCHECK(window->TargetVisibility());
614 gfx::Rect old_bounds = window->bounds();
615
616 // Create fresh layers for the window and all its children to paint into.
617 // Takes ownership of the old layer and all its children, which will be
618 // cleaned up after the animation completes.
619 ui::Layer* old_layer = RecreateWindowLayers(window);
620 ui::Layer* new_layer = window->layer();
621
622 // Ensure the higher-resolution layer is on top.
623 bool old_on_top = (old_bounds.width() > new_bounds.width());
624 if (old_on_top)
625 old_layer->parent()->StackBelow(new_layer, old_layer);
626 else
627 old_layer->parent()->StackAbove(new_layer, old_layer);
628
629 // Tween types for transform animations must match to keep the window edges
630 // aligned during the animation.
631 const ui::Tween::Type kTransformTween = ui::Tween::EASE_OUT;
632 {
633 // Scale up the old layer while translating to new position.
634 ui::ScopedLayerAnimationSettings settings(old_layer->GetAnimator());
635 // Animation observer owns the old layer and deletes itself.
636 settings.AddObserver(new CrossFadeObserver(window, old_layer));
637 settings.SetTransitionDuration(
638 TimeDelta::FromMilliseconds(kCrossFadeAnimationDurationMs));
639 settings.SetTweenType(kTransformTween);
640 ui::Transform out_transform;
641 float scale_x = static_cast<float>(new_bounds.width()) /
642 static_cast<float>(old_bounds.width());
643 float scale_y = static_cast<float>(new_bounds.height()) /
644 static_cast<float>(old_bounds.height());
645 out_transform.ConcatScale(scale_x, scale_y);
646 out_transform.ConcatTranslate(new_bounds.x() - old_bounds.x(),
647 new_bounds.y() - old_bounds.y());
648 old_layer->SetTransform(out_transform);
649 if (old_on_top) {
650 // The old layer is on top, and should fade out. The new layer below will
651 // stay opaque to block the desktop.
652 old_layer->SetOpacity(0.f);
653 }
654 // In tests |old_layer| is deleted here, as animations have zero duration.
655 }
656
657 // Resize the window to the new size, which will force a layout and paint.
658 window->SetBounds(new_bounds);
659
660 // Set the new layer's current transform, such that the user sees a scaled
661 // version of the window with the original bounds at the original position.
662 ui::Transform in_transform;
663 float scale_x = static_cast<float>(old_bounds.width()) /
664 static_cast<float>(new_bounds.width());
665 float scale_y = static_cast<float>(old_bounds.height()) /
666 static_cast<float>(new_bounds.height());
667 in_transform.ConcatScale(scale_x, scale_y);
668 in_transform.ConcatTranslate(old_bounds.x() - new_bounds.x(),
669 old_bounds.y() - new_bounds.y());
670 new_layer->SetTransform(in_transform);
671 if (!old_on_top) {
672 // The new layer is on top and should fade in. The old layer below will
673 // stay opaque and block the desktop.
674 new_layer->SetOpacity(0.f);
675 }
676 {
677 // Animate the new layer to the identity transform, so the window goes to
678 // its newly set bounds.
679 ui::ScopedLayerAnimationSettings settings(new_layer->GetAnimator());
680 settings.SetTransitionDuration(
681 TimeDelta::FromMilliseconds(kCrossFadeAnimationDurationMs));
682 settings.SetTweenType(kTransformTween);
683 new_layer->SetTransform(ui::Transform());
684 if (!old_on_top) {
685 // New layer is on top, fade it in.
686 new_layer->SetOpacity(1.f);
687 }
688 }
689 }
690
511 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) { 691 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
512 if (window->GetProperty(aura::client::kAnimationsDisabledKey) || 692 if (window->GetProperty(aura::client::kAnimationsDisabledKey) ||
513 CommandLine::ForCurrentProcess()->HasSwitch( 693 CommandLine::ForCurrentProcess()->HasSwitch(
514 switches::kAuraWindowAnimationsDisabled)) { 694 switches::kAuraWindowAnimationsDisabled)) {
515 return false; 695 return false;
516 } 696 }
517 if (visible) { 697 if (visible) {
518 return AnimateShowWindow(window); 698 return AnimateShowWindow(window);
519 } else { 699 } else {
520 // Don't start hiding the window again if it's already being hidden. 700 // Don't start hiding the window again if it's already being hidden.
521 return window->layer()->GetTargetOpacity() != 0.0f && 701 return window->layer()->GetTargetOpacity() != 0.0f &&
522 AnimateHideWindow(window); 702 AnimateHideWindow(window);
523 } 703 }
524 } 704 }
525 705
526 } // namespace internal 706 } // namespace internal
527 } // namespace ash 707 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698