This source file includes following definitions.
- IsUserEvent
- IsProcessingUserEvent
- RecordUMAForTransferredWindowType
- previous_animation_time_
- OnAppWindowAdded
- OnAppWindowIconChanged
- OnAppWindowRemoved
- animations_disabled_
- SetWindowOwner
- GetWindowOwner
- ShowWindowForUser
- AreWindowsSharedAmongUsers
- GetOwnersOfVisibleWindows
- IsWindowOnDesktopOfUser
- GetUserPresentingWindow
- AddUser
- AddObserver
- RemoveObserver
- ActiveUserChanged
- OnWindowDestroyed
- OnWindowVisibilityChanging
- OnWindowVisibilityChanged
- OnTransientChildAdded
- OnTransientChildRemoved
- Observe
- SetAnimationsForTest
- IsAnimationRunningForTest
- GetCurrentUserForTest
- ShowWindowForUserIntern
- TransitionUser
- TransitionWallpaper
- TransitionUserShelf
- AddBrowserWindow
- SetWindowVisibility
- ShowWithTransientChildrenRecursive
- GetOwningWindowInTransientChain
- AddTransientOwnerRecursive
- RemoveTransientOwnerRecursive
- SetWindowVisible
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
#include "apps/app_window.h"
#include "apps/app_window_registry.h"
#include "ash/ash_switches.h"
#include "ash/desktop_background/user_wallpaper_delegate.h"
#include "ash/multi_profile_uma.h"
#include "ash/root_window_controller.h"
#include "ash/session_state_delegate.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/window_positioner.h"
#include "ash/wm/window_state.h"
#include "base/auto_reset.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/wallpaper_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "content/public/browser/notification_service.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/ui_base_types.h"
#include "ui/events/event.h"
#include "ui/message_center/message_center.h"
#include "ui/wm/core/transient_window_manager.h"
#include "ui/wm/core/window_animations.h"
#include "ui/wm/core/window_util.h"
#include "ui/wm/public/activation_client.h"
namespace {
static int kAnimationTimeMS = 100;
static int kUserFadeTimeMS = 110;
static int kTeleportAnimationTimeMS = 300;
bool IsUserEvent(ui::Event* e) {
if (e) {
ui::EventType type = e->type();
if (type != ui::ET_CANCEL_MODE &&
type != ui::ET_UMA_DATA &&
type != ui::ET_UNKNOWN)
return true;
}
return false;
}
bool IsProcessingUserEvent() {
base::MessageLoop* message_loop = base::MessageLoop::current();
if (message_loop && message_loop->is_running() && message_loop->IsNested())
return false;
aura::Window::Windows root_window_list = ash::Shell::GetAllRootWindows();
for (aura::Window::Windows::iterator it = root_window_list.begin();
it != root_window_list.end();
++it) {
if (IsUserEvent((*it)->GetHost()->dispatcher()->current_event()))
return true;
}
return false;
}
void RecordUMAForTransferredWindowType(aura::Window* window) {
Browser* browser = chrome::FindBrowserWithWindow(window);
ash::MultiProfileUMA::TeleportWindowType window_type =
ash::MultiProfileUMA::TELEPORT_WINDOW_UNKNOWN;
if (browser) {
if (browser->profile()->IsOffTheRecord()) {
window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_INCOGNITO_BROWSER;
} else if (browser->is_app()) {
window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_V1_APP;
} else if (browser->is_type_popup()) {
window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_POPUP;
} else {
window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_BROWSER;
}
} else {
if (!g_browser_process->profile_manager())
return;
apps::AppWindow* app_window = NULL;
std::vector<Profile*> profiles =
g_browser_process->profile_manager()->GetLoadedProfiles();
for (std::vector<Profile*>::iterator it = profiles.begin();
it != profiles.end() && app_window == NULL;
it++) {
app_window = apps::AppWindowRegistry::Get(*it)
->GetAppWindowForNativeWindow(window);
}
if (app_window) {
if (app_window->window_type() == apps::AppWindow::WINDOW_TYPE_PANEL ||
app_window->window_type() == apps::AppWindow::WINDOW_TYPE_V1_PANEL) {
window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_PANEL;
} else {
window_type = ash::MultiProfileUMA::TELEPORT_WINDOW_V2_APP;
}
}
}
ash::MultiProfileUMA::RecordTeleportWindowType(window_type);
}
}
namespace chrome {
class AnimationSetter {
public:
AnimationSetter(aura::Window* window, int animation_time_in_ms)
: window_(window),
previous_animation_type_(
wm::GetWindowVisibilityAnimationType(window_)),
previous_animation_time_(
wm::GetWindowVisibilityAnimationDuration(*window_)) {
wm::SetWindowVisibilityAnimationType(
window_,
wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
wm::SetWindowVisibilityAnimationDuration(
window_,
base::TimeDelta::FromMilliseconds(animation_time_in_ms));
}
~AnimationSetter() {
wm::SetWindowVisibilityAnimationType(window_,
previous_animation_type_);
wm::SetWindowVisibilityAnimationDuration(
window_,
previous_animation_time_);
}
private:
aura::Window* window_;
const int previous_animation_type_;
const base::TimeDelta previous_animation_time_;
DISALLOW_COPY_AND_ASSIGN(AnimationSetter);
};
class UserChangeActionDisabler {
public:
UserChangeActionDisabler() {
ash::WindowPositioner::DisableAutoPositioning(true);
ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(true);
}
~UserChangeActionDisabler() {
ash::WindowPositioner::DisableAutoPositioning(false);
ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(
false);
}
private:
DISALLOW_COPY_AND_ASSIGN(UserChangeActionDisabler);
};
class AppObserver : public apps::AppWindowRegistry::Observer {
public:
explicit AppObserver(const std::string& user_id) : user_id_(user_id) {}
virtual ~AppObserver() {}
virtual void OnAppWindowAdded(apps::AppWindow* app_window) OVERRIDE {
aura::Window* window = app_window->GetNativeWindow();
DCHECK(window);
MultiUserWindowManagerChromeOS::GetInstance()->SetWindowOwner(window,
user_id_);
}
virtual void OnAppWindowIconChanged(apps::AppWindow* app_window) OVERRIDE {}
virtual void OnAppWindowRemoved(apps::AppWindow* app_window) OVERRIDE {}
private:
std::string user_id_;
DISALLOW_COPY_AND_ASSIGN(AppObserver);
};
MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS(
const std::string& current_user_id)
: current_user_id_(current_user_id),
notification_blocker_(new MultiUserNotificationBlockerChromeOS(
message_center::MessageCenter::Get(), this, current_user_id)),
suppress_visibility_changes_(false),
animations_disabled_(false) {
if (ash::Shell::HasInstance())
ash::Shell::GetInstance()->session_state_delegate()->
AddSessionStateObserver(this);
registrar_.Add(this, NOTIFICATION_BROWSER_WINDOW_READY,
content::NotificationService::AllSources());
Profile* profile = multi_user_util::GetProfileFromUserID(current_user_id);
if (profile)
AddUser(profile);
}
MultiUserWindowManagerChromeOS::~MultiUserWindowManagerChromeOS() {
WindowToEntryMap::iterator window = window_to_entry_.begin();
while (window != window_to_entry_.end()) {
OnWindowDestroyed(window->first);
window = window_to_entry_.begin();
}
UserIDToAppWindowObserver::iterator app_observer_iterator =
user_id_to_app_observer_.begin();
while (app_observer_iterator != user_id_to_app_observer_.end()) {
Profile* profile = multi_user_util::GetProfileFromUserID(
app_observer_iterator->first);
DCHECK(profile);
apps::AppWindowRegistry::Get(profile)
->RemoveObserver(app_observer_iterator->second);
delete app_observer_iterator->second;
user_id_to_app_observer_.erase(app_observer_iterator);
app_observer_iterator = user_id_to_app_observer_.begin();
}
if (ash::Shell::HasInstance())
ash::Shell::GetInstance()->session_state_delegate()->
RemoveSessionStateObserver(this);
}
void MultiUserWindowManagerChromeOS::SetWindowOwner(
aura::Window* window,
const std::string& user_id) {
DCHECK(window);
DCHECK(!user_id.empty());
if (GetWindowOwner(window) == user_id)
return;
DCHECK(GetWindowOwner(window).empty());
window_to_entry_[window] = new WindowEntry(user_id);
window_to_entry_[window]->set_show(window->IsVisible());
window->AddObserver(this);
wm::TransientWindowManager::Get(window)->AddObserver(this);
if (IsProcessingUserEvent())
window_to_entry_[window]->set_show_for_user(current_user_id_);
AddTransientOwnerRecursive(window, window);
FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryAdded(window));
if (!IsWindowOnDesktopOfUser(window, current_user_id_))
SetWindowVisibility(window, false, 0);
}
const std::string& MultiUserWindowManagerChromeOS::GetWindowOwner(
aura::Window* window) {
WindowToEntryMap::iterator it = window_to_entry_.find(window);
return it != window_to_entry_.end() ? it->second->owner()
: base::EmptyString();
}
void MultiUserWindowManagerChromeOS::ShowWindowForUser(
aura::Window* window,
const std::string& user_id) {
std::string previous_owner(GetUserPresentingWindow(window));
if (!ShowWindowForUserIntern(window, user_id))
return;
if (user_id == current_user_id_ || previous_owner != current_user_id_)
return;
ash::Shell::GetInstance()->session_state_delegate()->SwitchActiveUser(
user_id);
}
bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() {
WindowToEntryMap::iterator it = window_to_entry_.begin();
for (; it != window_to_entry_.end(); ++it) {
if (it->second->owner() != it->second->show_for_user())
return true;
}
return false;
}
void MultiUserWindowManagerChromeOS::GetOwnersOfVisibleWindows(
std::set<std::string>* user_ids) {
for (WindowToEntryMap::iterator it = window_to_entry_.begin();
it != window_to_entry_.end(); ++it) {
if (it->first->IsVisible())
user_ids->insert(it->second->owner());
}
}
bool MultiUserWindowManagerChromeOS::IsWindowOnDesktopOfUser(
aura::Window* window,
const std::string& user_id) {
const std::string& presenting_user = GetUserPresentingWindow(window);
return presenting_user.empty() || presenting_user == user_id;
}
const std::string& MultiUserWindowManagerChromeOS::GetUserPresentingWindow(
aura::Window* window) {
WindowToEntryMap::iterator it = window_to_entry_.find(window);
if (it == window_to_entry_.end())
return base::EmptyString();
return it->second->show_for_user();
}
void MultiUserWindowManagerChromeOS::AddUser(content::BrowserContext* context) {
Profile* profile = Profile::FromBrowserContext(context);
const std::string& user_id = multi_user_util::GetUserIDFromProfile(profile);
if (user_id_to_app_observer_.find(user_id) != user_id_to_app_observer_.end())
return;
user_id_to_app_observer_[user_id] = new AppObserver(user_id);
apps::AppWindowRegistry::Get(profile)
->AddObserver(user_id_to_app_observer_[user_id]);
const apps::AppWindowRegistry::AppWindowList& app_windows =
apps::AppWindowRegistry::Get(profile)->app_windows();
apps::AppWindowRegistry::AppWindowList::const_iterator it =
app_windows.begin();
for (; it != app_windows.end(); ++it)
user_id_to_app_observer_[user_id]->OnAppWindowAdded(*it);
BrowserList* browser_list = BrowserList::GetInstance(HOST_DESKTOP_TYPE_ASH);
BrowserList::const_iterator browser_it = browser_list->begin();
for (; browser_it != browser_list->end(); ++browser_it) {
if ((*browser_it)->profile()->GetOriginalProfile() == profile)
AddBrowserWindow(*browser_it);
}
}
void MultiUserWindowManagerChromeOS::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void MultiUserWindowManagerChromeOS::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void MultiUserWindowManagerChromeOS::ActiveUserChanged(
const std::string& user_id) {
DCHECK(user_id != current_user_id_);
current_user_id_ = user_id;
if (user_changed_animation_timer_.get())
TransitionUser(SHOW_NEW_USER);
TransitionUser(HIDE_OLD_USER);
if (animations_disabled_) {
TransitionUser(SHOW_NEW_USER);
} else {
user_changed_animation_timer_.reset(new base::Timer(
FROM_HERE,
base::TimeDelta::FromMilliseconds(kUserFadeTimeMS),
base::Bind(&MultiUserWindowManagerChromeOS::TransitionUser,
base::Unretained(this),
SHOW_NEW_USER),
false));
user_changed_animation_timer_->Reset();
}
}
void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) {
if (GetWindowOwner(window).empty()) {
RemoveTransientOwnerRecursive(window);
return;
}
wm::TransientWindowManager::Get(window)->RemoveObserver(this);
delete window_to_entry_[window];
window_to_entry_.erase(window);
FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryRemoved(window));
}
void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanging(
aura::Window* window, bool visible) {
if (suppress_visibility_changes_)
return;
WindowToEntryMap::iterator it = window_to_entry_.find(window);
if (it != window_to_entry_.end()) {
it->second->set_show(visible);
} else {
TransientWindowToVisibility::iterator it =
transient_window_to_visibility_.find(window);
if (it != transient_window_to_visibility_.end())
it->second = visible;
}
}
void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanged(
aura::Window* window, bool visible) {
if (suppress_visibility_changes_)
return;
if (visible && !IsWindowOnDesktopOfUser(window, current_user_id_)) {
SetWindowVisibility(window, false, 0);
return;
}
aura::Window* owned_parent = GetOwningWindowInTransientChain(window);
if (owned_parent && owned_parent != window && visible &&
!IsWindowOnDesktopOfUser(owned_parent, current_user_id_))
SetWindowVisibility(window, false, 0);
}
void MultiUserWindowManagerChromeOS::OnTransientChildAdded(
aura::Window* window,
aura::Window* transient_window) {
if (!GetWindowOwner(window).empty()) {
AddTransientOwnerRecursive(transient_window, window);
return;
}
aura::Window* owned_parent =
GetOwningWindowInTransientChain(transient_window);
if (!owned_parent)
return;
AddTransientOwnerRecursive(transient_window, owned_parent);
}
void MultiUserWindowManagerChromeOS::OnTransientChildRemoved(
aura::Window* window,
aura::Window* transient_window) {
if (!GetWindowOwner(window).empty() ||
GetOwningWindowInTransientChain(window))
RemoveTransientOwnerRecursive(transient_window);
}
void MultiUserWindowManagerChromeOS::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (type == NOTIFICATION_BROWSER_WINDOW_READY)
AddBrowserWindow(content::Source<Browser>(source).ptr());
}
void MultiUserWindowManagerChromeOS::SetAnimationsForTest(bool disable) {
animations_disabled_ = disable;
}
bool MultiUserWindowManagerChromeOS::IsAnimationRunningForTest() {
return user_changed_animation_timer_.get() != NULL;
}
const std::string& MultiUserWindowManagerChromeOS::GetCurrentUserForTest() {
return current_user_id_;
}
bool MultiUserWindowManagerChromeOS::ShowWindowForUserIntern(
aura::Window* window,
const std::string& user_id) {
const std::string& owner = GetWindowOwner(window);
if (owner.empty() ||
(owner == user_id && IsWindowOnDesktopOfUser(window, user_id)))
return false;
bool minimized = ash::wm::GetWindowState(window)->IsMinimized();
if (user_id != owner && minimized)
return false;
if (minimized) {
ash::MultiProfileUMA::RecordTeleportAction(
ash::MultiProfileUMA::TELEPORT_WINDOW_RETURN_BY_MINIMIZE);
} else {
RecordUMAForTransferredWindowType(window);
}
WindowToEntryMap::iterator it = window_to_entry_.find(window);
it->second->set_show_for_user(user_id);
if (user_id == current_user_id_) {
if (it->second->show())
SetWindowVisibility(window, true, kTeleportAnimationTimeMS);
} else {
SetWindowVisibility(window, false, kTeleportAnimationTimeMS);
}
FOR_EACH_OBSERVER(Observer, observers_, OnOwnerEntryChanged(window));
return true;
}
void MultiUserWindowManagerChromeOS::TransitionUser(
MultiUserWindowManagerChromeOS::AnimationStep animation_step) {
TransitionWallpaper(animation_step);
TransitionUserShelf(animation_step);
scoped_ptr<UserChangeActionDisabler> disabler(new UserChangeActionDisabler);
std::set<aura::Window*> parent_list;
for (WindowToEntryMap::iterator it = window_to_entry_.begin();
it != window_to_entry_.end(); ++it) {
aura::Window* parent = it->first->parent();
if (parent_list.find(parent) == parent_list.end())
parent_list.insert(parent);
}
for (std::set<aura::Window*>::iterator it_parents = parent_list.begin();
it_parents != parent_list.end(); ++it_parents) {
const aura::Window::Windows window_list = (*it_parents)->children();
for (aura::Window::Windows::const_iterator it_window = window_list.begin();
it_window != window_list.end(); ++it_window) {
aura::Window* window = *it_window;
WindowToEntryMap::iterator it_map = window_to_entry_.find(window);
if (it_map != window_to_entry_.end()) {
bool should_be_visible =
it_map->second->show_for_user() == current_user_id_ &&
it_map->second->show();
bool is_visible = window->IsVisible();
ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
if (animation_step == SHOW_NEW_USER &&
it_map->second->owner() == current_user_id_ &&
it_map->second->show_for_user() != current_user_id_ &&
window_state->IsMinimized()) {
ShowWindowForUserIntern(window, current_user_id_);
window_state->Unminimize();
} else if (should_be_visible != is_visible &&
should_be_visible == (animation_step == SHOW_NEW_USER)) {
SetWindowVisibility(window, should_be_visible, kUserFadeTimeMS);
}
}
}
}
if (animation_step == SHOW_NEW_USER) {
ash::MruWindowTracker::WindowList mru_list =
ash::Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList();
if (mru_list.size()) {
aura::Window* window = mru_list[0];
ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
if (IsWindowOnDesktopOfUser(window, current_user_id_) &&
!window_state->IsMinimized()) {
aura::client::ActivationClient* client =
aura::client::GetActivationClient(window->GetRootWindow());
if (client)
client->ActivateWindow(window);
}
}
notification_blocker_->ActiveUserChanged(current_user_id_);
user_changed_animation_timer_.reset();
}
}
void MultiUserWindowManagerChromeOS::TransitionWallpaper(
MultiUserWindowManagerChromeOS::AnimationStep animation_step) {
ash::UserWallpaperDelegate* wallpaper_delegate =
ash::Shell::GetInstance()->user_wallpaper_delegate();
if (animation_step == HIDE_OLD_USER) {
wallpaper_delegate->SetAnimationDurationOverride(2 * kUserFadeTimeMS);
chromeos::WallpaperManager::Get()->SetUserWallpaperDelayed(
current_user_id_);
} else {
wallpaper_delegate->SetAnimationDurationOverride(0);
}
}
void MultiUserWindowManagerChromeOS::TransitionUserShelf(
MultiUserWindowManagerChromeOS::AnimationStep animation_step) {
int duration_override = kUserFadeTimeMS;
if (animation_step == SHOW_NEW_USER) {
if (ChromeLauncherController::instance())
ChromeLauncherController::instance()->ActiveUserChanged(current_user_id_);
duration_override = 0;
}
if (animations_disabled_)
return;
ash::Shell::RootWindowControllerList controller =
ash::Shell::GetInstance()->GetAllRootWindowControllers();
for (ash::Shell::RootWindowControllerList::iterator it1 = controller.begin();
it1 != controller.end(); ++it1) {
(*it1)->GetShelfLayoutManager()->SetAnimationDurationOverride(
duration_override);
}
if (animation_step == HIDE_OLD_USER) {
aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
for (aura::Window::Windows::const_iterator iter = root_windows.begin();
iter != root_windows.end(); ++iter) {
ash::Shell::GetInstance()->SetShelfAutoHideBehavior(
ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN, *iter);
}
}
}
void MultiUserWindowManagerChromeOS::AddBrowserWindow(Browser* browser) {
if (!browser->window() || !browser->window()->GetNativeWindow())
return;
SetWindowOwner(browser->window()->GetNativeWindow(),
multi_user_util::GetUserIDFromProfile(browser->profile()));
}
void MultiUserWindowManagerChromeOS::SetWindowVisibility(
aura::Window* window, bool visible, int animation_time_in_ms) {
if (window->IsVisible() == visible)
return;
if (!visible && window->GetRootWindow()) {
aura::Window* system_modal_container =
window->GetRootWindow()->GetChildById(
ash::kShellWindowId_SystemModalContainer);
if (window->parent() == system_modal_container) {
std::string user_id = GetUserPresentingWindow(window);
if (user_id.empty()) {
aura::Window* owning_window = GetOwningWindowInTransientChain(window);
DCHECK(owning_window);
user_id = GetUserPresentingWindow(owning_window);
DCHECK(!user_id.empty());
}
ash::Shell::GetInstance()->session_state_delegate()->SwitchActiveUser(
user_id);
return;
}
}
base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true);
if (visible) {
ShowWithTransientChildrenRecursive(window, animation_time_in_ms);
} else {
if (window->HasFocus())
window->Blur();
SetWindowVisible(window, false, animation_time_in_ms);
}
}
void MultiUserWindowManagerChromeOS::ShowWithTransientChildrenRecursive(
aura::Window* window, int animation_time_in_ms) {
aura::Window::Windows::const_iterator it =
wm::GetTransientChildren(window).begin();
for (; it != wm::GetTransientChildren(window).end(); ++it)
ShowWithTransientChildrenRecursive(*it, animation_time_in_ms);
TransientWindowToVisibility::iterator it2 =
transient_window_to_visibility_.find(window);
if (it2 == transient_window_to_visibility_.end() || it2->second)
SetWindowVisible(window, true, animation_time_in_ms);
}
aura::Window* MultiUserWindowManagerChromeOS::GetOwningWindowInTransientChain(
aura::Window* window) {
if (!GetWindowOwner(window).empty())
return NULL;
aura::Window* parent = wm::GetTransientParent(window);
while (parent) {
if (!GetWindowOwner(parent).empty())
return parent;
parent = wm::GetTransientParent(parent);
}
return NULL;
}
void MultiUserWindowManagerChromeOS::AddTransientOwnerRecursive(
aura::Window* window,
aura::Window* owned_parent) {
aura::Window::Windows::const_iterator it =
wm::GetTransientChildren(window).begin();
for (; it != wm::GetTransientChildren(window).end(); ++it)
AddTransientOwnerRecursive(*it, owned_parent);
if (window == owned_parent)
return;
DCHECK(transient_window_to_visibility_.find(window) ==
transient_window_to_visibility_.end());
transient_window_to_visibility_[window] = window->IsVisible();
window->AddObserver(this);
wm::TransientWindowManager::Get(window)->AddObserver(this);
if (!IsWindowOnDesktopOfUser(owned_parent, current_user_id_))
SetWindowVisibility(window, false, kAnimationTimeMS);
}
void MultiUserWindowManagerChromeOS::RemoveTransientOwnerRecursive(
aura::Window* window) {
aura::Window::Windows::const_iterator it =
wm::GetTransientChildren(window).begin();
for (; it != wm::GetTransientChildren(window).end(); ++it)
RemoveTransientOwnerRecursive(*it);
TransientWindowToVisibility::iterator visibility_item =
transient_window_to_visibility_.find(window);
DCHECK(visibility_item != transient_window_to_visibility_.end());
window->RemoveObserver(this);
wm::TransientWindowManager::Get(window)->RemoveObserver(this);
bool unowned_view_state = visibility_item->second;
transient_window_to_visibility_.erase(visibility_item);
if (unowned_view_state && !window->IsVisible()) {
base::AutoReset<bool> suppressor(&suppress_visibility_changes_, true);
window->Show();
}
}
void MultiUserWindowManagerChromeOS::SetWindowVisible(
aura::Window* window,
bool visible,
int animation_time_in_ms) {
AnimationSetter animation_setter(
window,
animations_disabled_ ? 0 : animation_time_in_ms);
if (visible)
window->Show();
else
window->Hide();
DCHECK_EQ(visible, window->IsVisible());
}
}