forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmulti_user_window_manager.h
275 lines (216 loc) · 11.6 KB
/
multi_user_window_manager.h
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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
// Copyright 2018 The Chromium Authors. All rights reserved.
// 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_H_
#define ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_H_
#include <map>
#include <memory>
#include "ash/ash_export.h"
#include "ash/public/interfaces/multi_user_window_manager.mojom.h"
#include "ash/session/session_observer.h"
#include "ash/wm/tablet_mode/tablet_mode_observer.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "components/account_id/account_id.h"
#include "services/ws/common/types.h"
#include "ui/aura/window_observer.h"
#include "ui/wm/core/transient_window_observer.h"
namespace ash {
class MultiUserWindowManagerDelegateClassic;
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.
//
// MultiUserWindowManager makes use of the following client/delegate interfaces
// mojom::MultiUserWindowManagerClient: used for windows created by the window
// service, as well as major state changes (such as animation changing).
// MultiUserWindowManagerDelegateClassic: used for all other windows. See
// MultiUserWindowManagerDelegateClassic for details on what this means.
//
// 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 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.
};
MultiUserWindowManager(
mojom::MultiUserWindowManagerClient* client,
MultiUserWindowManagerDelegateClassic* classic_delegate,
const AccountId& account_id);
~MultiUserWindowManager() override;
static MultiUserWindowManager* Get();
// Resets the client. This is called when running in mash. In single-process
// mash, the browser creates this class (with no client) and
// MultiUserWindowManagerBridge sets the client (as the client is provided
// over mojom). In multi-process mash, MultiUserWindowManagerBridge creates
// this and sets the client. This function is only necessary until
// multi-process mash is the default.
void SetClient(mojom::MultiUserWindowManagerClient* client);
// Associates a window with a particular account. This may result in hiding
// |window|. This should *not* be called more than once with a different
// account. If |show_for_current_user| is true, this sets the 'shown'
// account to the current account. If |window_id| is valid, changes to
// |window| are notified through MultiUserWindowManagerClient. If |window_id|
// is empty, MultiUserWindowManagerDelegateClassic is used.
void SetWindowOwner(aura::Window* window,
const AccountId& account_id,
bool show_for_current_user,
base::Optional<ws::Id> window_id = base::nullopt);
// Sets the 'shown' account for a window. See class description for details on
// what the 'shown' account is. This function may trigger changing the active
// user. When the window is minimized, the 'shown' account is reset to the
// 'owning' account.
void ShowWindowForUser(aura::Window* window, const AccountId& account_id);
// 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 MultiUserWindowManagerClientImplTest;
friend class UserSwitchAnimator;
class WindowEntry {
public:
WindowEntry(const AccountId& account_id, base::Optional<ws::Id> window_id);
~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; }
// True if this window was created by the window service.
bool from_window_service() const { return from_window_service_; }
// Unsets the |window_id|. This does not effect whether the window is
// from the window-service, only the stored id. Resetting the id happens
// when the client changes. This is necessary as the id is generally unique
// to a client.
void reset_window_id() { window_id_.reset(); }
const base::Optional<ws::Id> window_id() const { return window_id_; }
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;
// The id assigned to the window by the WindowService.
base::Optional<ws::Id> window_id_;
const bool from_window_service_;
DISALLOW_COPY_AND_ASSIGN(WindowEntry);
};
using TransientWindowToVisibility = base::flat_map<aura::Window*, bool>;
using WindowToEntryMap =
std::map<aura::Window*, std::unique_ptr<WindowEntry>>;
const AccountId& GetWindowOwner(aura::Window* window) const;
// Returns true if at least one window's 'owner' account differs from its
// 'shown' account. In other words, a window from one account is shown with
// windows from another account.
bool AreWindowsSharedAmongUsers() const;
// 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;
mojom::MultiUserWindowManagerClient* client_;
MultiUserWindowManagerDelegateClassic* classic_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_;
DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManager);
};
} // namespace ash
#endif // ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_H_