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

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 lock screen, app windows 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
« no previous file with comments | « ash/wm/window_animations.h ('k') | ash/wm/window_animations_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include "ui/views/view.h" 28 #include "ui/views/view.h"
28 #include "ui/views/widget/widget.h" 29 #include "ui/views/widget/widget.h"
29 30
30 DECLARE_WINDOW_PROPERTY_TYPE(int) 31 DECLARE_WINDOW_PROPERTY_TYPE(int)
31 DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationType) 32 DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationType)
32 DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationTransition) 33 DECLARE_WINDOW_PROPERTY_TYPE(ash::WindowVisibilityAnimationTransition)
33 DECLARE_WINDOW_PROPERTY_TYPE(float) 34 DECLARE_WINDOW_PROPERTY_TYPE(float)
34 35
36 using aura::Window;
35 using base::TimeDelta; 37 using base::TimeDelta;
38 using ui::Layer;
36 39
37 namespace ash { 40 namespace ash {
38 namespace internal { 41 namespace internal {
39 namespace { 42 namespace {
40 const float kWindowAnimation_Vertical_TranslateY = 15.f; 43 const float kWindowAnimation_Vertical_TranslateY = 15.f;
41 } 44 }
42 45
43 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationType, 46 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationType,
44 kWindowVisibilityAnimationTypeKey, 47 kWindowVisibilityAnimationTypeKey,
45 WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT); 48 WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
46 DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0); 49 DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0);
47 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition, 50 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition,
48 kWindowVisibilityAnimationTransitionKey, 51 kWindowVisibilityAnimationTransitionKey,
49 ANIMATE_BOTH); 52 ANIMATE_BOTH);
50 DEFINE_WINDOW_PROPERTY_KEY(float, 53 DEFINE_WINDOW_PROPERTY_KEY(float,
51 kWindowVisibilityAnimationVerticalPositionKey, 54 kWindowVisibilityAnimationVerticalPositionKey,
52 kWindowAnimation_Vertical_TranslateY); 55 kWindowAnimation_Vertical_TranslateY);
53 56
54 namespace { 57 namespace {
55 58
56 const int kDefaultAnimationDurationForMenuMS = 150; 59 const int kDefaultAnimationDurationForMenuMS = 150;
57 60
61 // TODO(jamescook): Shorten the duration if the window doesn't move much.
62 const int kCrossFadeAnimationDurationMs = 400;
63
58 const float kWindowAnimation_HideOpacity = 0.f; 64 const float kWindowAnimation_HideOpacity = 0.f;
59 const float kWindowAnimation_ShowOpacity = 1.f; 65 const float kWindowAnimation_ShowOpacity = 1.f;
60 const float kWindowAnimation_TranslateFactor = -0.025f; 66 const float kWindowAnimation_TranslateFactor = -0.025f;
61 const float kWindowAnimation_ScaleFactor = 1.05f; 67 const float kWindowAnimation_ScaleFactor = 1.05f;
62 const float kWindowAnimation_MinimizeRotate = -5.f; 68 const float kWindowAnimation_MinimizeRotate = -5.f;
63 69
64 // Amount windows are scaled during workspace animations. 70 // Amount windows are scaled during workspace animations.
65 const float kWorkspaceScale = .95f; 71 const float kWorkspaceScale = .95f;
66 72
67 base::TimeDelta GetWindowVisibilityAnimationDuration(aura::Window* window) { 73 base::TimeDelta GetWindowVisibilityAnimationDuration(aura::Window* window) {
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 return true; 496 return true;
491 case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE: 497 case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE:
492 AnimateHideWindow_Minimize(window); 498 AnimateHideWindow_Minimize(window);
493 return true; 499 return true;
494 default: 500 default:
495 NOTREACHED(); 501 NOTREACHED();
496 return false; 502 return false;
497 } 503 }
498 } 504 }
499 505
506 // Recreates a fresh layer for |window| and all its child windows. Does not
507 // recreate shadows or other non-window layers. Returns the old layer and its
508 // children, maintaining the hierarchy.
509 Layer* RecreateWindowLayers(Window* window) {
510 Layer* old_layer = window->RecreateLayer();
511 for (Window::Windows::const_iterator it = window->children().begin();
512 it != window->children().end();
513 ++it) {
514 aura::Window* child = *it;
515 Layer* old_child_layer = RecreateWindowLayers(child);
516 // Maintain the hierarchy of the detached layers.
517 old_layer->Add(old_child_layer);
518 }
519 return old_layer;
520 }
521
522 // Deletes |layer| and all its child layers.
523 void DeepDelete(Layer* layer) {
524 std::vector<Layer*> children = layer->children();
525 for (std::vector<Layer*>::const_iterator it = children.begin();
526 it != children.end();
527 ++it) {
528 Layer* child = *it;
529 DeepDelete(child);
530 }
531 delete layer;
532 }
533
534 // Observer for a window cross-fade animation. If either the window closes or
535 // the layer's animation completes or compositing is aborted due to GPU crash,
536 // it deletes the layer and removes itself as an observer.
537 class CrossFadeObserver : public ui::CompositorObserver,
538 public aura::WindowObserver,
539 public ui::ImplicitAnimationObserver {
540 public:
541 // Observes |window| for destruction, but does not take ownership.
542 // Takes ownership of |layer| and its child layers.
543 CrossFadeObserver(Window* window, Layer* layer)
544 : window_(window),
545 layer_(layer) {
546 window_->AddObserver(this);
547 layer_->GetCompositor()->AddObserver(this);
548 }
549 virtual ~CrossFadeObserver() {
550 Cleanup();
551 }
552
553 // ui::CompositorObserver overrides:
554 virtual void OnCompositingStarted(ui::Compositor* compositor) OVERRIDE {
555 }
556 virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE {
557 }
558 virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE {
559 // Something went wrong with compositing and our layers are now invalid.
560 if (layer_)
561 layer_->GetAnimator()->StopAnimating();
562 // Delete is scheduled in OnImplicitAnimationsCompleted().
563 Cleanup();
564 }
565
566 // aura::WindowObserver overrides:
567 virtual void OnWindowDestroying(Window* window) OVERRIDE {
568 if (layer_)
569 layer_->GetAnimator()->StopAnimating();
570 // Delete is scheduled in OnImplicitAnimationsCompleted().
571 Cleanup();
572 }
573
574 // ui::ImplicitAnimationObserver overrides:
575 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
576 // ImplicitAnimationObserver's base class uses the object after calling
577 // this function, so we cannot delete |this|.
578 MessageLoop::current()->DeleteSoon(FROM_HERE, this);
579 }
580
581 private:
582 // Can be called multiple times if the window is closed or the compositor
583 // fails in the middle of the animation.
584 void Cleanup() {
585 if (window_) {
586 window_->RemoveObserver(this);
587 window_ = NULL;
588 }
589 if (layer_) {
590 layer_->GetCompositor()->RemoveObserver(this);
591 DeepDelete(layer_);
592 layer_ = NULL;
593 }
594 }
595
596 Window* window_; // not owned
597 Layer* layer_; // owned
598
599 DISALLOW_COPY_AND_ASSIGN(CrossFadeObserver);
600 };
601
500 } // namespace 602 } // namespace
501 } // namespace internal 603 } // namespace internal
502 604
503 //////////////////////////////////////////////////////////////////////////////// 605 ////////////////////////////////////////////////////////////////////////////////
504 // External interface 606 // External interface
505 607
506 void SetWindowVisibilityAnimationType(aura::Window* window, 608 void SetWindowVisibilityAnimationType(aura::Window* window,
507 WindowVisibilityAnimationType type) { 609 WindowVisibilityAnimationType type) {
508 window->SetProperty(internal::kWindowVisibilityAnimationTypeKey, type); 610 window->SetProperty(internal::kWindowVisibilityAnimationTypeKey, type);
509 } 611 }
(...skipping 22 matching lines...) Expand all
532 position); 634 position);
533 } 635 }
534 636
535 ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver( 637 ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver(
536 aura::Window* window) { 638 aura::Window* window) {
537 return new internal::HidingWindowAnimationObserver(window); 639 return new internal::HidingWindowAnimationObserver(window);
538 } 640 }
539 641
540 namespace internal { 642 namespace internal {
541 643
644 void CrossFadeToBounds(aura::Window* window, const gfx::Rect& new_bounds) {
645 DCHECK(window->TargetVisibility());
646 gfx::Rect old_bounds = window->bounds();
647
648 // Create fresh layers for the window and all its children to paint into.
649 // Takes ownership of the old layer and all its children, which will be
650 // cleaned up after the animation completes.
651 ui::Layer* old_layer = RecreateWindowLayers(window);
652 ui::Layer* new_layer = window->layer();
653
654 // Ensure the higher-resolution layer is on top.
655 bool old_on_top = (old_bounds.width() > new_bounds.width());
656 if (old_on_top)
657 old_layer->parent()->StackBelow(new_layer, old_layer);
658 else
659 old_layer->parent()->StackAbove(new_layer, old_layer);
660
661 // Tween types for transform animations must match to keep the window edges
662 // aligned during the animation.
663 const ui::Tween::Type kTransformTween = ui::Tween::EASE_OUT;
664 {
665 // Scale up the old layer while translating to new position.
666 ui::ScopedLayerAnimationSettings settings(old_layer->GetAnimator());
667 // Animation observer owns the old layer and deletes itself.
668 settings.AddObserver(new CrossFadeObserver(window, old_layer));
669 settings.SetTransitionDuration(
670 TimeDelta::FromMilliseconds(kCrossFadeAnimationDurationMs));
671 settings.SetTweenType(kTransformTween);
672 ui::Transform out_transform;
673 float scale_x = static_cast<float>(new_bounds.width()) /
674 static_cast<float>(old_bounds.width());
675 float scale_y = static_cast<float>(new_bounds.height()) /
676 static_cast<float>(old_bounds.height());
677 out_transform.ConcatScale(scale_x, scale_y);
678 out_transform.ConcatTranslate(new_bounds.x() - old_bounds.x(),
679 new_bounds.y() - old_bounds.y());
680 old_layer->SetTransform(out_transform);
681 if (old_on_top) {
682 // The old layer is on top, and should fade out. The new layer below will
683 // stay opaque to block the desktop.
684 old_layer->SetOpacity(0.f);
685 }
686 // In tests |old_layer| is deleted here, as animations have zero duration.
687 }
688
689 // Resize the window to the new size, which will force a layout and paint.
690 window->SetBounds(new_bounds);
691
692 // Set the new layer's current transform, such that the user sees a scaled
693 // version of the window with the original bounds at the original position.
694 ui::Transform in_transform;
695 float scale_x = static_cast<float>(old_bounds.width()) /
696 static_cast<float>(new_bounds.width());
697 float scale_y = static_cast<float>(old_bounds.height()) /
698 static_cast<float>(new_bounds.height());
699 in_transform.ConcatScale(scale_x, scale_y);
700 in_transform.ConcatTranslate(old_bounds.x() - new_bounds.x(),
701 old_bounds.y() - new_bounds.y());
702 new_layer->SetTransform(in_transform);
703 if (!old_on_top) {
704 // The new layer is on top and should fade in. The old layer below will
705 // stay opaque and block the desktop.
706 new_layer->SetOpacity(0.f);
707 }
708 {
709 // Animate the new layer to the identity transform, so the window goes to
710 // its newly set bounds.
711 ui::ScopedLayerAnimationSettings settings(new_layer->GetAnimator());
712 settings.SetTransitionDuration(
713 TimeDelta::FromMilliseconds(kCrossFadeAnimationDurationMs));
714 settings.SetTweenType(kTransformTween);
715 new_layer->SetTransform(ui::Transform());
716 if (!old_on_top) {
717 // New layer is on top, fade it in.
718 new_layer->SetOpacity(1.f);
719 }
720 }
721 }
722
542 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) { 723 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
543 if (window->GetProperty(aura::client::kAnimationsDisabledKey) || 724 if (window->GetProperty(aura::client::kAnimationsDisabledKey) ||
544 CommandLine::ForCurrentProcess()->HasSwitch( 725 CommandLine::ForCurrentProcess()->HasSwitch(
545 switches::kAshWindowAnimationsDisabled)) { 726 switches::kAshWindowAnimationsDisabled)) {
546 return false; 727 return false;
547 } 728 }
548 if (visible) { 729 if (visible) {
549 return AnimateShowWindow(window); 730 return AnimateShowWindow(window);
550 } else { 731 } else {
551 // Don't start hiding the window again if it's already being hidden. 732 // Don't start hiding the window again if it's already being hidden.
552 return window->layer()->GetTargetOpacity() != 0.0f && 733 return window->layer()->GetTargetOpacity() != 0.0f &&
553 AnimateHideWindow(window); 734 AnimateHideWindow(window);
554 } 735 }
555 } 736 }
556 737
557 } // namespace internal 738 } // namespace internal
558 } // namespace ash 739 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/window_animations.h ('k') | ash/wm/window_animations_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698