OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/workspace/workspace_manager.h" | 5 #include "ash/wm/workspace/workspace_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <functional> | 8 #include <functional> |
9 | 9 |
10 #include "ash/ash_switches.h" | 10 #include "ash/ash_switches.h" |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 active_workspace_->window()->Show(); | 124 active_workspace_->window()->Show(); |
125 Shell::GetInstance()->AddShellObserver(this); | 125 Shell::GetInstance()->AddShellObserver(this); |
126 } | 126 } |
127 | 127 |
128 WorkspaceManager::~WorkspaceManager() { | 128 WorkspaceManager::~WorkspaceManager() { |
129 Shell::GetInstance()->RemoveShellObserver(this); | 129 Shell::GetInstance()->RemoveShellObserver(this); |
130 // Release the windows, they'll be destroyed when |contents_view_| is | 130 // Release the windows, they'll be destroyed when |contents_view_| is |
131 // destroyed. | 131 // destroyed. |
132 std::for_each(workspaces_.begin(), workspaces_.end(), | 132 std::for_each(workspaces_.begin(), workspaces_.end(), |
133 std::mem_fun(&Workspace::ReleaseWindow)); | 133 std::mem_fun(&Workspace::ReleaseWindow)); |
| 134 std::for_each(hidden_workspaces_.begin(), hidden_workspaces_.end(), |
| 135 std::mem_fun(&Workspace::ReleaseWindow)); |
134 std::for_each(pending_workspaces_.begin(), pending_workspaces_.end(), | 136 std::for_each(pending_workspaces_.begin(), pending_workspaces_.end(), |
135 std::mem_fun(&Workspace::ReleaseWindow)); | 137 std::mem_fun(&Workspace::ReleaseWindow)); |
136 std::for_each(to_delete_.begin(), to_delete_.end(), | 138 std::for_each(to_delete_.begin(), to_delete_.end(), |
137 std::mem_fun(&Workspace::ReleaseWindow)); | 139 std::mem_fun(&Workspace::ReleaseWindow)); |
138 STLDeleteElements(&workspaces_); | 140 STLDeleteElements(&workspaces_); |
| 141 STLDeleteElements(&hidden_workspaces_); |
139 STLDeleteElements(&pending_workspaces_); | 142 STLDeleteElements(&pending_workspaces_); |
140 STLDeleteElements(&to_delete_); | 143 STLDeleteElements(&to_delete_); |
141 } | 144 } |
142 | 145 |
143 // static | 146 // static |
144 bool WorkspaceManager::IsMaximized(Window* window) { | 147 bool WorkspaceManager::IsMaximized(Window* window) { |
145 return IsMaximizedState(window->GetProperty(aura::client::kShowStateKey)); | 148 return IsMaximizedState(window->GetProperty(aura::client::kShowStateKey)); |
146 } | 149 } |
147 | 150 |
148 // static | 151 // static |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 pending_workspaces_.insert(workspace); | 260 pending_workspaces_.insert(workspace); |
258 return workspace->window(); | 261 return workspace->window(); |
259 } | 262 } |
260 | 263 |
261 if (!GetTrackedByWorkspace(window) || GetPersistsAcrossAllWorkspaces(window)) | 264 if (!GetTrackedByWorkspace(window) || GetPersistsAcrossAllWorkspaces(window)) |
262 return active_workspace_->window(); | 265 return active_workspace_->window(); |
263 | 266 |
264 return desktop_workspace()->window(); | 267 return desktop_workspace()->window(); |
265 } | 268 } |
266 | 269 |
| 270 bool WorkspaceManager::CycleAwayFromCurrentlyActiveWorkspace() { |
| 271 if (active_workspace_ == desktop_workspace()) |
| 272 return false; |
| 273 |
| 274 aura::Window* active_window = active_workspace_->GetActiveWindow(); |
| 275 MoveWorkspaceToHiddenOrDelete(active_workspace_, NULL, SWITCH_OTHER); |
| 276 |
| 277 // The activation controller will pick a window from the just activated |
| 278 // workspace to activate as a result of DeactivateWindow(). |
| 279 if (active_window) |
| 280 wm::DeactivateWindow(active_window); |
| 281 return true; |
| 282 } |
| 283 |
| 284 bool WorkspaceManager::CycleToNextHiddenWorkspace() { |
| 285 if (hidden_workspaces_.empty()) |
| 286 return false; |
| 287 |
| 288 aura::Window* active_window = active_workspace_->GetActiveWindow(); |
| 289 SetActiveWorkspace(hidden_workspaces_.back(), SWITCH_OTHER, |
| 290 base::TimeDelta()); |
| 291 |
| 292 // The activation controller will pick a window from the just activated |
| 293 // workspace to activate as a result of DeactivateWindow(). |
| 294 if (active_window) |
| 295 wm::DeactivateWindow(active_window); |
| 296 return true; |
| 297 } |
| 298 |
267 void WorkspaceManager::DoInitialAnimation() { | 299 void WorkspaceManager::DoInitialAnimation() { |
268 if (active_workspace_->is_maximized()) { | 300 if (active_workspace_->is_maximized()) { |
269 RootWindowController* root_controller = GetRootWindowController( | 301 RootWindowController* root_controller = GetRootWindowController( |
270 contents_view_->GetRootWindow()); | 302 contents_view_->GetRootWindow()); |
271 if (root_controller) { | 303 if (root_controller) { |
272 aura::Window* background = root_controller->GetContainer( | 304 aura::Window* background = root_controller->GetContainer( |
273 kShellWindowId_DesktopBackgroundContainer); | 305 kShellWindowId_DesktopBackgroundContainer); |
274 background->Show(); | 306 background->Show(); |
275 ShowOrHideDesktopBackground(background, SWITCH_INITIAL, | 307 ShowOrHideDesktopBackground(background, SWITCH_INITIAL, |
276 base::TimeDelta(), false); | 308 base::TimeDelta(), false); |
277 } | 309 } |
278 } | 310 } |
279 ShowWorkspace(active_workspace_, active_workspace_, SWITCH_INITIAL); | 311 ShowWorkspace(active_workspace_, active_workspace_, SWITCH_INITIAL); |
280 } | 312 } |
281 | 313 |
| 314 aura::Window* WorkspaceManager::GetActiveWorkspaceWindow() const { |
| 315 return active_workspace_->window(); |
| 316 } |
| 317 |
282 void WorkspaceManager::OnAppTerminating() { | 318 void WorkspaceManager::OnAppTerminating() { |
283 app_terminating_ = true; | 319 app_terminating_ = true; |
284 } | 320 } |
285 | 321 |
286 void WorkspaceManager::UpdateShelfVisibility() { | 322 void WorkspaceManager::UpdateShelfVisibility() { |
287 if (shelf_) | 323 if (shelf_) |
288 shelf_->UpdateVisibilityState(); | 324 shelf_->UpdateVisibilityState(); |
289 } | 325 } |
290 | 326 |
291 Workspace* WorkspaceManager::FindBy(Window* window) const { | 327 Workspace* WorkspaceManager::FindBy(Window* window) const { |
292 while (window) { | 328 while (window) { |
293 Workspace* workspace = window->GetProperty(kWorkspaceKey); | 329 Workspace* workspace = window->GetProperty(kWorkspaceKey); |
294 if (workspace) | 330 if (workspace) |
295 return workspace; | 331 return workspace; |
296 window = window->parent(); | 332 window = window->parent(); |
297 } | 333 } |
298 return NULL; | 334 return NULL; |
299 } | 335 } |
300 | 336 |
301 void WorkspaceManager::SetActiveWorkspace(Workspace* workspace, | 337 void WorkspaceManager::SetActiveWorkspace(Workspace* workspace, |
302 SwitchReason reason, | 338 SwitchReason reason, |
303 base::TimeDelta duration) { | 339 base::TimeDelta duration) { |
304 DCHECK(workspace); | 340 DCHECK(workspace); |
305 if (active_workspace_ == workspace) | 341 if (active_workspace_ == workspace) |
306 return; | 342 return; |
307 | 343 |
| 344 Workspaces::iterator it = std::find( |
| 345 hidden_workspaces_.begin(), hidden_workspaces_.end(), workspace); |
| 346 if (it != hidden_workspaces_.end()) |
| 347 hidden_workspaces_.erase(it); |
308 pending_workspaces_.erase(workspace); | 348 pending_workspaces_.erase(workspace); |
309 | 349 |
310 // Adjust the z-order. No need to adjust the z-order for the desktop since | 350 // Adjust the z-order. No need to adjust the z-order for the desktop since |
311 // it always stays at the bottom. | 351 // it always stays at the bottom. |
312 if (workspace != desktop_workspace() && | 352 if (workspace != desktop_workspace() && |
313 FindWorkspace(workspace) == workspaces_.end()) { | 353 FindWorkspace(workspace) == workspaces_.end()) { |
314 contents_view_->StackChildAbove(workspace->window(), | 354 contents_view_->StackChildAbove(workspace->window(), |
315 workspaces_.back()->window()); | 355 workspaces_.back()->window()); |
316 workspaces_.push_back(workspace); | 356 workspaces_.push_back(workspace); |
317 } | 357 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 | 404 |
365 WorkspaceManager::Workspaces::iterator | 405 WorkspaceManager::Workspaces::iterator |
366 WorkspaceManager::FindWorkspace(Workspace* workspace) { | 406 WorkspaceManager::FindWorkspace(Workspace* workspace) { |
367 return std::find(workspaces_.begin(), workspaces_.end(), workspace); | 407 return std::find(workspaces_.begin(), workspaces_.end(), workspace); |
368 } | 408 } |
369 | 409 |
370 Workspace* WorkspaceManager::CreateWorkspace(bool maximized) { | 410 Workspace* WorkspaceManager::CreateWorkspace(bool maximized) { |
371 return new Workspace(this, contents_view_, maximized); | 411 return new Workspace(this, contents_view_, maximized); |
372 } | 412 } |
373 | 413 |
374 void WorkspaceManager::MoveWorkspaceToPendingOrDelete( | 414 void WorkspaceManager::MoveWorkspaceToHiddenOrDelete( |
375 Workspace* workspace, | 415 Workspace* workspace, |
376 Window* stack_beneath, | 416 Window* stack_beneath, |
377 SwitchReason reason) { | 417 SwitchReason reason) { |
378 // We're all ready moving windows. | 418 // We're all ready moving windows. |
379 if (in_move_) | 419 if (in_move_) |
380 return; | 420 return; |
381 | 421 |
382 DCHECK_NE(desktop_workspace(), workspace); | 422 DCHECK_NE(desktop_workspace(), workspace); |
383 | 423 |
384 if (workspace == active_workspace_) | 424 if (workspace == active_workspace_) |
385 SelectNextWorkspace(reason); | 425 SelectNextWorkspace(reason); |
386 | 426 |
387 base::AutoReset<bool> setter(&in_move_, true); | 427 base::AutoReset<bool> setter(&in_move_, true); |
388 | 428 |
389 MoveChildrenToDesktop(workspace->window(), stack_beneath); | 429 MoveChildrenToDesktop(workspace->window(), stack_beneath); |
390 | 430 |
| 431 bool workspace_previously_active = false; |
391 { | 432 { |
392 Workspaces::iterator workspace_i(FindWorkspace(workspace)); | 433 Workspaces::iterator workspace_i(FindWorkspace(workspace)); |
393 if (workspace_i != workspaces_.end()) | 434 if (workspace_i != workspaces_.end()) { |
394 workspaces_.erase(workspace_i); | 435 workspaces_.erase(workspace_i); |
| 436 workspace_previously_active = true; |
| 437 } |
395 } | 438 } |
396 | 439 |
397 if (workspace->window()->children().empty()) { | 440 if (workspace->window()->children().empty()) { |
398 if (workspace == unminimizing_workspace_) | 441 if (workspace == unminimizing_workspace_) |
399 unminimizing_workspace_ = NULL; | 442 unminimizing_workspace_ = NULL; |
| 443 Workspaces::iterator hidden_i = std::find( |
| 444 hidden_workspaces_.begin(), hidden_workspaces_.end(), workspace); |
| 445 if (hidden_i != hidden_workspaces_.end()) |
| 446 hidden_workspaces_.erase(hidden_i); |
400 pending_workspaces_.erase(workspace); | 447 pending_workspaces_.erase(workspace); |
401 ScheduleDelete(workspace); | 448 ScheduleDelete(workspace); |
402 } else { | 449 } else if (workspace_previously_active) { |
403 pending_workspaces_.insert(workspace); | 450 hidden_workspaces_.push_back(workspace); |
404 } | 451 } |
405 } | 452 } |
406 | 453 |
407 void WorkspaceManager::MoveChildrenToDesktop(aura::Window* window, | 454 void WorkspaceManager::MoveChildrenToDesktop(aura::Window* window, |
408 aura::Window* stack_beneath) { | 455 aura::Window* stack_beneath) { |
409 // Build the list of windows to move. Exclude maximized/fullscreen and windows | 456 // Build the list of windows to move. Exclude maximized/fullscreen and windows |
410 // with transient parents. | 457 // with transient parents. |
411 Window::Windows to_move; | 458 Window::Windows to_move; |
412 for (size_t i = 0; i < window->children().size(); ++i) { | 459 for (size_t i = 0; i < window->children().size(); ++i) { |
413 Window* child = window->children()[i]; | 460 Window* child = window->children()[i]; |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 | 660 |
614 void WorkspaceManager::OnWillRemoveWindowFromWorkspace(Workspace* workspace, | 661 void WorkspaceManager::OnWillRemoveWindowFromWorkspace(Workspace* workspace, |
615 Window* child) { | 662 Window* child) { |
616 if (child->TargetVisibility()) | 663 if (child->TargetVisibility()) |
617 RearrangeVisibleWindowOnHideOrRemove(child); | 664 RearrangeVisibleWindowOnHideOrRemove(child); |
618 child->ClearProperty(kWorkspaceKey); | 665 child->ClearProperty(kWorkspaceKey); |
619 } | 666 } |
620 | 667 |
621 void WorkspaceManager::OnWindowRemovedFromWorkspace(Workspace* workspace, | 668 void WorkspaceManager::OnWindowRemovedFromWorkspace(Workspace* workspace, |
622 Window* child) { | 669 Window* child) { |
623 if (workspace->ShouldMoveToPending()) | 670 if (workspace->ShouldMoveToHidden()) |
624 MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_WINDOW_REMOVED); | 671 MoveWorkspaceToHiddenOrDelete(workspace, NULL, SWITCH_WINDOW_REMOVED); |
625 } | 672 } |
626 | 673 |
627 void WorkspaceManager::OnWorkspaceChildWindowVisibilityChanged( | 674 void WorkspaceManager::OnWorkspaceChildWindowVisibilityChanged( |
628 Workspace* workspace, | 675 Workspace* workspace, |
629 Window* child) { | 676 Window* child) { |
630 if (workspace->ShouldMoveToPending()) { | 677 if (workspace->ShouldMoveToHidden()) { |
631 MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_VISIBILITY_CHANGED); | 678 MoveWorkspaceToHiddenOrDelete(workspace, NULL, SWITCH_VISIBILITY_CHANGED); |
632 } else { | 679 } else { |
633 if (child->TargetVisibility()) | 680 if (child->TargetVisibility()) |
634 RearrangeVisibleWindowOnShow(child); | 681 RearrangeVisibleWindowOnShow(child); |
635 else | 682 else |
636 RearrangeVisibleWindowOnHideOrRemove(child); | 683 RearrangeVisibleWindowOnHideOrRemove(child); |
637 if (workspace == active_workspace_) | 684 if (workspace == active_workspace_) |
638 UpdateShelfVisibility(); | 685 UpdateShelfVisibility(); |
639 } | 686 } |
640 } | 687 } |
641 | 688 |
642 void WorkspaceManager::OnWorkspaceWindowChildBoundsChanged( | 689 void WorkspaceManager::OnWorkspaceWindowChildBoundsChanged( |
643 Workspace* workspace, | 690 Workspace* workspace, |
644 Window* child) { | 691 Window* child) { |
645 if (workspace == active_workspace_) | 692 if (workspace == active_workspace_) |
646 UpdateShelfVisibility(); | 693 UpdateShelfVisibility(); |
647 } | 694 } |
648 | 695 |
649 void WorkspaceManager::OnWorkspaceWindowShowStateChanged( | 696 void WorkspaceManager::OnWorkspaceWindowShowStateChanged( |
650 Workspace* workspace, | 697 Workspace* workspace, |
651 Window* child, | 698 Window* child, |
652 ui::WindowShowState last_show_state, | 699 ui::WindowShowState last_show_state, |
653 ui::Layer* old_layer) { | 700 ui::Layer* old_layer) { |
654 // |child| better still be in |workspace| else things have gone wrong. | 701 // |child| better still be in |workspace| else things have gone wrong. |
655 DCHECK_EQ(workspace, child->GetProperty(kWorkspaceKey)); | 702 DCHECK_EQ(workspace, child->GetProperty(kWorkspaceKey)); |
656 if (wm::IsWindowMinimized(child)) { | 703 if (wm::IsWindowMinimized(child)) { |
657 if (workspace->ShouldMoveToPending()) | 704 if (workspace->ShouldMoveToHidden()) |
658 MoveWorkspaceToPendingOrDelete(workspace, NULL, SWITCH_MINIMIZED); | 705 MoveWorkspaceToHiddenOrDelete(workspace, NULL, SWITCH_MINIMIZED); |
659 DCHECK(!old_layer); | 706 DCHECK(!old_layer); |
660 } else { | 707 } else { |
661 // Set of cases to deal with: | 708 // Set of cases to deal with: |
662 // . More than one maximized window: move newly maximized window into | 709 // . More than one maximized window: move newly maximized window into |
663 // own workspace. | 710 // own workspace. |
664 // . One maximized window and not in a maximized workspace: move window | 711 // . One maximized window and not in a maximized workspace: move window |
665 // into own workspace. | 712 // into own workspace. |
666 // . No maximized window and not in desktop: move to desktop and further | 713 // . No maximized window and not in desktop: move to desktop and further |
667 // any existing windows are stacked beneath |child|. | 714 // any existing windows are stacked beneath |child|. |
668 const bool is_active = wm::IsActiveWindow(child); | 715 const bool is_active = wm::IsActiveWindow(child); |
669 Workspace* new_workspace = NULL; | 716 Workspace* new_workspace = NULL; |
670 const int max_count = workspace->GetNumMaximizedWindows(); | 717 const int max_count = workspace->GetNumMaximizedWindows(); |
671 base::TimeDelta duration = old_layer && !IsMaximized(child) ? | 718 base::TimeDelta duration = old_layer && !IsMaximized(child) ? |
672 GetCrossFadeDuration(old_layer->bounds(), child->bounds()) : | 719 GetCrossFadeDuration(old_layer->bounds(), child->bounds()) : |
673 base::TimeDelta::FromMilliseconds(kCrossFadeSwitchTimeMS); | 720 base::TimeDelta::FromMilliseconds(kCrossFadeSwitchTimeMS); |
674 if (max_count == 0) { | 721 if (max_count == 0) { |
675 if (workspace != desktop_workspace()) { | 722 if (workspace != desktop_workspace()) { |
676 { | 723 { |
677 base::AutoReset<bool> setter(&in_move_, true); | 724 base::AutoReset<bool> setter(&in_move_, true); |
678 ReparentWindow(child, desktop_workspace()->window(), NULL); | 725 ReparentWindow(child, desktop_workspace()->window(), NULL); |
679 } | 726 } |
680 DCHECK(!is_active || old_layer); | 727 DCHECK(!is_active || old_layer); |
681 new_workspace = desktop_workspace(); | 728 new_workspace = desktop_workspace(); |
682 SetActiveWorkspace(new_workspace, SWITCH_MAXIMIZED_OR_RESTORED, | 729 SetActiveWorkspace(new_workspace, SWITCH_MAXIMIZED_OR_RESTORED, |
683 duration); | 730 duration); |
684 MoveWorkspaceToPendingOrDelete(workspace, child, | 731 MoveWorkspaceToHiddenOrDelete(workspace, child, |
685 SWITCH_MAXIMIZED_OR_RESTORED); | 732 SWITCH_MAXIMIZED_OR_RESTORED); |
686 if (FindWorkspace(workspace) == workspaces_.end()) | 733 if (FindWorkspace(workspace) == workspaces_.end()) |
687 workspace = NULL; | 734 workspace = NULL; |
688 } | 735 } |
689 } else if ((max_count == 1 && workspace == desktop_workspace()) || | 736 } else if ((max_count == 1 && workspace == desktop_workspace()) || |
690 max_count > 1) { | 737 max_count > 1) { |
691 new_workspace = CreateWorkspace(true); | 738 new_workspace = CreateWorkspace(true); |
692 pending_workspaces_.insert(new_workspace); | 739 pending_workspaces_.insert(new_workspace); |
693 ReparentWindow(child, new_workspace->window(), NULL); | 740 ReparentWindow(child, new_workspace->window(), NULL); |
694 } | 741 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 new_workspace->window()->Show(); | 783 new_workspace->window()->Show(); |
737 ReparentWindow(window, new_workspace->window(), NULL); | 784 ReparentWindow(window, new_workspace->window(), NULL); |
738 if (is_active) { | 785 if (is_active) { |
739 SetActiveWorkspace(new_workspace, SWITCH_TRACKED_BY_WORKSPACE_CHANGED, | 786 SetActiveWorkspace(new_workspace, SWITCH_TRACKED_BY_WORKSPACE_CHANGED, |
740 base::TimeDelta()); | 787 base::TimeDelta()); |
741 } | 788 } |
742 } | 789 } |
743 | 790 |
744 } // namespace internal | 791 } // namespace internal |
745 } // namespace ash | 792 } // namespace ash |
OLD | NEW |