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/ash_switches.h" | 10 #include "ash/ash_switches.h" |
11 #include "ash/metrics/user_metrics_recorder.h" | |
10 #include "ash/root_window_controller.h" | 12 #include "ash/root_window_controller.h" |
13 #include "ash/screen_util.h" | |
11 #include "ash/shell.h" | 14 #include "ash/shell.h" |
15 #include "ash/shell_window_ids.h" | |
12 #include "ash/switchable_windows.h" | 16 #include "ash/switchable_windows.h" |
13 #include "ash/wm/overview/window_overview.h" | 17 #include "ash/wm/overview/scoped_transform_overview_window.h" |
14 #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" | |
15 #include "ash/wm/overview/window_selector_panels.h" | 20 #include "ash/wm/overview/window_selector_panels.h" |
16 #include "ash/wm/overview/window_selector_window.h" | 21 #include "ash/wm/overview/window_selector_window.h" |
17 #include "ash/wm/window_state.h" | 22 #include "ash/wm/window_state.h" |
18 #include "base/auto_reset.h" | 23 #include "base/auto_reset.h" |
19 #include "base/command_line.h" | 24 #include "base/command_line.h" |
20 #include "base/metrics/histogram.h" | 25 #include "base/metrics/histogram.h" |
21 #include "base/strings/string_number_conversions.h" | 26 #include "base/strings/string_number_conversions.h" |
27 #include "third_party/skia/include/core/SkColor.h" | |
28 #include "ui/aura/client/cursor_client.h" | |
22 #include "ui/aura/client/focus_client.h" | 29 #include "ui/aura/client/focus_client.h" |
23 #include "ui/aura/window.h" | 30 #include "ui/aura/window.h" |
31 #include "ui/aura/window_event_dispatcher.h" | |
24 #include "ui/aura/window_observer.h" | 32 #include "ui/aura/window_observer.h" |
33 #include "ui/compositor/layer_animation_observer.h" | |
34 #include "ui/compositor/scoped_layer_animation_settings.h" | |
35 #include "ui/events/event.h" | |
36 #include "ui/gfx/screen.h" | |
37 #include "ui/views/background.h" | |
38 #include "ui/views/widget/widget.h" | |
25 #include "ui/wm/core/window_util.h" | 39 #include "ui/wm/core/window_util.h" |
26 #include "ui/wm/public/activation_client.h" | 40 #include "ui/wm/public/activation_client.h" |
27 | 41 |
28 namespace ash { | 42 namespace ash { |
29 | 43 |
30 namespace { | 44 namespace { |
31 | 45 |
32 // A comparator for locating a given selectable window. | 46 // Conceptually the window overview is a table or grid of cells having this |
47 // fixed aspect ratio. The number of columns is determined by maximizing the | |
48 // area of them based on the number of windows. | |
49 const float kCardAspectRatio = 4.0f / 3.0f; | |
50 | |
51 // In the conceptual overview table, the window margin is the space reserved | |
52 // around the window within the cell. This margin does not overlap so the | |
53 // closest distance between adjacent windows will be twice this amount. | |
54 const int kWindowMargin = 30; | |
55 | |
56 // The minimum number of cards along the major axis (i.e. horizontally on a | |
57 // landscape orientation). | |
58 const int kMinCardsMajor = 3; | |
59 | |
60 // The duration of transition animations on the overview selector. | |
61 const int kOverviewSelectorTransitionMilliseconds = 100; | |
62 | |
63 // The color and opacity of the overview selector. | |
64 const SkColor kWindowOverviewSelectionColor = SK_ColorBLACK; | |
65 const float kWindowOverviewSelectionOpacity = 0.5f; | |
66 | |
67 // The padding or amount of the window selector widget visible around the edges | |
68 // of the currently selected window. | |
69 const int kWindowOverviewSelectionPadding = 25; | |
70 | |
71 // A comparator for locating a given target window. | |
33 struct WindowSelectorItemComparator | 72 struct WindowSelectorItemComparator |
34 : public std::unary_function<WindowSelectorItem*, bool> { | 73 : public std::unary_function<WindowSelectorItem*, bool> { |
35 explicit WindowSelectorItemComparator(const aura::Window* window) | 74 explicit WindowSelectorItemComparator(const aura::Window* target_window) |
36 : window_(window) { | 75 : target(target_window) { |
37 } | 76 } |
38 | 77 |
39 bool operator()(WindowSelectorItem* window) const { | 78 bool operator()(WindowSelectorItem* window) const { |
40 return window->HasSelectableWindow(window_); | 79 return window->TargetedWindow(target) != NULL; |
41 } | 80 } |
42 | 81 |
43 const aura::Window* window_; | 82 const aura::Window* target; |
44 }; | 83 }; |
45 | 84 |
85 // An observer which holds onto the passed widget until the animation is | |
86 // complete. | |
87 class CleanupWidgetAfterAnimationObserver : public ui::LayerAnimationObserver { | |
88 public: | |
89 explicit CleanupWidgetAfterAnimationObserver( | |
90 scoped_ptr<views::Widget> widget); | |
91 | |
92 // ui::LayerAnimationObserver: | |
93 virtual void OnLayerAnimationEnded( | |
94 ui::LayerAnimationSequence* sequence) OVERRIDE; | |
95 virtual void OnLayerAnimationAborted( | |
96 ui::LayerAnimationSequence* sequence) OVERRIDE; | |
97 virtual void OnLayerAnimationScheduled( | |
98 ui::LayerAnimationSequence* sequence) OVERRIDE; | |
99 | |
100 private: | |
101 virtual ~CleanupWidgetAfterAnimationObserver(); | |
102 | |
103 scoped_ptr<views::Widget> widget_; | |
104 | |
105 DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver); | |
106 }; | |
107 | |
108 CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver( | |
109 scoped_ptr<views::Widget> widget) | |
110 : widget_(widget.Pass()) { | |
111 widget_->GetNativeWindow()->layer()->GetAnimator()->AddObserver(this); | |
112 } | |
113 | |
114 CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() { | |
115 widget_->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this); | |
116 } | |
117 | |
118 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationEnded( | |
119 ui::LayerAnimationSequence* sequence) { | |
120 delete this; | |
121 } | |
122 | |
123 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted( | |
124 ui::LayerAnimationSequence* sequence) { | |
125 delete this; | |
126 } | |
127 | |
128 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled( | |
129 ui::LayerAnimationSequence* sequence) { | |
130 } | |
131 | |
132 } // namespace | |
flackr
2014/05/14 20:59:32
Why were all of the following things moved out of
Nina
2014/05/15 12:32:04
Sloppy coding. Corrected.
| |
133 | |
46 // A comparator for locating a selectable window given a targeted window. | 134 // A comparator for locating a selectable window given a targeted window. |
47 struct WindowSelectorItemTargetComparator | 135 struct WindowSelectorItemTargetComparator |
48 : public std::unary_function<WindowSelectorItem*, bool> { | 136 : public std::unary_function<WindowSelectorItem*, bool> { |
49 explicit WindowSelectorItemTargetComparator(const aura::Window* target_window) | 137 explicit WindowSelectorItemTargetComparator(const aura::Window* target_window) |
50 : target(target_window) { | 138 : target(target_window) { |
51 } | 139 } |
52 | 140 |
53 bool operator()(WindowSelectorItem* window) const { | 141 bool operator()(WindowSelectorItem* window) const { |
54 return window->TargetedWindow(target) != NULL; | 142 return window->TargetedWindow(target) != NULL; |
55 } | 143 } |
(...skipping 19 matching lines...) Expand all Loading... | |
75 void UpdateShelfVisibility() { | 163 void UpdateShelfVisibility() { |
76 Shell::RootWindowControllerList root_window_controllers = | 164 Shell::RootWindowControllerList root_window_controllers = |
77 Shell::GetInstance()->GetAllRootWindowControllers(); | 165 Shell::GetInstance()->GetAllRootWindowControllers(); |
78 for (Shell::RootWindowControllerList::iterator iter = | 166 for (Shell::RootWindowControllerList::iterator iter = |
79 root_window_controllers.begin(); | 167 root_window_controllers.begin(); |
80 iter != root_window_controllers.end(); ++iter) { | 168 iter != root_window_controllers.end(); ++iter) { |
81 (*iter)->UpdateShelfVisibility(); | 169 (*iter)->UpdateShelfVisibility(); |
82 } | 170 } |
83 } | 171 } |
84 | 172 |
85 } // namespace | |
86 | |
87 WindowSelector::WindowSelector(const WindowList& windows, | 173 WindowSelector::WindowSelector(const WindowList& windows, |
88 WindowSelectorDelegate* delegate) | 174 WindowSelectorDelegate* delegate) |
89 : delegate_(delegate), | 175 : delegate_(delegate), |
90 restore_focus_window_(aura::client::GetFocusClient( | 176 restore_focus_window_(aura::client::GetFocusClient( |
91 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), | 177 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), |
92 ignore_activations_(false) { | 178 ignore_activations_(false) { |
93 DCHECK(delegate_); | 179 DCHECK(delegate_); |
94 | 180 |
95 if (restore_focus_window_) | 181 if (restore_focus_window_) |
96 restore_focus_window_->AddObserver(this); | 182 restore_focus_window_->AddObserver(this); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
146 } | 232 } |
147 | 233 |
148 WindowSelector::~WindowSelector() { | 234 WindowSelector::~WindowSelector() { |
149 ResetFocusRestoreWindow(true); | 235 ResetFocusRestoreWindow(true); |
150 for (std::set<aura::Window*>::iterator iter = observed_windows_.begin(); | 236 for (std::set<aura::Window*>::iterator iter = observed_windows_.begin(); |
151 iter != observed_windows_.end(); ++iter) { | 237 iter != observed_windows_.end(); ++iter) { |
152 (*iter)->RemoveObserver(this); | 238 (*iter)->RemoveObserver(this); |
153 } | 239 } |
154 Shell::GetInstance()->activation_client()->RemoveObserver(this); | 240 Shell::GetInstance()->activation_client()->RemoveObserver(this); |
155 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 241 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
156 window_overview_.reset(); | 242 |
243 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); | |
244 for (aura::WindowTracker::Windows::const_iterator iter = | |
flackr
2014/05/14 20:59:32
Unindent
Nina
2014/05/15 12:32:04
Done.
| |
245 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { | |
246 ui::ScopedLayerAnimationSettings settings( | |
247 (*iter)->layer()->GetAnimator()); | |
248 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( | |
249 ScopedTransformOverviewWindow::kTransitionMilliseconds)); | |
250 settings.SetPreemptionStrategy( | |
251 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
252 (*iter)->layer()->SetOpacity(1); | |
253 (*iter)->Show(); | |
254 } | |
255 | |
256 if (cursor_client_) | |
257 cursor_client_->UnlockCursor(); | |
258 ash::Shell* shell = ash::Shell::GetInstance(); | |
flackr
2014/05/14 20:59:32
Move this up and use for call to Shell::GetInstanc
Nina
2014/05/15 12:32:04
Done.
| |
259 shell->RemovePreTargetHandler(this); | |
260 shell->GetScreen()->RemoveObserver(this); | |
261 UMA_HISTOGRAM_MEDIUM_TIMES( | |
262 "Ash.WindowSelector.TimeInOverview", | |
263 base::Time::Now() - overview_start_time_); | |
264 shell->OnOverviewModeEnding(); | |
flackr
2014/05/14 20:59:32
Can you add a TODO to change this to OnOverviewMod
Nina
2014/05/15 12:32:04
Done. For the record, you mean like after the wind
flackr
2014/05/15 21:28:13
Yes.
| |
265 | |
157 // Clearing the window list resets the ignored_by_shelf flag on the windows. | 266 // Clearing the window list resets the ignored_by_shelf flag on the windows. |
158 windows_.clear(); | 267 windows_.clear(); |
159 UpdateShelfVisibility(); | 268 UpdateShelfVisibility(); |
160 } | 269 } |
161 | 270 |
162 void WindowSelector::SelectWindow(aura::Window* window) { | 271 void WindowSelector::SelectWindow(aura::Window* window) { |
163 ResetFocusRestoreWindow(false); | 272 ResetFocusRestoreWindow(false); |
164 ScopedVector<WindowSelectorItem>::iterator iter = | 273 ScopedVector<WindowSelectorItem>::iterator iter = |
165 std::find_if(windows_.begin(), windows_.end(), | 274 std::find_if(windows_.begin(), windows_.end(), |
166 WindowSelectorItemTargetComparator(window)); | 275 WindowSelectorItemTargetComparator(window)); |
167 DCHECK(iter != windows_.end()); | 276 DCHECK(iter != windows_.end()); |
168 // The selected window should not be minimized when window selection is | 277 // The selected window should not be minimized when window selection is |
169 // ended. | 278 // ended. |
170 (*iter)->RestoreWindowOnExit(window); | 279 (*iter)->RestoreWindowOnExit(window); |
171 delegate_->OnWindowSelected(window); | 280 delegate_->OnWindowSelected(window); |
172 } | 281 } |
173 | 282 |
174 void WindowSelector::CancelSelection() { | 283 void WindowSelector::CancelSelection() { |
175 delegate_->OnSelectionCanceled(); | 284 delegate_->OnSelectionCanceled(); |
176 } | 285 } |
177 | 286 |
287 void WindowSelector::OnKeyEvent(ui::KeyEvent* event) { | |
288 if (GetTargetedWindow(static_cast<aura::Window*>(event->target()))) | |
289 event->StopPropagation(); | |
290 if (event->type() != ui::ET_KEY_PRESSED) | |
291 return; | |
292 | |
293 if (event->key_code() == ui::VKEY_ESCAPE) | |
294 CancelSelection(); | |
295 } | |
296 | |
297 void WindowSelector::OnMouseEvent(ui::MouseEvent* event) { | |
298 aura::Window* target = GetEventTarget(event); | |
299 if (!target) | |
300 return; | |
301 | |
302 event->SetHandled(); | |
303 if (event->type() != ui::ET_MOUSE_RELEASED) | |
304 return; | |
305 | |
306 SelectWindow(target); | |
307 } | |
308 | |
309 void WindowSelector::OnScrollEvent(ui::ScrollEvent* event) { | |
310 // Set the handled flag to prevent delivering scroll events to the window but | |
311 // still allowing other pretarget handlers to process the scroll event. | |
312 if (GetTargetedWindow(static_cast<aura::Window*>(event->target()))) | |
313 event->SetHandled(); | |
314 } | |
315 | |
316 void WindowSelector::OnTouchEvent(ui::TouchEvent* event) { | |
317 // Existing touches should be allowed to continue. This prevents getting | |
318 // stuck in a gesture or with pressed fingers being tracked elsewhere. | |
319 if (event->type() != ui::ET_TOUCH_PRESSED) | |
320 return; | |
321 | |
322 aura::Window* target = GetEventTarget(event); | |
323 if (!target) | |
324 return; | |
325 | |
326 // TODO(flackr): StopPropogation prevents generation of gesture events. | |
327 // We should find a better way to prevent events from being delivered to | |
328 // the window, perhaps a transparent window in front of the target window | |
329 // or using EventClientImpl::CanProcessEventsWithinSubtree and then a tap | |
330 // gesture could be used to activate the window. | |
331 event->SetHandled(); | |
332 SelectWindow(target); | |
333 } | |
334 | |
335 void WindowSelector::OnDisplayBoundsChanged(const gfx::Display& display) { | |
336 PositionWindows(/* animate */ false); | |
337 } | |
338 | |
339 void WindowSelector::OnDisplayAdded(const gfx::Display& display) { | |
340 } | |
341 | |
342 void WindowSelector::OnDisplayRemoved(const gfx::Display& display) { | |
343 } | |
344 | |
178 void WindowSelector::OnWindowAdded(aura::Window* new_window) { | 345 void WindowSelector::OnWindowAdded(aura::Window* new_window) { |
179 if (new_window->type() != ui::wm::WINDOW_TYPE_NORMAL && | 346 if (new_window->type() != ui::wm::WINDOW_TYPE_NORMAL && |
180 new_window->type() != ui::wm::WINDOW_TYPE_PANEL) { | 347 new_window->type() != ui::wm::WINDOW_TYPE_PANEL) { |
181 return; | 348 return; |
182 } | 349 } |
183 | 350 |
184 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | 351 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
185 if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && | 352 if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && |
186 !::wm::GetTransientParent(new_window)) { | 353 !::wm::GetTransientParent(new_window)) { |
187 // The new window is in one of the switchable containers, abort overview. | 354 // The new window is in one of the switchable containers, abort overview. |
(...skipping 20 matching lines...) Expand all Loading... | |
208 // If there are still windows in this selector entry then the overview is | 375 // If there are still windows in this selector entry then the overview is |
209 // still active and the active selection remains the same. | 376 // still active and the active selection remains the same. |
210 if (!(*iter)->empty()) | 377 if (!(*iter)->empty()) |
211 return; | 378 return; |
212 | 379 |
213 windows_.erase(iter); | 380 windows_.erase(iter); |
214 if (windows_.empty()) { | 381 if (windows_.empty()) { |
215 CancelSelection(); | 382 CancelSelection(); |
216 return; | 383 return; |
217 } | 384 } |
218 if (window_overview_) | 385 PositionWindows(true); |
219 window_overview_->OnWindowsChanged(); | |
220 } | 386 } |
221 | 387 |
222 void WindowSelector::OnWindowBoundsChanged(aura::Window* window, | 388 void WindowSelector::OnWindowBoundsChanged(aura::Window* window, |
223 const gfx::Rect& old_bounds, | 389 const gfx::Rect& old_bounds, |
224 const gfx::Rect& new_bounds) { | 390 const gfx::Rect& new_bounds) { |
225 if (!window_overview_) | |
226 return; | |
227 | |
228 ScopedVector<WindowSelectorItem>::iterator iter = | 391 ScopedVector<WindowSelectorItem>::iterator iter = |
229 std::find_if(windows_.begin(), windows_.end(), | 392 std::find_if(windows_.begin(), windows_.end(), |
230 WindowSelectorItemTargetComparator(window)); | 393 WindowSelectorItemTargetComparator(window)); |
231 if (iter == windows_.end()) | 394 if (iter == windows_.end()) |
232 return; | 395 return; |
233 | 396 |
234 // Immediately finish any active bounds animation. | 397 // Immediately finish any active bounds animation. |
235 window->layer()->GetAnimator()->StopAnimatingProperty( | 398 window->layer()->GetAnimator()->StopAnimatingProperty( |
236 ui::LayerAnimationElement::BOUNDS); | 399 ui::LayerAnimationElement::BOUNDS); |
237 | 400 |
(...skipping 13 matching lines...) Expand all Loading... | |
251 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, | 414 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, |
252 aura::Window* actual_active) { | 415 aura::Window* actual_active) { |
253 if (ignore_activations_) | 416 if (ignore_activations_) |
254 return; | 417 return; |
255 // Don't restore focus on exit if a window was just activated. | 418 // Don't restore focus on exit if a window was just activated. |
256 ResetFocusRestoreWindow(false); | 419 ResetFocusRestoreWindow(false); |
257 CancelSelection(); | 420 CancelSelection(); |
258 } | 421 } |
259 | 422 |
260 void WindowSelector::StartOverview() { | 423 void WindowSelector::StartOverview() { |
261 DCHECK(!window_overview_); | |
262 // Remove focus from active window before entering overview. | 424 // Remove focus from active window before entering overview. |
263 aura::client::GetFocusClient( | 425 aura::client::GetFocusClient( |
264 Shell::GetPrimaryRootWindow())->FocusWindow(NULL); | 426 Shell::GetPrimaryRootWindow())->FocusWindow(NULL); |
265 | 427 |
266 window_overview_.reset(new WindowOverview(this, &windows_)); | 428 Shell* shell = Shell::GetInstance(); |
429 shell->OnOverviewModeStarting(); | |
430 | |
431 for (WindowSelectorItemList::iterator iter = windows_.begin(); | |
432 iter != windows_.end(); ++iter) { | |
433 (*iter)->PrepareForOverview(); | |
434 } | |
435 PositionWindows(/* animate */ true); | |
436 DCHECK(!windows_.empty()); | |
437 cursor_client_ = aura::client::GetCursorClient( | |
438 windows_.front()->GetRootWindow()); | |
439 if (cursor_client_) { | |
440 cursor_client_->SetCursor(ui::kCursorPointer); | |
441 cursor_client_->ShowCursor(); | |
442 // TODO(flackr): Only prevent cursor changes for windows in the overview. | |
443 // This will be easier to do without exposing the overview mode code if the | |
444 // cursor changes are moved to ToplevelWindowEventHandler::HandleMouseMoved | |
445 // as suggested there. | |
446 cursor_client_->LockCursor(); | |
447 } | |
448 shell->PrependPreTargetHandler(this); | |
449 shell->GetScreen()->AddObserver(this); | |
450 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); | |
451 HideAndTrackNonOverviewWindows(); | |
452 // Send an a11y alert. | |
453 shell->accessibility_delegate()->TriggerAccessibilityAlert( | |
454 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); | |
455 | |
267 UpdateShelfVisibility(); | 456 UpdateShelfVisibility(); |
268 } | 457 } |
269 | 458 |
459 void WindowSelector::PositionWindows(bool animate) { | |
460 aura::Window::Windows root_window_list = Shell::GetAllRootWindows(); | |
461 for (size_t i = 0; i < root_window_list.size(); ++i) | |
462 PositionWindowsFromRoot(root_window_list[i], animate); | |
463 } | |
464 | |
465 void WindowSelector::PositionWindowsFromRoot(aura::Window* root_window, | |
466 bool animate) { | |
467 std::vector<WindowSelectorItem*> windows; | |
468 for (WindowSelectorItemList::iterator iter = windows_.begin(); | |
469 iter != windows_.end(); ++iter) { | |
470 if ((*iter)->GetRootWindow() == root_window) | |
471 windows.push_back(*iter); | |
472 } | |
473 | |
474 if (windows.empty()) | |
475 return; | |
476 | |
477 gfx::Size window_size; | |
478 gfx::Rect total_bounds = ScreenUtil::ConvertRectToScreen( | |
479 root_window, | |
480 ScreenUtil::GetDisplayWorkAreaBoundsInParent( | |
481 Shell::GetContainer(root_window, kShellWindowId_DefaultContainer))); | |
482 | |
483 // Find the minimum number of windows per row that will fit all of the | |
484 // windows on screen. | |
485 size_t columns = std::max( | |
486 total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1, | |
487 static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() / | |
488 (kCardAspectRatio * total_bounds.height()))))); | |
489 size_t rows = ((windows.size() + columns - 1) / columns); | |
490 window_size.set_width(std::min( | |
491 static_cast<int>(total_bounds.width() / columns), | |
492 static_cast<int>(total_bounds.height() * kCardAspectRatio / rows))); | |
493 window_size.set_height(window_size.width() / kCardAspectRatio); | |
494 | |
495 // Calculate the X and Y offsets necessary to center the grid. | |
496 int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 : | |
497 (columns - windows.size()) * window_size.width()) + | |
498 (total_bounds.width() - columns * window_size.width())) / 2; | |
499 int y_offset = total_bounds.y() + (total_bounds.height() - | |
500 rows * window_size.height()) / 2; | |
501 for (size_t i = 0; i < windows.size(); ++i) { | |
502 gfx::Transform transform; | |
503 int column = i % columns; | |
504 int row = i / columns; | |
505 gfx::Rect target_bounds(window_size.width() * column + x_offset, | |
506 window_size.height() * row + y_offset, | |
507 window_size.width(), | |
508 window_size.height()); | |
509 target_bounds.Inset(kWindowMargin, kWindowMargin); | |
510 windows[i]->SetBounds(root_window, target_bounds, animate); | |
511 } | |
512 } | |
513 | |
514 void WindowSelector::HideAndTrackNonOverviewWindows() { | |
515 // Add the windows to hidden_windows first so that if any are destroyed | |
516 // while hiding them they are tracked. | |
517 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | |
518 for (aura::Window::Windows::const_iterator root_iter = root_windows.begin(); | |
519 root_iter != root_windows.end(); ++root_iter) { | |
520 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | |
521 aura::Window* container = Shell::GetContainer(*root_iter, | |
522 kSwitchableWindowContainerIds[i]); | |
523 for (aura::Window::Windows::const_iterator iter = | |
524 container->children().begin(); iter != container->children().end(); | |
525 ++iter) { | |
526 if (GetTargetedWindow(*iter) || !(*iter)->IsVisible()) | |
527 continue; | |
528 hidden_windows_.Add(*iter); | |
529 } | |
530 } | |
531 } | |
532 | |
533 // Copy the window list as it can change during iteration. | |
534 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); | |
535 for (aura::WindowTracker::Windows::const_iterator iter = | |
536 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { | |
537 if (!hidden_windows_.Contains(*iter)) | |
538 continue; | |
539 ui::ScopedLayerAnimationSettings settings( | |
540 (*iter)->layer()->GetAnimator()); | |
541 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( | |
542 ScopedTransformOverviewWindow::kTransitionMilliseconds)); | |
543 settings.SetPreemptionStrategy( | |
544 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
545 (*iter)->Hide(); | |
546 // Hiding the window can result in it being destroyed. | |
547 if (!hidden_windows_.Contains(*iter)) | |
548 continue; | |
549 (*iter)->layer()->SetOpacity(0); | |
550 } | |
551 } | |
552 | |
270 void WindowSelector::ResetFocusRestoreWindow(bool focus) { | 553 void WindowSelector::ResetFocusRestoreWindow(bool focus) { |
271 if (!restore_focus_window_) | 554 if (!restore_focus_window_) |
272 return; | 555 return; |
273 if (focus) { | 556 if (focus) { |
274 base::AutoReset<bool> restoring_focus(&ignore_activations_, true); | 557 base::AutoReset<bool> restoring_focus(&ignore_activations_, true); |
275 restore_focus_window_->Focus(); | 558 restore_focus_window_->Focus(); |
276 } | 559 } |
277 // If the window is in the observed_windows_ list it needs to continue to be | 560 // If the window is in the observed_windows_ list it needs to continue to be |
278 // observed. | 561 // observed. |
279 if (observed_windows_.find(restore_focus_window_) == | 562 if (observed_windows_.find(restore_focus_window_) == |
280 observed_windows_.end()) { | 563 observed_windows_.end()) { |
281 restore_focus_window_->RemoveObserver(this); | 564 restore_focus_window_->RemoveObserver(this); |
282 } | 565 } |
283 restore_focus_window_ = NULL; | 566 restore_focus_window_ = NULL; |
284 } | 567 } |
285 | 568 |
569 aura::Window* WindowSelector::GetEventTarget(ui::LocatedEvent* event) { | |
570 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
571 // If the target window doesn't actually contain the event location (i.e. | |
572 // mouse down over the window and mouse up elsewhere) then do not select the | |
573 // window. | |
574 if (!target->ContainsPoint(event->location())) | |
575 return NULL; | |
576 | |
577 return GetTargetedWindow(target); | |
578 } | |
579 | |
580 aura::Window* WindowSelector::GetTargetedWindow(aura::Window* window) { | |
581 for (WindowSelectorItemList::iterator iter = windows_.begin(); | |
582 iter != windows_.end(); ++iter) { | |
583 aura::Window* selected = (*iter)->TargetedWindow(window); | |
584 if (selected) | |
585 return selected; | |
586 } | |
587 return NULL; | |
588 } | |
589 | |
286 } // namespace ash | 590 } // namespace ash |
OLD | NEW |