Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ash / wm / overview / scoped_window_copy.cc
blobf32c84df77bc1116753f92b39010fecb84bb74ac
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/wm/overview/scoped_window_copy.h"
7 #include "ash/screen_util.h"
8 #include "ash/shell.h"
9 #include "ui/aura/client/aura_constants.h"
10 #include "ui/aura/client/screen_position_client.h"
11 #include "ui/aura/window.h"
12 #include "ui/aura/window_event_dispatcher.h"
13 #include "ui/compositor/layer_animation_observer.h"
14 #include "ui/compositor/layer_tree_owner.h"
15 #include "ui/gfx/display.h"
16 #include "ui/views/widget/widget.h"
17 #include "ui/wm/core/shadow_types.h"
18 #include "ui/wm/core/window_util.h"
20 namespace ash {
22 namespace {
24 // Creates a copy of |window| with |recreated_layer| in the |target_root|.
25 views::Widget* CreateCopyOfWindow(aura::Window* target_root,
26 aura::Window* src_window,
27 ui::Layer* recreated_layer) {
28 // Save and remove the transform from the layer to later reapply to both the
29 // source and newly created copy window.
30 gfx::Transform transform = recreated_layer->transform();
31 recreated_layer->SetTransform(gfx::Transform());
33 src_window->SetTransform(transform);
34 views::Widget* widget = new views::Widget;
35 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
36 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
37 params.parent = src_window->parent();
38 params.keep_on_top = true;
39 widget->set_focus_on_creation(false);
40 widget->Init(params);
41 widget->SetVisibilityChangedAnimationsEnabled(false);
42 std::string name = src_window->name() + " (Copy)";
43 widget->GetNativeWindow()->SetName(name);
44 ::wm::SetShadowType(widget->GetNativeWindow(),
45 ::wm::SHADOW_TYPE_RECTANGULAR);
47 // Set the bounds in the target root window.
48 gfx::Display target_display =
49 Shell::GetScreen()->GetDisplayNearestWindow(target_root);
50 aura::client::ScreenPositionClient* screen_position_client =
51 aura::client::GetScreenPositionClient(src_window->GetRootWindow());
52 if (screen_position_client && target_display.is_valid()) {
53 screen_position_client->SetBounds(widget->GetNativeWindow(),
54 src_window->GetBoundsInScreen(), target_display);
55 } else {
56 widget->SetBounds(src_window->GetBoundsInScreen());
58 widget->StackAbove(src_window);
60 // Move the |recreated_layer| to the newly created window.
61 recreated_layer->set_delegate(src_window->layer()->delegate());
62 gfx::Rect layer_bounds = recreated_layer->bounds();
63 layer_bounds.set_origin(gfx::Point(0, 0));
64 recreated_layer->SetBounds(layer_bounds);
65 recreated_layer->SetVisible(false);
66 recreated_layer->parent()->Remove(recreated_layer);
68 aura::Window* window = widget->GetNativeWindow();
69 recreated_layer->SetVisible(true);
70 window->layer()->Add(recreated_layer);
71 window->layer()->StackAtTop(recreated_layer);
72 window->layer()->SetOpacity(1);
73 window->SetTransform(transform);
74 window->Show();
75 return widget;
78 } // namespace
80 // An observer which closes the widget and deletes the layer after an
81 // animation finishes.
82 class CleanupWidgetAfterAnimationObserver : public ui::LayerAnimationObserver {
83 public:
84 CleanupWidgetAfterAnimationObserver(
85 views::Widget* widget,
86 scoped_ptr<ui::LayerTreeOwner> layer_owner);
88 // Takes ownership of the widget. At this point the class will delete itself
89 // and clean up the layer when there are no pending animations.
90 void TakeOwnershipOfWidget();
92 // ui::LayerAnimationObserver:
93 virtual void OnLayerAnimationEnded(
94 ui::LayerAnimationSequence* sequence) OVERRIDE;
95 virtual void OnLayerAnimationAborted(
96 ui::LayerAnimationSequence* sequence) OVERRIDE;
97 virtual void OnLayerAnimationScheduled(
98 ui::LayerAnimationSequence* sequence) OVERRIDE;
100 private:
101 virtual ~CleanupWidgetAfterAnimationObserver();
103 // If the necessary conditions have been satisfied to destruct this
104 // class, deletes itself and cleans up the widget and layer.
105 void MaybeDestruct();
107 views::Widget* widget_;
108 scoped_ptr<ui::LayerTreeOwner> layer_owner_;
109 bool owns_widget_;
110 int pending_animations_;
112 DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver);
115 CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver(
116 views::Widget* widget,
117 scoped_ptr<ui::LayerTreeOwner> layer_owner)
118 : widget_(widget),
119 layer_owner_(layer_owner.Pass()),
120 owns_widget_(false),
121 pending_animations_(0) {
122 widget_->GetNativeWindow()->layer()->GetAnimator()->AddObserver(this);
125 void CleanupWidgetAfterAnimationObserver::TakeOwnershipOfWidget() {
126 owns_widget_ = true;
127 MaybeDestruct();
130 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationEnded(
131 ui::LayerAnimationSequence* sequence) {
132 pending_animations_--;
133 MaybeDestruct();
136 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted(
137 ui::LayerAnimationSequence* sequence) {
138 pending_animations_--;
139 MaybeDestruct();
142 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled(
143 ui::LayerAnimationSequence* sequence) {
144 pending_animations_++;
147 CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() {
148 widget_->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this);
149 widget_->Close();
150 widget_ = NULL;
153 void CleanupWidgetAfterAnimationObserver::MaybeDestruct() {
154 if (pending_animations_ || !owns_widget_)
155 return;
156 delete this;
159 ScopedWindowCopy::ScopedWindowCopy(aura::Window* target_root,
160 aura::Window* src_window) {
161 scoped_ptr<ui::LayerTreeOwner> layer_owner =
162 ::wm::RecreateLayers(src_window);
163 widget_ = CreateCopyOfWindow(target_root, src_window, layer_owner->root());
164 cleanup_observer_ =
165 new CleanupWidgetAfterAnimationObserver(widget_, layer_owner.Pass());
168 ScopedWindowCopy::~ScopedWindowCopy() {
169 // The cleanup observer will delete itself and the window when any pending
170 // animations have completed.
171 cleanup_observer_->TakeOwnershipOfWidget();
174 aura::Window* ScopedWindowCopy::GetWindow() {
175 return widget_->GetNativeWindow();
178 } // namespace ash