1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_IMPL_H_
#define ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_IMPL_H_
#include <map>
#include <memory>
#include "ash/ash_export.h"
#include "ash/public/cpp/multi_user_window_manager.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/public/cpp/tablet_mode_observer.h"
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "components/account_id/account_id.h"
#include "ui/aura/window_observer.h"
#include "ui/wm/core/transient_window_observer.h"
namespace ash {
class MultiUserWindowManagerDelegate;
class UserSwitchAnimator;
// MultiUserWindowManager associates windows with users and ensures the
// appropriate set of windows are visible at the right time.
// MultiUserWindowManager must be explicitly told about the windows to manage.
// This is done by way of SetWindowOwner().
//
// Each window may be associated with two accounts. The owning account (the
// account supplied to SetWindowOwner()), and an account the window is shown
// with when the account is active. Typically the 'shown' account and 'owning'
// account are the same, but the user may choose to show a window from an other
// account, in which case the 'shown' account changes.
//
// Note:
// - aura::Window::Hide() is currently hiding the window and all owned transient
// children. However aura::Window::Show() is only showing the window itself.
// To address that, all transient children (and their children) are remembered
// in |transient_window_to_visibility_| and monitored to keep track of the
// visibility changes from the owning user. This way the visibility can be
// changed back to its requested state upon showing by us - or when the window
// gets detached from its current owning parent.
class ASH_EXPORT MultiUserWindowManagerImpl
: public MultiUserWindowManager,
public SessionObserver,
public aura::WindowObserver,
public ::wm::TransientWindowObserver,
public TabletModeObserver {
public:
// The speed which should be used to perform animations.
enum AnimationSpeed {
ANIMATION_SPEED_NORMAL, // The normal animation speed.
ANIMATION_SPEED_FAST, // Unit test speed which test animations.
ANIMATION_SPEED_DISABLED // Unit tests which do not require animations.
};
MultiUserWindowManagerImpl(MultiUserWindowManagerDelegate* delegate,
const AccountId& account_id);
MultiUserWindowManagerImpl(const MultiUserWindowManagerImpl&) = delete;
MultiUserWindowManagerImpl& operator=(const MultiUserWindowManagerImpl&) =
delete;
~MultiUserWindowManagerImpl() override;
static MultiUserWindowManagerImpl* Get();
// MultiUserWindowManager:
void SetWindowOwner(aura::Window* window,
const AccountId& account_id) override;
void ShowWindowForUser(aura::Window* window,
const AccountId& account_id) override;
const AccountId& GetWindowOwner(const aura::Window* window) const override;
bool AreWindowsSharedAmongUsers() const override;
std::set<AccountId> GetOwnersOfVisibleWindows() const override;
const AccountId& GetUserPresentingWindow(
const aura::Window* window) const override;
const AccountId& CurrentAccountId() const override;
// SessionObserver:
void OnActiveUserSessionChanged(const AccountId& account_id) override;
// WindowObserver overrides:
void OnWindowDestroyed(aura::Window* window) override;
void OnWindowVisibilityChanging(aura::Window* window, bool visible) override;
void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
// TransientWindowObserver overrides:
void OnTransientChildAdded(aura::Window* window,
aura::Window* transient) override;
void OnTransientChildRemoved(aura::Window* window,
aura::Window* transient) override;
// TabletModeObserver:
void OnTabletModeStarted() override;
// Disable any animations for unit tests.
void SetAnimationSpeedForTest(AnimationSpeed speed);
// Returns true when a user switch animation is running. For unit tests.
bool IsAnimationRunningForTest();
// Returns the current user for unit tests.
const AccountId& GetCurrentUserForTest() const;
private:
friend class MultiProfileSupportTest;
friend class UserSwitchAnimator;
class WindowEntry {
public:
explicit WindowEntry(const AccountId& account_id);
WindowEntry(const WindowEntry&) = delete;
WindowEntry& operator=(const WindowEntry&) = delete;
~WindowEntry();
// Returns the owner of this window. This cannot be changed.
const AccountId& owner() const { return owner_; }
// Returns the user for which this should be shown.
const AccountId& show_for_user() const { return show_for_user_; }
// Returns if the window should be shown for the "show user" or not.
bool show() const { return show_; }
// Set the user which will display the window on the owned desktop. If
// an empty user id gets passed the owner will be used.
void set_show_for_user(const AccountId& account_id) {
show_for_user_ = account_id.is_valid() ? account_id : owner_;
}
// Sets if the window gets shown for the active user or not.
void set_show(bool show) { show_ = show; }
private:
// The user id of the owner of this window.
const AccountId owner_;
// The user id of the user on which desktop the window gets shown.
AccountId show_for_user_;
// True if the window should be visible for the user which shows the window.
bool show_ = true;
};
using TransientWindowToVisibility = base::flat_map<aura::Window*, bool>;
using WindowToEntryMap =
std::map<aura::Window*, std::unique_ptr<WindowEntry>>;
// Returns true if the 'shown' owner of |window| is |account_id|.
bool IsWindowOnDesktopOfUser(aura::Window* window,
const AccountId& account_id) const;
// Returns the 'shown' owner.
const AccountId& GetUserPresentingWindow(aura::Window* window) const;
// Show a window for a user without switching the user.
// Returns true when the window moved to a new desktop.
bool ShowWindowForUserIntern(aura::Window* window,
const AccountId& account_id);
// Show / hide the given window. Note: By not doing this within the functions,
// this allows to either switching to different ways to show/hide and / or to
// distinguish state changes performed by this class vs. state changes
// performed by the others. Note furthermore that system modal dialogs will
// not get hidden. We will switch instead to the owners desktop.
// The |animation_time| is the time the animation should take, an empty value
// switches instantly.
void SetWindowVisibility(aura::Window* window,
bool visible,
base::TimeDelta animation_time = base::TimeDelta());
const WindowToEntryMap& window_to_entry() { return window_to_entry_; }
// Show the window and its transient children. However - if a transient child
// was turned invisible by some other operation, it will stay invisible.
// |animation_time| is the amount of time to animate.
void ShowWithTransientChildrenRecursive(aura::Window* window,
base::TimeDelta animation_time);
// Find the first owned window in the chain.
// Returns NULL when the window itself is owned.
aura::Window* GetOwningWindowInTransientChain(aura::Window* window) const;
// A |window| and its children were attached as transient children to an
// |owning_parent| and need to be registered. Note that the |owning_parent|
// itself will not be registered, but its children will.
void AddTransientOwnerRecursive(aura::Window* window,
aura::Window* owning_parent);
// A window and its children were removed from its parent and can be
// unregistered.
void RemoveTransientOwnerRecursive(aura::Window* window);
// Animate a |window| to be |visible| over a time of |animation_time|.
void SetWindowVisible(aura::Window* window,
bool visible,
base::TimeDelta aimation_time);
// Returns the time for an animation.
base::TimeDelta GetAdjustedAnimationTime(base::TimeDelta default_time) const;
raw_ptr<MultiUserWindowManagerDelegate, ExperimentalAsh> delegate_;
// A lookup to see to which user the given window belongs to, where and if it
// should get shown.
WindowToEntryMap window_to_entry_;
// A map which remembers for owned transient windows their own visibility.
TransientWindowToVisibility transient_window_to_visibility_;
// The currently selected active user. It is used to find the proper
// visibility state in various cases. The state is stored here instead of
// being read from the user manager to be in sync while a switch occurs.
AccountId current_account_id_;
// Suppress changes to the visibility flag while we are changing it ourselves.
bool suppress_visibility_changes_ = false;
// The speed which is used to perform any animations.
AnimationSpeed animation_speed_ = ANIMATION_SPEED_NORMAL;
// The animation between users.
std::unique_ptr<UserSwitchAnimator> animation_;
};
} // namespace ash
#endif // ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_IMPL_H_
|