• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ScopedTransformPanelWindow(aura::Window * window)49 ScopedTransformPanelWindow::ScopedTransformPanelWindow(aura::Window* window)
50     : ScopedTransformOverviewWindow(window) {
51 }
52 
~ScopedTransformPanelWindow()53 ScopedTransformPanelWindow::~ScopedTransformPanelWindow() {
54 }
55 
PrepareForOverview()56 void ScopedTransformPanelWindow::PrepareForOverview() {
57   ScopedTransformOverviewWindow::PrepareForOverview();
58   window_button_.reset(new TransparentActivateWindowButton(window()));
59 }
60 
SetTransform(aura::Window * root_window,const gfx::Transform & transform,bool animate)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 
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(),
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 
WindowSelectorPanels(aura::Window * panels_root_window)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 
~WindowSelectorPanels()91 WindowSelectorPanels::~WindowSelectorPanels() {
92   static_cast<PanelLayoutManager*>(
93       Shell::GetContainer(panels_root_window_, kShellWindowId_PanelContainer)->
94           layout_manager())->SetShowCalloutWidgets(true);
95 }
96 
AddWindow(aura::Window * window)97 void WindowSelectorPanels::AddWindow(aura::Window* window) {
98   DCHECK(window->GetRootWindow() == panels_root_window_);
99   transform_windows_.push_back(new ScopedTransformPanelWindow(window));
100 }
101 
GetRootWindow()102 aura::Window* WindowSelectorPanels::GetRootWindow() {
103   return transform_windows_.front()->window()->GetRootWindow();
104 }
105 
HasSelectableWindow(const aura::Window * window)106 bool WindowSelectorPanels::HasSelectableWindow(const aura::Window* window) {
107   for (WindowList::const_iterator iter = transform_windows_.begin();
108        iter != transform_windows_.end(); ++iter) {
109     if ((*iter)->window() == window)
110       return true;
111   }
112   return false;
113 }
114 
Contains(const aura::Window * target)115 bool WindowSelectorPanels::Contains(const aura::Window* target) {
116   for (WindowList::const_iterator iter = transform_windows_.begin();
117        iter != transform_windows_.end(); ++iter) {
118     if ((*iter)->Contains(target))
119       return true;
120   }
121   return false;
122 }
123 
RestoreWindowOnExit(aura::Window * window)124 void WindowSelectorPanels::RestoreWindowOnExit(aura::Window* window) {
125   for (WindowList::iterator iter = transform_windows_.begin();
126        iter != transform_windows_.end(); ++iter) {
127     if ((*iter)->Contains(window)) {
128       (*iter)->RestoreWindowOnExit();
129       break;
130     }
131   }
132 }
133 
SelectionWindow()134 aura::Window* WindowSelectorPanels::SelectionWindow() {
135   return transform_windows_.front()->window();
136 }
137 
RemoveWindow(const aura::Window * window)138 void WindowSelectorPanels::RemoveWindow(const aura::Window* window) {
139   for (WindowList::iterator iter = transform_windows_.begin();
140        iter != transform_windows_.end(); ++iter) {
141     if ((*iter)->window() == window) {
142       (*iter)->OnWindowDestroyed();
143       transform_windows_.erase(iter);
144       break;
145     }
146   }
147   WindowSelectorItem::RemoveWindow(window);
148 }
149 
empty() const150 bool WindowSelectorPanels::empty() const {
151   return transform_windows_.empty();
152 }
153 
PrepareForOverview()154 void WindowSelectorPanels::PrepareForOverview() {
155   // |panel_windows| will hold all the windows in the panel container, sorted
156   // according to their stacking order.
157   const aura::Window::Windows panels =
158       transform_windows_[0]->window()->parent()->children();
159 
160   // Call PrepareForOverview() in the reverse stacking order so that the
161   // transparent windows that handle the events are in the correct stacking
162   // order.
163   size_t transformed_windows = 0;
164   for (aura::Window::Windows::const_reverse_iterator iter = panels.rbegin();
165       iter != panels.rend(); iter++) {
166     for (size_t j = 0; j < transform_windows_.size(); ++j) {
167       if (transform_windows_[j]->window() == (*iter)) {
168         transform_windows_[j]->PrepareForOverview();
169         transformed_windows++;
170       }
171     }
172   }
173   DCHECK(transformed_windows == transform_windows_.size());
174 }
175 
SetItemBounds(aura::Window * root_window,const gfx::Rect & target_bounds,bool animate)176 void WindowSelectorPanels::SetItemBounds(aura::Window* root_window,
177                                          const gfx::Rect& target_bounds,
178                                          bool animate) {
179   gfx::Rect bounding_rect;
180   for (WindowList::iterator iter = transform_windows_.begin();
181        iter != transform_windows_.end(); ++iter) {
182     bounding_rect.Union((*iter)->GetBoundsInScreen());
183   }
184   set_bounds(ScopedTransformOverviewWindow::
185       ShrinkRectToFitPreservingAspectRatio(bounding_rect, target_bounds));
186   gfx::Transform bounding_transform =
187       ScopedTransformOverviewWindow::GetTransformForRect(bounding_rect,
188                                                          bounds());
189   for (WindowList::iterator iter = transform_windows_.begin();
190        iter != transform_windows_.end(); ++iter) {
191     gfx::Transform transform;
192     gfx::Rect bounds = (*iter)->GetBoundsInScreen();
193     transform.Translate(bounding_rect.x() - bounds.x(),
194                         bounding_rect.y() - bounds.y());
195     transform.PreconcatTransform(bounding_transform);
196     transform.Translate(bounds.x() - bounding_rect.x(),
197                         bounds.y() - bounding_rect.y());
198     (*iter)->SetTransform(root_window, transform, animate);
199   }
200 }
201 
202 }  // namespace ash
203