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 |
46 // A comparator for locating a selectable window given a targeted window. | 132 // A comparator for locating a selectable window given a targeted window. |
47 struct WindowSelectorItemTargetComparator | 133 struct WindowSelectorItemTargetComparator |
48 : public std::unary_function<WindowSelectorItem*, bool> { | 134 : public std::unary_function<WindowSelectorItem*, bool> { |
49 explicit WindowSelectorItemTargetComparator(const aura::Window* target_window) | 135 explicit WindowSelectorItemTargetComparator(const aura::Window* target_window) |
50 : target(target_window) { | 136 : target(target_window) { |
51 } | 137 } |
52 | 138 |
53 bool operator()(WindowSelectorItem* window) const { | 139 bool operator()(WindowSelectorItem* window) const { |
54 return window->TargetedWindow(target) != NULL; | 140 return window->TargetedWindow(target) != NULL; |
55 } | 141 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 kSwitchableWindowContainerIds[i]); | 225 kSwitchableWindowContainerIds[i]); |
140 container->AddObserver(this); | 226 container->AddObserver(this); |
141 observed_windows_.insert(container); | 227 observed_windows_.insert(container); |
142 } | 228 } |
143 } | 229 } |
144 | 230 |
145 StartOverview(); | 231 StartOverview(); |
146 } | 232 } |
147 | 233 |
148 WindowSelector::~WindowSelector() { | 234 WindowSelector::~WindowSelector() { |
| 235 ash::Shell* shell = ash::Shell::GetInstance(); |
| 236 |
149 ResetFocusRestoreWindow(true); | 237 ResetFocusRestoreWindow(true); |
150 for (std::set<aura::Window*>::iterator iter = observed_windows_.begin(); | 238 for (std::set<aura::Window*>::iterator iter = observed_windows_.begin(); |
151 iter != observed_windows_.end(); ++iter) { | 239 iter != observed_windows_.end(); ++iter) { |
152 (*iter)->RemoveObserver(this); | 240 (*iter)->RemoveObserver(this); |
153 } | 241 } |
154 Shell::GetInstance()->activation_client()->RemoveObserver(this); | 242 shell->activation_client()->RemoveObserver(this); |
155 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 243 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
156 window_overview_.reset(); | 244 |
| 245 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); |
| 246 for (aura::WindowTracker::Windows::const_iterator iter = |
| 247 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { |
| 248 ui::ScopedLayerAnimationSettings settings( |
| 249 (*iter)->layer()->GetAnimator()); |
| 250 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( |
| 251 ScopedTransformOverviewWindow::kTransitionMilliseconds)); |
| 252 settings.SetPreemptionStrategy( |
| 253 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| 254 (*iter)->layer()->SetOpacity(1); |
| 255 (*iter)->Show(); |
| 256 } |
| 257 |
| 258 if (cursor_client_) |
| 259 cursor_client_->UnlockCursor(); |
| 260 shell->RemovePreTargetHandler(this); |
| 261 shell->GetScreen()->RemoveObserver(this); |
| 262 UMA_HISTOGRAM_MEDIUM_TIMES( |
| 263 "Ash.WindowSelector.TimeInOverview", |
| 264 base::Time::Now() - overview_start_time_); |
| 265 |
| 266 // TODO(nsatragno): Change this to OnOverviewModeEnded and move it to when |
| 267 // everything is done. |
| 268 shell->OnOverviewModeEnding(); |
| 269 |
157 // Clearing the window list resets the ignored_by_shelf flag on the windows. | 270 // Clearing the window list resets the ignored_by_shelf flag on the windows. |
158 windows_.clear(); | 271 windows_.clear(); |
159 UpdateShelfVisibility(); | 272 UpdateShelfVisibility(); |
160 } | 273 } |
161 | 274 |
162 void WindowSelector::SelectWindow(aura::Window* window) { | 275 void WindowSelector::SelectWindow(aura::Window* window) { |
163 ResetFocusRestoreWindow(false); | 276 ResetFocusRestoreWindow(false); |
164 ScopedVector<WindowSelectorItem>::iterator iter = | 277 ScopedVector<WindowSelectorItem>::iterator iter = |
165 std::find_if(windows_.begin(), windows_.end(), | 278 std::find_if(windows_.begin(), windows_.end(), |
166 WindowSelectorItemTargetComparator(window)); | 279 WindowSelectorItemTargetComparator(window)); |
167 DCHECK(iter != windows_.end()); | 280 DCHECK(iter != windows_.end()); |
168 // The selected window should not be minimized when window selection is | 281 // The selected window should not be minimized when window selection is |
169 // ended. | 282 // ended. |
170 (*iter)->RestoreWindowOnExit(window); | 283 (*iter)->RestoreWindowOnExit(window); |
171 delegate_->OnWindowSelected(window); | 284 delegate_->OnWindowSelected(window); |
172 } | 285 } |
173 | 286 |
174 void WindowSelector::CancelSelection() { | 287 void WindowSelector::CancelSelection() { |
175 delegate_->OnSelectionCanceled(); | 288 delegate_->OnSelectionCanceled(); |
176 } | 289 } |
177 | 290 |
| 291 void WindowSelector::OnKeyEvent(ui::KeyEvent* event) { |
| 292 if (GetTargetedWindow(static_cast<aura::Window*>(event->target()))) |
| 293 event->StopPropagation(); |
| 294 if (event->type() != ui::ET_KEY_PRESSED) |
| 295 return; |
| 296 |
| 297 if (event->key_code() == ui::VKEY_ESCAPE) |
| 298 CancelSelection(); |
| 299 } |
| 300 |
| 301 void WindowSelector::OnMouseEvent(ui::MouseEvent* event) { |
| 302 aura::Window* target = GetEventTarget(event); |
| 303 if (!target) |
| 304 return; |
| 305 |
| 306 event->SetHandled(); |
| 307 if (event->type() != ui::ET_MOUSE_RELEASED) |
| 308 return; |
| 309 |
| 310 SelectWindow(target); |
| 311 } |
| 312 |
| 313 void WindowSelector::OnScrollEvent(ui::ScrollEvent* event) { |
| 314 // Set the handled flag to prevent delivering scroll events to the window but |
| 315 // still allowing other pretarget handlers to process the scroll event. |
| 316 if (GetTargetedWindow(static_cast<aura::Window*>(event->target()))) |
| 317 event->SetHandled(); |
| 318 } |
| 319 |
| 320 void WindowSelector::OnTouchEvent(ui::TouchEvent* event) { |
| 321 // Existing touches should be allowed to continue. This prevents getting |
| 322 // stuck in a gesture or with pressed fingers being tracked elsewhere. |
| 323 if (event->type() != ui::ET_TOUCH_PRESSED) |
| 324 return; |
| 325 |
| 326 aura::Window* target = GetEventTarget(event); |
| 327 if (!target) |
| 328 return; |
| 329 |
| 330 // TODO(flackr): StopPropogation prevents generation of gesture events. |
| 331 // We should find a better way to prevent events from being delivered to |
| 332 // the window, perhaps a transparent window in front of the target window |
| 333 // or using EventClientImpl::CanProcessEventsWithinSubtree and then a tap |
| 334 // gesture could be used to activate the window. |
| 335 event->SetHandled(); |
| 336 SelectWindow(target); |
| 337 } |
| 338 |
| 339 void WindowSelector::OnDisplayBoundsChanged(const gfx::Display& display) { |
| 340 PositionWindows(/* animate */ false); |
| 341 } |
| 342 |
| 343 void WindowSelector::OnDisplayAdded(const gfx::Display& display) { |
| 344 } |
| 345 |
| 346 void WindowSelector::OnDisplayRemoved(const gfx::Display& display) { |
| 347 } |
| 348 |
178 void WindowSelector::OnWindowAdded(aura::Window* new_window) { | 349 void WindowSelector::OnWindowAdded(aura::Window* new_window) { |
179 if (new_window->type() != ui::wm::WINDOW_TYPE_NORMAL && | 350 if (new_window->type() != ui::wm::WINDOW_TYPE_NORMAL && |
180 new_window->type() != ui::wm::WINDOW_TYPE_PANEL) { | 351 new_window->type() != ui::wm::WINDOW_TYPE_PANEL) { |
181 return; | 352 return; |
182 } | 353 } |
183 | 354 |
184 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | 355 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
185 if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && | 356 if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && |
186 !::wm::GetTransientParent(new_window)) { | 357 !::wm::GetTransientParent(new_window)) { |
187 // The new window is in one of the switchable containers, abort overview. | 358 // 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 | 379 // If there are still windows in this selector entry then the overview is |
209 // still active and the active selection remains the same. | 380 // still active and the active selection remains the same. |
210 if (!(*iter)->empty()) | 381 if (!(*iter)->empty()) |
211 return; | 382 return; |
212 | 383 |
213 windows_.erase(iter); | 384 windows_.erase(iter); |
214 if (windows_.empty()) { | 385 if (windows_.empty()) { |
215 CancelSelection(); | 386 CancelSelection(); |
216 return; | 387 return; |
217 } | 388 } |
218 if (window_overview_) | 389 PositionWindows(true); |
219 window_overview_->OnWindowsChanged(); | |
220 } | 390 } |
221 | 391 |
222 void WindowSelector::OnWindowBoundsChanged(aura::Window* window, | 392 void WindowSelector::OnWindowBoundsChanged(aura::Window* window, |
223 const gfx::Rect& old_bounds, | 393 const gfx::Rect& old_bounds, |
224 const gfx::Rect& new_bounds) { | 394 const gfx::Rect& new_bounds) { |
225 if (!window_overview_) | |
226 return; | |
227 | |
228 ScopedVector<WindowSelectorItem>::iterator iter = | 395 ScopedVector<WindowSelectorItem>::iterator iter = |
229 std::find_if(windows_.begin(), windows_.end(), | 396 std::find_if(windows_.begin(), windows_.end(), |
230 WindowSelectorItemTargetComparator(window)); | 397 WindowSelectorItemTargetComparator(window)); |
231 if (iter == windows_.end()) | 398 if (iter == windows_.end()) |
232 return; | 399 return; |
233 | 400 |
234 // Immediately finish any active bounds animation. | 401 // Immediately finish any active bounds animation. |
235 window->layer()->GetAnimator()->StopAnimatingProperty( | 402 window->layer()->GetAnimator()->StopAnimatingProperty( |
236 ui::LayerAnimationElement::BOUNDS); | 403 ui::LayerAnimationElement::BOUNDS); |
237 | 404 |
(...skipping 13 matching lines...) Expand all Loading... |
251 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, | 418 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, |
252 aura::Window* actual_active) { | 419 aura::Window* actual_active) { |
253 if (ignore_activations_) | 420 if (ignore_activations_) |
254 return; | 421 return; |
255 // Don't restore focus on exit if a window was just activated. | 422 // Don't restore focus on exit if a window was just activated. |
256 ResetFocusRestoreWindow(false); | 423 ResetFocusRestoreWindow(false); |
257 CancelSelection(); | 424 CancelSelection(); |
258 } | 425 } |
259 | 426 |
260 void WindowSelector::StartOverview() { | 427 void WindowSelector::StartOverview() { |
261 DCHECK(!window_overview_); | |
262 // Remove focus from active window before entering overview. | 428 // Remove focus from active window before entering overview. |
263 aura::client::GetFocusClient( | 429 aura::client::GetFocusClient( |
264 Shell::GetPrimaryRootWindow())->FocusWindow(NULL); | 430 Shell::GetPrimaryRootWindow())->FocusWindow(NULL); |
265 | 431 |
266 window_overview_.reset(new WindowOverview(this, &windows_)); | 432 Shell* shell = Shell::GetInstance(); |
| 433 shell->OnOverviewModeStarting(); |
| 434 |
| 435 for (WindowSelectorItemList::iterator iter = windows_.begin(); |
| 436 iter != windows_.end(); ++iter) { |
| 437 (*iter)->PrepareForOverview(); |
| 438 } |
| 439 PositionWindows(/* animate */ true); |
| 440 DCHECK(!windows_.empty()); |
| 441 cursor_client_ = aura::client::GetCursorClient( |
| 442 windows_.front()->GetRootWindow()); |
| 443 if (cursor_client_) { |
| 444 cursor_client_->SetCursor(ui::kCursorPointer); |
| 445 cursor_client_->ShowCursor(); |
| 446 // TODO(flackr): Only prevent cursor changes for windows in the overview. |
| 447 // This will be easier to do without exposing the overview mode code if the |
| 448 // cursor changes are moved to ToplevelWindowEventHandler::HandleMouseMoved |
| 449 // as suggested there. |
| 450 cursor_client_->LockCursor(); |
| 451 } |
| 452 shell->PrependPreTargetHandler(this); |
| 453 shell->GetScreen()->AddObserver(this); |
| 454 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); |
| 455 HideAndTrackNonOverviewWindows(); |
| 456 // Send an a11y alert. |
| 457 shell->accessibility_delegate()->TriggerAccessibilityAlert( |
| 458 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); |
| 459 |
267 UpdateShelfVisibility(); | 460 UpdateShelfVisibility(); |
268 } | 461 } |
269 | 462 |
| 463 void WindowSelector::PositionWindows(bool animate) { |
| 464 aura::Window::Windows root_window_list = Shell::GetAllRootWindows(); |
| 465 for (size_t i = 0; i < root_window_list.size(); ++i) |
| 466 PositionWindowsFromRoot(root_window_list[i], animate); |
| 467 } |
| 468 |
| 469 void WindowSelector::PositionWindowsFromRoot(aura::Window* root_window, |
| 470 bool animate) { |
| 471 std::vector<WindowSelectorItem*> windows; |
| 472 for (WindowSelectorItemList::iterator iter = windows_.begin(); |
| 473 iter != windows_.end(); ++iter) { |
| 474 if ((*iter)->GetRootWindow() == root_window) |
| 475 windows.push_back(*iter); |
| 476 } |
| 477 |
| 478 if (windows.empty()) |
| 479 return; |
| 480 |
| 481 gfx::Size window_size; |
| 482 gfx::Rect total_bounds = ScreenUtil::ConvertRectToScreen( |
| 483 root_window, |
| 484 ScreenUtil::GetDisplayWorkAreaBoundsInParent( |
| 485 Shell::GetContainer(root_window, kShellWindowId_DefaultContainer))); |
| 486 |
| 487 // Find the minimum number of windows per row that will fit all of the |
| 488 // windows on screen. |
| 489 size_t columns = std::max( |
| 490 total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1, |
| 491 static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() / |
| 492 (kCardAspectRatio * total_bounds.height()))))); |
| 493 size_t rows = ((windows.size() + columns - 1) / columns); |
| 494 window_size.set_width(std::min( |
| 495 static_cast<int>(total_bounds.width() / columns), |
| 496 static_cast<int>(total_bounds.height() * kCardAspectRatio / rows))); |
| 497 window_size.set_height(window_size.width() / kCardAspectRatio); |
| 498 |
| 499 // Calculate the X and Y offsets necessary to center the grid. |
| 500 int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 : |
| 501 (columns - windows.size()) * window_size.width()) + |
| 502 (total_bounds.width() - columns * window_size.width())) / 2; |
| 503 int y_offset = total_bounds.y() + (total_bounds.height() - |
| 504 rows * window_size.height()) / 2; |
| 505 for (size_t i = 0; i < windows.size(); ++i) { |
| 506 gfx::Transform transform; |
| 507 int column = i % columns; |
| 508 int row = i / columns; |
| 509 gfx::Rect target_bounds(window_size.width() * column + x_offset, |
| 510 window_size.height() * row + y_offset, |
| 511 window_size.width(), |
| 512 window_size.height()); |
| 513 target_bounds.Inset(kWindowMargin, kWindowMargin); |
| 514 windows[i]->SetBounds(root_window, target_bounds, animate); |
| 515 } |
| 516 } |
| 517 |
| 518 void WindowSelector::HideAndTrackNonOverviewWindows() { |
| 519 // Add the windows to hidden_windows first so that if any are destroyed |
| 520 // while hiding them they are tracked. |
| 521 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
| 522 for (aura::Window::Windows::const_iterator root_iter = root_windows.begin(); |
| 523 root_iter != root_windows.end(); ++root_iter) { |
| 524 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
| 525 aura::Window* container = Shell::GetContainer(*root_iter, |
| 526 kSwitchableWindowContainerIds[i]); |
| 527 for (aura::Window::Windows::const_iterator iter = |
| 528 container->children().begin(); iter != container->children().end(); |
| 529 ++iter) { |
| 530 if (GetTargetedWindow(*iter) || !(*iter)->IsVisible()) |
| 531 continue; |
| 532 hidden_windows_.Add(*iter); |
| 533 } |
| 534 } |
| 535 } |
| 536 |
| 537 // Copy the window list as it can change during iteration. |
| 538 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); |
| 539 for (aura::WindowTracker::Windows::const_iterator iter = |
| 540 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { |
| 541 if (!hidden_windows_.Contains(*iter)) |
| 542 continue; |
| 543 ui::ScopedLayerAnimationSettings settings( |
| 544 (*iter)->layer()->GetAnimator()); |
| 545 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( |
| 546 ScopedTransformOverviewWindow::kTransitionMilliseconds)); |
| 547 settings.SetPreemptionStrategy( |
| 548 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| 549 (*iter)->Hide(); |
| 550 // Hiding the window can result in it being destroyed. |
| 551 if (!hidden_windows_.Contains(*iter)) |
| 552 continue; |
| 553 (*iter)->layer()->SetOpacity(0); |
| 554 } |
| 555 } |
| 556 |
270 void WindowSelector::ResetFocusRestoreWindow(bool focus) { | 557 void WindowSelector::ResetFocusRestoreWindow(bool focus) { |
271 if (!restore_focus_window_) | 558 if (!restore_focus_window_) |
272 return; | 559 return; |
273 if (focus) { | 560 if (focus) { |
274 base::AutoReset<bool> restoring_focus(&ignore_activations_, true); | 561 base::AutoReset<bool> restoring_focus(&ignore_activations_, true); |
275 restore_focus_window_->Focus(); | 562 restore_focus_window_->Focus(); |
276 } | 563 } |
277 // If the window is in the observed_windows_ list it needs to continue to be | 564 // If the window is in the observed_windows_ list it needs to continue to be |
278 // observed. | 565 // observed. |
279 if (observed_windows_.find(restore_focus_window_) == | 566 if (observed_windows_.find(restore_focus_window_) == |
280 observed_windows_.end()) { | 567 observed_windows_.end()) { |
281 restore_focus_window_->RemoveObserver(this); | 568 restore_focus_window_->RemoveObserver(this); |
282 } | 569 } |
283 restore_focus_window_ = NULL; | 570 restore_focus_window_ = NULL; |
284 } | 571 } |
285 | 572 |
| 573 aura::Window* WindowSelector::GetEventTarget(ui::LocatedEvent* event) { |
| 574 aura::Window* target = static_cast<aura::Window*>(event->target()); |
| 575 // If the target window doesn't actually contain the event location (i.e. |
| 576 // mouse down over the window and mouse up elsewhere) then do not select the |
| 577 // window. |
| 578 if (!target->ContainsPoint(event->location())) |
| 579 return NULL; |
| 580 |
| 581 return GetTargetedWindow(target); |
| 582 } |
| 583 |
| 584 aura::Window* WindowSelector::GetTargetedWindow(aura::Window* window) { |
| 585 for (WindowSelectorItemList::iterator iter = windows_.begin(); |
| 586 iter != windows_.end(); ++iter) { |
| 587 aura::Window* selected = (*iter)->TargetedWindow(window); |
| 588 if (selected) |
| 589 return selected; |
| 590 } |
| 591 return NULL; |
| 592 } |
| 593 |
286 } // namespace ash | 594 } // namespace ash |
OLD | NEW |