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
ash / wm / overview / overview_controller.h [blame]
// Copyright 2013 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_WM_OVERVIEW_OVERVIEW_CONTROLLER_H_
#define ASH_WM_OVERVIEW_OVERVIEW_CONTROLLER_H_
#include <memory>
#include <vector>
#include "ash/ash_export.h"
#include "ash/wm/overview/delayed_animation_observer.h"
#include "ash/wm/overview/overview_delegate.h"
#include "ash/wm/overview/overview_metrics.h"
#include "ash/wm/overview/overview_observer.h"
#include "ash/wm/overview/overview_session_metrics_recorder.h"
#include "ash/wm/overview/overview_types.h"
#include "ash/wm/overview/overview_window_occlusion_calculator.h"
#include "ash/wm/raster_scale/raster_scale_controller.h"
#include "base/cancelable_callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "ui/aura/window_occlusion_tracker.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/public/activation_change_observer.h"
namespace ash {
class OverviewSession;
// Manages a overview session which displays an overview of all windows and
// allows selecting a window to activate it.
class ASH_EXPORT OverviewController : public OverviewDelegate,
public wm::ActivationChangeObserver {
public:
// `ScopedOcclusionPauser` pauses occlusion tracking for overview mode
// purposes until it is destroyed. When it is destroyed, occlusion tracking
// will be unpaused after the given unpause delay. If a
// `ScopedOcclusionPauser`s is destroyed while an unpause delay is in
// progress, that delay will be cancelled and the new delay will be used. This
// means that if two `ScopedOcclusionPauser`s are destroyed, the delay for the
// second `ScopedOcclusionPauser` to be destroyed will be used, even if the
// first delay is much longer.
class ScopedOcclusionPauser {
public:
ScopedOcclusionPauser(ScopedOcclusionPauser&&);
ScopedOcclusionPauser& operator=(ScopedOcclusionPauser&&);
ScopedOcclusionPauser(const ScopedOcclusionPauser&) = delete;
ScopedOcclusionPauser& operator=(const ScopedOcclusionPauser&) = delete;
~ScopedOcclusionPauser();
private:
friend class OverviewController;
ScopedOcclusionPauser(base::WeakPtr<OverviewController> controller,
base::TimeDelta unpause_delay);
base::WeakPtr<OverviewController> controller_;
base::TimeDelta unpause_delay_;
};
OverviewController();
OverviewController(const OverviewController&) = delete;
OverviewController& operator=(const OverviewController&) = delete;
~OverviewController() override;
[[nodiscard]] ScopedOcclusionPauser PauseOcclusionTracker(
base::TimeDelta unpause_delay);
// Convenience function to get the overview controller instance, which is
// created and owned by Shell.
static OverviewController* Get();
OverviewSession* overview_session() { return overview_session_.get(); }
bool disable_app_id_check_for_saved_desks() const {
return disable_app_id_check_for_saved_desks_;
}
bool is_continuous_scroll_in_progress() const {
return is_continuous_scroll_in_progress_;
}
bool windows_have_snapshot() const { return windows_have_snapshot_; }
// Starts/Ends overview with `type`. Returns true if enter or exit overview
// successful. Depending on `type` the enter/exit animation will look
// different. `start_action`/`end_action` is used by UMA to record the reasons
// that trigger overview starts or ends. E.g, pressing the overview button.
bool StartOverview(
OverviewStartAction start_action,
OverviewEnterExitType type = OverviewEnterExitType::kNormal);
bool EndOverview(OverviewEndAction end_action,
OverviewEnterExitType type = OverviewEnterExitType::kNormal);
// Returns true if it's possible to enter overview mode in the current
// configuration. This can be false at certain times, such as when the lock
// screen is visible we can't enter overview mode.
bool CanEnterOverview() const;
// Returns true if overview mode is active.
bool InOverviewSession() const;
// Receives a continuous scroll event from the gesture handler and either
// initializes overview mode in preparation for future continuous scrolls, or
// immediately calls `OverviewGrid::PositionWindowsForContinuousScrolls()` if
// overview mode has already been initialized.
bool HandleContinuousScroll(float y_offset, OverviewEnterExitType type);
// Moves the current selection forward or backward.
void IncrementSelection(bool forward);
// Accepts current selection if any. Returns true if a selection was made,
// false otherwise.
bool AcceptSelection();
// Returns true if we're in start-overview animation.
bool IsInStartAnimation();
// Returns true if overview has been shutdown, but is still animating to the
// end state ui.
bool IsCompletingShutdownAnimations() const;
void AddObserver(OverviewObserver* observer);
void RemoveObserver(OverviewObserver* observer);
// Post a task to update the shadow and rounded corners of overview windows.
void DelayedUpdateRoundedCornersAndShadow();
// OverviewDelegate:
void AddExitAnimationObserver(
std::unique_ptr<DelayedAnimationObserver> animation) override;
void RemoveAndDestroyExitAnimationObserver(
DelayedAnimationObserver* animation) override;
void AddEnterAnimationObserver(
std::unique_ptr<DelayedAnimationObserver> animation_observer) override;
void RemoveAndDestroyEnterAnimationObserver(
DelayedAnimationObserver* animation_observer) override;
// ::wm::ActivationChangeObserver:
void OnWindowActivating(ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) override;
void OnWindowActivated(ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) override {}
base::AutoReset<bool> SetDisableAppIdCheckForTests();
void set_occlusion_pause_duration_for_start_for_test(
base::TimeDelta duration) {
occlusion_pause_duration_for_start_ = duration;
}
void set_occlusion_pause_duration_for_end_for_test(base::TimeDelta duration) {
occlusion_pause_duration_for_end_ = duration;
}
void set_delayed_animation_task_delay_for_test(base::TimeDelta delta) {
delayed_animation_task_delay_ = delta;
}
void set_windows_have_snapshot_for_test(bool windows_have_snapshot) {
windows_have_snapshot_ = windows_have_snapshot;
}
private:
// Toggle overview mode. Depending on |type| the enter/exit animation will
// look different.
void ToggleOverview(
OverviewEnterExitType type = OverviewEnterExitType::kNormal);
// Returns true if it's possible to exit overview mode in the current
// configuration. This can be false at certain times, such as when the divider
// or desks are animating.
bool CanEndOverview(OverviewEnterExitType type) const;
void OnStartingAnimationComplete(bool canceled);
void OnEndingAnimationComplete(bool canceled);
void UpdateRoundedCornersAndShadow();
// Pause or unpause the occlusion tracker. Resets the unpause delay if we were
// already in the process of unpausing.
void MaybePauseOcclusionTracker();
void MaybeUnpauseOcclusionTracker(base::TimeDelta delay);
void ResetPauser();
// Collection of DelayedAnimationObserver objects that own widgets that may be
// still animating after overview mode ends. If shell needs to shut down while
// those animations are in progress, the animations are shut down and the
// widgets destroyed.
std::vector<std::unique_ptr<DelayedAnimationObserver>> delayed_animations_;
// Collection of DelayedAnimationObserver objects. When this becomes empty,
// notify shell that the starting animations have been completed.
std::vector<std::unique_ptr<DelayedAnimationObserver>> start_animations_;
// Indicates that overview shall gain focus when the starting animations have
// completed.
bool should_focus_overview_ = false;
// Used when feature ContinuousOverviewScrollAnimation is enabled to
// determine the start/end positions of overview items as well as their shadow
// bounds and corner radii during a continuous scroll. It's true only if the
// last scroll event was the start of a continuous scroll or a continuous
// scroll update that is within the threshold.
bool is_continuous_scroll_in_progress_ = false;
// We may pause occlusion tracking on enter and exit overview mode.
std::optional<ScopedOcclusionPauser> enter_pauser_;
std::optional<ScopedOcclusionPauser> exit_pauser_;
// The following state tracks occlusion pausing and its delayed unpausing for
// overview mode.
int pause_count_ = 0;
std::unique_ptr<aura::WindowOcclusionTracker::ScopedPause>
occlusion_tracker_pauser_;
base::CancelableOnceClosure reset_pauser_task_;
// In order to guarantee relative ordering between occlusion updates and
// raster scale updates, we need to pause raster scale updates sometimes.
std::optional<ScopedPauseRasterScaleUpdates> raster_scale_pauser_;
std::unique_ptr<OverviewSession> overview_session_;
base::Time last_overview_session_time_;
base::TimeDelta occlusion_pause_duration_for_start_;
base::TimeDelta occlusion_pause_duration_for_end_;
// App dragging enters overview right away. This task is used to delay the
// |OnStartingAnimationComplete| call so that some animations do not make the
// initial setup less performant.
base::TimeDelta delayed_animation_task_delay_;
base::ObserverList<OverviewObserver> observers_;
std::unique_ptr<views::Widget::PaintAsActiveLock> paint_as_active_lock_;
// In ash unittests, the `FullRestoreSaveHandler` isn't hooked up so
// initialized windows lack an app id. If a window doesn't have a valid app
// id, then it won't be tracked by `OverviewGrid` as a supported window and
// those windows will be deemed unsupported for Saved Desks. If
// `disable_app_id_check_for_saved_desks_` is true, then this check is
// omitted so we can test Saved Desks.
bool disable_app_id_check_for_saved_desks_ = false;
// True if windows shown in overview mode will have a snapshot available.
// If a snapshot is available then we can pause occlusion tracking until
// overview mode as finished its enter animation. Otherwise, we must mark
// all windows as visible immediately.
bool windows_have_snapshot_ = false;
std::optional<OverviewSessionMetricsRecorder> session_metrics_recorder_;
OverviewWindowOcclusionCalculator overview_window_occlusion_calculator_;
base::WeakPtrFactory<OverviewController> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_WM_OVERVIEW_OVERVIEW_CONTROLLER_H_