| 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/shell_window.h" | 7 #include "apps/shell_window.h" |
| 8 #include "apps/shell_window_registry.h" | 8 #include "apps/shell_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/multi_profile_uma.h" | 11 #include "ash/multi_profile_uma.h" |
| 12 #include "ash/root_window_controller.h" |
| 11 #include "ash/session_state_delegate.h" | 13 #include "ash/session_state_delegate.h" |
| 14 #include "ash/shelf/shelf.h" |
| 15 #include "ash/shelf/shelf_layout_manager.h" |
| 12 #include "ash/shell.h" | 16 #include "ash/shell.h" |
| 13 #include "ash/shell_delegate.h" | 17 #include "ash/shell_delegate.h" |
| 14 #include "ash/shell_window_ids.h" | 18 #include "ash/shell_window_ids.h" |
| 15 #include "ash/wm/mru_window_tracker.h" | 19 #include "ash/wm/mru_window_tracker.h" |
| 16 #include "ash/wm/window_positioner.h" | 20 #include "ash/wm/window_positioner.h" |
| 17 #include "ash/wm/window_state.h" | 21 #include "ash/wm/window_state.h" |
| 18 #include "base/auto_reset.h" | 22 #include "base/auto_reset.h" |
| 19 #include "base/message_loop/message_loop.h" | 23 #include "base/message_loop/message_loop.h" |
| 20 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
| 21 #include "chrome/browser/browser_process.h" | 25 #include "chrome/browser/browser_process.h" |
| 22 #include "chrome/browser/chrome_notification_types.h" | 26 #include "chrome/browser/chrome_notification_types.h" |
| 23 #include "chrome/browser/chromeos/login/user_manager.h" | 27 #include "chrome/browser/chromeos/login/user_manager.h" |
| 28 #include "chrome/browser/chromeos/login/wallpaper_manager.h" |
| 24 #include "chrome/browser/profiles/profile.h" | 29 #include "chrome/browser/profiles/profile.h" |
| 25 #include "chrome/browser/profiles/profile_manager.h" | 30 #include "chrome/browser/profiles/profile_manager.h" |
| 31 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" |
| 26 #include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chrom
eos.h" | 32 #include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chrom
eos.h" |
| 27 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" | 33 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" |
| 28 #include "chrome/browser/ui/browser.h" | 34 #include "chrome/browser/ui/browser.h" |
| 29 #include "chrome/browser/ui/browser_finder.h" | 35 #include "chrome/browser/ui/browser_finder.h" |
| 30 #include "chrome/browser/ui/browser_list.h" | 36 #include "chrome/browser/ui/browser_list.h" |
| 31 #include "chrome/browser/ui/browser_window.h" | 37 #include "chrome/browser/ui/browser_window.h" |
| 32 #include "content/public/browser/notification_service.h" | 38 #include "content/public/browser/notification_service.h" |
| 33 #include "google_apis/gaia/gaia_auth_util.h" | 39 #include "google_apis/gaia/gaia_auth_util.h" |
| 34 #include "ui/aura/client/activation_client.h" | 40 #include "ui/aura/client/activation_client.h" |
| 35 #include "ui/aura/client/aura_constants.h" | 41 #include "ui/aura/client/aura_constants.h" |
| 36 #include "ui/aura/root_window.h" | 42 #include "ui/aura/root_window.h" |
| 37 #include "ui/aura/window.h" | 43 #include "ui/aura/window.h" |
| 38 #include "ui/base/ui_base_types.h" | 44 #include "ui/base/ui_base_types.h" |
| 39 #include "ui/events/event.h" | 45 #include "ui/events/event.h" |
| 40 #include "ui/message_center/message_center.h" | 46 #include "ui/message_center/message_center.h" |
| 41 #include "ui/views/corewm/transient_window_manager.h" | 47 #include "ui/views/corewm/transient_window_manager.h" |
| 48 #include "ui/views/corewm/window_animations.h" |
| 42 #include "ui/views/corewm/window_util.h" | 49 #include "ui/views/corewm/window_util.h" |
| 43 | 50 |
| 44 namespace { | 51 namespace { |
| 45 | 52 |
| 53 // The animation time in milliseconds for a single window which is fading |
| 54 // in / out. |
| 55 static int kAnimationTimeMS = 100; |
| 56 |
| 57 // The animation time in millseconds for the fade in and / or out when switching |
| 58 // users. |
| 59 static int kUserFadeTimeMS = 110; |
| 60 |
| 61 // The animation time in ms for a window which get teleported to another screen. |
| 62 static int kTeleportAnimationTimeMS = 300; |
| 63 |
| 46 // Checks if a given event is a user event. | 64 // Checks if a given event is a user event. |
| 47 bool IsUserEvent(ui::Event* e) { | 65 bool IsUserEvent(ui::Event* e) { |
| 48 if (e) { | 66 if (e) { |
| 49 ui::EventType type = e->type(); | 67 ui::EventType type = e->type(); |
| 50 if (type != ui::ET_CANCEL_MODE && | 68 if (type != ui::ET_CANCEL_MODE && |
| 51 type != ui::ET_UMA_DATA && | 69 type != ui::ET_UMA_DATA && |
| 52 type != ui::ET_UNKNOWN) | 70 type != ui::ET_UNKNOWN) |
| 53 return true; | 71 return true; |
| 54 } | 72 } |
| 55 return false; | 73 return false; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 } | 143 } |
| 126 } | 144 } |
| 127 } | 145 } |
| 128 ash::MultiProfileUMA::RecordTeleportWindowType(window_type); | 146 ash::MultiProfileUMA::RecordTeleportWindowType(window_type); |
| 129 } | 147 } |
| 130 | 148 |
| 131 } // namespace | 149 } // namespace |
| 132 | 150 |
| 133 namespace chrome { | 151 namespace chrome { |
| 134 | 152 |
| 153 // A class to temporarily change the animation properties for a window. |
| 154 class AnimationSetter { |
| 155 public: |
| 156 AnimationSetter(aura::Window* window, int animation_time_in_ms) |
| 157 : window_(window), |
| 158 previous_animation_type_( |
| 159 views::corewm::GetWindowVisibilityAnimationType(window_)), |
| 160 previous_animation_time_( |
| 161 views::corewm::GetWindowVisibilityAnimationDuration(*window_)) { |
| 162 views::corewm::SetWindowVisibilityAnimationType( |
| 163 window_, |
| 164 views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); |
| 165 views::corewm::SetWindowVisibilityAnimationDuration( |
| 166 window_, |
| 167 base::TimeDelta::FromMilliseconds(animation_time_in_ms)); |
| 168 } |
| 169 |
| 170 ~AnimationSetter() { |
| 171 views::corewm::SetWindowVisibilityAnimationType(window_, |
| 172 previous_animation_type_); |
| 173 views::corewm::SetWindowVisibilityAnimationDuration( |
| 174 window_, |
| 175 previous_animation_time_); |
| 176 } |
| 177 |
| 178 private: |
| 179 // The window which gets used. |
| 180 aura::Window* window_; |
| 181 |
| 182 // Previous animation type. |
| 183 const int previous_animation_type_; |
| 184 |
| 185 // Previous animation time. |
| 186 const base::TimeDelta previous_animation_time_; |
| 187 |
| 188 DISALLOW_COPY_AND_ASSIGN(AnimationSetter); |
| 189 }; |
| 190 |
| 135 // logic while the user gets switched. | 191 // logic while the user gets switched. |
| 136 class UserChangeActionDisabler { | 192 class UserChangeActionDisabler { |
| 137 public: | 193 public: |
| 138 UserChangeActionDisabler() { | 194 UserChangeActionDisabler() { |
| 139 ash::WindowPositioner::DisableAutoPositioning(true); | 195 ash::WindowPositioner::DisableAutoPositioning(true); |
| 140 ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(true); | 196 ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(true); |
| 141 } | 197 } |
| 142 | 198 |
| 143 ~UserChangeActionDisabler() { | 199 ~UserChangeActionDisabler() { |
| 144 ash::WindowPositioner::DisableAutoPositioning(false); | 200 ash::WindowPositioner::DisableAutoPositioning(false); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 175 std::string user_id_; | 231 std::string user_id_; |
| 176 | 232 |
| 177 DISALLOW_COPY_AND_ASSIGN(AppObserver); | 233 DISALLOW_COPY_AND_ASSIGN(AppObserver); |
| 178 }; | 234 }; |
| 179 | 235 |
| 180 MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS( | 236 MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS( |
| 181 const std::string& current_user_id) | 237 const std::string& current_user_id) |
| 182 : current_user_id_(current_user_id), | 238 : current_user_id_(current_user_id), |
| 183 notification_blocker_(new MultiUserNotificationBlockerChromeOS( | 239 notification_blocker_(new MultiUserNotificationBlockerChromeOS( |
| 184 message_center::MessageCenter::Get(), this)), | 240 message_center::MessageCenter::Get(), this)), |
| 185 suppress_visibility_changes_(false) { | 241 suppress_visibility_changes_(false), |
| 242 animations_disabled_(false) { |
| 186 // Add a session state observer to be able to monitor session changes. | 243 // Add a session state observer to be able to monitor session changes. |
| 187 if (ash::Shell::HasInstance()) | 244 if (ash::Shell::HasInstance()) |
| 188 ash::Shell::GetInstance()->session_state_delegate()-> | 245 ash::Shell::GetInstance()->session_state_delegate()-> |
| 189 AddSessionStateObserver(this); | 246 AddSessionStateObserver(this); |
| 190 | 247 |
| 191 // The BrowserListObserver would have been better to use then the old | 248 // The BrowserListObserver would have been better to use then the old |
| 192 // notification system, but that observer fires before the window got created. | 249 // notification system, but that observer fires before the window got created. |
| 193 registrar_.Add(this, NOTIFICATION_BROWSER_WINDOW_READY, | 250 registrar_.Add(this, NOTIFICATION_BROWSER_WINDOW_READY, |
| 194 content::NotificationService::AllSources()); | 251 content::NotificationService::AllSources()); |
| 195 | 252 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 // Add all transient children to our set of windows. Note that the function | 310 // Add all transient children to our set of windows. Note that the function |
| 254 // will add the children but not the owner to the transient children map. | 311 // will add the children but not the owner to the transient children map. |
| 255 AddTransientOwnerRecursive(window, window); | 312 AddTransientOwnerRecursive(window, window); |
| 256 | 313 |
| 257 // Right now only |notification_blocker_| needs to know when the list of | 314 // Right now only |notification_blocker_| needs to know when the list of |
| 258 // owners may change. | 315 // owners may change. |
| 259 // TODO(skuhne): replace this by observer when another one needs this event. | 316 // TODO(skuhne): replace this by observer when another one needs this event. |
| 260 notification_blocker_->UpdateWindowOwners(); | 317 notification_blocker_->UpdateWindowOwners(); |
| 261 | 318 |
| 262 if (!IsWindowOnDesktopOfUser(window, current_user_id_)) | 319 if (!IsWindowOnDesktopOfUser(window, current_user_id_)) |
| 263 SetWindowVisibility(window, false); | 320 SetWindowVisibility(window, false, 0); |
| 264 } | 321 } |
| 265 | 322 |
| 266 const std::string& MultiUserWindowManagerChromeOS::GetWindowOwner( | 323 const std::string& MultiUserWindowManagerChromeOS::GetWindowOwner( |
| 267 aura::Window* window) { | 324 aura::Window* window) { |
| 268 WindowToEntryMap::iterator it = window_to_entry_.find(window); | 325 WindowToEntryMap::iterator it = window_to_entry_.find(window); |
| 269 return it != window_to_entry_.end() ? it->second->owner() | 326 return it != window_to_entry_.end() ? it->second->owner() |
| 270 : base::EmptyString(); | 327 : base::EmptyString(); |
| 271 } | 328 } |
| 272 | 329 |
| 273 void MultiUserWindowManagerChromeOS::ShowWindowForUser( | 330 void MultiUserWindowManagerChromeOS::ShowWindowForUser( |
| (...skipping 21 matching lines...) Expand all Loading... |
| 295 RecordUMAForTransferredWindowType(window); | 352 RecordUMAForTransferredWindowType(window); |
| 296 } | 353 } |
| 297 | 354 |
| 298 WindowToEntryMap::iterator it = window_to_entry_.find(window); | 355 WindowToEntryMap::iterator it = window_to_entry_.find(window); |
| 299 it->second->set_show_for_user(user_id); | 356 it->second->set_show_for_user(user_id); |
| 300 | 357 |
| 301 // Show the window if the added user is the current one. | 358 // Show the window if the added user is the current one. |
| 302 if (user_id == current_user_id_) { | 359 if (user_id == current_user_id_) { |
| 303 // Only show the window if it should be shown according to its state. | 360 // Only show the window if it should be shown according to its state. |
| 304 if (it->second->show()) | 361 if (it->second->show()) |
| 305 SetWindowVisibility(window, true); | 362 SetWindowVisibility(window, true, kTeleportAnimationTimeMS); |
| 306 } else { | 363 } else { |
| 307 SetWindowVisibility(window, false); | 364 SetWindowVisibility(window, false, kTeleportAnimationTimeMS); |
| 308 } | 365 } |
| 309 | 366 |
| 310 // TODO(skuhne): replace this by observer when another one needs this event. | 367 // TODO(skuhne): replace this by observer when another one needs this event. |
| 311 notification_blocker_->UpdateWindowOwners(); | 368 notification_blocker_->UpdateWindowOwners(); |
| 312 } | 369 } |
| 313 | 370 |
| 314 bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() { | 371 bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() { |
| 315 WindowToEntryMap::iterator it = window_to_entry_.begin(); | 372 WindowToEntryMap::iterator it = window_to_entry_.begin(); |
| 316 for (; it != window_to_entry_.end(); ++it) { | 373 for (; it != window_to_entry_.end(); ++it) { |
| 317 if (it->second->owner() != it->second->show_for_user()) | 374 if (it->second->owner() != it->second->show_for_user()) |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 BrowserList::const_iterator browser_it = browser_list->begin(); | 426 BrowserList::const_iterator browser_it = browser_list->begin(); |
| 370 for (; browser_it != browser_list->end(); ++browser_it) { | 427 for (; browser_it != browser_list->end(); ++browser_it) { |
| 371 if ((*browser_it)->profile()->GetOriginalProfile() == profile) | 428 if ((*browser_it)->profile()->GetOriginalProfile() == profile) |
| 372 AddBrowserWindow(*browser_it); | 429 AddBrowserWindow(*browser_it); |
| 373 } | 430 } |
| 374 } | 431 } |
| 375 | 432 |
| 376 void MultiUserWindowManagerChromeOS::ActiveUserChanged( | 433 void MultiUserWindowManagerChromeOS::ActiveUserChanged( |
| 377 const std::string& user_id) { | 434 const std::string& user_id) { |
| 378 DCHECK(user_id != current_user_id_); | 435 DCHECK(user_id != current_user_id_); |
| 379 std::string old_user = current_user_id_; | |
| 380 current_user_id_ = user_id; | 436 current_user_id_ = user_id; |
| 381 // Disable the window position manager and the MRU window tracker temporarily. | 437 // If there is an animation in progress finish the pending switch which also |
| 382 scoped_ptr<UserChangeActionDisabler> disabler(new UserChangeActionDisabler); | 438 // kills the timer (if there is one). |
| 439 if (user_changed_animation_timer_.get()) |
| 440 TransitionUser(SHOW_NEW_USER); |
| 383 | 441 |
| 384 // We need to show/hide the windows in the same order as they were created in | 442 // Start the animation by hiding the old user. |
| 385 // their parent window(s) to keep the layer / window hierarchy in sync. To | 443 TransitionUser(HIDE_OLD_USER); |
| 386 // achieve that we first collect all parent windows and then enumerate all | |
| 387 // windows in those parent windows and show or hide them accordingly. | |
| 388 | 444 |
| 389 // Create a list of all parent windows we have to check and their parents. | 445 // If animations are disabled we immediately switch to the new user, otherwise |
| 390 std::set<aura::Window*> parent_list; | 446 // we create a timer which will fade in the new user once the other user has |
| 391 for (WindowToEntryMap::iterator it = window_to_entry_.begin(); | 447 // been faded away. |
| 392 it != window_to_entry_.end(); ++it) { | 448 if (animations_disabled_) { |
| 393 aura::Window* parent = it->first->parent(); | 449 TransitionUser(SHOW_NEW_USER); |
| 394 if (parent_list.find(parent) == parent_list.end()) | 450 } else { |
| 395 parent_list.insert(parent); | 451 user_changed_animation_timer_.reset(new base::Timer( |
| 452 FROM_HERE, |
| 453 base::TimeDelta::FromMilliseconds(kUserFadeTimeMS), |
| 454 base::Bind(&MultiUserWindowManagerChromeOS::TransitionUser, |
| 455 base::Unretained(this), |
| 456 SHOW_NEW_USER), |
| 457 false)); |
| 458 user_changed_animation_timer_->Reset(); |
| 396 } | 459 } |
| 397 | |
| 398 // Traverse the found parent windows to handle their child windows in order of | |
| 399 // their appearance. | |
| 400 for (std::set<aura::Window*>::iterator it_parents = parent_list.begin(); | |
| 401 it_parents != parent_list.end(); ++it_parents) { | |
| 402 const aura::Window::Windows window_list = (*it_parents)->children(); | |
| 403 for (aura::Window::Windows::const_iterator it_window = window_list.begin(); | |
| 404 it_window != window_list.end(); ++it_window) { | |
| 405 aura::Window* window = *it_window; | |
| 406 WindowToEntryMap::iterator it_map = window_to_entry_.find(window); | |
| 407 if (it_map != window_to_entry_.end()) { | |
| 408 bool should_be_visible = it_map->second->show_for_user() == user_id && | |
| 409 it_map->second->show(); | |
| 410 bool is_visible = window->IsVisible(); | |
| 411 if (should_be_visible != is_visible) | |
| 412 SetWindowVisibility(window, should_be_visible); | |
| 413 } | |
| 414 } | |
| 415 } | |
| 416 | |
| 417 // Finally we need to restore the previously active window. | |
| 418 ash::MruWindowTracker::WindowList mru_list = | |
| 419 ash::Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList(); | |
| 420 if (mru_list.size()) { | |
| 421 aura::Window* window = mru_list[0]; | |
| 422 ash::wm::WindowState* window_state = ash::wm::GetWindowState(window); | |
| 423 if (IsWindowOnDesktopOfUser(window, user_id) && | |
| 424 !window_state->IsMinimized()) { | |
| 425 aura::client::ActivationClient* client = | |
| 426 aura::client::GetActivationClient(window->GetRootWindow()); | |
| 427 // Several unit tests come here without an activation client. | |
| 428 if (client) | |
| 429 client->ActivateWindow(window); | |
| 430 } | |
| 431 } | |
| 432 | |
| 433 // This is called directly here to make sure notification_blocker will see the | |
| 434 // new window status. | |
| 435 notification_blocker_->ActiveUserChanged(user_id); | |
| 436 } | 460 } |
| 437 | 461 |
| 438 void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) { | 462 void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) { |
| 439 if (GetWindowOwner(window).empty()) { | 463 if (GetWindowOwner(window).empty()) { |
| 440 // This must be a window in the transient chain - remove it and its | 464 // This must be a window in the transient chain - remove it and its |
| 441 // children from the owner. | 465 // children from the owner. |
| 442 RemoveTransientOwnerRecursive(window); | 466 RemoveTransientOwnerRecursive(window); |
| 443 return; | 467 return; |
| 444 } | 468 } |
| 445 ash::wm::GetWindowState(window)->RemoveObserver(this); | 469 ash::wm::GetWindowState(window)->RemoveObserver(this); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 475 } | 499 } |
| 476 } | 500 } |
| 477 | 501 |
| 478 void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanged( | 502 void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanged( |
| 479 aura::Window* window, bool visible) { | 503 aura::Window* window, bool visible) { |
| 480 if (suppress_visibility_changes_) | 504 if (suppress_visibility_changes_) |
| 481 return; | 505 return; |
| 482 | 506 |
| 483 // Don't allow to make the window visible if it shouldn't be. | 507 // Don't allow to make the window visible if it shouldn't be. |
| 484 if (visible && !IsWindowOnDesktopOfUser(window, current_user_id_)) { | 508 if (visible && !IsWindowOnDesktopOfUser(window, current_user_id_)) { |
| 485 SetWindowVisibility(window, false); | 509 SetWindowVisibility(window, false, 0); |
| 486 return; | 510 return; |
| 487 } | 511 } |
| 488 aura::Window* owned_parent = GetOwningWindowInTransientChain(window); | 512 aura::Window* owned_parent = GetOwningWindowInTransientChain(window); |
| 489 if (owned_parent && owned_parent != window && visible && | 513 if (owned_parent && owned_parent != window && visible && |
| 490 !IsWindowOnDesktopOfUser(owned_parent, current_user_id_)) | 514 !IsWindowOnDesktopOfUser(owned_parent, current_user_id_)) |
| 491 SetWindowVisibility(window, false); | 515 SetWindowVisibility(window, false, 0); |
| 492 } | 516 } |
| 493 | 517 |
| 494 void MultiUserWindowManagerChromeOS::OnTransientChildAdded( | 518 void MultiUserWindowManagerChromeOS::OnTransientChildAdded( |
| 495 aura::Window* window, | 519 aura::Window* window, |
| 496 aura::Window* transient_window) { | 520 aura::Window* transient_window) { |
| 497 if (!GetWindowOwner(window).empty()) { | 521 if (!GetWindowOwner(window).empty()) { |
| 498 AddTransientOwnerRecursive(transient_window, window); | 522 AddTransientOwnerRecursive(transient_window, window); |
| 499 return; | 523 return; |
| 500 } | 524 } |
| 501 aura::Window* owned_parent = | 525 aura::Window* owned_parent = |
| (...skipping 28 matching lines...) Expand all Loading... |
| 530 } | 554 } |
| 531 | 555 |
| 532 void MultiUserWindowManagerChromeOS::Observe( | 556 void MultiUserWindowManagerChromeOS::Observe( |
| 533 int type, | 557 int type, |
| 534 const content::NotificationSource& source, | 558 const content::NotificationSource& source, |
| 535 const content::NotificationDetails& details) { | 559 const content::NotificationDetails& details) { |
| 536 if (type == NOTIFICATION_BROWSER_WINDOW_READY) | 560 if (type == NOTIFICATION_BROWSER_WINDOW_READY) |
| 537 AddBrowserWindow(content::Source<Browser>(source).ptr()); | 561 AddBrowserWindow(content::Source<Browser>(source).ptr()); |
| 538 } | 562 } |
| 539 | 563 |
| 564 void MultiUserWindowManagerChromeOS::SetAnimationsForTest(bool disable) { |
| 565 animations_disabled_ = disable; |
| 566 } |
| 567 |
| 568 bool MultiUserWindowManagerChromeOS::IsAnimationRunningForTest() { |
| 569 return user_changed_animation_timer_.get() != NULL; |
| 570 } |
| 571 |
| 572 void MultiUserWindowManagerChromeOS::TransitionUser( |
| 573 MultiUserWindowManagerChromeOS::AnimationStep animation_step) { |
| 574 TransitionWallpaper(animation_step); |
| 575 TransitionUserShelf(animation_step); |
| 576 |
| 577 // Disable the window position manager and the MRU window tracker temporarily. |
| 578 scoped_ptr<UserChangeActionDisabler> disabler(new UserChangeActionDisabler); |
| 579 |
| 580 // We need to show/hide the windows in the same order as they were created in |
| 581 // their parent window(s) to keep the layer / window hierarchy in sync. To |
| 582 // achieve that we first collect all parent windows and then enumerate all |
| 583 // windows in those parent windows and show or hide them accordingly. |
| 584 |
| 585 // Create a list of all parent windows we have to check and their parents. |
| 586 std::set<aura::Window*> parent_list; |
| 587 for (WindowToEntryMap::iterator it = window_to_entry_.begin(); |
| 588 it != window_to_entry_.end(); ++it) { |
| 589 aura::Window* parent = it->first->parent(); |
| 590 if (parent_list.find(parent) == parent_list.end()) |
| 591 parent_list.insert(parent); |
| 592 } |
| 593 |
| 594 // Traverse the found parent windows to handle their child windows in order of |
| 595 // their appearance. |
| 596 for (std::set<aura::Window*>::iterator it_parents = parent_list.begin(); |
| 597 it_parents != parent_list.end(); ++it_parents) { |
| 598 const aura::Window::Windows window_list = (*it_parents)->children(); |
| 599 for (aura::Window::Windows::const_iterator it_window = window_list.begin(); |
| 600 it_window != window_list.end(); ++it_window) { |
| 601 aura::Window* window = *it_window; |
| 602 WindowToEntryMap::iterator it_map = window_to_entry_.find(window); |
| 603 if (it_map != window_to_entry_.end()) { |
| 604 bool should_be_visible = |
| 605 it_map->second->show_for_user() == current_user_id_ && |
| 606 it_map->second->show(); |
| 607 bool is_visible = window->IsVisible(); |
| 608 if (should_be_visible != is_visible && |
| 609 should_be_visible == (animation_step == SHOW_NEW_USER)) |
| 610 SetWindowVisibility(window, should_be_visible, kUserFadeTimeMS); |
| 611 } |
| 612 } |
| 613 } |
| 614 |
| 615 // Activation and real switch are happening after the other user gets shown. |
| 616 if (animation_step == SHOW_NEW_USER) { |
| 617 // Finally we need to restore the previously active window. |
| 618 ash::MruWindowTracker::WindowList mru_list = |
| 619 ash::Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList(); |
| 620 if (mru_list.size()) { |
| 621 aura::Window* window = mru_list[0]; |
| 622 ash::wm::WindowState* window_state = ash::wm::GetWindowState(window); |
| 623 if (IsWindowOnDesktopOfUser(window, current_user_id_) && |
| 624 !window_state->IsMinimized()) { |
| 625 aura::client::ActivationClient* client = |
| 626 aura::client::GetActivationClient(window->GetRootWindow()); |
| 627 // Several unit tests come here without an activation client. |
| 628 if (client) |
| 629 client->ActivateWindow(window); |
| 630 } |
| 631 } |
| 632 |
| 633 // This is called directly here to make sure notification_blocker will see |
| 634 // the new window status. |
| 635 notification_blocker_->ActiveUserChanged(current_user_id_); |
| 636 |
| 637 // We can reset the timer at this point. |
| 638 // Note: The timer can be destroyed while it is performing its task. |
| 639 user_changed_animation_timer_.reset(); |
| 640 } |
| 641 } |
| 642 |
| 643 void MultiUserWindowManagerChromeOS::TransitionWallpaper( |
| 644 MultiUserWindowManagerChromeOS::AnimationStep animation_step) { |
| 645 // Handle the wallpaper switch. |
| 646 if (chromeos::WallpaperManager::Get()) { |
| 647 ash::UserWallpaperDelegate* wallpaper_delegate = |
| 648 ash::Shell::GetInstance()->user_wallpaper_delegate(); |
| 649 if (animation_step == HIDE_OLD_USER) { |
| 650 // Set the wallpaper cross dissolve animation duration to our complete |
| 651 // animation cycle for a fade in and fade out. |
| 652 wallpaper_delegate->SetAnimationDurationOverride(2 * kUserFadeTimeMS); |
| 653 chromeos::WallpaperManager::Get()->SetUserWallpaperDelayed( |
| 654 current_user_id_); |
| 655 } else { |
| 656 // Revert the wallpaper cross dissolve animation duration back to the |
| 657 // default. |
| 658 wallpaper_delegate->SetAnimationDurationOverride(0); |
| 659 } |
| 660 } |
| 661 } |
| 662 |
| 663 void MultiUserWindowManagerChromeOS::TransitionUserShelf( |
| 664 MultiUserWindowManagerChromeOS::AnimationStep animation_step) { |
| 665 // The shelf animation duration override. |
| 666 int duration_override = kUserFadeTimeMS; |
| 667 // Handle the shelf order of items. This is done once the old user is hidden. |
| 668 if (animation_step == SHOW_NEW_USER) { |
| 669 // Some unit tests have no ChromeLauncherController. |
| 670 if (ChromeLauncherController::instance()) |
| 671 ChromeLauncherController::instance()->ActiveUserChanged(current_user_id_); |
| 672 // We kicked off the shelf animation in the command above. As such we can |
| 673 // disable the override now again. |
| 674 duration_override = 0; |
| 675 } |
| 676 |
| 677 if (animations_disabled_) |
| 678 return; |
| 679 |
| 680 ash::Shell::RootWindowControllerList controller = |
| 681 ash::Shell::GetInstance()->GetAllRootWindowControllers(); |
| 682 for (ash::Shell::RootWindowControllerList::iterator it1 = controller.begin(); |
| 683 it1 != controller.end(); ++it1) { |
| 684 (*it1)->GetShelfLayoutManager()->SetAnimationDurationOverride( |
| 685 duration_override); |
| 686 } |
| 687 |
| 688 // For each root window hide the shelf. |
| 689 if (animation_step == HIDE_OLD_USER) { |
| 690 aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows(); |
| 691 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); |
| 692 iter != root_windows.end(); ++iter) { |
| 693 ash::Shell::GetInstance()->SetShelfAutoHideBehavior( |
| 694 ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN, *iter); |
| 695 } |
| 696 } |
| 697 } |
| 698 |
| 540 void MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) { | 699 void MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) { |
| 541 // A unit test (e.g. CrashRestoreComplexTest.RestoreSessionForThreeUsers) can | 700 // A unit test (e.g. CrashRestoreComplexTest.RestoreSessionForThreeUsers) can |
| 542 // come here with no valid window. | 701 // come here with no valid window. |
| 543 if (!browser->window() || !browser->window()->GetNativeWindow()) | 702 if (!browser->window() || !browser->window()->GetNativeWindow()) |
| 544 return; | 703 return; |
| 545 SetWindowOwner(browser->window()->GetNativeWindow(), | 704 SetWindowOwner(browser->window()->GetNativeWindow(), |
| 546 multi_user_util::GetUserIDFromProfile(browser->profile())); | 705 multi_user_util::GetUserIDFromProfile(browser->profile())); |
| 547 } | 706 } |
| 548 | 707 |
| 549 void MultiUserWindowManagerChromeOS::SetWindowVisibility( | 708 void MultiUserWindowManagerChromeOS::SetWindowVisibility( |
| 550 aura::Window* window, bool visible) { | 709 aura::Window* window, bool visible, int animation_time_in_ms) { |
| 551 if (window->IsVisible() == visible) | 710 if (window->IsVisible() == visible) |
| 552 return; | 711 return; |
| 553 | 712 |
| 554 // Hiding a system modal dialog should not be allowed. Instead we switch to | 713 // Hiding a system modal dialog should not be allowed. Instead we switch to |
| 555 // the user which is showing the system modal window. | 714 // the user which is showing the system modal window. |
| 556 // Note that in some cases (e.g. unit test) windows might not have a root | 715 // Note that in some cases (e.g. unit test) windows might not have a root |
| 557 // window. | 716 // window. |
| 558 if (!visible && window->GetRootWindow()) { | 717 if (!visible && window->GetRootWindow()) { |
| 559 // Get the system modal container for the window's root window. | 718 // Get the system modal container for the window's root window. |
| 560 aura::Window* system_modal_container = | 719 aura::Window* system_modal_container = |
| (...skipping 13 matching lines...) Expand all Loading... |
| 574 user_id); | 733 user_id); |
| 575 return; | 734 return; |
| 576 } | 735 } |
| 577 } | 736 } |
| 578 | 737 |
| 579 // To avoid that these commands are recorded as any other commands, we are | 738 // To avoid that these commands are recorded as any other commands, we are |
| 580 // suppressing any window entry changes while this is going on. | 739 // suppressing any window entry changes while this is going on. |
| 581 base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); | 740 base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); |
| 582 | 741 |
| 583 if (visible) { | 742 if (visible) { |
| 584 ShowWithTransientChildrenRecursive(window); | 743 ShowWithTransientChildrenRecursive(window, animation_time_in_ms); |
| 585 } else { | 744 } else { |
| 586 if (window->HasFocus()) | 745 if (window->HasFocus()) |
| 587 window->Blur(); | 746 window->Blur(); |
| 588 window->Hide(); | 747 SetWindowVisible(window, false, animation_time_in_ms); |
| 589 } | 748 } |
| 590 } | 749 } |
| 591 | 750 |
| 592 void MultiUserWindowManagerChromeOS::ShowWithTransientChildrenRecursive( | 751 void MultiUserWindowManagerChromeOS::ShowWithTransientChildrenRecursive( |
| 593 aura::Window* window) { | 752 aura::Window* window, int animation_time_in_ms) { |
| 594 aura::Window::Windows::const_iterator it = | 753 aura::Window::Windows::const_iterator it = |
| 595 views::corewm::GetTransientChildren(window).begin(); | 754 views::corewm::GetTransientChildren(window).begin(); |
| 596 for (; it != views::corewm::GetTransientChildren(window).end(); ++it) | 755 for (; it != views::corewm::GetTransientChildren(window).end(); ++it) |
| 597 ShowWithTransientChildrenRecursive(*it); | 756 ShowWithTransientChildrenRecursive(*it, animation_time_in_ms); |
| 598 | 757 |
| 599 // We show all children which were not explicitly hidden. | 758 // We show all children which were not explicitly hidden. |
| 600 TransientWindowToVisibility::iterator it2 = | 759 TransientWindowToVisibility::iterator it2 = |
| 601 transient_window_to_visibility_.find(window); | 760 transient_window_to_visibility_.find(window); |
| 602 if (it2 == transient_window_to_visibility_.end() || it2->second) | 761 if (it2 == transient_window_to_visibility_.end() || it2->second) |
| 603 window->Show(); | 762 SetWindowVisible(window, true, animation_time_in_ms); |
| 604 } | 763 } |
| 605 | 764 |
| 606 aura::Window* MultiUserWindowManagerChromeOS::GetOwningWindowInTransientChain( | 765 aura::Window* MultiUserWindowManagerChromeOS::GetOwningWindowInTransientChain( |
| 607 aura::Window* window) { | 766 aura::Window* window) { |
| 608 if (!GetWindowOwner(window).empty()) | 767 if (!GetWindowOwner(window).empty()) |
| 609 return NULL; | 768 return NULL; |
| 610 aura::Window* parent = views::corewm::GetTransientParent(window); | 769 aura::Window* parent = views::corewm::GetTransientParent(window); |
| 611 while (parent) { | 770 while (parent) { |
| 612 if (!GetWindowOwner(parent).empty()) | 771 if (!GetWindowOwner(parent).empty()) |
| 613 return parent; | 772 return parent; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 635 transient_window_to_visibility_[window] = window->IsVisible(); | 794 transient_window_to_visibility_[window] = window->IsVisible(); |
| 636 | 795 |
| 637 // Add observers to track state changes. | 796 // Add observers to track state changes. |
| 638 window->AddObserver(this); | 797 window->AddObserver(this); |
| 639 views::corewm::TransientWindowManager::Get(window)->AddObserver(this); | 798 views::corewm::TransientWindowManager::Get(window)->AddObserver(this); |
| 640 | 799 |
| 641 // Hide the window if it should not be shown. Note that this hide operation | 800 // Hide the window if it should not be shown. Note that this hide operation |
| 642 // will hide recursively this and all children - but we have already collected | 801 // will hide recursively this and all children - but we have already collected |
| 643 // their initial view state. | 802 // their initial view state. |
| 644 if (!IsWindowOnDesktopOfUser(owned_parent, current_user_id_)) | 803 if (!IsWindowOnDesktopOfUser(owned_parent, current_user_id_)) |
| 645 SetWindowVisibility(window, false); | 804 SetWindowVisibility(window, false, kAnimationTimeMS); |
| 646 } | 805 } |
| 647 | 806 |
| 648 void MultiUserWindowManagerChromeOS::RemoveTransientOwnerRecursive( | 807 void MultiUserWindowManagerChromeOS::RemoveTransientOwnerRecursive( |
| 649 aura::Window* window) { | 808 aura::Window* window) { |
| 650 // First remove all child windows. | 809 // First remove all child windows. |
| 651 aura::Window::Windows::const_iterator it = | 810 aura::Window::Windows::const_iterator it = |
| 652 views::corewm::GetTransientChildren(window).begin(); | 811 views::corewm::GetTransientChildren(window).begin(); |
| 653 for (; it != views::corewm::GetTransientChildren(window).end(); ++it) | 812 for (; it != views::corewm::GetTransientChildren(window).end(); ++it) |
| 654 RemoveTransientOwnerRecursive(*it); | 813 RemoveTransientOwnerRecursive(*it); |
| 655 | 814 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 667 if (unowned_view_state && !window->IsVisible()) { | 826 if (unowned_view_state && !window->IsVisible()) { |
| 668 // To prevent these commands from being recorded as any other commands, we | 827 // To prevent these commands from being recorded as any other commands, we |
| 669 // are suppressing any window entry changes while this is going on. | 828 // are suppressing any window entry changes while this is going on. |
| 670 // Instead of calling SetWindowVisible, only show gets called here since all | 829 // Instead of calling SetWindowVisible, only show gets called here since all |
| 671 // dependents have been shown previously already. | 830 // dependents have been shown previously already. |
| 672 base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); | 831 base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true); |
| 673 window->Show(); | 832 window->Show(); |
| 674 } | 833 } |
| 675 } | 834 } |
| 676 | 835 |
| 836 void MultiUserWindowManagerChromeOS::SetWindowVisible( |
| 837 aura::Window* window, |
| 838 bool visible, |
| 839 int animation_time_in_ms) { |
| 840 AnimationSetter animation_setter( |
| 841 window, |
| 842 animations_disabled_ ? 0 : animation_time_in_ms); |
| 843 |
| 844 if (visible) |
| 845 window->Show(); |
| 846 else |
| 847 window->Hide(); |
| 848 |
| 849 // Make sure that animations have no influence on the window state after the |
| 850 // call. |
| 851 DCHECK_EQ(visible, window->IsVisible()); |
| 852 } |
| 853 |
| 677 } // namespace chrome | 854 } // namespace chrome |
| OLD | NEW |