| 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 #include <functional> | 8 #include <functional> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "ash/accessibility_delegate.h" | 12 #include "ash/accessibility_delegate.h" |
| 13 #include "ash/ash_switches.h" | 13 #include "ash/ash_switches.h" |
| 14 #include "ash/metrics/user_metrics_recorder.h" | 14 #include "ash/metrics/user_metrics_recorder.h" |
| 15 #include "ash/root_window_controller.h" | 15 #include "ash/root_window_controller.h" |
| 16 #include "ash/shell.h" | 16 #include "ash/shell.h" |
| 17 #include "ash/shell_window_ids.h" | 17 #include "ash/shell_window_ids.h" |
| 18 #include "ash/switchable_windows.h" | 18 #include "ash/switchable_windows.h" |
| 19 #include "ash/wm/overview/scoped_overview_animation_settings.h" | |
| 20 #include "ash/wm/overview/scoped_transform_overview_window.h" | |
| 21 #include "ash/wm/overview/window_grid.h" | 19 #include "ash/wm/overview/window_grid.h" |
| 22 #include "ash/wm/overview/window_selector_delegate.h" | 20 #include "ash/wm/overview/window_selector_delegate.h" |
| 23 #include "ash/wm/overview/window_selector_item.h" | 21 #include "ash/wm/overview/window_selector_item.h" |
| 24 #include "ash/wm/panels/panel_layout_manager.h" | 22 #include "ash/wm/panels/panel_layout_manager.h" |
| 25 #include "ash/wm/window_state.h" | 23 #include "ash/wm/window_state.h" |
| 26 #include "base/auto_reset.h" | 24 #include "base/auto_reset.h" |
| 27 #include "base/command_line.h" | 25 #include "base/command_line.h" |
| 28 #include "base/metrics/histogram.h" | 26 #include "base/metrics/histogram.h" |
| 29 #include "third_party/skia/include/core/SkPaint.h" | 27 #include "third_party/skia/include/core/SkPaint.h" |
| 30 #include "third_party/skia/include/core/SkPath.h" | 28 #include "third_party/skia/include/core/SkPath.h" |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 textfield->RequestFocus(); | 209 textfield->RequestFocus(); |
| 212 | 210 |
| 213 return widget; | 211 return widget; |
| 214 } | 212 } |
| 215 | 213 |
| 216 } // namespace | 214 } // namespace |
| 217 | 215 |
| 218 const int WindowSelector::kTextFilterBottomEdge = | 216 const int WindowSelector::kTextFilterBottomEdge = |
| 219 kTextFilterDistanceFromTop + kTextFilterHeight; | 217 kTextFilterDistanceFromTop + kTextFilterHeight; |
| 220 | 218 |
| 219 // static |
| 220 bool WindowSelector::IsSelectable(aura::Window* window) { |
| 221 wm::WindowState* state = wm::GetWindowState(window); |
| 222 if (state->GetStateType() == wm::WINDOW_STATE_TYPE_DOCKED || |
| 223 state->GetStateType() == wm::WINDOW_STATE_TYPE_DOCKED_MINIMIZED) { |
| 224 return false; |
| 225 } |
| 226 return window->type() == ui::wm::WINDOW_TYPE_NORMAL || |
| 227 window->type() == ui::wm::WINDOW_TYPE_PANEL; |
| 228 } |
| 229 |
| 221 WindowSelector::WindowSelector(WindowSelectorDelegate* delegate) | 230 WindowSelector::WindowSelector(WindowSelectorDelegate* delegate) |
| 222 : delegate_(delegate), | 231 : delegate_(delegate), |
| 223 restore_focus_window_(aura::client::GetFocusClient( | 232 restore_focus_window_(aura::client::GetFocusClient( |
| 224 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), | 233 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), |
| 225 ignore_activations_(false), | 234 ignore_activations_(false), |
| 226 selected_grid_index_(0), | 235 selected_grid_index_(0), |
| 227 overview_start_time_(base::Time::Now()), | 236 overview_start_time_(base::Time::Now()), |
| 228 num_key_presses_(0), | 237 num_key_presses_(0), |
| 229 num_items_(0), | 238 num_items_(0), |
| 230 showing_selection_widget_(false), | 239 showing_selection_widget_(false), |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 | 304 |
| 296 DCHECK(!grid_list_.empty()); | 305 DCHECK(!grid_list_.empty()); |
| 297 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_); | 306 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_); |
| 298 | 307 |
| 299 Shell* shell = Shell::GetInstance(); | 308 Shell* shell = Shell::GetInstance(); |
| 300 | 309 |
| 301 shell->activation_client()->AddObserver(this); | 310 shell->activation_client()->AddObserver(this); |
| 302 | 311 |
| 303 shell->GetScreen()->AddObserver(this); | 312 shell->GetScreen()->AddObserver(this); |
| 304 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); | 313 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); |
| 305 HideAndTrackNonOverviewWindows(); | |
| 306 // Send an a11y alert. | 314 // Send an a11y alert. |
| 307 shell->accessibility_delegate()->TriggerAccessibilityAlert( | 315 shell->accessibility_delegate()->TriggerAccessibilityAlert( |
| 308 ui::A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); | 316 ui::A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); |
| 309 | 317 |
| 310 UpdateShelfVisibility(); | 318 UpdateShelfVisibility(); |
| 311 } | 319 } |
| 312 | 320 |
| 313 // NOTE: The work done in Shutdown() is not done in the destructor because it | 321 // NOTE: The work done in Shutdown() is not done in the destructor because it |
| 314 // may cause other, unrelated classes, (ie PanelLayoutManager) to make indirect | 322 // may cause other, unrelated classes, (ie PanelLayoutManager) to make indirect |
| 315 // calls to restoring_minimized_windows() on a partially destructed object. | 323 // calls to restoring_minimized_windows() on a partially destructed object. |
| 316 void WindowSelector::Shutdown() { | 324 void WindowSelector::Shutdown() { |
| 317 ResetFocusRestoreWindow(true); | 325 ResetFocusRestoreWindow(true); |
| 318 RemoveAllObservers(); | 326 RemoveAllObservers(); |
| 319 | 327 |
| 320 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 328 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
| 321 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); | 329 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); |
| 322 iter != root_windows.end(); iter++) { | 330 iter != root_windows.end(); iter++) { |
| 323 // Un-hide the callout widgets for panels. It is safe to call this for | 331 // Un-hide the callout widgets for panels. It is safe to call this for |
| 324 // root_windows that don't contain any panel windows. | 332 // root_windows that don't contain any panel windows. |
| 325 static_cast<PanelLayoutManager*>( | 333 static_cast<PanelLayoutManager*>( |
| 326 Shell::GetContainer(*iter, kShellWindowId_PanelContainer) | 334 Shell::GetContainer(*iter, kShellWindowId_PanelContainer) |
| 327 ->layout_manager())->SetShowCalloutWidgets(true); | 335 ->layout_manager())->SetShowCalloutWidgets(true); |
| 328 } | 336 } |
| 329 | 337 |
| 330 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); | |
| 331 for (aura::WindowTracker::Windows::const_iterator iter = | |
| 332 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { | |
| 333 ScopedOverviewAnimationSettings animation_settings( | |
| 334 OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS, | |
| 335 *iter); | |
| 336 (*iter)->layer()->SetOpacity(1); | |
| 337 (*iter)->Show(); | |
| 338 } | |
| 339 | |
| 340 size_t remaining_items = 0; | 338 size_t remaining_items = 0; |
| 341 for (WindowGrid* window_grid : grid_list_) { | 339 for (WindowGrid* window_grid : grid_list_) { |
| 342 for (WindowSelectorItem* window_selector_item : window_grid->window_list()) | 340 for (WindowSelectorItem* window_selector_item : window_grid->window_list()) |
| 343 window_selector_item->RestoreWindow(); | 341 window_selector_item->RestoreWindow(); |
| 344 remaining_items += window_grid->size(); | 342 remaining_items += window_grid->size(); |
| 345 } | 343 } |
| 346 | 344 |
| 347 DCHECK(num_items_ >= remaining_items); | 345 DCHECK(num_items_ >= remaining_items); |
| 348 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems", | 346 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems", |
| 349 num_items_ - remaining_items); | 347 num_items_ - remaining_items); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 // TODO(flackr): Keep window selection active on remaining displays. | 447 // TODO(flackr): Keep window selection active on remaining displays. |
| 450 CancelSelection(); | 448 CancelSelection(); |
| 451 } | 449 } |
| 452 | 450 |
| 453 void WindowSelector::OnDisplayMetricsChanged(const gfx::Display& display, | 451 void WindowSelector::OnDisplayMetricsChanged(const gfx::Display& display, |
| 454 uint32_t metrics) { | 452 uint32_t metrics) { |
| 455 PositionWindows(/* animate */ false); | 453 PositionWindows(/* animate */ false); |
| 456 } | 454 } |
| 457 | 455 |
| 458 void WindowSelector::OnWindowAdded(aura::Window* new_window) { | 456 void WindowSelector::OnWindowAdded(aura::Window* new_window) { |
| 459 if (new_window->type() != ui::wm::WINDOW_TYPE_NORMAL && | 457 if (!IsSelectable(new_window)) |
| 460 new_window->type() != ui::wm::WINDOW_TYPE_PANEL) { | |
| 461 return; | 458 return; |
| 462 } | |
| 463 | 459 |
| 464 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | 460 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
| 465 if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && | 461 if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && |
| 466 !::wm::GetTransientParent(new_window)) { | 462 !::wm::GetTransientParent(new_window)) { |
| 467 // The new window is in one of the switchable containers, abort overview. | 463 // The new window is in one of the switchable containers, abort overview. |
| 468 CancelSelection(); | 464 CancelSelection(); |
| 469 return; | 465 return; |
| 470 } | 466 } |
| 471 } | 467 } |
| 472 } | 468 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 Move(WindowSelector::RIGHT, false); | 545 Move(WindowSelector::RIGHT, false); |
| 550 } | 546 } |
| 551 | 547 |
| 552 void WindowSelector::PositionWindows(bool animate) { | 548 void WindowSelector::PositionWindows(bool animate) { |
| 553 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); | 549 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); |
| 554 iter != grid_list_.end(); iter++) { | 550 iter != grid_list_.end(); iter++) { |
| 555 (*iter)->PositionWindows(animate); | 551 (*iter)->PositionWindows(animate); |
| 556 } | 552 } |
| 557 } | 553 } |
| 558 | 554 |
| 559 void WindowSelector::HideAndTrackNonOverviewWindows() { | |
| 560 // Add the windows to hidden_windows first so that if any are destroyed | |
| 561 // while hiding them they are tracked. | |
| 562 for (ScopedVector<WindowGrid>::iterator grid_iter = grid_list_.begin(); | |
| 563 grid_iter != grid_list_.end(); ++grid_iter) { | |
| 564 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | |
| 565 const aura::Window* container = | |
| 566 Shell::GetContainer((*grid_iter)->root_window(), | |
| 567 kSwitchableWindowContainerIds[i]); | |
| 568 for (aura::Window::Windows::const_iterator iter = | |
| 569 container->children().begin(); iter != container->children().end(); | |
| 570 ++iter) { | |
| 571 if (!(*iter)->IsVisible() || (*grid_iter)->Contains(*iter)) | |
| 572 continue; | |
| 573 hidden_windows_.Add(*iter); | |
| 574 } | |
| 575 } | |
| 576 } | |
| 577 | |
| 578 // Copy the window list as it can change during iteration. | |
| 579 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); | |
| 580 for (aura::WindowTracker::Windows::const_iterator iter = | |
| 581 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { | |
| 582 if (!hidden_windows_.Contains(*iter)) | |
| 583 continue; | |
| 584 ScopedOverviewAnimationSettings animation_settings( | |
| 585 OverviewAnimationType::OVERVIEW_ANIMATION_HIDE_WINDOW, | |
| 586 *iter); | |
| 587 (*iter)->Hide(); | |
| 588 // Hiding the window can result in it being destroyed. | |
| 589 if (!hidden_windows_.Contains(*iter)) | |
| 590 continue; | |
| 591 (*iter)->layer()->SetOpacity(0); | |
| 592 } | |
| 593 } | |
| 594 | |
| 595 void WindowSelector::ResetFocusRestoreWindow(bool focus) { | 555 void WindowSelector::ResetFocusRestoreWindow(bool focus) { |
| 596 if (!restore_focus_window_) | 556 if (!restore_focus_window_) |
| 597 return; | 557 return; |
| 598 if (focus) { | 558 if (focus) { |
| 599 base::AutoReset<bool> restoring_focus(&ignore_activations_, true); | 559 base::AutoReset<bool> restoring_focus(&ignore_activations_, true); |
| 600 restore_focus_window_->Focus(); | 560 restore_focus_window_->Focus(); |
| 601 } | 561 } |
| 602 // If the window is in the observed_windows_ list it needs to continue to be | 562 // If the window is in the observed_windows_ list it needs to continue to be |
| 603 // observed. | 563 // observed. |
| 604 if (observed_windows_.find(restore_focus_window_) == | 564 if (observed_windows_.find(restore_focus_window_) == |
| 605 observed_windows_.end()) { | 565 observed_windows_.end()) { |
| 606 restore_focus_window_->RemoveObserver(this); | 566 restore_focus_window_->RemoveObserver(this); |
| 607 } | 567 } |
| 608 restore_focus_window_ = nullptr; | 568 restore_focus_window_ = nullptr; |
| 609 } | 569 } |
| 610 | 570 |
| 611 void WindowSelector::Move(Direction direction, bool animate) { | 571 void WindowSelector::Move(Direction direction, bool animate) { |
| 612 // Keep calling Move() on the grids until one of them reports no overflow or | 572 // Keep calling Move() on the grids until one of them reports no overflow or |
| 613 // we made a full cycle on all the grids. | 573 // we made a full cycle on all the grids. |
| 614 for (size_t i = 0; | 574 for (size_t i = 0; |
| 615 i <= grid_list_.size() && | 575 i <= grid_list_.size() && |
| 616 grid_list_[selected_grid_index_]->Move(direction, animate); i++) { | 576 grid_list_[selected_grid_index_]->Move(direction, animate); i++) { |
| 617 // TODO(flackr): If there are more than two monitors, move between grids | 577 // TODO(flackr): If there are more than two monitors, move between grids |
| 618 // in the requested direction. | 578 // in the requested direction. |
| 619 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size(); | 579 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size(); |
| 620 } | 580 } |
| 621 } | 581 } |
| 622 | 582 |
| 623 } // namespace ash | 583 } // namespace ash |
| OLD | NEW |