// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "ash/session/user_info.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/test_session_state_delegate.h"
#include "ash/test/test_shell_delegate.h"
+#include "ash/wm/maximize_mode/maximize_mode_controller.h"
+#include "ash/wm/maximize_mode/maximize_mode_window_manager.h"
#include "ash/wm/window_state.h"
+#include "ash/wm/wm_event.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
+#include "base/time/time.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h"
#include "chrome/test/base/testing_profile.h"
-#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/ui_base_types.h"
-#include "ui/views/corewm/window_util.h"
+#include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
namespace ash {
namespace test {
// Set up the test environment for this many windows.
void SetUpForThisManyWindows(int windows);
+ // Switch the user and wait until the animation is finished.
+ void SwitchUserAndWaitForAnimation(const std::string& user_id) {
+ multi_user_window_manager_->ActiveUserChanged(user_id);
+ base::TimeTicks now = base::TimeTicks::Now();
+ while (multi_user_window_manager_->IsAnimationRunningForTest()) {
+ // This should never take longer then a second.
+ ASSERT_GE(1000, (base::TimeTicks::Now() - now).InMilliseconds());
+ base::MessageLoop::current()->RunUntilIdle();
+ }
+ }
+
// Return the window with the given index.
aura::Window* window(size_t index) {
DCHECK(index < window_.size());
void MakeWindowSystemModal(aura::Window* window) {
aura::Window* system_modal_container =
window->GetRootWindow()->GetChildById(
- ash::internal::kShellWindowId_SystemModalContainer);
+ ash::kShellWindowId_SystemModalContainer);
system_modal_container->AddChild(window);
}
+ void ShowWindowForUserNoUserTransition(aura::Window* window,
+ const std::string& user_id) {
+ multi_user_window_manager_->ShowWindowForUserIntern(window, user_id);
+ }
+
+ // The test session state observer does not automatically call the window
+ // manager. This function gets the current user from it and also sets it to
+ // the multi user window manager.
+ std::string GetAndValidateCurrentUserFromSessionStateObserver() {
+ const std::string& user =
+ session_state_delegate()->GetActiveUserInfo()->GetUserID();
+ if (user != multi_user_window_manager_->GetCurrentUserForTest())
+ multi_user_window_manager()->ActiveUserChanged(user);
+ return user;
+ }
+
+ // Initiate a user transition.
+ void StartUserTransitionAnimation(const std::string& user_id) {
+ multi_user_window_manager_->ActiveUserChanged(user_id);
+ }
+
+ // Call next animation step.
+ void AdvanceUserTransitionAnimation() {
+ multi_user_window_manager_->animation_->AdvanceUserTransitionAnimation();
+ }
+
+ // Return the user id of the wallpaper which is currently set.
+ const std::string& GetWallaperUserIdForTest() {
+ return multi_user_window_manager_->animation_->wallpaper_user_id_for_test();
+ }
+
+ // Returns true if the given window covers the screen.
+ bool CoversScreen(aura::Window* window) {
+ return chrome::UserSwichAnimatorChromeOS::CoversScreen(
+ window);
+ }
+
+ // Create a maximize mode window manager.
+ ash::MaximizeModeWindowManager* CreateMaximizeModeWindowManager() {
+ EXPECT_FALSE(maximize_mode_window_manager());
+ Shell::GetInstance()->maximize_mode_controller()->
+ EnableMaximizeModeWindowManager(true);
+ return maximize_mode_window_manager();
+ }
+
+ ash::MaximizeModeWindowManager* maximize_mode_window_manager() {
+ return Shell::GetInstance()->maximize_mode_controller()->
+ maximize_mode_window_manager_.get();
+ }
+
private:
// These get created for each session.
std::vector<aura::Window*> window_;
// The session state delegate.
ash::test::TestSessionStateDelegate* session_state_delegate_;
+ // The maximized window manager (if enabled).
+ scoped_ptr<MaximizeModeWindowManager> maximize_mode_window_manager_;
+
DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManagerChromeOSTest);
};
void MultiUserWindowManagerChromeOSTest::SetUp() {
- CommandLine::ForCurrentProcess()->AppendSwitch(switches::kMultiProfiles);
AshTestBase::SetUp();
session_state_delegate_ =
static_cast<TestSessionStateDelegate*> (
ash::Shell::GetInstance()->session_state_delegate());
+ session_state_delegate_->AddUser("a");
+ session_state_delegate_->AddUser("b");
+ session_state_delegate_->AddUser("c");
}
void MultiUserWindowManagerChromeOSTest::SetUpForThisManyWindows(int windows) {
window_[i]->Show();
}
multi_user_window_manager_ = new chrome::MultiUserWindowManagerChromeOS("A");
+ multi_user_window_manager_->SetAnimationSpeedForTest(
+ chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_DISABLED);
chrome::MultiUserWindowManager::SetInstanceForTest(multi_user_window_manager_,
chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED);
EXPECT_TRUE(multi_user_window_manager_);
// Overriding it with another state should show it on the other user's
// desktop.
- multi_user_window_manager()->ShowWindowForUser(window(0), "B");
+ ShowWindowForUserNoUserTransition(window(0), "B");
EXPECT_EQ("A", multi_user_window_manager()->GetWindowOwner(window(0)));
EXPECT_EQ("B",
multi_user_window_manager()->GetUserPresentingWindow(window(0)));
SetUpForThisManyWindows(1);
multi_user_window_manager()->SetWindowOwner(window(0), "B");
EXPECT_EQ("H[B]", GetStatus());
- multi_user_window_manager()->ShowWindowForUser(window(0), "A");
+ ShowWindowForUserNoUserTransition(window(0), "A");
EXPECT_EQ("S[B,A]", GetStatus());
EXPECT_TRUE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
EXPECT_EQ("B", GetOwnersOfVisibleWindowsAsString());
EXPECT_EQ("A", GetOwnersOfVisibleWindowsAsString());
// For all following tests we override window 2 to be shown by user B.
- multi_user_window_manager()->ShowWindowForUser(window(1), "B");
+ ShowWindowForUserNoUserTransition(window(1), "B");
// Change window 3 between two users and see that it changes
// accordingly (or not).
- multi_user_window_manager()->ShowWindowForUser(window(2), "A");
+ ShowWindowForUserNoUserTransition(window(2), "A");
EXPECT_EQ("S[A], H[A,B], S[B,A], H[B], H[C]", GetStatus());
EXPECT_TRUE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
EXPECT_EQ("A B", GetOwnersOfVisibleWindowsAsString());
- multi_user_window_manager()->ShowWindowForUser(window(2), "C");
+ ShowWindowForUserNoUserTransition(window(2), "C");
EXPECT_EQ("S[A], H[A,B], H[B,C], H[B], H[C]", GetStatus());
EXPECT_TRUE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
EXPECT_EQ("A", GetOwnersOfVisibleWindowsAsString());
EXPECT_EQ("B C", GetOwnersOfVisibleWindowsAsString());
// Showing on the desktop of the already owning user should have no impact.
- multi_user_window_manager()->ShowWindowForUser(window(4), "C");
+ ShowWindowForUserNoUserTransition(window(4), "C");
EXPECT_EQ("H[A], H[A,B], S[B,C], H[B], S[C]", GetStatus());
EXPECT_EQ("B C", GetOwnersOfVisibleWindowsAsString());
// Changing however a shown window back to the original owner should hide it.
- multi_user_window_manager()->ShowWindowForUser(window(2), "B");
+ ShowWindowForUserNoUserTransition(window(2), "B");
EXPECT_EQ("H[A], H[A,B], H[B], H[B], S[C]", GetStatus());
EXPECT_TRUE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
EXPECT_EQ("C", GetOwnersOfVisibleWindowsAsString());
// After switching window 2 back to its original desktop, all desktops should
// be "clean" again.
- multi_user_window_manager()->ShowWindowForUser(window(1), "A");
+ ShowWindowForUserNoUserTransition(window(1), "A");
EXPECT_FALSE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
}
multi_user_window_manager()->SetWindowOwner(window(0), "B");
// Add two references to the same window.
- multi_user_window_manager()->ShowWindowForUser(window(0), "A");
- multi_user_window_manager()->ShowWindowForUser(window(0), "A");
+ ShowWindowForUserNoUserTransition(window(0), "A");
+ ShowWindowForUserNoUserTransition(window(0), "A");
EXPECT_TRUE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
// Close the window.
multi_user_window_manager()->SetWindowOwner(window(1), "A");
multi_user_window_manager()->SetWindowOwner(window(2), "B");
multi_user_window_manager()->SetWindowOwner(window(3), "B");
- multi_user_window_manager()->ShowWindowForUser(window(2), "A");
- multi_user_window_manager()->ShowWindowForUser(window(3), "A");
+ ShowWindowForUserNoUserTransition(window(2), "A");
+ ShowWindowForUserNoUserTransition(window(3), "A");
EXPECT_EQ("S[A], S[A], S[B,A], S[B,A], S[]", GetStatus());
// Hiding a window should be respected - no matter if it is owned by that user
}
// Check that minimizing a window which is owned by another user will move it
-// back.
+// back and gets restored upon switching back to the original user.
TEST_F(MultiUserWindowManagerChromeOSTest, MinimizeChangesOwnershipBack) {
SetUpForThisManyWindows(4);
multi_user_window_manager()->SetWindowOwner(window(0), "A");
multi_user_window_manager()->SetWindowOwner(window(1), "B");
multi_user_window_manager()->SetWindowOwner(window(2), "B");
- multi_user_window_manager()->ShowWindowForUser(window(1), "A");
+ ShowWindowForUserNoUserTransition(window(1), "A");
EXPECT_EQ("S[A], S[B,A], H[B], S[]", GetStatus());
EXPECT_TRUE(multi_user_window_manager()->IsWindowOnDesktopOfUser(window(1),
"A"));
wm::GetWindowState(window(1))->Minimize();
- EXPECT_EQ("S[A], H[B], H[B], S[]", GetStatus());
- EXPECT_FALSE(multi_user_window_manager()->IsWindowOnDesktopOfUser(window(1),
- "A"));
-
+ // At this time the window is still on the desktop of that user, but the user
+ // does not have a way to get to it.
+ EXPECT_EQ("S[A], H[B,A], H[B], S[]", GetStatus());
+ EXPECT_TRUE(multi_user_window_manager()->IsWindowOnDesktopOfUser(window(1),
+ "A"));
+ EXPECT_TRUE(wm::GetWindowState(window(1))->IsMinimized());
// Change to user B and make sure that minimizing does not change anything.
multi_user_window_manager()->ActiveUserChanged("B");
- EXPECT_EQ("H[A], H[B], S[B], S[]", GetStatus());
- wm::GetWindowState(window(1))->Minimize();
- EXPECT_EQ("H[A], H[B], S[B], S[]", GetStatus());
+ EXPECT_EQ("H[A], S[B], S[B], S[]", GetStatus());
+ EXPECT_FALSE(wm::GetWindowState(window(1))->IsMinimized());
}
// Check that we cannot transfer the ownership of a minimized window.
EXPECT_EQ("H[A]", GetStatus());
// Try to transfer the window to user B - which should get ignored.
- multi_user_window_manager()->ShowWindowForUser(window(0), "B");
+ ShowWindowForUserNoUserTransition(window(0), "B");
EXPECT_EQ("H[A]", GetStatus());
}
// 3 - ..
multi_user_window_manager()->SetWindowOwner(window(0), "A");
multi_user_window_manager()->SetWindowOwner(window(4), "B");
- views::corewm::AddTransientChild(window(0), window(1));
+ ::wm::AddTransientChild(window(0), window(1));
// We first attach 2->3 and then 1->2 to see that the ownership gets
// properly propagated through the sub tree upon assigning.
- views::corewm::AddTransientChild(window(2), window(3));
- views::corewm::AddTransientChild(window(1), window(2));
- views::corewm::AddTransientChild(window(4), window(5));
- views::corewm::AddTransientChild(window(4), window(6));
- views::corewm::AddTransientChild(window(7), window(8));
- views::corewm::AddTransientChild(window(7), window(9));
+ ::wm::AddTransientChild(window(2), window(3));
+ ::wm::AddTransientChild(window(1), window(2));
+ ::wm::AddTransientChild(window(4), window(5));
+ ::wm::AddTransientChild(window(4), window(6));
+ ::wm::AddTransientChild(window(7), window(8));
+ ::wm::AddTransientChild(window(7), window(9));
// By now the hierarchy should have updated itself to show all windows of A
// and hide all windows of B. Unowned windows should remain in what ever state
// 1 5 8
// |
// 9
- views::corewm::RemoveTransientChild(window(2), window(3));
- views::corewm::RemoveTransientChild(window(4), window(6));
+ ::wm::RemoveTransientChild(window(2), window(3));
+ ::wm::RemoveTransientChild(window(4), window(6));
EXPECT_EQ("S[A], S[], H[], H[], H[B], H[], S[], S[], S[], H[]", GetStatus());
// Before we leave we need to reverse all transient window ownerships.
- views::corewm::RemoveTransientChild(window(0), window(1));
- views::corewm::RemoveTransientChild(window(1), window(2));
- views::corewm::RemoveTransientChild(window(4), window(5));
- views::corewm::RemoveTransientChild(window(7), window(8));
- views::corewm::RemoveTransientChild(window(7), window(9));
+ ::wm::RemoveTransientChild(window(0), window(1));
+ ::wm::RemoveTransientChild(window(1), window(2));
+ ::wm::RemoveTransientChild(window(4), window(5));
+ ::wm::RemoveTransientChild(window(7), window(8));
+ ::wm::RemoveTransientChild(window(7), window(9));
}
// Test that the initial visibility state gets remembered.
// Second test: Transferring the window to another desktop preserves the
// show state.
- multi_user_window_manager()->ShowWindowForUser(window(0), "B");
- multi_user_window_manager()->ShowWindowForUser(window(1), "B");
- multi_user_window_manager()->ShowWindowForUser(window(2), "A");
- multi_user_window_manager()->ShowWindowForUser(window(3), "A");
+ ShowWindowForUserNoUserTransition(window(0), "B");
+ ShowWindowForUserNoUserTransition(window(1), "B");
+ ShowWindowForUserNoUserTransition(window(2), "A");
+ ShowWindowForUserNoUserTransition(window(3), "A");
EXPECT_EQ("H[A,B], H[A,B], S[B,A], H[B,A]", GetStatus());
multi_user_window_manager()->ActiveUserChanged("B");
EXPECT_EQ("S[A,B], H[A,B], H[B,A], H[B,A]", GetStatus());
EXPECT_EQ("H[A,B], H[A,B], S[B,A], H[B,A]", GetStatus());
}
+// Test that in case of an activated maximize mode, windows from other users get
+// maximized after a user switch.
+TEST_F(MultiUserWindowManagerChromeOSTest, MaximizeModeInteraction) {
+ SetUpForThisManyWindows(2);
+
+ multi_user_window_manager()->SetWindowOwner(window(0), "A");
+ multi_user_window_manager()->SetWindowOwner(window(1), "B");
+
+ EXPECT_FALSE(wm::GetWindowState(window(0))->IsMaximized());
+ EXPECT_FALSE(wm::GetWindowState(window(1))->IsMaximized());
+
+ ash::MaximizeModeWindowManager* manager = CreateMaximizeModeWindowManager();
+ ASSERT_TRUE(manager);
+
+ EXPECT_TRUE(wm::GetWindowState(window(0))->IsMaximized());
+ EXPECT_FALSE(wm::GetWindowState(window(1))->IsMaximized());
+
+ // After we start switching to B, the windows of user B should maximize.
+ StartUserTransitionAnimation("B");
+
+ EXPECT_TRUE(wm::GetWindowState(window(0))->IsMaximized());
+ EXPECT_TRUE(wm::GetWindowState(window(1))->IsMaximized());
+}
+
// Test that a system modal dialog will switch to the desktop of the owning
// user.
TEST_F(MultiUserWindowManagerChromeOSTest, SwitchUsersUponModalityChange) {
// Making the window system modal should not change anything.
MakeWindowSystemModal(window(0));
- EXPECT_EQ("a", session_state_delegate()->get_activated_user());
+ EXPECT_EQ("a", session_state_delegate()->GetActiveUserInfo()->GetUserID());
// Making the window owned by user B should switch users.
multi_user_window_manager()->SetWindowOwner(window(0), "b");
- EXPECT_EQ("b", session_state_delegate()->get_activated_user());
+ EXPECT_EQ("b", session_state_delegate()->GetActiveUserInfo()->GetUserID());
}
// Test that a system modal dialog will not switch desktop if active user has
// Making the window system modal should not change anything.
MakeWindowSystemModal(window(0));
- EXPECT_EQ("a", session_state_delegate()->get_activated_user());
+ EXPECT_EQ("a", session_state_delegate()->GetActiveUserInfo()->GetUserID());
// Making the window owned by user a should not switch users.
multi_user_window_manager()->SetWindowOwner(window(0), "a");
- EXPECT_EQ("a", session_state_delegate()->get_activated_user());
+ EXPECT_EQ("a", session_state_delegate()->GetActiveUserInfo()->GetUserID());
}
// Test that a system modal dialog will not switch if shown on correct desktop
window(0)->Hide();
multi_user_window_manager()->SetWindowOwner(window(0), "b");
- multi_user_window_manager()->ShowWindowForUser(window(0), "a");
+ ShowWindowForUserNoUserTransition(window(0), "a");
MakeWindowSystemModal(window(0));
// Showing the window should trigger no user switch.
window(0)->Show();
- EXPECT_EQ("a", session_state_delegate()->get_activated_user());
+ EXPECT_EQ("a", session_state_delegate()->GetActiveUserInfo()->GetUserID());
}
// Test that a system modal dialog will switch if shown on incorrect desktop but
window(0)->Hide();
multi_user_window_manager()->SetWindowOwner(window(0), "a");
- multi_user_window_manager()->ShowWindowForUser(window(0), "b");
+ ShowWindowForUserNoUserTransition(window(0), "b");
MakeWindowSystemModal(window(0));
// Showing the window should trigger a user switch.
window(0)->Show();
- EXPECT_EQ("b", session_state_delegate()->get_activated_user());
+ EXPECT_EQ("b", session_state_delegate()->GetActiveUserInfo()->GetUserID());
+}
+
+// Test that using the full user switch animations are working as expected.
+TEST_F(MultiUserWindowManagerChromeOSTest, FullUserSwitchAnimationTests) {
+ SetUpForThisManyWindows(3);
+ // Turn the use of delays and animation on.
+ multi_user_window_manager()->SetAnimationSpeedForTest(
+ chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST);
+ // Set some owners and make sure we got what we asked for.
+ multi_user_window_manager()->SetWindowOwner(window(0), "A");
+ multi_user_window_manager()->SetWindowOwner(window(1), "B");
+ multi_user_window_manager()->SetWindowOwner(window(2), "C");
+ EXPECT_EQ("S[A], H[B], H[C]", GetStatus());
+ EXPECT_EQ("A", GetOwnersOfVisibleWindowsAsString());
+
+ // Switch the user fore and back and see that the results are correct.
+ SwitchUserAndWaitForAnimation("B");
+
+ EXPECT_EQ("H[A], S[B], H[C]", GetStatus());
+ EXPECT_EQ("B", GetOwnersOfVisibleWindowsAsString());
+
+ SwitchUserAndWaitForAnimation("A");
+
+ EXPECT_EQ("S[A], H[B], H[C]", GetStatus());
+
+ // Switch the user quickly to another user and before the animation is done
+ // switch back and see that this works.
+ multi_user_window_manager()->ActiveUserChanged("B");
+ // With the start of the animation B should become visible.
+ EXPECT_EQ("H[A], S[B], H[C]", GetStatus());
+ // Check that after switching to C, C is fully visible.
+ SwitchUserAndWaitForAnimation("C");
+ EXPECT_EQ("H[A], H[B], S[C]", GetStatus());
+}
+
+// Make sure that we do not crash upon shutdown when an animation is pending and
+// a shutdown happens.
+TEST_F(MultiUserWindowManagerChromeOSTest, SystemShutdownWithActiveAnimation) {
+ SetUpForThisManyWindows(2);
+ // Turn the use of delays and animation on.
+ multi_user_window_manager()->SetAnimationSpeedForTest(
+ chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST);
+ // Set some owners and make sure we got what we asked for.
+ multi_user_window_manager()->SetWindowOwner(window(0), "A");
+ multi_user_window_manager()->SetWindowOwner(window(1), "B");
+ StartUserTransitionAnimation("B");
+ // We don't do anything more here - the animations are pending and with the
+ // shutdown of the framework the animations should get cancelled. If not a
+ // crash would happen.
+}
+
+// Test that using the full user switch, the animations are transitioning as
+// we expect them to in all animation steps.
+TEST_F(MultiUserWindowManagerChromeOSTest, AnimationSteps) {
+ SetUpForThisManyWindows(3);
+ // Turn the use of delays and animation on.
+ multi_user_window_manager()->SetAnimationSpeedForTest(
+ chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST);
+ // Set some owners and make sure we got what we asked for.
+ multi_user_window_manager()->SetWindowOwner(window(0), "A");
+ multi_user_window_manager()->SetWindowOwner(window(1), "B");
+ multi_user_window_manager()->SetWindowOwner(window(2), "C");
+ EXPECT_FALSE(CoversScreen(window(0)));
+ EXPECT_FALSE(CoversScreen(window(1)));
+ EXPECT_EQ("S[A], H[B], H[C]", GetStatus());
+ EXPECT_EQ("A", GetOwnersOfVisibleWindowsAsString());
+ EXPECT_NE(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN,
+ ash::Shell::GetInstance()->GetShelfAutoHideBehavior(
+ window(0)->GetRootWindow()));
+ EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity());
+
+ // Start the animation and see that the old window is becoming invisible, the
+ // new one visible, the background starts transitionining and the shelf hides.
+ StartUserTransitionAnimation("B");
+ EXPECT_EQ("->B", GetWallaperUserIdForTest());
+ EXPECT_EQ("H[A], S[B], H[C]", GetStatus());
+ EXPECT_EQ(0.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(1.0f, window(1)->layer()->GetTargetOpacity());
+ EXPECT_EQ(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN,
+ ash::Shell::GetInstance()->GetShelfAutoHideBehavior(
+ window(0)->GetRootWindow()));
+
+ // Staring the next step should show the shelf again, but there are many
+ // subsystems missing (preferences system, ChromeLauncherController, ...)
+ // which should set the shelf to its users state. Since that isn't there we
+ // can only make sure that it stays where it is.
+ AdvanceUserTransitionAnimation();
+ EXPECT_EQ("->B", GetWallaperUserIdForTest());
+ EXPECT_EQ("H[A], S[B], H[C]", GetStatus());
+ EXPECT_EQ(ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN,
+ ash::Shell::GetInstance()->GetShelfAutoHideBehavior(
+ window(0)->GetRootWindow()));
+
+ // After the finalize the animation of the wallpaper should be finished.
+ AdvanceUserTransitionAnimation();
+ EXPECT_EQ("B", GetWallaperUserIdForTest());
+}
+
+// Test that the screen coverage is properly determined.
+TEST_F(MultiUserWindowManagerChromeOSTest, AnimationStepsScreenCoverage) {
+ SetUpForThisManyWindows(3);
+ // Maximizing, fully covering the screen by bounds or fullscreen mode should
+ // make CoversScreen return true.
+ wm::GetWindowState(window(0))->Maximize();
+ window(1)->SetBounds(gfx::Rect(0, 0, 3000, 3000));
+
+ EXPECT_TRUE(CoversScreen(window(0)));
+ EXPECT_TRUE(CoversScreen(window(1)));
+ EXPECT_FALSE(CoversScreen(window(2)));
+
+ ash::wm::WMEvent event(ash::wm::WM_EVENT_FULLSCREEN);
+ wm::GetWindowState(window(2))->OnWMEvent(&event);
+ EXPECT_TRUE(CoversScreen(window(2)));
+}
+
+// Test that switching from a desktop which has a maximized window to a desktop
+// which has no maximized window will produce the proper animation.
+TEST_F(MultiUserWindowManagerChromeOSTest, AnimationStepsMaximizeToNormal) {
+ SetUpForThisManyWindows(3);
+ // Turn the use of delays and animation on.
+ multi_user_window_manager()->SetAnimationSpeedForTest(
+ chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST);
+ // Set some owners and make sure we got what we asked for.
+ multi_user_window_manager()->SetWindowOwner(window(0), "A");
+ wm::GetWindowState(window(0))->Maximize();
+ multi_user_window_manager()->SetWindowOwner(window(1), "B");
+ multi_user_window_manager()->SetWindowOwner(window(2), "C");
+ EXPECT_TRUE(CoversScreen(window(0)));
+ EXPECT_FALSE(CoversScreen(window(1)));
+ EXPECT_EQ("S[A], H[B], H[C]", GetStatus());
+ EXPECT_EQ("A", GetOwnersOfVisibleWindowsAsString());
+ EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity());
+
+ // Start the animation and see that the new background is immediately set.
+ StartUserTransitionAnimation("B");
+ EXPECT_EQ("H[A], S[B], H[C]", GetStatus());
+ EXPECT_EQ("B", GetWallaperUserIdForTest());
+ EXPECT_EQ(0.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(1.0f, window(1)->layer()->GetTargetOpacity());
+
+ // The next step will not change anything.
+ AdvanceUserTransitionAnimation();
+ EXPECT_EQ("B", GetWallaperUserIdForTest());
+ EXPECT_EQ(0.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(1.0f, window(1)->layer()->GetTargetOpacity());
+
+ // The final step will also not have any visible impact.
+ AdvanceUserTransitionAnimation();
+ EXPECT_EQ("H[A], S[B], H[C]", GetStatus());
+ EXPECT_EQ("B", GetWallaperUserIdForTest());
+ EXPECT_EQ(0.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(1.0f, window(1)->layer()->GetTargetOpacity());
+}
+
+// Test that switching from a desktop which has a normal window to a desktop
+// which has a maximized window will produce the proper animation.
+TEST_F(MultiUserWindowManagerChromeOSTest, AnimationStepsNormalToMaximized) {
+ SetUpForThisManyWindows(3);
+ // Turn the use of delays and animation on.
+ multi_user_window_manager()->SetAnimationSpeedForTest(
+ chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST);
+ // Set some owners and make sure we got what we asked for.
+ multi_user_window_manager()->SetWindowOwner(window(0), "A");
+ multi_user_window_manager()->SetWindowOwner(window(1), "B");
+ wm::GetWindowState(window(1))->Maximize();
+ multi_user_window_manager()->SetWindowOwner(window(2), "C");
+ EXPECT_FALSE(CoversScreen(window(0)));
+ EXPECT_TRUE(CoversScreen(window(1)));
+ EXPECT_EQ("S[A], H[B], H[C]", GetStatus());
+ EXPECT_EQ("A", GetOwnersOfVisibleWindowsAsString());
+ EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity());
+
+ // Start the animation and see that the old window is becoming invisible, the
+ // new one visible and the background remains as is.
+ StartUserTransitionAnimation("B");
+ EXPECT_EQ("H[A], S[B], H[C]", GetStatus());
+ EXPECT_EQ("", GetWallaperUserIdForTest());
+ EXPECT_EQ(0.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(1.0f, window(1)->layer()->GetTargetOpacity());
+
+ // The next step will not change anything.
+ AdvanceUserTransitionAnimation();
+ EXPECT_EQ("", GetWallaperUserIdForTest());
+ EXPECT_EQ(0.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(1.0f, window(1)->layer()->GetTargetOpacity());
+
+ // The final step however will switch the background.
+ AdvanceUserTransitionAnimation();
+ EXPECT_EQ("H[A], S[B], H[C]", GetStatus());
+ EXPECT_EQ("B", GetWallaperUserIdForTest());
+ EXPECT_EQ(0.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(1.0f, window(1)->layer()->GetTargetOpacity());
+}
+
+// Test that switching from a desktop which has a maximized window to a desktop
+// which has a maximized window will produce the proper animation.
+TEST_F(MultiUserWindowManagerChromeOSTest, AnimationStepsMaximizedToMaximized) {
+ SetUpForThisManyWindows(3);
+ // Turn the use of delays and animation on.
+ multi_user_window_manager()->SetAnimationSpeedForTest(
+ chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_FAST);
+ // Set some owners and make sure we got what we asked for.
+ multi_user_window_manager()->SetWindowOwner(window(0), "A");
+ wm::GetWindowState(window(0))->Maximize();
+ multi_user_window_manager()->SetWindowOwner(window(1), "B");
+ wm::GetWindowState(window(1))->Maximize();
+ multi_user_window_manager()->SetWindowOwner(window(2), "C");
+ EXPECT_TRUE(CoversScreen(window(0)));
+ EXPECT_TRUE(CoversScreen(window(1)));
+ EXPECT_EQ("S[A], H[B], H[C]", GetStatus());
+ EXPECT_EQ("A", GetOwnersOfVisibleWindowsAsString());
+ EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity());
+
+ // Start the animation and see that the old window is staying visible, the
+ // new one slowly visible and the background changes immediately.
+ StartUserTransitionAnimation("B");
+ EXPECT_EQ("S[A], S[B], H[C]", GetStatus());
+ EXPECT_EQ("B", GetWallaperUserIdForTest());
+ EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(1.0f, window(1)->layer()->GetTargetOpacity());
+
+ // The next step will not change anything.
+ AdvanceUserTransitionAnimation();
+ EXPECT_EQ("B", GetWallaperUserIdForTest());
+ EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(1.0f, window(1)->layer()->GetTargetOpacity());
+
+ // The final step however will hide the old window.
+ AdvanceUserTransitionAnimation();
+ EXPECT_EQ("H[A], S[B], H[C]", GetStatus());
+ EXPECT_EQ("B", GetWallaperUserIdForTest());
+ EXPECT_EQ(0.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(1.0f, window(1)->layer()->GetTargetOpacity());
+
+ // Switching back will preserve the z-order by instantly showing the new
+ // window, hiding the layer above it and switching instantly the wallpaper.
+ StartUserTransitionAnimation("A");
+ EXPECT_EQ("S[A], H[B], H[C]", GetStatus());
+ EXPECT_EQ("A", GetWallaperUserIdForTest());
+ EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(0.0f, window(1)->layer()->GetTargetOpacity());
+
+ // The next step will not change anything.
+ AdvanceUserTransitionAnimation();
+ EXPECT_EQ("A", GetWallaperUserIdForTest());
+ EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(0.0f, window(1)->layer()->GetTargetOpacity());
+
+ // The final step is also not changing anything to the status.
+ AdvanceUserTransitionAnimation();
+ EXPECT_EQ("S[A], H[B], H[C]", GetStatus());
+ EXPECT_EQ("A", GetWallaperUserIdForTest());
+ EXPECT_EQ(1.0f, window(0)->layer()->GetTargetOpacity());
+ EXPECT_EQ(0.0f, window(1)->layer()->GetTargetOpacity());
+}
+
+// Test that showing a window for another user also switches the desktop.
+TEST_F(MultiUserWindowManagerChromeOSTest, ShowForUserSwitchesDesktop) {
+ SetUpForThisManyWindows(3);
+ multi_user_window_manager()->ActiveUserChanged("a");
+ session_state_delegate()->SwitchActiveUser("a");
+
+ // Set some owners and make sure we got what we asked for.
+ multi_user_window_manager()->SetWindowOwner(window(0), "a");
+ multi_user_window_manager()->SetWindowOwner(window(1), "b");
+ multi_user_window_manager()->SetWindowOwner(window(2), "c");
+ EXPECT_EQ("S[a], H[b], H[c]", GetStatus());
+
+ // SetWindowOwner should not have changed the active user.
+ EXPECT_EQ("a", GetAndValidateCurrentUserFromSessionStateObserver());
+
+ // Check that teleporting the window of the currently active user will
+ // teleport to the new desktop.
+ multi_user_window_manager()->ShowWindowForUser(window(0), "b");
+ EXPECT_EQ("b", GetAndValidateCurrentUserFromSessionStateObserver());
+ EXPECT_EQ("S[a,b], S[b], H[c]", GetStatus());
+
+ // Check that teleporting a window from a currently inactive user will not
+ // trigger a switch.
+ multi_user_window_manager()->ShowWindowForUser(window(2), "a");
+ EXPECT_EQ("b", GetAndValidateCurrentUserFromSessionStateObserver());
+ EXPECT_EQ("S[a,b], S[b], H[c,a]", GetStatus());
+ multi_user_window_manager()->ShowWindowForUser(window(2), "b");
+ EXPECT_EQ("b", GetAndValidateCurrentUserFromSessionStateObserver());
+ EXPECT_EQ("S[a,b], S[b], S[c,b]", GetStatus());
+
+ // Check that teleporting back will also change the desktop.
+ multi_user_window_manager()->ShowWindowForUser(window(2), "c");
+ EXPECT_EQ("c", GetAndValidateCurrentUserFromSessionStateObserver());
+ EXPECT_EQ("H[a,b], H[b], S[c]", GetStatus());
}
} // namespace test