Mac: Fix performance issues with remote CoreAnimation
[chromium-blink-merge.git] / ash / wm / overview / window_selector_panels.cc
blobe2d3e8cd9207bfd28893b654bf743f9eca56653b
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"
8 #include "ash/shell.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"
20 namespace ash {
22 namespace {
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 {
28 public:
29 explicit ScopedTransformPanelWindow(aura::Window* window);
30 ~ScopedTransformPanelWindow() override;
32 // ScopedTransformOverviewWindow overrides:
33 void PrepareForOverview() override;
35 void SetTransform(aura::Window* root_window,
36 const gfx::Transform& transform,
37 bool animate) override;
39 private:
40 // Returns the panel window bounds after the transformation.
41 gfx::Rect GetTransformedBounds();
43 scoped_ptr<TransparentActivateWindowButton> window_button_;
45 DISALLOW_COPY_AND_ASSIGN(ScopedTransformPanelWindow);
48 ScopedTransformPanelWindow::ScopedTransformPanelWindow(aura::Window* window)
49 : ScopedTransformOverviewWindow(window) {
52 ScopedTransformPanelWindow::~ScopedTransformPanelWindow() {
55 void ScopedTransformPanelWindow::PrepareForOverview() {
56 ScopedTransformOverviewWindow::PrepareForOverview();
57 window_button_.reset(new TransparentActivateWindowButton(window()));
60 void ScopedTransformPanelWindow::SetTransform(
61 aura::Window* root_window,
62 const gfx::Transform& transform,
63 bool animate) {
64 ScopedTransformOverviewWindow::SetTransform(root_window, transform, animate);
65 window_button_->SetBounds(GetTransformedBounds());
68 gfx::Rect ScopedTransformPanelWindow::GetTransformedBounds() {
69 gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(
70 window()->GetRootWindow(), window()->layer()->bounds()));
71 gfx::Transform new_transform;
72 new_transform.Translate(bounds.x(),
73 bounds.y());
74 new_transform.PreconcatTransform(window()->layer()->GetTargetTransform());
75 new_transform.Translate(-bounds.x(),
76 -bounds.y());
77 new_transform.TransformRect(&bounds);
78 return ToEnclosingRect(bounds);
81 } // namespace
83 WindowSelectorPanels::WindowSelectorPanels(aura::Window* panels_root_window)
84 : panels_root_window_(panels_root_window) {
85 static_cast<PanelLayoutManager*>(
86 Shell::GetContainer(panels_root_window_, kShellWindowId_PanelContainer)->
87 layout_manager())->SetShowCalloutWidgets(false);
90 WindowSelectorPanels::~WindowSelectorPanels() {
91 static_cast<PanelLayoutManager*>(
92 Shell::GetContainer(panels_root_window_, kShellWindowId_PanelContainer)->
93 layout_manager())->SetShowCalloutWidgets(true);
94 for (WindowList::iterator iter = transform_windows_.begin();
95 iter != transform_windows_.end(); iter++) {
96 (*iter)->window()->RemoveObserver(this);
100 void WindowSelectorPanels::AddWindow(aura::Window* window) {
101 DCHECK(window->GetRootWindow() == panels_root_window_);
102 window->AddObserver(this);
103 transform_windows_.push_back(new ScopedTransformPanelWindow(window));
106 aura::Window* WindowSelectorPanels::GetRootWindow() {
107 return transform_windows_.front()->window()->GetRootWindow();
110 bool WindowSelectorPanels::HasSelectableWindow(const aura::Window* window) {
111 for (WindowList::const_iterator iter = transform_windows_.begin();
112 iter != transform_windows_.end(); ++iter) {
113 if ((*iter)->window() == window)
114 return true;
116 return false;
119 bool WindowSelectorPanels::Contains(const aura::Window* target) {
120 for (WindowList::const_iterator iter = transform_windows_.begin();
121 iter != transform_windows_.end(); ++iter) {
122 if ((*iter)->Contains(target))
123 return true;
125 return false;
128 void WindowSelectorPanels::RestoreWindowOnExit(aura::Window* window) {
129 for (WindowList::iterator iter = transform_windows_.begin();
130 iter != transform_windows_.end(); ++iter) {
131 if ((*iter)->Contains(window)) {
132 (*iter)->RestoreWindowOnExit();
133 break;
138 aura::Window* WindowSelectorPanels::SelectionWindow() {
139 return transform_windows_.front()->window();
142 void WindowSelectorPanels::RemoveWindow(const aura::Window* window) {
143 for (WindowList::iterator iter = transform_windows_.begin();
144 iter != transform_windows_.end(); ++iter) {
145 if ((*iter)->window() == window) {
146 (*iter)->window()->RemoveObserver(this);
147 (*iter)->OnWindowDestroyed();
148 transform_windows_.erase(iter);
149 break;
152 WindowSelectorItem::RemoveWindow(window);
155 bool WindowSelectorPanels::empty() const {
156 return transform_windows_.empty();
159 void WindowSelectorPanels::PrepareForOverview() {
160 // |panel_windows| will hold all the windows in the panel container, sorted
161 // according to their stacking order.
162 const aura::Window::Windows panels =
163 transform_windows_.front()->window()->parent()->children();
165 // Call PrepareForOverview() in the reverse stacking order so that the
166 // transparent windows that handle the events are in the correct stacking
167 // order.
168 size_t transformed_windows = 0;
169 for (aura::Window::Windows::const_reverse_iterator iter = panels.rbegin();
170 iter != panels.rend(); iter++) {
171 for (size_t j = 0; j < transform_windows_.size(); ++j) {
172 if (transform_windows_[j]->window() == (*iter)) {
173 transform_windows_[j]->PrepareForOverview();
174 transformed_windows++;
178 DCHECK(transformed_windows == transform_windows_.size());
181 void WindowSelectorPanels::SetItemBounds(aura::Window* root_window,
182 const gfx::Rect& target_bounds,
183 bool animate) {
184 gfx::Rect bounding_rect;
185 for (WindowList::iterator iter = transform_windows_.begin();
186 iter != transform_windows_.end(); ++iter) {
187 bounding_rect.Union((*iter)->GetBoundsInScreen());
189 set_bounds(ScopedTransformOverviewWindow::
190 ShrinkRectToFitPreservingAspectRatio(bounding_rect, target_bounds));
191 gfx::Transform bounding_transform =
192 ScopedTransformOverviewWindow::GetTransformForRect(bounding_rect,
193 bounds());
194 for (WindowList::iterator iter = transform_windows_.begin();
195 iter != transform_windows_.end(); ++iter) {
196 gfx::Transform transform;
197 gfx::Rect bounds = (*iter)->GetBoundsInScreen();
198 transform.Translate(bounding_rect.x() - bounds.x(),
199 bounding_rect.y() - bounds.y());
200 transform.PreconcatTransform(bounding_transform);
201 transform.Translate(bounds.x() - bounding_rect.x(),
202 bounds.y() - bounding_rect.y());
203 (*iter)->SetTransform(root_window, transform, animate);
207 void WindowSelectorPanels::SetOpacity(float opacity) {
208 // TODO(flackr): find a way to make panels that are hidden behind other panels
209 // look nice.
210 for (WindowList::iterator iter = transform_windows_.begin();
211 iter != transform_windows_.end(); iter++) {
212 (*iter)->window()->layer()->SetOpacity(opacity);
214 WindowSelectorItem::SetOpacity(opacity);
217 } // namespace ash