• 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_ash.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/panels/panel_layout_manager.h"
12 #include "ui/aura/client/screen_position_client.h"
13 #include "ui/aura/window.h"
14 #include "ui/compositor/layer.h"
15 #include "ui/compositor/layer_animation_observer.h"
16 #include "ui/compositor/layer_animation_sequence.h"
17 #include "ui/views/widget/widget.h"
18 
19 namespace ash {
20 
21 namespace {
22 
23 const int kPanelCalloutFadeInDurationMilliseconds = 50;
24 
25 // This class extends ScopedTransformOverviewMode to hide and show the callout
26 // widget for a panel window when entering / leaving overview mode.
27 class ScopedTransformPanelWindow : public ScopedTransformOverviewWindow {
28  public:
29   ScopedTransformPanelWindow(aura::Window* window);
30   virtual ~ScopedTransformPanelWindow();
31 
32   // ScopedTransformOverviewWindow overrides:
33   virtual void PrepareForOverview() OVERRIDE;
34 
35  private:
36   // Returns the callout widget for the transformed panel.
37   views::Widget* GetCalloutWidget();
38 
39   // Restores the callout visibility.
40   void RestoreCallout();
41 
42   // Trigger relayout
43   void Relayout();
44 
45   bool callout_visible_;
46 
47   DISALLOW_COPY_AND_ASSIGN(ScopedTransformPanelWindow);
48 };
49 
ScopedTransformPanelWindow(aura::Window * window)50 ScopedTransformPanelWindow::ScopedTransformPanelWindow(aura::Window* window)
51     : ScopedTransformOverviewWindow(window) {
52 }
53 
~ScopedTransformPanelWindow()54 ScopedTransformPanelWindow::~ScopedTransformPanelWindow() {
55   // window() will be NULL if the window was destroyed.
56   if (window())
57     RestoreCallout();
58 }
59 
PrepareForOverview()60 void ScopedTransformPanelWindow::PrepareForOverview() {
61   ScopedTransformOverviewWindow::PrepareForOverview();
62   GetCalloutWidget()->GetLayer()->SetOpacity(0.0f);
63 }
64 
GetCalloutWidget()65 views::Widget* ScopedTransformPanelWindow::GetCalloutWidget() {
66   DCHECK(window()->parent()->id() == internal::kShellWindowId_PanelContainer);
67   internal::PanelLayoutManager* panel_layout_manager =
68       static_cast<internal::PanelLayoutManager*>(
69           window()->parent()->layout_manager());
70   return panel_layout_manager->GetCalloutWidgetForPanel(window());
71 }
72 
RestoreCallout()73 void ScopedTransformPanelWindow::RestoreCallout() {
74   scoped_ptr<ui::LayerAnimationSequence> sequence(
75       new ui::LayerAnimationSequence);
76   ui::LayerAnimationElement::AnimatableProperties paused_properties;
77   paused_properties.insert(ui::LayerAnimationElement::OPACITY);
78   sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement(
79       paused_properties, base::TimeDelta::FromMilliseconds(
80           ScopedTransformOverviewWindow::kTransitionMilliseconds)));
81   sequence->AddElement(ui::LayerAnimationElement::CreateOpacityElement(1,
82       base::TimeDelta::FromMilliseconds(
83           kPanelCalloutFadeInDurationMilliseconds)));
84   GetCalloutWidget()->GetLayer()->GetAnimator()->StartAnimation(
85       sequence.release());
86 }
87 
88 }  // namespace
89 
WindowSelectorPanels()90 WindowSelectorPanels::WindowSelectorPanels() {
91 }
92 
~WindowSelectorPanels()93 WindowSelectorPanels::~WindowSelectorPanels() {
94 }
95 
AddWindow(aura::Window * window)96 void WindowSelectorPanels::AddWindow(aura::Window* window) {
97   transform_windows_.push_back(new ScopedTransformPanelWindow(window));
98 }
99 
GetRootWindow()100 aura::Window* WindowSelectorPanels::GetRootWindow() {
101   return transform_windows_.front()->window()->GetRootWindow();
102 }
103 
HasSelectableWindow(const aura::Window * window)104 bool WindowSelectorPanels::HasSelectableWindow(const aura::Window* window) {
105   for (WindowList::const_iterator iter = transform_windows_.begin();
106        iter != transform_windows_.end(); ++iter) {
107     if ((*iter)->window() == window)
108       return true;
109   }
110   return false;
111 }
112 
TargetedWindow(const aura::Window * target)113 aura::Window* WindowSelectorPanels::TargetedWindow(const aura::Window* target) {
114   for (WindowList::const_iterator iter = transform_windows_.begin();
115        iter != transform_windows_.end(); ++iter) {
116     if ((*iter)->Contains(target))
117       return (*iter)->window();
118   }
119   return NULL;
120 }
121 
RestoreWindowOnExit(aura::Window * window)122 void WindowSelectorPanels::RestoreWindowOnExit(aura::Window* window) {
123   for (WindowList::iterator iter = transform_windows_.begin();
124        iter != transform_windows_.end(); ++iter) {
125     if ((*iter)->Contains(window)) {
126       (*iter)->RestoreWindowOnExit();
127       break;
128     }
129   }
130 }
131 
SelectionWindow()132 aura::Window* WindowSelectorPanels::SelectionWindow() {
133   return transform_windows_.front()->window();
134 }
135 
RemoveWindow(const aura::Window * window)136 void WindowSelectorPanels::RemoveWindow(const aura::Window* window) {
137   for (WindowList::iterator iter = transform_windows_.begin();
138        iter != transform_windows_.end(); ++iter) {
139     if ((*iter)->window() == window) {
140       (*iter)->OnWindowDestroyed();
141       transform_windows_.erase(iter);
142       break;
143     }
144   }
145 }
146 
empty() const147 bool WindowSelectorPanels::empty() const {
148   return transform_windows_.empty();
149 }
150 
PrepareForOverview()151 void WindowSelectorPanels::PrepareForOverview() {
152   for (WindowList::iterator iter = transform_windows_.begin();
153        iter != transform_windows_.end(); ++iter) {
154     (*iter)->PrepareForOverview();
155   }
156 }
157 
SetItemBounds(aura::Window * root_window,const gfx::Rect & target_bounds,bool animate)158 void WindowSelectorPanels::SetItemBounds(aura::Window* root_window,
159                                          const gfx::Rect& target_bounds,
160                                          bool animate) {
161   gfx::Rect bounding_rect;
162   for (WindowList::iterator iter = transform_windows_.begin();
163        iter != transform_windows_.end(); ++iter) {
164     bounding_rect.Union((*iter)->GetBoundsInScreen());
165   }
166   set_bounds(ScopedTransformOverviewWindow::
167       ShrinkRectToFitPreservingAspectRatio(bounding_rect, target_bounds));
168   gfx::Transform bounding_transform =
169       ScopedTransformOverviewWindow::GetTransformForRect(bounding_rect,
170                                                          bounds());
171   for (WindowList::iterator iter = transform_windows_.begin();
172        iter != transform_windows_.end(); ++iter) {
173     gfx::Transform transform;
174     gfx::Rect bounds = (*iter)->GetBoundsInScreen();
175     transform.Translate(bounding_rect.x() - bounds.x(),
176                         bounding_rect.y() - bounds.y());
177     transform.PreconcatTransform(bounding_transform);
178     transform.Translate(bounds.x() - bounding_rect.x(),
179                         bounds.y() - bounding_rect.y());
180     (*iter)->SetTransform(root_window, transform, animate);
181   }
182 }
183 
184 }  // namespace ash
185