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 |