1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file.
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h"
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ash/desktop_background/user_wallpaper_delegate.h"
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ash/root_window_controller.h"
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ash/shelf/shelf_layout_manager.h"
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ash/shell.h"
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ash/wm/mru_window_tracker.h"
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ash/wm/window_positioner.h"
13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ash/wm/window_state.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.h"
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/wm/public/activation_client.h"
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace chrome {
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace {
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// The minimal possible animation time for animations which should happen
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// "instantly".
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst int kMinimalAnimationTimeMS = 1;
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// logic while the user gets switched.
29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass UserChangeActionDisabler {
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  UserChangeActionDisabler() {
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ash::WindowPositioner::DisableAutoPositioning(true);
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(true);
34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ~UserChangeActionDisabler() {
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ash::WindowPositioner::DisableAutoPositioning(false);
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        false);
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DISALLOW_COPY_AND_ASSIGN(UserChangeActionDisabler);
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochUserSwichAnimatorChromeOS::UserSwichAnimatorChromeOS(
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    MultiUserWindowManagerChromeOS* owner,
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const std::string& new_user_id,
51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    int animation_speed_ms)
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : owner_(owner),
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      new_user_id_(new_user_id),
54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      animation_speed_ms_(animation_speed_ms),
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      animation_step_(ANIMATION_STEP_HIDE_OLD_USER),
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      screen_cover_(GetScreenCover()) {
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  AdvanceUserTransitionAnimation();
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!animation_speed_ms_) {
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    FinalizeAnimation();
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else {
62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    user_changed_animation_timer_.reset(new base::Timer(
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        FROM_HERE,
64a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        base::TimeDelta::FromMilliseconds(animation_speed_ms_),
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        base::Bind(
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            &UserSwichAnimatorChromeOS::AdvanceUserTransitionAnimation,
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            base::Unretained(this)),
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        true));
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    user_changed_animation_timer_->Reset();
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochUserSwichAnimatorChromeOS::~UserSwichAnimatorChromeOS() {
74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  FinalizeAnimation();
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// static
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool UserSwichAnimatorChromeOS::CoversScreen(aura::Window* window) {
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Full screen covers the screen naturally. Since a normal window can have the
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // same size as the work area, we only compare the bounds against the work
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // area.
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (ash::wm::GetWindowState(window)->IsFullscreen())
83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return true;
84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect bounds = window->GetBoundsInRootWindow();
85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Rect work_area = gfx::Screen::GetScreenFor(window)->
86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      GetDisplayNearestWindow(window).work_area();
87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bounds.Intersect(work_area);
88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return work_area == bounds;
89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
90c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid UserSwichAnimatorChromeOS::AdvanceUserTransitionAnimation() {
92c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK_NE(animation_step_, ANIMATION_STEP_ENDED);
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  TransitionWallpaper(animation_step_);
95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  TransitionUserShelf(animation_step_);
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  TransitionWindows(animation_step_);
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Advance to the next step.
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  switch (animation_step_) {
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ANIMATION_STEP_HIDE_OLD_USER:
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      animation_step_ = ANIMATION_STEP_SHOW_NEW_USER;
102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ANIMATION_STEP_SHOW_NEW_USER:
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      animation_step_ = ANIMATION_STEP_FINALIZE;
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ANIMATION_STEP_FINALIZE:
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      user_changed_animation_timer_.reset();
108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      animation_step_ = ANIMATION_STEP_ENDED;
109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case ANIMATION_STEP_ENDED:
111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      NOTREACHED();
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid UserSwichAnimatorChromeOS::CancelAnimation() {
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  animation_step_ = ANIMATION_STEP_ENDED;
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid UserSwichAnimatorChromeOS::FinalizeAnimation() {
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  user_changed_animation_timer_.reset();
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  while (ANIMATION_STEP_ENDED != animation_step_)
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    AdvanceUserTransitionAnimation();
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid UserSwichAnimatorChromeOS::TransitionWallpaper(
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    AnimationStep animation_step) {
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Handle the wallpaper switch.
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ash::UserWallpaperDelegate* wallpaper_delegate =
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ash::Shell::GetInstance()->user_wallpaper_delegate();
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (animation_step == ANIMATION_STEP_HIDE_OLD_USER) {
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Set the wallpaper cross dissolve animation duration to our complete
133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // animation cycle for a fade in and fade out.
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    int duration =
135a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        NO_USER_COVERS_SCREEN == screen_cover_ ? (2 * animation_speed_ms_) : 0;
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    wallpaper_delegate->SetAnimationDurationOverride(
137a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        std::max(duration, kMinimalAnimationTimeMS));
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (screen_cover_ != NEW_USER_COVERS_SCREEN) {
139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      chromeos::WallpaperManager::Get()->SetUserWallpaperNow(new_user_id_);
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      wallpaper_user_id_ =
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          (NO_USER_COVERS_SCREEN == screen_cover_ ? "->" : "") +
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          new_user_id_;
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
144c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  } else if (animation_step == ANIMATION_STEP_FINALIZE) {
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Revert the wallpaper cross dissolve animation duration back to the
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // default.
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (screen_cover_ == NEW_USER_COVERS_SCREEN)
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      chromeos::WallpaperManager::Get()->SetUserWallpaperNow(new_user_id_);
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Coming here the wallpaper user id is the final result. No matter how we
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // got here.
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    wallpaper_user_id_ = new_user_id_;
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    wallpaper_delegate->SetAnimationDurationOverride(0);
154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid UserSwichAnimatorChromeOS::TransitionUserShelf(
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    AnimationStep animation_step) {
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // The shelf animation duration override.
160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int duration_override = animation_speed_ms_;
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Handle the shelf order of items. This is done once the old user is hidden.
162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (animation_step == ANIMATION_STEP_SHOW_NEW_USER) {
163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Some unit tests have no ChromeLauncherController.
164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (ChromeLauncherController::instance())
165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ChromeLauncherController::instance()->ActiveUserChanged(new_user_id_);
166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // We kicked off the shelf animation in the command above. As such we can
167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // disable the override now again.
168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    duration_override = 0;
169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
171a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!animation_speed_ms_ || animation_step == ANIMATION_STEP_FINALIZE)
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ash::Shell::RootWindowControllerList controller =
175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ash::Shell::GetInstance()->GetAllRootWindowControllers();
176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (ash::Shell::RootWindowControllerList::iterator iter = controller.begin();
177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       iter != controller.end(); ++iter) {
178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    (*iter)->GetShelfLayoutManager()->SetAnimationDurationOverride(
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        duration_override);
180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // For each root window hide the shelf.
183c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (animation_step == ANIMATION_STEP_HIDE_OLD_USER) {
184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    for (aura::Window::Windows::const_iterator iter = root_windows.begin();
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         iter != root_windows.end(); ++iter) {
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // This shelf change is only part of the animation and will be updated by
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // ChromeLauncherController::ActiveUserChanged() to the new users value.
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // Note that the user perference will not be changed.
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ash::Shell::GetInstance()->SetShelfAutoHideBehavior(
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN, *iter);
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid UserSwichAnimatorChromeOS::TransitionWindows(
197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    AnimationStep animation_step) {
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Disable the window position manager and the MRU window tracker temporarily.
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  UserChangeActionDisabler disabler;
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (animation_step == ANIMATION_STEP_HIDE_OLD_USER ||
202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      (animation_step == ANIMATION_STEP_FINALIZE &&
203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       screen_cover_ == BOTH_USERS_COVER_SCREEN)) {
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // We need to show/hide the windows in the same order as they were created
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // in their parent window(s) to keep the layer / window hierarchy in sync.
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // To achieve that we first collect all parent windows and then enumerate
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // all windows in those parent windows and show or hide them accordingly.
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Create a list of all parent windows we have to check.
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    std::set<aura::Window*> parent_list;
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    for (MultiUserWindowManagerChromeOS::WindowToEntryMap::const_iterator it =
212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch             owner_->window_to_entry().begin();
213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         it != owner_->window_to_entry().end(); ++it) {
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      aura::Window* parent = it->first->parent();
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (parent_list.find(parent) == parent_list.end())
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        parent_list.insert(parent);
217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    for (std::set<aura::Window*>::iterator it_parents = parent_list.begin();
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         it_parents != parent_list.end(); ++it_parents) {
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      const aura::Window::Windows window_list = (*it_parents)->children();
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // In case of |BOTH_USERS_COVER_SCREEN| the desktop might shine through
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // if all windows fade (in or out). To avoid this we only fade the topmost
224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // covering window (in / out) and make / keep all other covering windows
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // visible while animating. |foreground_window_found| will get set when
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // the top fading window was found.
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      bool foreground_window_found = false;
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // Covering windows which follow the fade direction will also fade - all
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // others will get immediately shown / kept shown until the animation is
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // finished.
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      bool foreground_becomes_visible = false;
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      for (aura::Window::Windows::const_reverse_iterator it_window =
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               window_list.rbegin();
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch           it_window != window_list.rend(); ++it_window) {
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        aura::Window* window = *it_window;
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        MultiUserWindowManagerChromeOS::WindowToEntryMap::const_iterator
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            it_map = owner_->window_to_entry().find(window);
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        if (it_map != owner_->window_to_entry().end()) {
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          bool should_be_visible =
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              it_map->second->show_for_user() == new_user_id_ &&
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              it_map->second->show();
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          bool is_visible = window->IsVisible();
243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          if (it_map->second->owner() == new_user_id_ &&
245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              it_map->second->show_for_user() != new_user_id_ &&
246c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              window_state->IsMinimized()) {
247c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            // Pull back minimized visiting windows to the owners desktop.
248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            owner_->ShowWindowForUserIntern(window, new_user_id_);
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            window_state->Unminimize();
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          } else if (should_be_visible != is_visible) {
251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            bool animate = true;
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            int duration = animation_step == ANIMATION_STEP_FINALIZE ?
253a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                               0 : (2 * animation_speed_ms_);
254a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            duration = std::max(kMinimalAnimationTimeMS, duration);
255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            if (animation_step != ANIMATION_STEP_FINALIZE &&
256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                screen_cover_ == BOTH_USERS_COVER_SCREEN &&
257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                CoversScreen(window)) {
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              if (!foreground_window_found) {
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                foreground_window_found = true;
260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                foreground_becomes_visible = should_be_visible;
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              } else if (should_be_visible != foreground_becomes_visible) {
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                // Covering windows behind the foreground window which are
263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                // inverting their visibility should immediately become visible
264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                // or stay visible until the animation is finished.
265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                duration = kMinimalAnimationTimeMS;
266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                if (!should_be_visible)
267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                  animate = false;
268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              }
269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            }
270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            if (animate)
271c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              owner_->SetWindowVisibility(window, should_be_visible, duration);
272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          }
273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        }
274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      }
275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Activation and real switch are happening after the other user gets shown.
279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (animation_step == ANIMATION_STEP_SHOW_NEW_USER) {
280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Finally we need to restore the previously active window.
281c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ash::MruWindowTracker::WindowList mru_list =
282c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        ash::Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList();
283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!mru_list.empty()) {
284c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      aura::Window* window = mru_list[0];
285c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
286c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (owner_->IsWindowOnDesktopOfUser(window, new_user_id_) &&
287c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          !window_state->IsMinimized()) {
288c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        aura::client::ActivationClient* client =
289c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            aura::client::GetActivationClient(window->GetRootWindow());
290c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        // Several unit tests come here without an activation client.
291c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        if (client)
292c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          client->ActivateWindow(window);
293c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      }
294c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
295c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
296c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // This is called directly here to make sure notification_blocker will see
297c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // the new window status.
298c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    owner_->notification_blocker()->ActiveUserChanged(new_user_id_);
299c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
300c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
301c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
302c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochUserSwichAnimatorChromeOS::TransitioningScreenCover
303c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochUserSwichAnimatorChromeOS::GetScreenCover() {
304c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  TransitioningScreenCover cover = NO_USER_COVERS_SCREEN;
305c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (MultiUserWindowManagerChromeOS::WindowToEntryMap::const_iterator it_map =
306c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch           owner_->window_to_entry().begin();
307c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       it_map != owner_->window_to_entry().end();
308c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       ++it_map) {
309c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    aura::Window* window = it_map->first;
310c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (window->IsVisible() && CoversScreen(window)) {
311c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (cover == NEW_USER_COVERS_SCREEN)
312c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return BOTH_USERS_COVER_SCREEN;
313c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      else
314c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        cover = OLD_USER_COVERS_SCREEN;
315c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    } else if (owner_->IsWindowOnDesktopOfUser(window, new_user_id_) &&
316c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               CoversScreen(window)) {
317c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (cover == OLD_USER_COVERS_SCREEN)
318c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return BOTH_USERS_COVER_SCREEN;
319c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      else
320c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        cover = NEW_USER_COVERS_SCREEN;
321c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
322c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
323c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return cover;
324c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
325c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
326c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace chrome
327