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"
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"
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);
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
);
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
);
80 // An observer which closes the widget and deletes the layer after an
81 // animation finishes.
82 class CleanupWidgetAfterAnimationObserver
: public ui::LayerAnimationObserver
{
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 void OnLayerAnimationEnded(ui::LayerAnimationSequence
* sequence
) override
;
94 void OnLayerAnimationAborted(ui::LayerAnimationSequence
* sequence
) override
;
95 void OnLayerAnimationScheduled(ui::LayerAnimationSequence
* sequence
) override
;
98 ~CleanupWidgetAfterAnimationObserver() override
;
100 // If the necessary conditions have been satisfied to destruct this
101 // class, deletes itself and cleans up the widget and layer.
102 void MaybeDestruct();
104 views::Widget
* widget_
;
105 scoped_ptr
<ui::LayerTreeOwner
> layer_owner_
;
107 int pending_animations_
;
109 DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver
);
112 CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver(
113 views::Widget
* widget
,
114 scoped_ptr
<ui::LayerTreeOwner
> layer_owner
)
116 layer_owner_(layer_owner
.Pass()),
118 pending_animations_(0) {
119 widget_
->GetNativeWindow()->layer()->GetAnimator()->AddObserver(this);
122 void CleanupWidgetAfterAnimationObserver::TakeOwnershipOfWidget() {
127 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationEnded(
128 ui::LayerAnimationSequence
* sequence
) {
129 pending_animations_
--;
133 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted(
134 ui::LayerAnimationSequence
* sequence
) {
135 pending_animations_
--;
139 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled(
140 ui::LayerAnimationSequence
* sequence
) {
141 pending_animations_
++;
144 CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() {
145 widget_
->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this);
150 void CleanupWidgetAfterAnimationObserver::MaybeDestruct() {
151 if (pending_animations_
|| !owns_widget_
)
156 ScopedWindowCopy::ScopedWindowCopy(aura::Window
* target_root
,
157 aura::Window
* src_window
) {
158 scoped_ptr
<ui::LayerTreeOwner
> layer_owner
=
159 ::wm::RecreateLayers(src_window
);
160 widget_
= CreateCopyOfWindow(target_root
, src_window
, layer_owner
->root());
162 new CleanupWidgetAfterAnimationObserver(widget_
, layer_owner
.Pass());
165 ScopedWindowCopy::~ScopedWindowCopy() {
166 // The cleanup observer will delete itself and the window when any pending
167 // animations have completed.
168 cleanup_observer_
->TakeOwnershipOfWidget();
171 aura::Window
* ScopedWindowCopy::GetWindow() {
172 return widget_
->GetNativeWindow();