OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/wm/overview/window_selector.h" | 5 #include "ash/wm/overview/window_selector.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "ash/accessibility_delegate.h" | 9 #include "ash/accessibility_delegate.h" |
10 #include "ash/ash_switches.h" | 10 #include "ash/ash_switches.h" |
11 #include "ash/metrics/user_metrics_recorder.h" | 11 #include "ash/metrics/user_metrics_recorder.h" |
12 #include "ash/root_window_controller.h" | 12 #include "ash/root_window_controller.h" |
13 #include "ash/screen_util.h" | |
14 #include "ash/shell.h" | 13 #include "ash/shell.h" |
15 #include "ash/shell_window_ids.h" | 14 #include "ash/shell_window_ids.h" |
16 #include "ash/switchable_windows.h" | 15 #include "ash/switchable_windows.h" |
17 #include "ash/wm/overview/scoped_transform_overview_window.h" | 16 #include "ash/wm/overview/scoped_transform_overview_window.h" |
17 #include "ash/wm/overview/window_grid.h" | |
18 #include "ash/wm/overview/window_selector_delegate.h" | 18 #include "ash/wm/overview/window_selector_delegate.h" |
19 #include "ash/wm/overview/window_selector_item.h" | 19 #include "ash/wm/overview/window_selector_item.h" |
20 #include "ash/wm/overview/window_selector_panels.h" | 20 #include "ash/wm/overview/window_selector_panels.h" |
21 #include "ash/wm/overview/window_selector_window.h" | 21 #include "ash/wm/overview/window_selector_window.h" |
22 #include "ash/wm/window_state.h" | 22 #include "ash/wm/window_state.h" |
23 #include "base/auto_reset.h" | 23 #include "base/auto_reset.h" |
24 #include "base/command_line.h" | 24 #include "base/command_line.h" |
25 #include "base/metrics/histogram.h" | 25 #include "base/metrics/histogram.h" |
26 #include "base/strings/string_number_conversions.h" | 26 #include "base/strings/string_number_conversions.h" |
27 #include "third_party/skia/include/core/SkColor.h" | 27 #include "third_party/skia/include/core/SkColor.h" |
28 #include "ui/aura/client/focus_client.h" | 28 #include "ui/aura/client/focus_client.h" |
29 #include "ui/aura/window.h" | 29 #include "ui/aura/window.h" |
30 #include "ui/aura/window_event_dispatcher.h" | 30 #include "ui/aura/window_event_dispatcher.h" |
31 #include "ui/aura/window_observer.h" | 31 #include "ui/aura/window_observer.h" |
32 #include "ui/compositor/layer_animation_observer.h" | |
33 #include "ui/compositor/scoped_layer_animation_settings.h" | 32 #include "ui/compositor/scoped_layer_animation_settings.h" |
34 #include "ui/events/event.h" | 33 #include "ui/events/event.h" |
35 #include "ui/gfx/screen.h" | 34 #include "ui/gfx/screen.h" |
36 #include "ui/views/background.h" | 35 #include "ui/views/background.h" |
37 #include "ui/views/widget/widget.h" | 36 #include "ui/views/widget/widget.h" |
38 #include "ui/wm/core/window_util.h" | 37 #include "ui/wm/core/window_util.h" |
39 #include "ui/wm/public/activation_client.h" | 38 #include "ui/wm/public/activation_client.h" |
40 | 39 |
41 namespace ash { | 40 namespace ash { |
42 | 41 |
43 namespace { | 42 namespace { |
44 | 43 |
45 // Conceptually the window overview is a table or grid of cells having this | 44 // A comparator for locating a grid with a given root window. |
46 // fixed aspect ratio. The number of columns is determined by maximizing the | 45 struct RootWindowGridComparator |
47 // area of them based on the number of windows. | 46 : public std::unary_function<WindowGrid*, bool> { |
48 const float kCardAspectRatio = 4.0f / 3.0f; | 47 explicit RootWindowGridComparator(const aura::Window* root_window) |
48 : root_window_(root_window) { | |
49 } | |
49 | 50 |
50 // The minimum number of cards along the major axis (i.e. horizontally on a | 51 bool operator()(WindowGrid* grid) const { |
51 // landscape orientation). | 52 return (grid->root_window() == root_window_); |
52 const int kMinCardsMajor = 3; | 53 } |
53 | 54 |
54 // A comparator for locating a given target window. | 55 const aura::Window* root_window_; |
56 }; | |
57 | |
58 // A comparator for locating a WindowSelectorItem that contains a given target. | |
flackr
2014/06/03 17:12:07
Why would using WindowSelectorItemTargetComparator
Nina
2014/06/04 20:21:13
Yes, this is more reasonable. We still use this co
| |
55 struct WindowSelectorItemComparator | 59 struct WindowSelectorItemComparator |
56 : public std::unary_function<WindowSelectorItem*, bool> { | 60 : public std::unary_function<WindowSelectorItem*, bool> { |
57 explicit WindowSelectorItemComparator(const aura::Window* target_window) | 61 explicit WindowSelectorItemComparator(const aura::Window* target_window) |
58 : target(target_window) { | 62 : target(target_window) { |
59 } | 63 } |
60 | 64 |
61 bool operator()(WindowSelectorItem* window) const { | 65 bool operator()(WindowSelectorItem* window) const { |
62 return window->HasSelectableWindow(target); | 66 return window->HasSelectableWindow(target); |
63 } | 67 } |
64 | 68 |
65 const aura::Window* target; | 69 const aura::Window* target; |
66 }; | 70 }; |
67 | 71 |
68 // An observer which holds onto the passed widget until the animation is | |
69 // complete. | |
70 class CleanupWidgetAfterAnimationObserver : public ui::LayerAnimationObserver { | |
71 public: | |
72 explicit CleanupWidgetAfterAnimationObserver( | |
73 scoped_ptr<views::Widget> widget); | |
74 | |
75 // ui::LayerAnimationObserver: | |
76 virtual void OnLayerAnimationEnded( | |
77 ui::LayerAnimationSequence* sequence) OVERRIDE; | |
78 virtual void OnLayerAnimationAborted( | |
79 ui::LayerAnimationSequence* sequence) OVERRIDE; | |
80 virtual void OnLayerAnimationScheduled( | |
81 ui::LayerAnimationSequence* sequence) OVERRIDE; | |
82 | |
83 private: | |
84 virtual ~CleanupWidgetAfterAnimationObserver(); | |
85 | |
86 scoped_ptr<views::Widget> widget_; | |
87 | |
88 DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver); | |
89 }; | |
90 | |
91 CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver( | |
92 scoped_ptr<views::Widget> widget) | |
93 : widget_(widget.Pass()) { | |
94 widget_->GetNativeWindow()->layer()->GetAnimator()->AddObserver(this); | |
95 } | |
96 | |
97 CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() { | |
98 widget_->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this); | |
99 } | |
100 | |
101 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationEnded( | |
102 ui::LayerAnimationSequence* sequence) { | |
103 delete this; | |
104 } | |
105 | |
106 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted( | |
107 ui::LayerAnimationSequence* sequence) { | |
108 delete this; | |
109 } | |
110 | |
111 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled( | |
112 ui::LayerAnimationSequence* sequence) { | |
113 } | |
114 | |
115 // A comparator for locating a selectable window given a targeted window. | 72 // A comparator for locating a selectable window given a targeted window. |
116 struct WindowSelectorItemTargetComparator | 73 struct WindowSelectorItemTargetComparator |
117 : public std::unary_function<WindowSelectorItem*, bool> { | 74 : public std::unary_function<WindowSelectorItem*, bool> { |
118 explicit WindowSelectorItemTargetComparator(const aura::Window* target_window) | 75 explicit WindowSelectorItemTargetComparator(const aura::Window* target_window) |
119 : target(target_window) { | 76 : target(target_window) { |
120 } | 77 } |
121 | 78 |
122 bool operator()(WindowSelectorItem* window) const { | 79 bool operator()(WindowSelectorItem* window) const { |
123 return window->Contains(target); | 80 return window->Contains(target); |
124 } | 81 } |
(...skipping 19 matching lines...) Expand all Loading... | |
144 void UpdateShelfVisibility() { | 101 void UpdateShelfVisibility() { |
145 Shell::RootWindowControllerList root_window_controllers = | 102 Shell::RootWindowControllerList root_window_controllers = |
146 Shell::GetInstance()->GetAllRootWindowControllers(); | 103 Shell::GetInstance()->GetAllRootWindowControllers(); |
147 for (Shell::RootWindowControllerList::iterator iter = | 104 for (Shell::RootWindowControllerList::iterator iter = |
148 root_window_controllers.begin(); | 105 root_window_controllers.begin(); |
149 iter != root_window_controllers.end(); ++iter) { | 106 iter != root_window_controllers.end(); ++iter) { |
150 (*iter)->UpdateShelfVisibility(); | 107 (*iter)->UpdateShelfVisibility(); |
151 } | 108 } |
152 } | 109 } |
153 | 110 |
111 // Returns true if a window is contained in any of the windows passed on the | |
112 // list. | |
113 bool ContainedIn(const aura::Window* window, | |
114 const std::vector<WindowSelectorItem*>& window_list) { | |
flackr
2014/06/03 17:12:07
nit: Seems like you can use find_in with the Windo
Nina
2014/06/04 20:21:13
Done.
| |
115 for (std::vector<WindowSelectorItem*>::const_iterator iter = | |
116 window_list.begin(); iter != window_list.end(); ++iter) { | |
117 if ((*iter)->Contains(window)) | |
118 return true; | |
119 } | |
120 return false; | |
121 } | |
122 | |
154 } // namespace | 123 } // namespace |
155 | 124 |
156 WindowSelector::WindowSelector(const WindowList& windows, | 125 WindowSelector::WindowSelector(const WindowList& windows, |
157 WindowSelectorDelegate* delegate) | 126 WindowSelectorDelegate* delegate) |
158 : delegate_(delegate), | 127 : delegate_(delegate), |
159 restore_focus_window_(aura::client::GetFocusClient( | 128 restore_focus_window_(aura::client::GetFocusClient( |
160 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), | 129 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), |
161 ignore_activations_(false) { | 130 ignore_activations_(false), |
131 selected_grid_index_(0) { | |
162 DCHECK(delegate_); | 132 DCHECK(delegate_); |
163 | 133 |
164 if (restore_focus_window_) | 134 if (restore_focus_window_) { |
flackr
2014/06/03 17:12:07
nit: no curlies { } for single line block
Nina
2014/06/04 20:21:13
Done.
| |
165 restore_focus_window_->AddObserver(this); | 135 restore_focus_window_->AddObserver(this); |
136 } | |
166 | 137 |
167 std::vector<WindowSelectorPanels*> panels_items; | 138 std::vector<WindowSelectorPanels*> panels_items; |
139 std::vector<WindowSelectorItem*> overview_items; | |
168 for (size_t i = 0; i < windows.size(); ++i) { | 140 for (size_t i = 0; i < windows.size(); ++i) { |
169 WindowSelectorItem* item = NULL; | 141 WindowSelectorItem* item = NULL; |
170 if (windows[i] != restore_focus_window_) | 142 if (windows[i] != restore_focus_window_) |
171 windows[i]->AddObserver(this); | 143 windows[i]->AddObserver(this); |
172 observed_windows_.insert(windows[i]); | 144 observed_windows_.insert(windows[i]); |
173 | 145 |
174 if (windows[i]->type() == ui::wm::WINDOW_TYPE_PANEL && | 146 if (windows[i]->type() == ui::wm::WINDOW_TYPE_PANEL && |
175 wm::GetWindowState(windows[i])->panel_attached()) { | 147 wm::GetWindowState(windows[i])->panel_attached()) { |
176 // Attached panel windows are grouped into a single overview item per | 148 // Attached panel windows are grouped into a single overview item per |
177 // root window (display). | 149 // root window (display). |
178 std::vector<WindowSelectorPanels*>::iterator iter = | 150 std::vector<WindowSelectorPanels*>::iterator iter = |
179 std::find_if(panels_items.begin(), panels_items.end(), | 151 std::find_if(panels_items.begin(), panels_items.end(), |
180 WindowSelectorItemForRoot(windows[i]->GetRootWindow())); | 152 WindowSelectorItemForRoot(windows[i]->GetRootWindow())); |
181 WindowSelectorPanels* panels_item = NULL; | 153 WindowSelectorPanels* panels_item = NULL; |
182 if (iter == panels_items.end()) { | 154 if (iter == panels_items.end()) { |
183 panels_item = new WindowSelectorPanels(); | 155 panels_item = new WindowSelectorPanels(); |
184 panels_items.push_back(panels_item); | 156 panels_items.push_back(panels_item); |
185 windows_.push_back(panels_item); | 157 overview_items.push_back(panels_item); |
186 } else { | 158 } else { |
187 panels_item = *iter; | 159 panels_item = *iter; |
188 } | 160 } |
189 panels_item->AddWindow(windows[i]); | 161 panels_item->AddWindow(windows[i]); |
190 item = panels_item; | 162 item = panels_item; |
191 } else { | 163 } else { |
192 item = new WindowSelectorWindow(windows[i]); | 164 item = new WindowSelectorWindow(windows[i]); |
193 windows_.push_back(item); | 165 overview_items.push_back(item); |
194 } | 166 } |
195 // Verify that the window has been added to an item in overview. | 167 // Verify that the window has been added to an item in overview. |
196 CHECK(item->Contains(windows[i])); | 168 CHECK(item->Contains(windows[i])); |
197 } | 169 } |
flackr
2014/06/03 17:12:07
All of this building the list of overview items co
Nina
2014/06/04 20:21:13
Done. I also moved the window removal code to the
| |
198 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", windows_.size()); | 170 DCHECK(!overview_items.empty()); |
171 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", overview_items.size()); | |
199 | 172 |
200 // Observe window activations and switchable containers on all root windows | 173 // Observe window activations and switchable containers on all root windows |
201 // for newly created windows during overview. | 174 // for newly created windows during overview. |
202 Shell::GetInstance()->activation_client()->AddObserver(this); | 175 Shell::GetInstance()->activation_client()->AddObserver(this); |
203 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 176 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
204 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); | 177 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); |
205 iter != root_windows.end(); ++iter) { | 178 iter != root_windows.end(); ++iter) { |
206 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | 179 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
207 aura::Window* container = Shell::GetContainer(*iter, | 180 aura::Window* container = Shell::GetContainer(*iter, |
208 kSwitchableWindowContainerIds[i]); | 181 kSwitchableWindowContainerIds[i]); |
209 container->AddObserver(this); | 182 container->AddObserver(this); |
210 observed_windows_.insert(container); | 183 observed_windows_.insert(container); |
211 } | 184 } |
212 } | 185 } |
213 | 186 |
214 StartOverview(); | 187 // Remove focus from active window before entering overview. |
188 aura::client::GetFocusClient( | |
189 Shell::GetPrimaryRootWindow())->FocusWindow(NULL); | |
190 | |
191 Shell* shell = Shell::GetInstance(); | |
flackr
2014/06/03 17:12:07
Shell::GetInstance() is also used on 175, move bef
Nina
2014/06/04 20:21:13
Done.
| |
192 shell->OnOverviewModeStarting(); | |
flackr
2014/06/03 17:12:07
OnOverviewModeStarting should be sent before we st
Nina
2014/06/04 20:21:13
Done.
| |
193 | |
194 for (WindowSelectorItemList::iterator iter = overview_items.begin(); | |
195 iter != overview_items.end(); ++iter) { | |
196 (*iter)->PrepareForOverview(); | |
197 } | |
198 | |
199 // Build the window_grid list | |
200 aura::Window::Windows root_window_list = Shell::GetAllRootWindows(); | |
201 for (size_t i = 0; i < root_window_list.size(); ++i) { | |
202 // Make sure the root window hosts at least one overview window. | |
203 if (std::find_if(overview_items.begin(), overview_items.end(), | |
204 WindowSelectorItemForRoot(root_window_list[i])) != | |
205 overview_items.end()) { | |
206 grid_list_.push_back(new WindowGrid(root_window_list[i], | |
207 overview_items)); | |
208 } | |
209 } | |
210 DCHECK(!grid_list_.empty()); | |
211 | |
212 shell->PrependPreTargetHandler(this); | |
213 shell->GetScreen()->AddObserver(this); | |
214 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); | |
215 HideAndTrackNonOverviewWindows(overview_items); | |
216 // Send an a11y alert. | |
217 shell->accessibility_delegate()->TriggerAccessibilityAlert( | |
218 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); | |
219 | |
220 UpdateShelfVisibility(); | |
215 } | 221 } |
216 | 222 |
217 WindowSelector::~WindowSelector() { | 223 WindowSelector::~WindowSelector() { |
218 ash::Shell* shell = ash::Shell::GetInstance(); | 224 ash::Shell* shell = ash::Shell::GetInstance(); |
219 | 225 |
220 ResetFocusRestoreWindow(true); | 226 ResetFocusRestoreWindow(true); |
221 for (std::set<aura::Window*>::iterator iter = observed_windows_.begin(); | 227 for (std::set<aura::Window*>::iterator iter = observed_windows_.begin(); |
222 iter != observed_windows_.end(); ++iter) { | 228 iter != observed_windows_.end(); ++iter) { |
223 (*iter)->RemoveObserver(this); | 229 (*iter)->RemoveObserver(this); |
224 } | 230 } |
(...skipping 17 matching lines...) Expand all Loading... | |
242 shell->GetScreen()->RemoveObserver(this); | 248 shell->GetScreen()->RemoveObserver(this); |
243 UMA_HISTOGRAM_MEDIUM_TIMES( | 249 UMA_HISTOGRAM_MEDIUM_TIMES( |
244 "Ash.WindowSelector.TimeInOverview", | 250 "Ash.WindowSelector.TimeInOverview", |
245 base::Time::Now() - overview_start_time_); | 251 base::Time::Now() - overview_start_time_); |
246 | 252 |
247 // TODO(nsatragno): Change this to OnOverviewModeEnded and move it to when | 253 // TODO(nsatragno): Change this to OnOverviewModeEnded and move it to when |
248 // everything is done. | 254 // everything is done. |
249 shell->OnOverviewModeEnding(); | 255 shell->OnOverviewModeEnding(); |
250 | 256 |
251 // Clearing the window list resets the ignored_by_shelf flag on the windows. | 257 // Clearing the window list resets the ignored_by_shelf flag on the windows. |
252 windows_.clear(); | 258 grid_list_.clear(); |
253 UpdateShelfVisibility(); | 259 UpdateShelfVisibility(); |
254 } | 260 } |
255 | 261 |
256 void WindowSelector::CancelSelection() { | 262 void WindowSelector::CancelSelection() { |
257 delegate_->OnSelectionEnded(); | 263 delegate_->OnSelectionEnded(); |
258 } | 264 } |
259 | 265 |
260 void WindowSelector::OnKeyEvent(ui::KeyEvent* event) { | 266 void WindowSelector::OnKeyEvent(ui::KeyEvent* event) { |
261 if (event->type() != ui::ET_KEY_PRESSED) | 267 if (event->type() != ui::ET_KEY_PRESSED) |
262 return; | 268 return; |
263 | 269 |
264 if (event->key_code() == ui::VKEY_ESCAPE) { | 270 bool handled = true; |
265 CancelSelection(); | 271 |
272 switch (event->key_code()) { | |
273 case ui::VKEY_ESCAPE: | |
274 CancelSelection(); | |
275 break; | |
276 case ui::VKEY_UP: | |
277 Move(WindowSelector::UP); | |
278 break; | |
279 case ui::VKEY_DOWN: | |
280 Move(WindowSelector::DOWN); | |
281 break; | |
282 case ui::VKEY_RIGHT: | |
283 Move(WindowSelector::RIGHT); | |
284 break; | |
285 case ui::VKEY_LEFT: | |
286 Move(WindowSelector::LEFT); | |
287 break; | |
288 case ui::VKEY_RETURN: | |
289 wm::GetWindowState( | |
290 grid_list_[selected_grid_index_]-> | |
291 SelectedWindow()->SelectionWindow())->Activate(); | |
292 break; | |
293 default: | |
294 // Not a key we are interested in. | |
295 handled = false; | |
296 break; | |
297 } | |
298 if (handled) | |
266 event->SetHandled(); | 299 event->SetHandled(); |
267 } | |
268 } | 300 } |
269 | 301 |
270 void WindowSelector::OnDisplayAdded(const gfx::Display& display) { | 302 void WindowSelector::OnDisplayAdded(const gfx::Display& display) { |
271 } | 303 } |
272 | 304 |
273 void WindowSelector::OnDisplayRemoved(const gfx::Display& display) { | 305 void WindowSelector::OnDisplayRemoved(const gfx::Display& display) { |
306 CancelSelection(); | |
flackr
2014/06/03 17:12:07
TODO(nsatragno): Keep window selection active on r
Nina
2014/06/04 20:21:13
This does sound like a good idea. Adding TODO.
| |
274 } | 307 } |
275 | 308 |
276 void WindowSelector::OnDisplayMetricsChanged(const gfx::Display& display, | 309 void WindowSelector::OnDisplayMetricsChanged(const gfx::Display& display, |
277 uint32_t metrics) { | 310 uint32_t metrics) { |
278 PositionWindows(/* animate */ false); | 311 PositionWindows(/* animate */ false); |
279 } | 312 } |
280 | 313 |
281 void WindowSelector::OnWindowAdded(aura::Window* new_window) { | 314 void WindowSelector::OnWindowAdded(aura::Window* new_window) { |
282 if (new_window->type() != ui::wm::WINDOW_TYPE_NORMAL && | 315 if (new_window->type() != ui::wm::WINDOW_TYPE_NORMAL && |
283 new_window->type() != ui::wm::WINDOW_TYPE_PANEL) { | 316 new_window->type() != ui::wm::WINDOW_TYPE_PANEL) { |
284 return; | 317 return; |
285 } | 318 } |
286 | 319 |
287 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | 320 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
288 if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && | 321 if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && |
289 !::wm::GetTransientParent(new_window)) { | 322 !::wm::GetTransientParent(new_window)) { |
290 // The new window is in one of the switchable containers, abort overview. | 323 // The new window is in one of the switchable containers, abort overview. |
291 CancelSelection(); | 324 CancelSelection(); |
292 return; | 325 return; |
293 } | 326 } |
294 } | 327 } |
295 } | 328 } |
296 | 329 |
297 void WindowSelector::OnWindowDestroying(aura::Window* window) { | 330 void WindowSelector::OnWindowDestroying(aura::Window* window) { |
298 // window is one of a container, the restore_focus_window and/or | |
299 // one of the selectable windows in overview. | |
300 ScopedVector<WindowSelectorItem>::iterator iter = | |
301 std::find_if(windows_.begin(), windows_.end(), | |
302 WindowSelectorItemComparator(window)); | |
303 window->RemoveObserver(this); | 331 window->RemoveObserver(this); |
304 observed_windows_.erase(window); | 332 observed_windows_.erase(window); |
305 if (window == restore_focus_window_) | 333 if (window == restore_focus_window_) |
306 restore_focus_window_ = NULL; | 334 restore_focus_window_ = NULL; |
307 if (iter == windows_.end()) | 335 |
336 // Find the grid corresponding to the window's root window. | |
337 ScopedVector<WindowGrid>::iterator grid_iter = | |
338 std::find_if(grid_list_.begin(), grid_list_.end(), | |
339 RootWindowGridComparator(window->GetRootWindow())); | |
340 | |
341 // If the a container or the |restore_focus_window_| are destroyed but not | |
342 // part of the overview, they will not be found in the grid list. Nothing | |
343 // else to do. | |
344 if (grid_iter == grid_list_.end()) | |
308 return; | 345 return; |
309 | 346 |
310 (*iter)->RemoveWindow(window); | 347 (*grid_iter)->RemoveWindow(window); |
311 // If there are still windows in this selector entry then the overview is | |
312 // still active and the active selection remains the same. | |
313 if (!(*iter)->empty()) | |
314 return; | |
315 | 348 |
316 windows_.erase(iter); | 349 if ((*grid_iter)->empty()) { |
317 if (windows_.empty()) { | 350 grid_list_.erase(grid_iter); |
318 CancelSelection(); | 351 selected_grid_index_ = 0; |
flackr
2014/06/03 17:12:07
TODO, For more than 2 displays / grids the new sel
Nina
2014/06/04 20:21:13
Added TODO although this would not be a problem cu
| |
319 return; | 352 if (grid_list_.size() == 0) |
353 CancelSelection(); | |
320 } | 354 } |
321 PositionWindows(true); | |
322 } | 355 } |
323 | 356 |
324 void WindowSelector::OnWindowBoundsChanged(aura::Window* window, | 357 void WindowSelector::OnWindowBoundsChanged(aura::Window* window, |
flackr
2014/06/03 17:12:07
Bounds changed should really be handled in the Win
Nina
2014/06/04 20:21:13
This should be relatively easy to implement. Added
| |
325 const gfx::Rect& old_bounds, | 358 const gfx::Rect& old_bounds, |
326 const gfx::Rect& new_bounds) { | 359 const gfx::Rect& new_bounds) { |
327 ScopedVector<WindowSelectorItem>::iterator iter = | 360 ScopedVector<WindowGrid>::iterator grid = |
328 std::find_if(windows_.begin(), windows_.end(), | 361 std::find_if(grid_list_.begin(), grid_list_.end(), |
362 RootWindowGridComparator(window->GetRootWindow())); | |
363 if (grid == grid_list_.end()) | |
364 return; | |
365 const std::vector<WindowSelectorItem*> windows = (*grid)->window_list(); | |
366 ScopedVector<WindowSelectorItem>::const_iterator iter = | |
367 std::find_if(windows.begin(), windows.end(), | |
329 WindowSelectorItemTargetComparator(window)); | 368 WindowSelectorItemTargetComparator(window)); |
330 if (iter == windows_.end()) | 369 if (iter == windows.end()) |
331 return; | 370 return; |
332 | 371 |
333 // Immediately finish any active bounds animation. | 372 // Immediately finish any active bounds animation. |
334 window->layer()->GetAnimator()->StopAnimatingProperty( | 373 window->layer()->GetAnimator()->StopAnimatingProperty( |
335 ui::LayerAnimationElement::BOUNDS); | 374 ui::LayerAnimationElement::BOUNDS); |
336 | 375 |
337 // Recompute the transform for the window. | 376 // Recompute the transform for the window. |
338 (*iter)->RecomputeWindowTransforms(); | 377 (*iter)->RecomputeWindowTransforms(); |
339 } | 378 } |
340 | 379 |
341 void WindowSelector::OnWindowActivated(aura::Window* gained_active, | 380 void WindowSelector::OnWindowActivated(aura::Window* gained_active, |
342 aura::Window* lost_active) { | 381 aura::Window* lost_active) { |
343 if (ignore_activations_ || !gained_active) | 382 if (ignore_activations_ || !gained_active) |
344 return; | 383 return; |
345 | 384 |
346 ScopedVector<WindowSelectorItem>::iterator iter = std::find_if( | 385 ScopedVector<WindowGrid>::iterator grid = |
347 windows_.begin(), windows_.end(), | 386 std::find_if(grid_list_.begin(), grid_list_.end(), |
387 RootWindowGridComparator(gained_active->GetRootWindow())); | |
388 if (grid == grid_list_.end()) | |
389 return; | |
390 const std::vector<WindowSelectorItem*> windows = (*grid)->window_list(); | |
391 | |
392 ScopedVector<WindowSelectorItem>::const_iterator iter = std::find_if( | |
393 windows.begin(), windows.end(), | |
348 WindowSelectorItemComparator(gained_active)); | 394 WindowSelectorItemComparator(gained_active)); |
349 | 395 |
350 if (iter != windows_.end()) | 396 if (iter != windows.end()) |
351 (*iter)->RestoreWindowOnExit(gained_active); | 397 (*iter)->RestoreWindowOnExit(gained_active); |
352 | 398 |
353 // Don't restore focus on exit if a window was just activated. | 399 // Don't restore focus on exit if a window was just activated. |
354 ResetFocusRestoreWindow(false); | 400 ResetFocusRestoreWindow(false); |
355 CancelSelection(); | 401 CancelSelection(); |
356 } | 402 } |
357 | 403 |
358 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, | 404 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, |
359 aura::Window* actual_active) { | 405 aura::Window* actual_active) { |
360 OnWindowActivated(request_active, actual_active); | 406 OnWindowActivated(request_active, actual_active); |
361 } | 407 } |
362 | 408 |
363 void WindowSelector::StartOverview() { | |
364 // Remove focus from active window before entering overview. | |
365 aura::client::GetFocusClient( | |
366 Shell::GetPrimaryRootWindow())->FocusWindow(NULL); | |
367 | |
368 Shell* shell = Shell::GetInstance(); | |
369 shell->OnOverviewModeStarting(); | |
370 | |
371 for (WindowSelectorItemList::iterator iter = windows_.begin(); | |
372 iter != windows_.end(); ++iter) { | |
373 (*iter)->PrepareForOverview(); | |
374 } | |
375 PositionWindows(/* animate */ true); | |
376 DCHECK(!windows_.empty()); | |
377 shell->PrependPreTargetHandler(this); | |
378 shell->GetScreen()->AddObserver(this); | |
379 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); | |
380 HideAndTrackNonOverviewWindows(); | |
381 // Send an a11y alert. | |
382 shell->accessibility_delegate()->TriggerAccessibilityAlert( | |
383 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); | |
384 | |
385 UpdateShelfVisibility(); | |
386 } | |
387 | |
388 bool WindowSelector::Contains(const aura::Window* window) { | |
389 for (WindowSelectorItemList::iterator iter = windows_.begin(); | |
390 iter != windows_.end(); ++iter) { | |
391 if ((*iter)->Contains(window)) | |
392 return true; | |
393 } | |
394 return false; | |
395 } | |
396 | |
397 void WindowSelector::PositionWindows(bool animate) { | 409 void WindowSelector::PositionWindows(bool animate) { |
398 aura::Window::Windows root_window_list = Shell::GetAllRootWindows(); | 410 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); |
399 for (size_t i = 0; i < root_window_list.size(); ++i) | 411 iter != grid_list_.end(); iter++) { |
400 PositionWindowsFromRoot(root_window_list[i], animate); | 412 (*iter)->PositionWindows(animate); |
401 } | |
402 | |
403 void WindowSelector::PositionWindowsFromRoot(aura::Window* root_window, | |
404 bool animate) { | |
405 std::vector<WindowSelectorItem*> windows; | |
406 for (WindowSelectorItemList::iterator iter = windows_.begin(); | |
407 iter != windows_.end(); ++iter) { | |
408 if ((*iter)->GetRootWindow() == root_window) | |
409 windows.push_back(*iter); | |
410 } | |
411 | |
412 if (windows.empty()) | |
413 return; | |
414 | |
415 gfx::Size window_size; | |
416 gfx::Rect total_bounds = ScreenUtil::ConvertRectToScreen( | |
417 root_window, | |
418 ScreenUtil::GetDisplayWorkAreaBoundsInParent( | |
419 Shell::GetContainer(root_window, kShellWindowId_DefaultContainer))); | |
420 | |
421 // Find the minimum number of windows per row that will fit all of the | |
422 // windows on screen. | |
423 size_t columns = std::max( | |
424 total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1, | |
425 static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() / | |
426 (kCardAspectRatio * total_bounds.height()))))); | |
427 size_t rows = ((windows.size() + columns - 1) / columns); | |
428 window_size.set_width(std::min( | |
429 static_cast<int>(total_bounds.width() / columns), | |
430 static_cast<int>(total_bounds.height() * kCardAspectRatio / rows))); | |
431 window_size.set_height(window_size.width() / kCardAspectRatio); | |
432 | |
433 // Calculate the X and Y offsets necessary to center the grid. | |
434 int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 : | |
435 (columns - windows.size()) * window_size.width()) + | |
436 (total_bounds.width() - columns * window_size.width())) / 2; | |
437 int y_offset = total_bounds.y() + (total_bounds.height() - | |
438 rows * window_size.height()) / 2; | |
439 for (size_t i = 0; i < windows.size(); ++i) { | |
440 gfx::Transform transform; | |
441 int column = i % columns; | |
442 int row = i / columns; | |
443 gfx::Rect target_bounds(window_size.width() * column + x_offset, | |
444 window_size.height() * row + y_offset, | |
445 window_size.width(), | |
446 window_size.height()); | |
447 windows[i]->SetBounds(root_window, target_bounds, animate); | |
448 } | 413 } |
449 } | 414 } |
450 | 415 |
451 void WindowSelector::HideAndTrackNonOverviewWindows() { | 416 void WindowSelector::HideAndTrackNonOverviewWindows( |
417 const std::vector<WindowSelectorItem*>& overview_items) { | |
452 // Add the windows to hidden_windows first so that if any are destroyed | 418 // Add the windows to hidden_windows first so that if any are destroyed |
453 // while hiding them they are tracked. | 419 // while hiding them they are tracked. |
454 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 420 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
455 for (aura::Window::Windows::const_iterator root_iter = root_windows.begin(); | 421 for (aura::Window::Windows::const_iterator root_iter = root_windows.begin(); |
456 root_iter != root_windows.end(); ++root_iter) { | 422 root_iter != root_windows.end(); ++root_iter) { |
457 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | 423 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
458 aura::Window* container = Shell::GetContainer(*root_iter, | 424 aura::Window* container = Shell::GetContainer(*root_iter, |
459 kSwitchableWindowContainerIds[i]); | 425 kSwitchableWindowContainerIds[i]); |
460 for (aura::Window::Windows::const_iterator iter = | 426 for (aura::Window::Windows::const_iterator iter = |
461 container->children().begin(); iter != container->children().end(); | 427 container->children().begin(); iter != container->children().end(); |
462 ++iter) { | 428 ++iter) { |
463 if (Contains(*iter) || !(*iter)->IsVisible()) | 429 if (ContainedIn(*iter, overview_items) || !(*iter)->IsVisible()) |
464 continue; | 430 continue; |
465 hidden_windows_.Add(*iter); | 431 hidden_windows_.Add(*iter); |
466 } | 432 } |
467 } | 433 } |
468 } | 434 } |
469 | 435 |
470 // Copy the window list as it can change during iteration. | 436 // Copy the window list as it can change during iteration. |
471 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); | 437 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); |
472 for (aura::WindowTracker::Windows::const_iterator iter = | 438 for (aura::WindowTracker::Windows::const_iterator iter = |
473 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { | 439 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { |
(...skipping 22 matching lines...) Expand all Loading... | |
496 } | 462 } |
497 // If the window is in the observed_windows_ list it needs to continue to be | 463 // If the window is in the observed_windows_ list it needs to continue to be |
498 // observed. | 464 // observed. |
499 if (observed_windows_.find(restore_focus_window_) == | 465 if (observed_windows_.find(restore_focus_window_) == |
500 observed_windows_.end()) { | 466 observed_windows_.end()) { |
501 restore_focus_window_->RemoveObserver(this); | 467 restore_focus_window_->RemoveObserver(this); |
502 } | 468 } |
503 restore_focus_window_ = NULL; | 469 restore_focus_window_ = NULL; |
504 } | 470 } |
505 | 471 |
472 void WindowSelector::Move(Direction direction) { | |
473 if (grid_list_[selected_grid_index_]->Move(direction)) { | |
474 // The grid reported that the movement command corresponds to the next | |
475 // root window, identify it and call Move() on it to initialize the | |
476 // selection widget. | |
flackr
2014/06/03 17:12:07
TODO: If there are more than 2 monitors, move betw
Nina
2014/06/04 20:21:13
Added TODO. Again, this will not be a problem for
| |
477 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size(); | |
478 grid_list_[selected_grid_index_]->Move(direction); | |
479 } | |
480 } | |
481 | |
506 } // namespace ash | 482 } // namespace ash |
OLD | NEW |