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 |