Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ash / wm / overview / window_selector_panels.cc
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.
4
5 #include "ash/wm/overview/window_selector_panels.h"
6
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"
19
20 namespace ash {
21
22 namespace {
23
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;
31
32   // ScopedTransformOverviewWindow overrides:
33   void PrepareForOverview() override;
34
35   void SetTransform(aura::Window* root_window,
36                     const gfx::Transform& transform,
37                     bool animate) override;
38
39  private:
40   // Returns the panel window bounds after the transformation.
41   gfx::Rect GetTransformedBounds();
42
43   scoped_ptr<TransparentActivateWindowButton> window_button_;
44
45   DISALLOW_COPY_AND_ASSIGN(ScopedTransformPanelWindow);
46 };
47
48 ScopedTransformPanelWindow::ScopedTransformPanelWindow(aura::Window* window)
49     : ScopedTransformOverviewWindow(window) {
50 }
51
52 ScopedTransformPanelWindow::~ScopedTransformPanelWindow() {
53 }
54
55 void ScopedTransformPanelWindow::PrepareForOverview() {
56   ScopedTransformOverviewWindow::PrepareForOverview();
57   window_button_.reset(new TransparentActivateWindowButton(window()));
58 }
59
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());
66 }
67
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);
79 }
80
81 }  // namespace
82
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);
88 }
89
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);
97   }
98 }
99
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));
104 }
105
106 aura::Window* WindowSelectorPanels::GetRootWindow() {
107   return transform_windows_.front()->window()->GetRootWindow();
108 }
109
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;
115   }
116   return false;
117 }
118
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;
124   }
125   return false;
126 }
127
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;
134     }
135   }
136 }
137
138 aura::Window* WindowSelectorPanels::SelectionWindow() {
139   return transform_windows_.front()->window();
140 }
141
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;
150     }
151   }
152   WindowSelectorItem::RemoveWindow(window);
153 }
154
155 bool WindowSelectorPanels::empty() const {
156   return transform_windows_.empty();
157 }
158
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();
164
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++;
175       }
176     }
177   }
178   DCHECK(transformed_windows == transform_windows_.size());
179 }
180
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());
188   }
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);
204   }
205 }
206
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);
213   }
214   WindowSelectorItem::SetOpacity(opacity);
215 }
216
217 }  // namespace ash