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/window_selector_panels.h"
7 #include "ash/screen_util.h"
9 #include "ash/shell_window_ids.h"
10 #include "ash/wm/overview/scoped_transform_overview_window.h"
11 #include "ash/wm/overview/transparent_activate_window_button.h"
12 #include "ash/wm/panels/panel_layout_manager.h"
13 #include "ash/wm/window_util.h"
14 #include "ui/aura/window.h"
15 #include "ui/compositor/layer.h"
16 #include "ui/compositor/layer_animation_observer.h"
17 #include "ui/compositor/layer_animation_sequence.h"
18 #include "ui/views/controls/button/button.h"
24 // This class extends ScopedTransformOverviewMode to hide and show the callout
25 // widget for a panel window when entering / leaving overview mode, as well as
26 // to add a transparent button for each panel window.
27 class ScopedTransformPanelWindow
: public ScopedTransformOverviewWindow
{
29 explicit ScopedTransformPanelWindow(aura::Window
* window
);
30 virtual ~ScopedTransformPanelWindow();
32 // ScopedTransformOverviewWindow overrides:
33 virtual void PrepareForOverview() OVERRIDE
;
35 virtual void SetTransform(
36 aura::Window
* root_window
,
37 const gfx::Transform
& transform
,
38 bool animate
) OVERRIDE
;
41 // Returns the panel window bounds after the transformation.
42 gfx::Rect
GetTransformedBounds();
44 scoped_ptr
<TransparentActivateWindowButton
> window_button_
;
46 DISALLOW_COPY_AND_ASSIGN(ScopedTransformPanelWindow
);
49 ScopedTransformPanelWindow::ScopedTransformPanelWindow(aura::Window
* window
)
50 : ScopedTransformOverviewWindow(window
) {
53 ScopedTransformPanelWindow::~ScopedTransformPanelWindow() {
56 void ScopedTransformPanelWindow::PrepareForOverview() {
57 ScopedTransformOverviewWindow::PrepareForOverview();
58 window_button_
.reset(new TransparentActivateWindowButton(window()));
61 void ScopedTransformPanelWindow::SetTransform(
62 aura::Window
* root_window
,
63 const gfx::Transform
& transform
,
65 ScopedTransformOverviewWindow::SetTransform(root_window
, transform
, animate
);
66 window_button_
->SetBounds(GetTransformedBounds());
69 gfx::Rect
ScopedTransformPanelWindow::GetTransformedBounds() {
70 gfx::RectF
bounds(ScreenUtil::ConvertRectToScreen(
71 window()->GetRootWindow(), window()->layer()->bounds()));
72 gfx::Transform new_transform
;
73 new_transform
.Translate(bounds
.x(),
75 new_transform
.PreconcatTransform(window()->layer()->GetTargetTransform());
76 new_transform
.Translate(-bounds
.x(),
78 new_transform
.TransformRect(&bounds
);
79 return ToEnclosingRect(bounds
);
84 WindowSelectorPanels::WindowSelectorPanels(aura::Window
* panels_root_window
)
85 : panels_root_window_(panels_root_window
) {
86 static_cast<PanelLayoutManager
*>(
87 Shell::GetContainer(panels_root_window_
, kShellWindowId_PanelContainer
)->
88 layout_manager())->SetShowCalloutWidgets(false);
91 WindowSelectorPanels::~WindowSelectorPanels() {
92 static_cast<PanelLayoutManager
*>(
93 Shell::GetContainer(panels_root_window_
, kShellWindowId_PanelContainer
)->
94 layout_manager())->SetShowCalloutWidgets(true);
95 for (WindowList::iterator iter
= transform_windows_
.begin();
96 iter
!= transform_windows_
.end(); iter
++) {
97 (*iter
)->window()->RemoveObserver(this);
101 void WindowSelectorPanels::AddWindow(aura::Window
* window
) {
102 DCHECK(window
->GetRootWindow() == panels_root_window_
);
103 window
->AddObserver(this);
104 transform_windows_
.push_back(new ScopedTransformPanelWindow(window
));
107 aura::Window
* WindowSelectorPanels::GetRootWindow() {
108 return transform_windows_
.front()->window()->GetRootWindow();
111 bool WindowSelectorPanels::HasSelectableWindow(const aura::Window
* window
) {
112 for (WindowList::const_iterator iter
= transform_windows_
.begin();
113 iter
!= transform_windows_
.end(); ++iter
) {
114 if ((*iter
)->window() == window
)
120 bool WindowSelectorPanels::Contains(const aura::Window
* target
) {
121 for (WindowList::const_iterator iter
= transform_windows_
.begin();
122 iter
!= transform_windows_
.end(); ++iter
) {
123 if ((*iter
)->Contains(target
))
129 void WindowSelectorPanels::RestoreWindowOnExit(aura::Window
* window
) {
130 for (WindowList::iterator iter
= transform_windows_
.begin();
131 iter
!= transform_windows_
.end(); ++iter
) {
132 if ((*iter
)->Contains(window
)) {
133 (*iter
)->RestoreWindowOnExit();
139 aura::Window
* WindowSelectorPanels::SelectionWindow() {
140 return transform_windows_
.front()->window();
143 void WindowSelectorPanels::RemoveWindow(const aura::Window
* window
) {
144 for (WindowList::iterator iter
= transform_windows_
.begin();
145 iter
!= transform_windows_
.end(); ++iter
) {
146 if ((*iter
)->window() == window
) {
147 (*iter
)->window()->RemoveObserver(this);
148 (*iter
)->OnWindowDestroyed();
149 transform_windows_
.erase(iter
);
153 WindowSelectorItem::RemoveWindow(window
);
156 bool WindowSelectorPanels::empty() const {
157 return transform_windows_
.empty();
160 void WindowSelectorPanels::PrepareForOverview() {
161 // |panel_windows| will hold all the windows in the panel container, sorted
162 // according to their stacking order.
163 const aura::Window::Windows panels
=
164 transform_windows_
.front()->window()->parent()->children();
166 // Call PrepareForOverview() in the reverse stacking order so that the
167 // transparent windows that handle the events are in the correct stacking
169 size_t transformed_windows
= 0;
170 for (aura::Window::Windows::const_reverse_iterator iter
= panels
.rbegin();
171 iter
!= panels
.rend(); iter
++) {
172 for (size_t j
= 0; j
< transform_windows_
.size(); ++j
) {
173 if (transform_windows_
[j
]->window() == (*iter
)) {
174 transform_windows_
[j
]->PrepareForOverview();
175 transformed_windows
++;
179 DCHECK(transformed_windows
== transform_windows_
.size());
182 void WindowSelectorPanels::SetItemBounds(aura::Window
* root_window
,
183 const gfx::Rect
& target_bounds
,
185 gfx::Rect bounding_rect
;
186 for (WindowList::iterator iter
= transform_windows_
.begin();
187 iter
!= transform_windows_
.end(); ++iter
) {
188 bounding_rect
.Union((*iter
)->GetBoundsInScreen());
190 set_bounds(ScopedTransformOverviewWindow::
191 ShrinkRectToFitPreservingAspectRatio(bounding_rect
, target_bounds
));
192 gfx::Transform bounding_transform
=
193 ScopedTransformOverviewWindow::GetTransformForRect(bounding_rect
,
195 for (WindowList::iterator iter
= transform_windows_
.begin();
196 iter
!= transform_windows_
.end(); ++iter
) {
197 gfx::Transform transform
;
198 gfx::Rect bounds
= (*iter
)->GetBoundsInScreen();
199 transform
.Translate(bounding_rect
.x() - bounds
.x(),
200 bounding_rect
.y() - bounds
.y());
201 transform
.PreconcatTransform(bounding_transform
);
202 transform
.Translate(bounds
.x() - bounding_rect
.x(),
203 bounds
.y() - bounding_rect
.y());
204 (*iter
)->SetTransform(root_window
, transform
, animate
);
208 void WindowSelectorPanels::SetOpacity(float opacity
) {
209 // TODO(flackr): find a way to make panels that are hidden behind other panels
211 for (WindowList::iterator iter
= transform_windows_
.begin();
212 iter
!= transform_windows_
.end(); iter
++) {
213 (*iter
)->window()->layer()->SetOpacity(opacity
);
215 WindowSelectorItem::SetOpacity(opacity
);