Upstream version 9.38.198.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   virtual ~ScopedTransformPanelWindow();
31
32   // ScopedTransformOverviewWindow overrides:
33   virtual void PrepareForOverview() OVERRIDE;
34
35   virtual void SetTransform(
36       aura::Window* root_window,
37       const gfx::Transform& transform,
38       bool animate) OVERRIDE;
39
40  private:
41   // Returns the panel window bounds after the transformation.
42   gfx::Rect GetTransformedBounds();
43
44   scoped_ptr<TransparentActivateWindowButton> window_button_;
45
46   DISALLOW_COPY_AND_ASSIGN(ScopedTransformPanelWindow);
47 };
48
49 ScopedTransformPanelWindow::ScopedTransformPanelWindow(aura::Window* window)
50     : ScopedTransformOverviewWindow(window) {
51 }
52
53 ScopedTransformPanelWindow::~ScopedTransformPanelWindow() {
54 }
55
56 void ScopedTransformPanelWindow::PrepareForOverview() {
57   ScopedTransformOverviewWindow::PrepareForOverview();
58   window_button_.reset(new TransparentActivateWindowButton(window()));
59 }
60
61 void ScopedTransformPanelWindow::SetTransform(
62     aura::Window* root_window,
63     const gfx::Transform& transform,
64     bool animate) {
65   ScopedTransformOverviewWindow::SetTransform(root_window, transform, animate);
66   window_button_->SetBounds(GetTransformedBounds());
67 }
68
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(),
74                           bounds.y());
75   new_transform.PreconcatTransform(window()->layer()->GetTargetTransform());
76   new_transform.Translate(-bounds.x(),
77                           -bounds.y());
78   new_transform.TransformRect(&bounds);
79   return ToEnclosingRect(bounds);
80 }
81
82 }  // namespace
83
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);
89 }
90
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);
98   }
99 }
100
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));
105 }
106
107 aura::Window* WindowSelectorPanels::GetRootWindow() {
108   return transform_windows_.front()->window()->GetRootWindow();
109 }
110
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)
115       return true;
116   }
117   return false;
118 }
119
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))
124       return true;
125   }
126   return false;
127 }
128
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();
134       break;
135     }
136   }
137 }
138
139 aura::Window* WindowSelectorPanels::SelectionWindow() {
140   return transform_windows_.front()->window();
141 }
142
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);
150       break;
151     }
152   }
153   WindowSelectorItem::RemoveWindow(window);
154 }
155
156 bool WindowSelectorPanels::empty() const {
157   return transform_windows_.empty();
158 }
159
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();
165
166   // Call PrepareForOverview() in the reverse stacking order so that the
167   // transparent windows that handle the events are in the correct stacking
168   // order.
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++;
176       }
177     }
178   }
179   DCHECK(transformed_windows == transform_windows_.size());
180 }
181
182 void WindowSelectorPanels::SetItemBounds(aura::Window* root_window,
183                                          const gfx::Rect& target_bounds,
184                                          bool animate) {
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());
189   }
190   set_bounds(ScopedTransformOverviewWindow::
191       ShrinkRectToFitPreservingAspectRatio(bounding_rect, target_bounds));
192   gfx::Transform bounding_transform =
193       ScopedTransformOverviewWindow::GetTransformForRect(bounding_rect,
194                                                          bounds());
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);
205   }
206 }
207
208 void WindowSelectorPanels::SetOpacity(float opacity) {
209   // TODO(flackr): find a way to make panels that are hidden behind other panels
210   // look nice.
211   for (WindowList::iterator iter = transform_windows_.begin();
212        iter != transform_windows_.end(); iter++) {
213     (*iter)->window()->layer()->SetOpacity(opacity);
214   }
215   WindowSelectorItem::SetOpacity(opacity);
216 }
217
218 }  // namespace ash