Chromium Code Reviews| 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 | |
| 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 = | |
| 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(); | |
| 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(); | |
| 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. | |
|
tdanderson
2014/05/13 23:25:32
Keep this comment in.
Nina
2014/05/14 13:52:54
Done.
| |
| 263 aura::client::GetFocusClient( | 424 aura::client::GetFocusClient( |
| 264 Shell::GetPrimaryRootWindow())->FocusWindow(NULL); | 425 Shell::GetPrimaryRootWindow())->FocusWindow(NULL); |
| 265 | 426 |
| 266 window_overview_.reset(new WindowOverview(this, &windows_)); | 427 Shell* shell = Shell::GetInstance(); |
| 428 shell->OnOverviewModeStarting(); | |
| 429 | |
| 430 for (WindowSelectorItemList::iterator iter = windows_.begin(); | |
| 431 iter != windows_.end(); ++iter) { | |
| 432 (*iter)->PrepareForOverview(); | |
| 433 } | |
| 434 PositionWindows(/* animate */ true); | |
| 435 DCHECK(!windows_.empty()); | |
| 436 cursor_client_ = aura::client::GetCursorClient( | |
| 437 windows_.front()->GetRootWindow()); | |
| 438 if (cursor_client_) { | |
| 439 cursor_client_->SetCursor(ui::kCursorPointer); | |
| 440 cursor_client_->ShowCursor(); | |
| 441 // TODO(flackr): Only prevent cursor changes for windows in the overview. | |
| 442 // This will be easier to do without exposing the overview mode code if the | |
| 443 // cursor changes are moved to ToplevelWindowEventHandler::HandleMouseMoved | |
| 444 // as suggested there. | |
| 445 cursor_client_->LockCursor(); | |
| 446 } | |
| 447 shell->PrependPreTargetHandler(this); | |
| 448 shell->GetScreen()->AddObserver(this); | |
| 449 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); | |
| 450 HideAndTrackNonOverviewWindows(); | |
| 451 // Send an a11y alert. | |
| 452 shell->accessibility_delegate()->TriggerAccessibilityAlert( | |
| 453 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); | |
| 454 | |
| 267 UpdateShelfVisibility(); | 455 UpdateShelfVisibility(); |
| 268 } | 456 } |
| 269 | 457 |
| 458 void WindowSelector::PositionWindows(bool animate) { | |
| 459 aura::Window::Windows root_window_list = Shell::GetAllRootWindows(); | |
| 460 for (size_t i = 0; i < root_window_list.size(); ++i) | |
| 461 PositionWindowsFromRoot(root_window_list[i], animate); | |
| 462 } | |
| 463 | |
| 464 void WindowSelector::PositionWindowsFromRoot(aura::Window* root_window, | |
| 465 bool animate) { | |
| 466 std::vector<WindowSelectorItem*> windows; | |
| 467 for (WindowSelectorItemList::iterator iter = windows_.begin(); | |
| 468 iter != windows_.end(); ++iter) { | |
| 469 if ((*iter)->GetRootWindow() == root_window) | |
| 470 windows.push_back(*iter); | |
| 471 } | |
| 472 | |
| 473 if (windows.empty()) | |
| 474 return; | |
| 475 | |
| 476 gfx::Size window_size; | |
| 477 gfx::Rect total_bounds = ScreenUtil::ConvertRectToScreen( | |
| 478 root_window, | |
| 479 ScreenUtil::GetDisplayWorkAreaBoundsInParent( | |
| 480 Shell::GetContainer(root_window, kShellWindowId_DefaultContainer))); | |
| 481 | |
| 482 // Find the minimum number of windows per row that will fit all of the | |
| 483 // windows on screen. | |
| 484 size_t columns = std::max( | |
| 485 total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1, | |
| 486 static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() / | |
| 487 (kCardAspectRatio * total_bounds.height()))))); | |
| 488 size_t rows = ((windows.size() + columns - 1) / columns); | |
| 489 window_size.set_width(std::min( | |
| 490 static_cast<int>(total_bounds.width() / columns), | |
| 491 static_cast<int>(total_bounds.height() * kCardAspectRatio / rows))); | |
| 492 window_size.set_height(window_size.width() / kCardAspectRatio); | |
| 493 | |
| 494 // Calculate the X and Y offsets necessary to center the grid. | |
| 495 int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 : | |
| 496 (columns - windows.size()) * window_size.width()) + | |
| 497 (total_bounds.width() - columns * window_size.width())) / 2; | |
| 498 int y_offset = total_bounds.y() + (total_bounds.height() - | |
| 499 rows * window_size.height()) / 2; | |
| 500 for (size_t i = 0; i < windows.size(); ++i) { | |
| 501 gfx::Transform transform; | |
| 502 int column = i % columns; | |
| 503 int row = i / columns; | |
| 504 gfx::Rect target_bounds(window_size.width() * column + x_offset, | |
| 505 window_size.height() * row + y_offset, | |
| 506 window_size.width(), | |
| 507 window_size.height()); | |
| 508 target_bounds.Inset(kWindowMargin, kWindowMargin); | |
| 509 windows[i]->SetBounds(root_window, target_bounds, animate); | |
| 510 } | |
| 511 } | |
| 512 | |
| 513 void WindowSelector::HideAndTrackNonOverviewWindows() { | |
| 514 // Add the windows to hidden_windows first so that if any are destroyed | |
| 515 // while hiding them they are tracked. | |
| 516 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | |
| 517 for (aura::Window::Windows::const_iterator root_iter = root_windows.begin(); | |
| 518 root_iter != root_windows.end(); ++root_iter) { | |
| 519 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | |
| 520 aura::Window* container = Shell::GetContainer(*root_iter, | |
| 521 kSwitchableWindowContainerIds[i]); | |
| 522 for (aura::Window::Windows::const_iterator iter = | |
| 523 container->children().begin(); iter != container->children().end(); | |
| 524 ++iter) { | |
| 525 if (GetTargetedWindow(*iter) || !(*iter)->IsVisible()) | |
| 526 continue; | |
| 527 hidden_windows_.Add(*iter); | |
| 528 } | |
| 529 } | |
| 530 } | |
| 531 | |
| 532 // Copy the window list as it can change during iteration. | |
| 533 const aura::WindowTracker::Windows hidden_windows(hidden_windows_.windows()); | |
| 534 for (aura::WindowTracker::Windows::const_iterator iter = | |
| 535 hidden_windows.begin(); iter != hidden_windows.end(); ++iter) { | |
| 536 if (!hidden_windows_.Contains(*iter)) | |
| 537 continue; | |
| 538 ui::ScopedLayerAnimationSettings settings( | |
| 539 (*iter)->layer()->GetAnimator()); | |
| 540 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( | |
| 541 ScopedTransformOverviewWindow::kTransitionMilliseconds)); | |
| 542 settings.SetPreemptionStrategy( | |
| 543 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
| 544 (*iter)->Hide(); | |
| 545 // Hiding the window can result in it being destroyed. | |
| 546 if (!hidden_windows_.Contains(*iter)) | |
| 547 continue; | |
| 548 (*iter)->layer()->SetOpacity(0); | |
| 549 } | |
| 550 } | |
| 551 | |
| 270 void WindowSelector::ResetFocusRestoreWindow(bool focus) { | 552 void WindowSelector::ResetFocusRestoreWindow(bool focus) { |
| 271 if (!restore_focus_window_) | 553 if (!restore_focus_window_) |
| 272 return; | 554 return; |
| 273 if (focus) { | 555 if (focus) { |
| 274 base::AutoReset<bool> restoring_focus(&ignore_activations_, true); | 556 base::AutoReset<bool> restoring_focus(&ignore_activations_, true); |
| 275 restore_focus_window_->Focus(); | 557 restore_focus_window_->Focus(); |
| 276 } | 558 } |
| 277 // If the window is in the observed_windows_ list it needs to continue to be | 559 // If the window is in the observed_windows_ list it needs to continue to be |
| 278 // observed. | 560 // observed. |
| 279 if (observed_windows_.find(restore_focus_window_) == | 561 if (observed_windows_.find(restore_focus_window_) == |
| 280 observed_windows_.end()) { | 562 observed_windows_.end()) { |
| 281 restore_focus_window_->RemoveObserver(this); | 563 restore_focus_window_->RemoveObserver(this); |
| 282 } | 564 } |
| 283 restore_focus_window_ = NULL; | 565 restore_focus_window_ = NULL; |
| 284 } | 566 } |
| 285 | 567 |
| 568 aura::Window* WindowSelector::GetEventTarget(ui::LocatedEvent* event) { | |
| 569 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
| 570 // If the target window doesn't actually contain the event location (i.e. | |
| 571 // mouse down over the window and mouse up elsewhere) then do not select the | |
| 572 // window. | |
| 573 if (!target->ContainsPoint(event->location())) | |
| 574 return NULL; | |
| 575 | |
| 576 return GetTargetedWindow(target); | |
| 577 } | |
| 578 | |
| 579 aura::Window* WindowSelector::GetTargetedWindow(aura::Window* window) { | |
| 580 for (WindowSelectorItemList::iterator iter = windows_.begin(); | |
| 581 iter != windows_.end(); ++iter) { | |
| 582 aura::Window* selected = (*iter)->TargetedWindow(window); | |
| 583 if (selected) | |
| 584 return selected; | |
| 585 } | |
| 586 return NULL; | |
| 587 } | |
| 588 | |
| 286 } // namespace ash | 589 } // namespace ash |
| OLD | NEW |