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