Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: ash/wm/overview/window_selector.cc

Issue 251103005: Added arrow key navigation to Overview Mode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Simplified RemoveWindow() Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698