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
ash / wm / desks / templates / admin_template_launch_tracker.h [blame]
// Copyright 2023 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_DESKS_TEMPLATES_ADMIN_TEMPLATE_LAUNCH_TRACKER_H_
#define ASH_WM_DESKS_TEMPLATES_ADMIN_TEMPLATE_LAUNCH_TRACKER_H_
#include <memory>
#include <optional>
#include <vector>
#include "ash/ash_export.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list_types.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace ash {
class DeskTemplate;
class SavedDeskDelegate;
// Holds updates to apply to a window in an admin template.
struct AdminTemplateWindowUpdate {
// The restore window id (RWID) of the window that is being updated. This is
// the RWID as it appears in the originating template, not what the launched
// window has since the latter has been made unique for each launch.
int32_t template_rwid;
// Optional new bounds for the window.
std::optional<gfx::Rect> bounds;
// Optional new display ID for the window.
std::optional<int64_t> display_id;
// Optional new Z index for the window, relative to the other tracked
// windows.
std::optional<int32_t> activation_index;
};
// Apply changes in `update` to `admin_template`. If `update` has specified a
// window that doesn't exist in the template, false is returned and the template
// is left unchanged.
ASH_EXPORT bool MergeAdminTemplateWindowUpdate(
DeskTemplate& admin_template,
const AdminTemplateWindowUpdate& update);
// Figures out where to place an admin template window. The passed `bounds` is
// first adjusted to fit inside `work_area` (note that this may change the
// size). It is then placed, if possible, so that it does not overlap exactly
// with any of the bounds in `existing_bounds`.
ASH_EXPORT void AdjustAdminTemplateWindowBounds(
const gfx::Rect& work_area,
const std::vector<gfx::Rect>& existing_bounds,
gfx::Rect& bounds);
// Returns `window_count` bounds for windows automatically laid to fit
// `work_area_size`.
ASH_EXPORT std::vector<gfx::Rect> GetInitialWindowLayout(
const gfx::Size& work_area_size,
const int window_count);
// This class is used to launch an admin template and track the windows that
// have been launched from it.
class ASH_EXPORT AdminTemplateLaunchTracker {
public:
// Construct an admin template launch tracker. The passed `admin_template`
// (which must not be null) will be updated as the user interacts with
// launched windows. Updates to the template are sent to
// `template_update_cb`. Updates are held (and merged) for `update_delay` so
// that rapid window changes do not result in a deluge of callback calls.
AdminTemplateLaunchTracker(
std::unique_ptr<DeskTemplate> admin_template,
base::RepeatingCallback<void(const DeskTemplate&)> template_update_cb,
base::TimeDelta update_delay);
AdminTemplateLaunchTracker(const AdminTemplateLaunchTracker&) = delete;
AdminTemplateLaunchTracker& operator=(const AdminTemplateLaunchTracker&) =
delete;
// Destroys the launch tracker, as well as all internal window observers. The
// update callback will not be invoked after the tracker has been destroyed.
~AdminTemplateLaunchTracker();
// Sets up window observers for windows that are expected to be launched. It
// then launches the template using `delegate`.
void LaunchTemplate(SavedDeskDelegate* delegate, int64_t default_display_id);
// If there is an existing pending update to this template, it will be
// dispatched using the update callback. If there are no pending updates, then
// this is a no-op.
void FlushPendingUpdate();
// Returns true if there are launched windows from this tracker that are still
// open. When this returns false, there are no more windows that can generate
// updates. Note that there may still be a pending update, so
// `FlushPendingUpdate` should typically be called before the tracker is
// destroyed.
bool IsActive() const;
private:
// Called when an observer is created (either a desk or window observer).
void OnObserverCreated(std::unique_ptr<base::CheckedObserver> observer);
// Called when an observer is done (the observee has been destroyed).
void OnObserverDone(base::CheckedObserver* observer);
// Called when an observed window has changed.
void OnUpdate(const AdminTemplateWindowUpdate& update);
// Called when it's time to fire off a delayed callback.
void OnTimer();
// The template that will be updated based on received events. Changes are
// eventually saved to the storage model.
std::unique_ptr<DeskTemplate> admin_template_;
// Callback that will be invoked when the template has been updated.
base::RepeatingCallback<void(const DeskTemplate&)> template_update_cb_;
// Window observers launched by the tracker. They are tracked so that they can
// be destroyed, if the launchtracker itself is destroyed.
std::vector<std::unique_ptr<base::CheckedObserver>> window_observers_;
// Calls to the update callback are delayed by this much.
base::TimeDelta update_delay_;
// Timer used for callback delays.
base::OneShotTimer update_delay_timer_;
base::WeakPtrFactory<AdminTemplateLaunchTracker> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_WM_DESKS_TEMPLATES_ADMIN_TEMPLATE_LAUNCH_TRACKER_H_