#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
-#include "apps/shell_window.h"
-#include "apps/shell_window_registry.h"
+#include "apps/app_window.h"
+#include "apps/app_window_registry.h"
#include "ash/ash_switches.h"
+#include "ash/desktop_background/user_wallpaper_delegate.h"
#include "ash/multi_profile_uma.h"
+#include "ash/root_window_controller.h"
#include "ash/session_state_delegate.h"
+#include "ash/shelf/shelf.h"
+#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/shell_window_ids.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/login/wallpaper_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#include "chrome/browser/ui/browser.h"
#include "ui/events/event.h"
#include "ui/message_center/message_center.h"
#include "ui/views/corewm/transient_window_manager.h"
+#include "ui/views/corewm/window_animations.h"
#include "ui/views/corewm/window_util.h"
namespace {
+// The animation time in milliseconds for a single window which is fading
+// in / out.
+static int kAnimationTimeMS = 100;
+
+// The animation time in millseconds for the fade in and / or out when switching
+// users.
+static int kUserFadeTimeMS = 110;
+
+// The animation time in ms for a window which get teleported to another screen.
+static int kTeleportAnimationTimeMS = 300;
+
// Checks if a given event is a user event.
bool IsUserEvent(ui::Event* e) {
if (e) {
if (!g_browser_process->profile_manager())
return;
// If it is not a browser, it is probably be a V2 application. In that case
- // one of the ShellWindowRegistries should know about it.
- apps::ShellWindow* shell_window = NULL;
+ // one of the AppWindowRegistry instances should know about it.
+ apps::AppWindow* app_window = NULL;
std::vector<Profile*> profiles =
g_browser_process->profile_manager()->GetLoadedProfiles();
for (std::vector<Profile*>::iterator it = profiles.begin();
- it != profiles.end() && shell_window == NULL; it++) {
- shell_window = apps::ShellWindowRegistry::Get(
- *it)->GetShellWindowForNativeWindow(window);
+ it != profiles.end() && app_window == NULL;
+ it++) {
+ app_window = apps::AppWindowRegistry::Get(*it)
+ ->GetAppWindowForNativeWindow(window);
}
- if (shell_window) {
- if (shell_window->window_type() ==
- apps::ShellWindow::WINDOW_TYPE_PANEL ||
- shell_window->window_type() ==
- apps::ShellWindow::WINDOW_TYPE_V1_PANEL) {
+ if (app_window) {
+ if (app_window->window_type() == apps::AppWindow::WINDOW_TYPE_PANEL ||
+ app_window->window_type() == apps::AppWindow::WINDOW_TYPE_V1_PANEL) {
window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_PANEL;
} else {
window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_V2_APP;
namespace chrome {
+// A class to temporarily change the animation properties for a window.
+class AnimationSetter {
+ public:
+ AnimationSetter(aura::Window* window, int animation_time_in_ms)
+ : window_(window),
+ previous_animation_type_(
+ views::corewm::GetWindowVisibilityAnimationType(window_)),
+ previous_animation_time_(
+ views::corewm::GetWindowVisibilityAnimationDuration(*window_)) {
+ views::corewm::SetWindowVisibilityAnimationType(
+ window_,
+ views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
+ views::corewm::SetWindowVisibilityAnimationDuration(
+ window_,
+ base::TimeDelta::FromMilliseconds(animation_time_in_ms));
+ }
+
+ ~AnimationSetter() {
+ views::corewm::SetWindowVisibilityAnimationType(window_,
+ previous_animation_type_);
+ views::corewm::SetWindowVisibilityAnimationDuration(
+ window_,
+ previous_animation_time_);
+ }
+
+ private:
+ // The window which gets used.
+ aura::Window* window_;
+
+ // Previous animation type.
+ const int previous_animation_type_;
+
+ // Previous animation time.
+ const base::TimeDelta previous_animation_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(AnimationSetter);
+};
+
// logic while the user gets switched.
class UserChangeActionDisabler {
public:
// When an app gets created, the window will be tagged for that user. Note
// that the destruction does not need to be tracked here since the universal
// window observer will take care of that.
-class AppObserver : public apps::ShellWindowRegistry::Observer {
+class AppObserver : public apps::AppWindowRegistry::Observer {
public:
explicit AppObserver(const std::string& user_id) : user_id_(user_id) {}
virtual ~AppObserver() {}
- // ShellWindowRegistry::Observer overrides:
- virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE {
- aura::Window* window = shell_window->GetNativeWindow();
+ // AppWindowRegistry::Observer overrides:
+ virtual void OnAppWindowAdded(apps::AppWindow* app_window) OVERRIDE {
+ aura::Window* window = app_window->GetNativeWindow();
DCHECK(window);
MultiUserWindowManagerChromeOS::GetInstance()->SetWindowOwner(window,
user_id_);
}
- virtual void OnShellWindowIconChanged(apps::ShellWindow* shell_window)
- OVERRIDE {}
- virtual void OnShellWindowRemoved(apps::ShellWindow* shell_window)
- OVERRIDE {}
+ virtual void OnAppWindowIconChanged(apps::AppWindow* app_window) OVERRIDE {}
+ virtual void OnAppWindowRemoved(apps::AppWindow* app_window) OVERRIDE {}
private:
std::string user_id_;
const std::string& current_user_id)
: current_user_id_(current_user_id),
notification_blocker_(new MultiUserNotificationBlockerChromeOS(
- message_center::MessageCenter::Get(), this)),
- suppress_visibility_changes_(false) {
+ message_center::MessageCenter::Get(), this, current_user_id)),
+ suppress_visibility_changes_(false),
+ animations_disabled_(false) {
// Add a session state observer to be able to monitor session changes.
if (ash::Shell::HasInstance())
ash::Shell::GetInstance()->session_state_delegate()->
MultiUserWindowManagerChromeOS::~MultiUserWindowManagerChromeOS() {
// Remove all window observers.
- WindowToEntryMap::iterator window_observer = window_to_entry_.begin();
- while (window_observer != window_to_entry_.end()) {
- OnWindowDestroyed(window_observer->first);
- window_observer = window_to_entry_.begin();
+ WindowToEntryMap::iterator window = window_to_entry_.begin();
+ while (window != window_to_entry_.end()) {
+ OnWindowDestroyed(window->first);
+ window = window_to_entry_.begin();
}
// Remove all app observers.
- UserIDToShellWindowObserver::iterator app_observer_iterator =
+ UserIDToAppWindowObserver::iterator app_observer_iterator =
user_id_to_app_observer_.begin();
while (app_observer_iterator != user_id_to_app_observer_.end()) {
Profile* profile = multi_user_util::GetProfileFromUserID(
app_observer_iterator->first);
DCHECK(profile);
- apps::ShellWindowRegistry::Get(profile)->RemoveObserver(
- app_observer_iterator->second);
+ apps::AppWindowRegistry::Get(profile)
+ ->RemoveObserver(app_observer_iterator->second);
delete app_observer_iterator->second;
user_id_to_app_observer_.erase(app_observer_iterator);
app_observer_iterator = user_id_to_app_observer_.begin();
// Add observers to track state changes.
window->AddObserver(this);
- ash::wm::GetWindowState(window)->AddObserver(this);
views::corewm::TransientWindowManager::Get(window)->AddObserver(this);
// Check if this window was created due to a user interaction. If it was,
// will add the children but not the owner to the transient children map.
AddTransientOwnerRecursive(window, window);
- // Right now only |notification_blocker_| needs to know when the list of
- // owners may change.
- // TODO(skuhne): replace this by observer when another one needs this event.
- notification_blocker_->UpdateWindowOwners();
+ // Notify entry adding.
+ FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryAdded(window));
if (!IsWindowOnDesktopOfUser(window, current_user_id_))
- SetWindowVisibility(window, false);
+ SetWindowVisibility(window, false, 0);
}
const std::string& MultiUserWindowManagerChromeOS::GetWindowOwner(
void MultiUserWindowManagerChromeOS::ShowWindowForUser(
aura::Window* window,
const std::string& user_id) {
- // If there is either no owner, or the owner is the current user, no action
- // is required.
- const std::string& owner = GetWindowOwner(window);
- if (owner.empty() ||
- (owner == user_id && IsWindowOnDesktopOfUser(window, user_id)))
+ std::string previous_owner(GetUserPresentingWindow(window));
+ if (!ShowWindowForUserIntern(window, user_id))
return;
-
- bool minimized = ash::wm::GetWindowState(window)->IsMinimized();
- // Check that we are not trying to transfer ownership of a minimized window.
- if (user_id != owner && minimized)
+ // The window switched to a new desktop and we have to switch to that desktop,
+ // but only when it was on the visible desktop and the the target is not the
+ // visible desktop.
+ if (user_id == current_user_id_ || previous_owner != current_user_id_)
return;
- if (minimized) {
- // If it is minimized it falls back to the original desktop.
- ash::MultiProfileUMA::RecordTeleportAction(
- ash::MultiProfileUMA::TELEPORT_WINDOW_RETURN_BY_MINIMIZE);
- } else {
- // If the window was transferred without getting minimized, we should record
- // the window type.
- RecordUMAForTransferredWindowType(window);
- }
-
- WindowToEntryMap::iterator it = window_to_entry_.find(window);
- it->second->set_show_for_user(user_id);
-
- // Show the window if the added user is the current one.
- if (user_id == current_user_id_) {
- // Only show the window if it should be shown according to its state.
- if (it->second->show())
- SetWindowVisibility(window, true);
- } else {
- SetWindowVisibility(window, false);
- }
-
- // TODO(skuhne): replace this by observer when another one needs this event.
- notification_blocker_->UpdateWindowOwners();
+ ash::Shell::GetInstance()->session_state_delegate()->SwitchActiveUser(
+ user_id);
}
bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() {
return;
user_id_to_app_observer_[user_id] = new AppObserver(user_id);
- apps::ShellWindowRegistry::Get(profile)->AddObserver(
- user_id_to_app_observer_[user_id]);
+ apps::AppWindowRegistry::Get(profile)
+ ->AddObserver(user_id_to_app_observer_[user_id]);
// Account all existing application windows of this user accordingly.
- const apps::ShellWindowRegistry::ShellWindowList& shell_windows =
- apps::ShellWindowRegistry::Get(profile)->shell_windows();
- apps::ShellWindowRegistry::ShellWindowList::const_iterator it =
- shell_windows.begin();
- for (; it != shell_windows.end(); ++it)
- user_id_to_app_observer_[user_id]->OnShellWindowAdded(*it);
+ const apps::AppWindowRegistry::AppWindowList& app_windows =
+ apps::AppWindowRegistry::Get(profile)->app_windows();
+ apps::AppWindowRegistry::AppWindowList::const_iterator it =
+ app_windows.begin();
+ for (; it != app_windows.end(); ++it)
+ user_id_to_app_observer_[user_id]->OnAppWindowAdded(*it);
// Account all existing browser windows of this user accordingly.
BrowserList* browser_list = BrowserList::GetInstance(HOST_DESKTOP_TYPE_ASH);
}
}
+void MultiUserWindowManagerChromeOS::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void MultiUserWindowManagerChromeOS::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
void MultiUserWindowManagerChromeOS::ActiveUserChanged(
const std::string& user_id) {
DCHECK(user_id != current_user_id_);
- std::string old_user = current_user_id_;
current_user_id_ = user_id;
- // Disable the window position manager and the MRU window tracker temporarily.
- scoped_ptr<UserChangeActionDisabler> disabler(new UserChangeActionDisabler);
-
- // We need to show/hide the windows in the same order as they were created in
- // their parent window(s) to keep the layer / window hierarchy in sync. To
- // achieve that we first collect all parent windows and then enumerate all
- // windows in those parent windows and show or hide them accordingly.
-
- // Create a list of all parent windows we have to check and their parents.
- std::set<aura::Window*> parent_list;
- for (WindowToEntryMap::iterator it = window_to_entry_.begin();
- it != window_to_entry_.end(); ++it) {
- aura::Window* parent = it->first->parent();
- if (parent_list.find(parent) == parent_list.end())
- parent_list.insert(parent);
- }
-
- // Traverse the found parent windows to handle their child windows in order of
- // their appearance.
- for (std::set<aura::Window*>::iterator it_parents = parent_list.begin();
- it_parents != parent_list.end(); ++it_parents) {
- const aura::Window::Windows window_list = (*it_parents)->children();
- for (aura::Window::Windows::const_iterator it_window = window_list.begin();
- it_window != window_list.end(); ++it_window) {
- aura::Window* window = *it_window;
- WindowToEntryMap::iterator it_map = window_to_entry_.find(window);
- if (it_map != window_to_entry_.end()) {
- bool should_be_visible = it_map->second->show_for_user() == user_id &&
- it_map->second->show();
- bool is_visible = window->IsVisible();
- if (should_be_visible != is_visible)
- SetWindowVisibility(window, should_be_visible);
- }
- }
- }
-
- // Finally we need to restore the previously active window.
- ash::MruWindowTracker::WindowList mru_list =
- ash::Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList();
- if (mru_list.size()) {
- aura::Window* window = mru_list[0];
- ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
- if (IsWindowOnDesktopOfUser(window, user_id) &&
- !window_state->IsMinimized()) {
- aura::client::ActivationClient* client =
- aura::client::GetActivationClient(window->GetRootWindow());
- // Several unit tests come here without an activation client.
- if (client)
- client->ActivateWindow(window);
- }
+ // If there is an animation in progress finish the pending switch which also
+ // kills the timer (if there is one).
+ if (user_changed_animation_timer_.get())
+ TransitionUser(SHOW_NEW_USER);
+
+ // Start the animation by hiding the old user.
+ TransitionUser(HIDE_OLD_USER);
+
+ // If animations are disabled we immediately switch to the new user, otherwise
+ // we create a timer which will fade in the new user once the other user has
+ // been faded away.
+ if (animations_disabled_) {
+ TransitionUser(SHOW_NEW_USER);
+ } else {
+ user_changed_animation_timer_.reset(new base::Timer(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kUserFadeTimeMS),
+ base::Bind(&MultiUserWindowManagerChromeOS::TransitionUser,
+ base::Unretained(this),
+ SHOW_NEW_USER),
+ false));
+ user_changed_animation_timer_->Reset();
}
-
- // This is called directly here to make sure notification_blocker will see the
- // new window status.
- notification_blocker_->ActiveUserChanged(user_id);
}
void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) {
RemoveTransientOwnerRecursive(window);
return;
}
- ash::wm::GetWindowState(window)->RemoveObserver(this);
views::corewm::TransientWindowManager::Get(window)->RemoveObserver(this);
// Remove the window from the owners list.
delete window_to_entry_[window];
window_to_entry_.erase(window);
- // TODO(skuhne): replace this by observer when another one needs this event.
- notification_blocker_->UpdateWindowOwners();
+
+ // Notify entry change.
+ FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryRemoved(window));
}
void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanging(
// Don't allow to make the window visible if it shouldn't be.
if (visible && !IsWindowOnDesktopOfUser(window, current_user_id_)) {
- SetWindowVisibility(window, false);
+ SetWindowVisibility(window, false, 0);
return;
}
aura::Window* owned_parent = GetOwningWindowInTransientChain(window);
if (owned_parent && owned_parent != window && visible &&
!IsWindowOnDesktopOfUser(owned_parent, current_user_id_))
- SetWindowVisibility(window, false);
+ SetWindowVisibility(window, false, 0);
}
void MultiUserWindowManagerChromeOS::OnTransientChildAdded(
RemoveTransientOwnerRecursive(transient_window);
}
-void MultiUserWindowManagerChromeOS::OnWindowShowTypeChanged(
- ash::wm::WindowState* window_state,
- ash::wm::WindowShowType old_type) {
- if (!window_state->IsMinimized())
- return;
-
- aura::Window* window = window_state->window();
- // If the window was shown on a different users desktop: move it back.
- const std::string& owner = GetWindowOwner(window);
- if (!IsWindowOnDesktopOfUser(window, owner))
- ShowWindowForUser(window, owner);
-}
-
void MultiUserWindowManagerChromeOS::Observe(
int type,
const content::NotificationSource& source,
AddBrowserWindow(content::Source<Browser>(source).ptr());
}
+void MultiUserWindowManagerChromeOS::SetAnimationsForTest(bool disable) {
+ animations_disabled_ = disable;
+}
+
+bool MultiUserWindowManagerChromeOS::IsAnimationRunningForTest() {
+ return user_changed_animation_timer_.get() != NULL;
+}
+
+const std::string& MultiUserWindowManagerChromeOS::GetCurrentUserForTest() {
+ return current_user_id_;
+}
+
+bool MultiUserWindowManagerChromeOS::ShowWindowForUserIntern(
+ aura::Window* window,
+ const std::string& user_id) {
+ // If there is either no owner, or the owner is the current user, no action
+ // is required.
+ const std::string& owner = GetWindowOwner(window);
+ if (owner.empty() ||
+ (owner == user_id && IsWindowOnDesktopOfUser(window, user_id)))
+ return false;
+
+ bool minimized = ash::wm::GetWindowState(window)->IsMinimized();
+ // Check that we are not trying to transfer ownership of a minimized window.
+ if (user_id != owner && minimized)
+ return false;
+
+ if (minimized) {
+ // If it is minimized it falls back to the original desktop.
+ ash::MultiProfileUMA::RecordTeleportAction(
+ ash::MultiProfileUMA::TELEPORT_WINDOW_RETURN_BY_MINIMIZE);
+ } else {
+ // If the window was transferred without getting minimized, we should record
+ // the window type.
+ RecordUMAForTransferredWindowType(window);
+ }
+
+ WindowToEntryMap::iterator it = window_to_entry_.find(window);
+ it->second->set_show_for_user(user_id);
+
+ // Show the window if the added user is the current one.
+ if (user_id == current_user_id_) {
+ // Only show the window if it should be shown according to its state.
+ if (it->second->show())
+ SetWindowVisibility(window, true, kTeleportAnimationTimeMS);
+ } else {
+ SetWindowVisibility(window, false, kTeleportAnimationTimeMS);
+ }
+
+ // Notify entry change.
+ FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryChanged(window));
+ return true;
+}
+
+void MultiUserWindowManagerChromeOS::TransitionUser(
+ MultiUserWindowManagerChromeOS::AnimationStep animation_step) {
+ TransitionWallpaper(animation_step);
+ TransitionUserShelf(animation_step);
+
+ // Disable the window position manager and the MRU window tracker temporarily.
+ scoped_ptr<UserChangeActionDisabler> disabler(new UserChangeActionDisabler);
+
+ // We need to show/hide the windows in the same order as they were created in
+ // their parent window(s) to keep the layer / window hierarchy in sync. To
+ // achieve that we first collect all parent windows and then enumerate all
+ // windows in those parent windows and show or hide them accordingly.
+
+ // Create a list of all parent windows we have to check and their parents.
+ std::set<aura::Window*> parent_list;
+ for (WindowToEntryMap::iterator it = window_to_entry_.begin();
+ it != window_to_entry_.end(); ++it) {
+ aura::Window* parent = it->first->parent();
+ if (parent_list.find(parent) == parent_list.end())
+ parent_list.insert(parent);
+ }
+
+ // Traverse the found parent windows to handle their child windows in order of
+ // their appearance.
+ for (std::set<aura::Window*>::iterator it_parents = parent_list.begin();
+ it_parents != parent_list.end(); ++it_parents) {
+ const aura::Window::Windows window_list = (*it_parents)->children();
+ for (aura::Window::Windows::const_iterator it_window = window_list.begin();
+ it_window != window_list.end(); ++it_window) {
+ aura::Window* window = *it_window;
+ WindowToEntryMap::iterator it_map = window_to_entry_.find(window);
+ if (it_map != window_to_entry_.end()) {
+ bool should_be_visible =
+ it_map->second->show_for_user() == current_user_id_ &&
+ it_map->second->show();
+ bool is_visible = window->IsVisible();
+ ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
+ if (animation_step == SHOW_NEW_USER &&
+ it_map->second->owner() == current_user_id_ &&
+ it_map->second->show_for_user() != current_user_id_ &&
+ window_state->IsMinimized()) {
+ // Pull back minimized visiting windows to the owners desktop.
+ ShowWindowForUserIntern(window, current_user_id_);
+ window_state->Unminimize();
+ } else if (should_be_visible != is_visible &&
+ should_be_visible == (animation_step == SHOW_NEW_USER)) {
+ SetWindowVisibility(window, should_be_visible, kUserFadeTimeMS);
+ }
+ }
+ }
+ }
+
+ // Activation and real switch are happening after the other user gets shown.
+ if (animation_step == SHOW_NEW_USER) {
+ // Finally we need to restore the previously active window.
+ ash::MruWindowTracker::WindowList mru_list =
+ ash::Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList();
+ if (mru_list.size()) {
+ aura::Window* window = mru_list[0];
+ ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
+ if (IsWindowOnDesktopOfUser(window, current_user_id_) &&
+ !window_state->IsMinimized()) {
+ aura::client::ActivationClient* client =
+ aura::client::GetActivationClient(window->GetRootWindow());
+ // Several unit tests come here without an activation client.
+ if (client)
+ client->ActivateWindow(window);
+ }
+ }
+
+ // This is called directly here to make sure notification_blocker will see
+ // the new window status.
+ notification_blocker_->ActiveUserChanged(current_user_id_);
+
+ // We can reset the timer at this point.
+ // Note: The timer can be destroyed while it is performing its task.
+ user_changed_animation_timer_.reset();
+ }
+}
+
+void MultiUserWindowManagerChromeOS::TransitionWallpaper(
+ MultiUserWindowManagerChromeOS::AnimationStep animation_step) {
+ // Handle the wallpaper switch.
+ if (chromeos::WallpaperManager::Get()) {
+ ash::UserWallpaperDelegate* wallpaper_delegate =
+ ash::Shell::GetInstance()->user_wallpaper_delegate();
+ if (animation_step == HIDE_OLD_USER) {
+ // Set the wallpaper cross dissolve animation duration to our complete
+ // animation cycle for a fade in and fade out.
+ wallpaper_delegate->SetAnimationDurationOverride(2 * kUserFadeTimeMS);
+ chromeos::WallpaperManager::Get()->SetUserWallpaperDelayed(
+ current_user_id_);
+ } else {
+ // Revert the wallpaper cross dissolve animation duration back to the
+ // default.
+ wallpaper_delegate->SetAnimationDurationOverride(0);
+ }
+ }
+}
+
+void MultiUserWindowManagerChromeOS::TransitionUserShelf(
+ MultiUserWindowManagerChromeOS::AnimationStep animation_step) {
+ // The shelf animation duration override.
+ int duration_override = kUserFadeTimeMS;
+ // Handle the shelf order of items. This is done once the old user is hidden.
+ if (animation_step == SHOW_NEW_USER) {
+ // Some unit tests have no ChromeLauncherController.
+ if (ChromeLauncherController::instance())
+ ChromeLauncherController::instance()->ActiveUserChanged(current_user_id_);
+ // We kicked off the shelf animation in the command above. As such we can
+ // disable the override now again.
+ duration_override = 0;
+ }
+
+ if (animations_disabled_)
+ return;
+
+ ash::Shell::RootWindowControllerList controller =
+ ash::Shell::GetInstance()->GetAllRootWindowControllers();
+ for (ash::Shell::RootWindowControllerList::iterator it1 = controller.begin();
+ it1 != controller.end(); ++it1) {
+ (*it1)->GetShelfLayoutManager()->SetAnimationDurationOverride(
+ duration_override);
+ }
+
+ // For each root window hide the shelf.
+ if (animation_step == HIDE_OLD_USER) {
+ aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
+ for (aura::Window::Windows::const_iterator iter = root_windows.begin();
+ iter != root_windows.end(); ++iter) {
+ ash::Shell::GetInstance()->SetShelfAutoHideBehavior(
+ ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN, *iter);
+ }
+ }
+}
+
void MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) {
// A unit test (e.g. CrashRestoreComplexTest.RestoreSessionForThreeUsers) can
// come here with no valid window.
}
void MultiUserWindowManagerChromeOS::SetWindowVisibility(
- aura::Window* window, bool visible) {
+ aura::Window* window, bool visible, int animation_time_in_ms) {
if (window->IsVisible() == visible)
return;
base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true);
if (visible) {
- ShowWithTransientChildrenRecursive(window);
+ ShowWithTransientChildrenRecursive(window, animation_time_in_ms);
} else {
if (window->HasFocus())
window->Blur();
- window->Hide();
+ SetWindowVisible(window, false, animation_time_in_ms);
}
}
void MultiUserWindowManagerChromeOS::ShowWithTransientChildrenRecursive(
- aura::Window* window) {
+ aura::Window* window, int animation_time_in_ms) {
aura::Window::Windows::const_iterator it =
views::corewm::GetTransientChildren(window).begin();
for (; it != views::corewm::GetTransientChildren(window).end(); ++it)
- ShowWithTransientChildrenRecursive(*it);
+ ShowWithTransientChildrenRecursive(*it, animation_time_in_ms);
// We show all children which were not explicitly hidden.
TransientWindowToVisibility::iterator it2 =
transient_window_to_visibility_.find(window);
if (it2 == transient_window_to_visibility_.end() || it2->second)
- window->Show();
+ SetWindowVisible(window, true, animation_time_in_ms);
}
aura::Window* MultiUserWindowManagerChromeOS::GetOwningWindowInTransientChain(
// will hide recursively this and all children - but we have already collected
// their initial view state.
if (!IsWindowOnDesktopOfUser(owned_parent, current_user_id_))
- SetWindowVisibility(window, false);
+ SetWindowVisibility(window, false, kAnimationTimeMS);
}
void MultiUserWindowManagerChromeOS::RemoveTransientOwnerRecursive(
}
}
+void MultiUserWindowManagerChromeOS::SetWindowVisible(
+ aura::Window* window,
+ bool visible,
+ int animation_time_in_ms) {
+ AnimationSetter animation_setter(
+ window,
+ animations_disabled_ ? 0 : animation_time_in_ms);
+
+ if (visible)
+ window->Show();
+ else
+ window->Hide();
+
+ // Make sure that animations have no influence on the window state after the
+ // call.
+ DCHECK_EQ(visible, window->IsVisible());
+}
+
} // namespace chrome