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 "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h" | 5 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h" |
| 6 | 6 |
| 7 #include "apps/app_window.h" | 7 #include "apps/app_window.h" |
| 8 #include "apps/app_window_registry.h" | 8 #include "apps/app_window_registry.h" |
| 9 #include "ash/ash_switches.h" | 9 #include "ash/ash_switches.h" |
| 10 #include "ash/desktop_background/user_wallpaper_delegate.h" | 10 #include "ash/desktop_background/user_wallpaper_delegate.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 // in / out. | 54 // in / out. |
| 55 static int kAnimationTimeMS = 100; | 55 static int kAnimationTimeMS = 100; |
| 56 | 56 |
| 57 // The animation time in millseconds for the fade in and / or out when switching | 57 // The animation time in millseconds for the fade in and / or out when switching |
| 58 // users. | 58 // users. |
| 59 static int kUserFadeTimeMS = 110; | 59 static int kUserFadeTimeMS = 110; |
| 60 | 60 |
| 61 // The animation time in ms for a window which get teleported to another screen. | 61 // The animation time in ms for a window which get teleported to another screen. |
| 62 static int kTeleportAnimationTimeMS = 300; | 62 static int kTeleportAnimationTimeMS = 300; |
| 63 | 63 |
| 64 // The minimal possible animation time for animations which should happen | |
| 65 // "instantly". | |
| 66 static int kMinimalAnimationTime = 1; | |
|
oshima
2014/04/03 19:21:41
kMinimalAnimationTimeMs (assuming it's millisecond
Mr4D (OOO till 08-26)
2014/04/03 22:57:00
Done.
| |
| 67 | |
| 64 // Checks if a given event is a user event. | 68 // Checks if a given event is a user event. |
| 65 bool IsUserEvent(ui::Event* e) { | 69 bool IsUserEvent(ui::Event* e) { |
|
oshima
2014/04/03 19:21:41
const ui::Event*
Mr4D (OOO till 08-26)
2014/04/03 22:57:00
Done.
| |
| 66 if (e) { | 70 if (e) { |
| 67 ui::EventType type = e->type(); | 71 ui::EventType type = e->type(); |
| 68 if (type != ui::ET_CANCEL_MODE && | 72 if (type != ui::ET_CANCEL_MODE && |
| 69 type != ui::ET_UMA_DATA && | 73 type != ui::ET_UMA_DATA && |
| 70 type != ui::ET_UNKNOWN) | 74 type != ui::ET_UNKNOWN) |
| 71 return true; | 75 return true; |
| 72 } | 76 } |
| 73 return false; | 77 return false; |
| 74 } | 78 } |
| 75 | 79 |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 | 233 |
| 230 DISALLOW_COPY_AND_ASSIGN(AppObserver); | 234 DISALLOW_COPY_AND_ASSIGN(AppObserver); |
| 231 }; | 235 }; |
| 232 | 236 |
| 233 MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS( | 237 MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS( |
| 234 const std::string& current_user_id) | 238 const std::string& current_user_id) |
| 235 : current_user_id_(current_user_id), | 239 : current_user_id_(current_user_id), |
| 236 notification_blocker_(new MultiUserNotificationBlockerChromeOS( | 240 notification_blocker_(new MultiUserNotificationBlockerChromeOS( |
| 237 message_center::MessageCenter::Get(), this, current_user_id)), | 241 message_center::MessageCenter::Get(), this, current_user_id)), |
| 238 suppress_visibility_changes_(false), | 242 suppress_visibility_changes_(false), |
| 239 animations_disabled_(false) { | 243 screen_cover_(NO_USER_COVERS_SCREEN), |
| 244 animation_step_(ANIMATION_STEP_ENDED), | |
| 245 animations_disabled_(false), | |
| 246 wallpaper_user_id_(current_user_id) { | |
| 240 // Add a session state observer to be able to monitor session changes. | 247 // Add a session state observer to be able to monitor session changes. |
| 241 if (ash::Shell::HasInstance()) | 248 if (ash::Shell::HasInstance()) |
| 242 ash::Shell::GetInstance()->session_state_delegate()-> | 249 ash::Shell::GetInstance()->session_state_delegate()-> |
| 243 AddSessionStateObserver(this); | 250 AddSessionStateObserver(this); |
| 244 | 251 |
| 245 // The BrowserListObserver would have been better to use then the old | 252 // The BrowserListObserver would have been better to use then the old |
| 246 // notification system, but that observer fires before the window got created. | 253 // notification system, but that observer fires before the window got created. |
| 247 registrar_.Add(this, NOTIFICATION_BROWSER_WINDOW_READY, | 254 registrar_.Add(this, NOTIFICATION_BROWSER_WINDOW_READY, |
| 248 content::NotificationService::AllSources()); | 255 content::NotificationService::AllSources()); |
| 249 | 256 |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 404 observers_.AddObserver(observer); | 411 observers_.AddObserver(observer); |
| 405 } | 412 } |
| 406 | 413 |
| 407 void MultiUserWindowManagerChromeOS::RemoveObserver(Observer* observer) { | 414 void MultiUserWindowManagerChromeOS::RemoveObserver(Observer* observer) { |
| 408 observers_.RemoveObserver(observer); | 415 observers_.RemoveObserver(observer); |
| 409 } | 416 } |
| 410 | 417 |
| 411 void MultiUserWindowManagerChromeOS::ActiveUserChanged( | 418 void MultiUserWindowManagerChromeOS::ActiveUserChanged( |
| 412 const std::string& user_id) { | 419 const std::string& user_id) { |
| 413 DCHECK(user_id != current_user_id_); | 420 DCHECK(user_id != current_user_id_); |
| 414 current_user_id_ = user_id; | |
| 415 // If there is an animation in progress finish the pending switch which also | |
| 416 // kills the timer (if there is one). | |
| 417 if (user_changed_animation_timer_.get()) | |
| 418 TransitionUser(SHOW_NEW_USER); | |
| 419 | 421 |
| 420 // Start the animation by hiding the old user. | 422 // Kick off a new animation (this will first finish outstanding animations). |
| 421 TransitionUser(HIDE_OLD_USER); | 423 StartUserTransitionAnimation(user_id); |
| 422 | 424 |
| 423 // If animations are disabled we immediately switch to the new user, otherwise | 425 // Immediately switch to new layer if animations are disabled, otherwise |
| 424 // we create a timer which will fade in the new user once the other user has | 426 // create a timer which will fade in the new user once the other user has |
| 425 // been faded away. | 427 // been faded away. |
| 426 if (animations_disabled_) { | 428 if (animations_disabled_) { |
| 427 TransitionUser(SHOW_NEW_USER); | 429 while (ANIMATION_STEP_ENDED != animation_step_) |
| 430 AdvanceUserTransitionAnimation(); | |
| 428 } else { | 431 } else { |
| 429 user_changed_animation_timer_.reset(new base::Timer( | 432 user_changed_animation_timer_.reset(new base::Timer( |
| 430 FROM_HERE, | 433 FROM_HERE, |
| 431 base::TimeDelta::FromMilliseconds(kUserFadeTimeMS), | 434 base::TimeDelta::FromMilliseconds(kUserFadeTimeMS), |
| 432 base::Bind(&MultiUserWindowManagerChromeOS::TransitionUser, | 435 base::Bind( |
| 433 base::Unretained(this), | 436 &MultiUserWindowManagerChromeOS::AdvanceUserTransitionAnimation, |
| 434 SHOW_NEW_USER), | 437 base::Unretained(this)), |
|
oshima
2014/04/03 19:21:41
can you change to use weak pointer? 110 ms is a bi
oshima
2014/04/03 20:13:20
never mind. I somehow thought it's passed to messa
| |
| 435 false)); | 438 true)); |
| 436 user_changed_animation_timer_->Reset(); | 439 user_changed_animation_timer_->Reset(); |
| 437 } | 440 } |
| 438 } | 441 } |
| 439 | 442 |
| 440 void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) { | 443 void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) { |
| 441 if (GetWindowOwner(window).empty()) { | 444 if (GetWindowOwner(window).empty()) { |
| 442 // This must be a window in the transient chain - remove it and its | 445 // This must be a window in the transient chain - remove it and its |
| 443 // children from the owner. | 446 // children from the owner. |
| 444 RemoveTransientOwnerRecursive(window); | 447 RemoveTransientOwnerRecursive(window); |
| 445 return; | 448 return; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 SetWindowVisibility(window, true, kTeleportAnimationTimeMS); | 576 SetWindowVisibility(window, true, kTeleportAnimationTimeMS); |
| 574 } else { | 577 } else { |
| 575 SetWindowVisibility(window, false, kTeleportAnimationTimeMS); | 578 SetWindowVisibility(window, false, kTeleportAnimationTimeMS); |
| 576 } | 579 } |
| 577 | 580 |
| 578 // Notify entry change. | 581 // Notify entry change. |
| 579 FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryChanged(window)); | 582 FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryChanged(window)); |
| 580 return true; | 583 return true; |
| 581 } | 584 } |
| 582 | 585 |
| 583 void MultiUserWindowManagerChromeOS::TransitionUser( | |
| 584 MultiUserWindowManagerChromeOS::AnimationStep animation_step) { | |
| 585 TransitionWallpaper(animation_step); | |
| 586 TransitionUserShelf(animation_step); | |
| 587 | |
| 588 // Disable the window position manager and the MRU window tracker temporarily. | |
| 589 scoped_ptr<UserChangeActionDisabler> disabler(new UserChangeActionDisabler); | |
| 590 | |
| 591 // We need to show/hide the windows in the same order as they were created in | |
| 592 // their parent window(s) to keep the layer / window hierarchy in sync. To | |
| 593 // achieve that we first collect all parent windows and then enumerate all | |
| 594 // windows in those parent windows and show or hide them accordingly. | |
| 595 | |
| 596 // Create a list of all parent windows we have to check and their parents. | |
| 597 std::set<aura::Window*> parent_list; | |
| 598 for (WindowToEntryMap::iterator it = window_to_entry_.begin(); | |
| 599 it != window_to_entry_.end(); ++it) { | |
| 600 aura::Window* parent = it->first->parent(); | |
| 601 if (parent_list.find(parent) == parent_list.end()) | |
| 602 parent_list.insert(parent); | |
| 603 } | |
| 604 | |
| 605 // Traverse the found parent windows to handle their child windows in order of | |
| 606 // their appearance. | |
| 607 for (std::set<aura::Window*>::iterator it_parents = parent_list.begin(); | |
| 608 it_parents != parent_list.end(); ++it_parents) { | |
| 609 const aura::Window::Windows window_list = (*it_parents)->children(); | |
| 610 for (aura::Window::Windows::const_iterator it_window = window_list.begin(); | |
| 611 it_window != window_list.end(); ++it_window) { | |
| 612 aura::Window* window = *it_window; | |
| 613 WindowToEntryMap::iterator it_map = window_to_entry_.find(window); | |
| 614 if (it_map != window_to_entry_.end()) { | |
| 615 bool should_be_visible = | |
| 616 it_map->second->show_for_user() == current_user_id_ && | |
| 617 it_map->second->show(); | |
| 618 bool is_visible = window->IsVisible(); | |
| 619 ash::wm::WindowState* window_state = ash::wm::GetWindowState(window); | |
| 620 if (animation_step == SHOW_NEW_USER && | |
| 621 it_map->second->owner() == current_user_id_ && | |
| 622 it_map->second->show_for_user() != current_user_id_ && | |
| 623 window_state->IsMinimized()) { | |
| 624 // Pull back minimized visiting windows to the owners desktop. | |
| 625 ShowWindowForUserIntern(window, current_user_id_); | |
| 626 window_state->Unminimize(); | |
| 627 } else if (should_be_visible != is_visible && | |
| 628 should_be_visible == (animation_step == SHOW_NEW_USER)) { | |
| 629 SetWindowVisibility(window, should_be_visible, kUserFadeTimeMS); | |
| 630 } | |
| 631 } | |
| 632 } | |
| 633 } | |
| 634 | |
| 635 // Activation and real switch are happening after the other user gets shown. | |
| 636 if (animation_step == SHOW_NEW_USER) { | |
| 637 // Finally we need to restore the previously active window. | |
| 638 ash::MruWindowTracker::WindowList mru_list = | |
| 639 ash::Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList(); | |
| 640 if (mru_list.size()) { | |
| 641 aura::Window* window = mru_list[0]; | |
| 642 ash::wm::WindowState* window_state = ash::wm::GetWindowState(window); | |
| 643 if (IsWindowOnDesktopOfUser(window, current_user_id_) && | |
| 644 !window_state->IsMinimized()) { | |
| 645 aura::client::ActivationClient* client = | |
| 646 aura::client::GetActivationClient(window->GetRootWindow()); | |
| 647 // Several unit tests come here without an activation client. | |
| 648 if (client) | |
| 649 client->ActivateWindow(window); | |
| 650 } | |
| 651 } | |
| 652 | |
| 653 // This is called directly here to make sure notification_blocker will see | |
| 654 // the new window status. | |
| 655 notification_blocker_->ActiveUserChanged(current_user_id_); | |
| 656 | |
| 657 // We can reset the timer at this point. | |
| 658 // Note: The timer can be destroyed while it is performing its task. | |
| 659 user_changed_animation_timer_.reset(); | |
| 660 } | |
| 661 } | |
| 662 | |
| 663 void MultiUserWindowManagerChromeOS::TransitionWallpaper( | |
| 664 MultiUserWindowManagerChromeOS::AnimationStep animation_step) { | |
| 665 // Handle the wallpaper switch. | |
| 666 ash::UserWallpaperDelegate* wallpaper_delegate = | |
| 667 ash::Shell::GetInstance()->user_wallpaper_delegate(); | |
| 668 if (animation_step == HIDE_OLD_USER) { | |
| 669 // Set the wallpaper cross dissolve animation duration to our complete | |
| 670 // animation cycle for a fade in and fade out. | |
| 671 wallpaper_delegate->SetAnimationDurationOverride(2 * kUserFadeTimeMS); | |
| 672 chromeos::WallpaperManager::Get()->SetUserWallpaperDelayed( | |
| 673 current_user_id_); | |
| 674 } else { | |
| 675 // Revert the wallpaper cross dissolve animation duration back to the | |
| 676 // default. | |
| 677 wallpaper_delegate->SetAnimationDurationOverride(0); | |
| 678 } | |
| 679 } | |
| 680 | |
| 681 void MultiUserWindowManagerChromeOS::TransitionUserShelf( | |
| 682 MultiUserWindowManagerChromeOS::AnimationStep animation_step) { | |
| 683 // The shelf animation duration override. | |
| 684 int duration_override = kUserFadeTimeMS; | |
| 685 // Handle the shelf order of items. This is done once the old user is hidden. | |
| 686 if (animation_step == SHOW_NEW_USER) { | |
| 687 // Some unit tests have no ChromeLauncherController. | |
| 688 if (ChromeLauncherController::instance()) | |
| 689 ChromeLauncherController::instance()->ActiveUserChanged(current_user_id_); | |
| 690 // We kicked off the shelf animation in the command above. As such we can | |
| 691 // disable the override now again. | |
| 692 duration_override = 0; | |
| 693 } | |
| 694 | |
| 695 if (animations_disabled_) | |
| 696 return; | |
| 697 | |
| 698 ash::Shell::RootWindowControllerList controller = | |
| 699 ash::Shell::GetInstance()->GetAllRootWindowControllers(); | |
| 700 for (ash::Shell::RootWindowControllerList::iterator it1 = controller.begin(); | |
| 701 it1 != controller.end(); ++it1) { | |
| 702 (*it1)->GetShelfLayoutManager()->SetAnimationDurationOverride( | |
| 703 duration_override); | |
| 704 } | |
| 705 | |
| 706 // For each root window hide the shelf. | |
| 707 if (animation_step == HIDE_OLD_USER) { | |
| 708 aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows(); | |
| 709 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); | |
| 710 iter != root_windows.end(); ++iter) { | |
| 711 ash::Shell::GetInstance()->SetShelfAutoHideBehavior( | |
| 712 ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN, *iter); | |
| 713 } | |
| 714 } | |
| 715 } | |
| 716 | |
| 717 void MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) { | 586 void MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) { |
| 718 // A unit test (e.g. CrashRestoreComplexTest.RestoreSessionForThreeUsers) can | 587 // A unit test (e.g. CrashRestoreComplexTest.RestoreSessionForThreeUsers) can |
| 719 // come here with no valid window. | 588 // come here with no valid window. |
| 720 if (!browser->window() || !browser->window()->GetNativeWindow()) | 589 if (!browser->window() || !browser->window()->GetNativeWindow()) |
| 721 return; | 590 return; |
| 722 SetWindowOwner(browser->window()->GetNativeWindow(), | 591 SetWindowOwner(browser->window()->GetNativeWindow(), |
| 723 multi_user_util::GetUserIDFromProfile(browser->profile())); | 592 multi_user_util::GetUserIDFromProfile(browser->profile())); |
| 724 } | 593 } |
| 725 | 594 |
| 726 void MultiUserWindowManagerChromeOS::SetWindowVisibility( | 595 void MultiUserWindowManagerChromeOS::SetWindowVisibility( |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 862 if (visible) | 731 if (visible) |
| 863 window->Show(); | 732 window->Show(); |
| 864 else | 733 else |
| 865 window->Hide(); | 734 window->Hide(); |
| 866 | 735 |
| 867 // Make sure that animations have no influence on the window state after the | 736 // Make sure that animations have no influence on the window state after the |
| 868 // call. | 737 // call. |
| 869 DCHECK_EQ(visible, window->IsVisible()); | 738 DCHECK_EQ(visible, window->IsVisible()); |
| 870 } | 739 } |
| 871 | 740 |
| 741 void MultiUserWindowManagerChromeOS::StartUserTransitionAnimation( | |
| 742 const std::string& user_id) { | |
| 743 // If there is an animation in progress, finish it before the new one starts. | |
| 744 while (ANIMATION_STEP_ENDED != animation_step_) | |
| 745 AdvanceUserTransitionAnimation(); | |
| 746 | |
| 747 // Set up the transition parameters before the animation gets called the first | |
| 748 // time. Note that the screen cover state needs to be analyzed and remembered | |
| 749 // before the animation starts and after the user got set. | |
| 750 current_user_id_ = user_id; | |
| 751 screen_cover_ = GetScreenCover(); | |
| 752 animation_step_ = ANIMATION_STEP_HIDE_OLD_USER; | |
| 753 | |
| 754 AdvanceUserTransitionAnimation(); | |
| 755 } | |
| 756 | |
| 757 void MultiUserWindowManagerChromeOS::AdvanceUserTransitionAnimation() { | |
| 758 DCHECK_NE(animation_step_, ANIMATION_STEP_ENDED); | |
| 759 | |
| 760 TransitionWallpaper(animation_step_); | |
| 761 TransitionUserShelf(animation_step_); | |
| 762 TransitionWindows(animation_step_); | |
| 763 | |
| 764 // Advance to the next step. | |
| 765 if (animation_step_ == ANIMATION_STEP_FINALIZE) { | |
|
oshima
2014/04/03 19:21:41
optional: using switch would make it easy to under
Mr4D (OOO till 08-26)
2014/04/03 22:57:00
Done.
| |
| 766 user_changed_animation_timer_.reset(); | |
| 767 animation_step_ = ANIMATION_STEP_ENDED; | |
| 768 } else { | |
| 769 animation_step_ = animation_step_ == ANIMATION_STEP_HIDE_OLD_USER ? | |
| 770 ANIMATION_STEP_SHOW_NEW_USER : ANIMATION_STEP_FINALIZE; | |
| 771 } | |
| 772 } | |
| 773 | |
| 774 void MultiUserWindowManagerChromeOS::TransitionWallpaper( | |
| 775 MultiUserWindowManagerChromeOS::AnimationStep animation_step) { | |
| 776 // Handle the wallpaper switch. | |
| 777 ash::UserWallpaperDelegate* wallpaper_delegate = | |
| 778 ash::Shell::GetInstance()->user_wallpaper_delegate(); | |
| 779 if (animation_step == ANIMATION_STEP_HIDE_OLD_USER) { | |
| 780 // Set the wallpaper cross dissolve animation duration to our complete | |
| 781 // animation cycle for a fade in and fade out. | |
| 782 wallpaper_delegate->SetAnimationDurationOverride( | |
| 783 NO_USER_COVERS_SCREEN == screen_cover_ ? (2 * kUserFadeTimeMS) : | |
| 784 kMinimalAnimationTime); | |
| 785 if (screen_cover_ != NEW_USER_COVERS_SCREEN) { | |
| 786 chromeos::WallpaperManager::Get()->SetUserWallpaperNow(current_user_id_); | |
| 787 wallpaper_user_id_ = NO_USER_COVERS_SCREEN == screen_cover_ ? | |
| 788 (wallpaper_user_id_ + "->" + current_user_id_) : current_user_id_; | |
| 789 } | |
| 790 } else if (animation_step == ANIMATION_STEP_FINALIZE) { | |
| 791 // Revert the wallpaper cross dissolve animation duration back to the | |
| 792 // default. | |
| 793 if (screen_cover_ == NEW_USER_COVERS_SCREEN) | |
| 794 chromeos::WallpaperManager::Get()->SetUserWallpaperNow(current_user_id_); | |
| 795 | |
| 796 // Coming here the wallpaper user id is the final result. No matter how we | |
| 797 // got here. | |
| 798 wallpaper_user_id_ = current_user_id_; | |
| 799 wallpaper_delegate->SetAnimationDurationOverride(0); | |
| 800 } | |
| 801 } | |
| 802 | |
| 803 void MultiUserWindowManagerChromeOS::TransitionUserShelf( | |
| 804 MultiUserWindowManagerChromeOS::AnimationStep animation_step) { | |
| 805 // The shelf animation duration override. | |
| 806 int duration_override = kUserFadeTimeMS; | |
| 807 // Handle the shelf order of items. This is done once the old user is hidden. | |
| 808 if (animation_step == ANIMATION_STEP_SHOW_NEW_USER) { | |
| 809 // Some unit tests have no ChromeLauncherController. | |
| 810 if (ChromeLauncherController::instance()) | |
| 811 ChromeLauncherController::instance()->ActiveUserChanged(current_user_id_); | |
| 812 // We kicked off the shelf animation in the command above. As such we can | |
| 813 // disable the override now again. | |
| 814 duration_override = 0; | |
| 815 } | |
| 816 | |
| 817 if (animations_disabled_ || animation_step == ANIMATION_STEP_FINALIZE) | |
| 818 return; | |
| 819 | |
| 820 ash::Shell::RootWindowControllerList controller = | |
| 821 ash::Shell::GetInstance()->GetAllRootWindowControllers(); | |
| 822 for (ash::Shell::RootWindowControllerList::iterator it1 = controller.begin(); | |
| 823 it1 != controller.end(); ++it1) { | |
| 824 (*it1)->GetShelfLayoutManager()->SetAnimationDurationOverride( | |
| 825 duration_override); | |
| 826 } | |
| 827 | |
| 828 // For each root window hide the shelf. | |
| 829 if (animation_step == ANIMATION_STEP_HIDE_OLD_USER) { | |
| 830 aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows(); | |
| 831 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); | |
| 832 iter != root_windows.end(); ++iter) { | |
| 833 ash::Shell::GetInstance()->SetShelfAutoHideBehavior( | |
| 834 ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN, *iter); | |
|
oshima
2014/04/03 19:21:41
q: how/where the user's shelf setting is restored?
Mr4D (OOO till 08-26)
2014/04/03 22:57:00
Added comment to explain.
| |
| 835 } | |
| 836 } | |
| 837 } | |
| 838 | |
| 839 void MultiUserWindowManagerChromeOS::TransitionWindows( | |
| 840 AnimationStep animation_step) { | |
| 841 // Disable the window position manager and the MRU window tracker temporarily. | |
| 842 scoped_ptr<UserChangeActionDisabler> disabler(new UserChangeActionDisabler); | |
|
oshima
2014/04/03 19:21:41
This can be just created on stack ?
Mr4D (OOO till 08-26)
2014/04/03 22:57:00
Done.
| |
| 843 | |
| 844 if (animation_step == ANIMATION_STEP_HIDE_OLD_USER || | |
| 845 (animation_step == ANIMATION_STEP_FINALIZE && | |
| 846 screen_cover_ == BOTH_USERS_COVER_SCREEN)) { | |
| 847 // We need to show/hide the windows in the same order as they were created | |
| 848 // in their parent window(s) to keep the layer / window hierarchy in sync. | |
| 849 // To achieve that we first collect all parent windows and then enumerate | |
| 850 // all windows in those parent windows and show or hide them accordingly. | |
| 851 | |
| 852 // Create a list of all parent windows we have to check. | |
| 853 std::set<aura::Window*> parent_list; | |
| 854 for (WindowToEntryMap::iterator it = window_to_entry_.begin(); | |
| 855 it != window_to_entry_.end(); ++it) { | |
| 856 aura::Window* parent = it->first->parent(); | |
| 857 if (parent_list.find(parent) == parent_list.end()) | |
| 858 parent_list.insert(parent); | |
| 859 } | |
| 860 | |
| 861 for (std::set<aura::Window*>::iterator it_parents = parent_list.begin(); | |
| 862 it_parents != parent_list.end(); ++it_parents) { | |
| 863 const aura::Window::Windows window_list = (*it_parents)->children(); | |
| 864 // In case of |BOTH_USERS_COVER_SCREEN| the desktop might shine through | |
| 865 // if all windows fade (in or out). To avoid this we only fade the topmost | |
| 866 // covering window (in / out) and make / keep all other covering windows | |
| 867 // visible while animating. |foreground_window_found| will get set when | |
| 868 // the top fading window was found. | |
| 869 bool foreground_window_found = false; | |
| 870 // Covering windows which follow the fade direction will also fade - all | |
| 871 // others will get immediately shown / kept shown until the animation is | |
| 872 // finished. | |
| 873 bool foreground_becomes_visible = false; | |
| 874 for (aura::Window::Windows::const_reverse_iterator it_window = | |
| 875 window_list.rbegin(); | |
| 876 it_window != window_list.rend(); ++it_window) { | |
| 877 aura::Window* window = *it_window; | |
| 878 WindowToEntryMap::iterator it_map = window_to_entry_.find(window); | |
| 879 if (it_map != window_to_entry_.end()) { | |
| 880 bool should_be_visible = | |
| 881 it_map->second->show_for_user() == current_user_id_ && | |
| 882 it_map->second->show(); | |
| 883 bool is_visible = window->IsVisible(); | |
| 884 ash::wm::WindowState* window_state = ash::wm::GetWindowState(window); | |
| 885 if (it_map->second->owner() == current_user_id_ && | |
| 886 it_map->second->show_for_user() != current_user_id_ && | |
| 887 window_state->IsMinimized()) { | |
| 888 // Pull back minimized visiting windows to the owners desktop. | |
| 889 ShowWindowForUserIntern(window, current_user_id_); | |
| 890 window_state->Unminimize(); | |
| 891 } else if (should_be_visible != is_visible) { | |
| 892 bool animate = true; | |
| 893 int duration = animation_step == ANIMATION_STEP_FINALIZE ? | |
| 894 kMinimalAnimationTime : (2 * kUserFadeTimeMS); | |
| 895 if (animation_step != ANIMATION_STEP_FINALIZE && | |
| 896 screen_cover_ == BOTH_USERS_COVER_SCREEN && | |
| 897 CoversScreen(window)) { | |
| 898 if (!foreground_window_found) { | |
| 899 foreground_window_found = true; | |
| 900 foreground_becomes_visible = should_be_visible; | |
| 901 } else if (should_be_visible != foreground_becomes_visible) { | |
| 902 // Covering windows behind the foreground window which are | |
| 903 // inverting their visibility should immediately become visible | |
| 904 // or stay visible until the animation is finished. | |
| 905 duration = kMinimalAnimationTime; | |
| 906 if (!should_be_visible) | |
| 907 animate = false; | |
| 908 } | |
| 909 } | |
| 910 if (animate) | |
| 911 SetWindowVisibility(window, should_be_visible, duration); | |
| 912 } | |
| 913 } | |
| 914 } | |
| 915 } | |
| 916 } | |
| 917 | |
| 918 // Activation and real switch are happening after the other user gets shown. | |
| 919 if (animation_step == ANIMATION_STEP_SHOW_NEW_USER) { | |
| 920 // Finally we need to restore the previously active window. | |
| 921 ash::MruWindowTracker::WindowList mru_list = | |
| 922 ash::Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList(); | |
| 923 if (mru_list.size()) { | |
|
oshima
2014/04/03 19:21:41
!empty()
Mr4D (OOO till 08-26)
2014/04/03 22:57:00
Done.
| |
| 924 aura::Window* window = mru_list[0]; | |
| 925 ash::wm::WindowState* window_state = ash::wm::GetWindowState(window); | |
| 926 if (IsWindowOnDesktopOfUser(window, current_user_id_) && | |
| 927 !window_state->IsMinimized()) { | |
| 928 aura::client::ActivationClient* client = | |
| 929 aura::client::GetActivationClient(window->GetRootWindow()); | |
| 930 // Several unit tests come here without an activation client. | |
| 931 if (client) | |
| 932 client->ActivateWindow(window); | |
| 933 } | |
| 934 } | |
| 935 | |
| 936 // This is called directly here to make sure notification_blocker will see | |
| 937 // the new window status. | |
| 938 notification_blocker_->ActiveUserChanged(current_user_id_); | |
| 939 } | |
| 940 } | |
| 941 | |
| 942 MultiUserWindowManagerChromeOS::TransitioningScreenCover | |
| 943 MultiUserWindowManagerChromeOS::GetScreenCover() { | |
| 944 TransitioningScreenCover cover = NO_USER_COVERS_SCREEN; | |
| 945 for (WindowToEntryMap::iterator it_map = window_to_entry_.begin(); | |
| 946 it_map != window_to_entry_.end(); | |
| 947 ++it_map) { | |
| 948 aura::Window* window = it_map->first; | |
| 949 if (window->IsVisible() && CoversScreen(window)) { | |
| 950 if (cover == NEW_USER_COVERS_SCREEN) | |
| 951 return BOTH_USERS_COVER_SCREEN; | |
| 952 else | |
| 953 cover = OLD_USER_COVERS_SCREEN; | |
| 954 } else if (IsWindowOnDesktopOfUser(window, current_user_id_) && | |
| 955 CoversScreen(window)) { | |
| 956 if (cover == OLD_USER_COVERS_SCREEN) | |
| 957 return BOTH_USERS_COVER_SCREEN; | |
| 958 else | |
| 959 cover = NEW_USER_COVERS_SCREEN; | |
| 960 } | |
| 961 } | |
| 962 return cover; | |
| 963 } | |
| 964 | |
| 965 bool MultiUserWindowManagerChromeOS::CoversScreen(aura::Window* window) { | |
| 966 // Full screen covers the screen naturally. Maximized however can be smaller | |
| 967 // then the work area - so we do not check for that mode, but instead check if | |
| 968 // the window is covering everything. | |
| 969 if (ash::wm::GetWindowState(window)->IsFullscreen()) | |
| 970 return true; | |
| 971 gfx::Rect bounds = window->GetBoundsInRootWindow(); | |
| 972 gfx::Rect work_area = gfx::Screen::GetScreenFor(window)-> | |
| 973 GetDisplayNearestWindow(window).work_area(); | |
| 974 bounds.Intersect(work_area); | |
| 975 return work_area == bounds; | |
| 976 } | |
| 977 | |
| 872 } // namespace chrome | 978 } // namespace chrome |
| OLD | NEW |