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
ash / game_dashboard / game_dashboard_controller.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_GAME_DASHBOARD_GAME_DASHBOARD_CONTROLLER_H_
#define ASH_GAME_DASHBOARD_GAME_DASHBOARD_CONTROLLER_H_
#include <map>
#include <memory>
#include "ash/ash_export.h"
#include "ash/capture_mode/capture_mode_observer.h"
#include "ash/game_dashboard/game_dashboard_context.h"
#include "ash/game_dashboard/game_dashboard_delegate.h"
#include "ash/game_dashboard/game_dashboard_metrics.h"
#include "ash/wm/overview/overview_observer.h"
#include "base/scoped_multi_source_observation.h"
#include "base/scoped_observation.h"
#include "ui/aura/env.h"
#include "ui/aura/env_observer.h"
#include "ui/aura/window_observer.h"
#include "ui/display/display_observer.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/wm/public/activation_change_observer.h"
class PrefRegistrySimple;
namespace aura {
class Window;
class WindowTracker;
} // namespace aura
namespace display {
enum class TabletState;
} // namespace display
namespace ash {
// Controls the Game Dashboard behavior on supported windows.
class ASH_EXPORT GameDashboardController : public aura::EnvObserver,
public aura::WindowObserver,
public CaptureModeObserver,
public display::DisplayObserver,
public OverviewObserver,
public wm::ActivationChangeObserver {
public:
explicit GameDashboardController(
std::unique_ptr<GameDashboardDelegate> delegate);
GameDashboardController(const GameDashboardController&) = delete;
GameDashboardController& operator=(const GameDashboardController&) = delete;
~GameDashboardController() override;
// Returns the singleton instance owned by `Shell`.
static GameDashboardController* Get();
// Checks whether the `window` is a game.
static bool IsGameWindow(aura::Window* window);
// Checks whether the `window` can respond to accelerator commands.
static bool ReadyForAccelerator(aura::Window* window);
// Registers preferences used by this class in the provided `registry`.
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
// Gets the app name by `app_id`.
std::string GetArcAppName(const std::string& app_id) const;
GameDashboardContext* active_recording_context() {
return active_recording_context_;
}
// Returns a pointer to the `GameDashboardContext` if the given `window` is a
// game window, otherwise nullptr.
GameDashboardContext* GetGameDashboardContext(aura::Window* window) const;
// Stacks all of the `window`'s Game Dashboard widgets on top of `widget`.
void MaybeStackAboveWidget(aura::Window* window, views::Widget* widget);
// Represents the start of the `context`'s game window capture session.
// Sets `context` as the `active_recording_context_`, and requests
// `CaptureModeController` to start a capture session for the `context`'s game
// window. The session ends when `OnRecordingEnded` or
// `OnRecordingStartAborted` is called.
void StartCaptureSession(GameDashboardContext* context);
// Shows the compat mode resize toggle menu for the given `window`.
void ShowResizeToggleMenu(aura::Window* window);
// Gets the UKM source id by `app_id`.
ukm::SourceId GetUkmSourceId(const std::string& app_id) const;
// aura::EnvObserver:
void OnWindowInitialized(aura::Window* new_window) override;
// aura::WindowObserver:
void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) override;
void OnWindowParentChanged(aura::Window* window,
aura::Window* parent) override;
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) override;
void OnWindowDestroying(aura::Window* window) override;
void OnWindowTransformed(aura::Window* window,
ui::PropertyChangeReason reason) override;
// CaptureModeObserver:
void OnRecordingStarted(aura::Window* current_root) override;
void OnRecordingEnded() override;
void OnVideoFileFinalized(bool user_deleted_video_file,
const gfx::ImageSkia& thumbnail) override;
void OnRecordedWindowChangingRoot(aura::Window* new_root) override;
void OnRecordingStartAborted() override;
// display::DisplayObserver:
void OnDisplayTabletStateChanged(display::TabletState state) override;
// OverviewObserver:
void OnOverviewModeWillStart() override;
void OnOverviewModeEnded() override;
// wm::ActivationChangeObserver:
void OnWindowActivated(wm::ActivationChangeObserver::ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) override;
private:
friend class GameDashboardControllerTest;
friend class GameDashboardTestBase;
enum class WindowGameState { kGame, kNotGame, kNotYetKnown };
using GetWindowStateCallback = base::OnceCallback<void(WindowGameState)>;
// Creates a `GameDashboardContext` for the given `window` and
// adds it to `game_window_contexts_`, if `GameDashboardContext` doesn't
// exist, the given window is a game, the `window` is parented, and the
// `window` has a valid `WindowState`. Otherwise, no object is created.
void MaybeCreateGameDashboardContext(aura::Window* window);
// Checks whether the given window is a game, and then calls
// `RefreshWindowTracking`. If there's not enough information, it passes
// `kNotYetKnown`, otherwise `kGame` or `kNotGame`, as the `game_state`.
void GetWindowGameState(aura::Window* window);
// Callback when `GetWindowGameState` calls `GameDashboardDelegate` to
// retrieve the app category for the given window in `window_tracker`.
// This function calls `RefreshWindowTracking`, as long as the window has not
// been destroyed.
void OnArcWindowIsGame(std::unique_ptr<aura::WindowTracker> window_tracker,
bool is_game);
// Updates the window observation, dependent on `game_state`.
void RefreshWindowTracking(aura::Window* window, WindowGameState game_state);
// Updates the Game Dashboard button state and toolbar for a game window.
void RefreshForGameControlsFlags(aura::Window* window);
// Enables or disables feature entry partially depending on `enable`. In
// addition, it needs to check
// `game_dashboard_utils::ShouldEnableFeatures()`. It may close main menu
// by `main_menu_toggle_method` when disabling the features.
void MaybeEnableFeatures(
bool enable,
GameDashboardMainMenuToggleMethod main_menu_toggle_method);
std::map<aura::Window*, std::unique_ptr<GameDashboardContext>>
game_window_contexts_;
// The delegate responsible for communicating with between Ash and the Game
// Dashboard service in the browser.
std::unique_ptr<GameDashboardDelegate> delegate_;
base::ScopedObservation<aura::Env, aura::EnvObserver> env_observation_{this};
base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver>
window_observations_{this};
display::ScopedDisplayObserver display_observer_{this};
// Represents the active `GameDashboardContext`. If
// `active_recording_context_` is non-null, then `CaptureModeController` is
// recording the game window, or has been requested to record it. Resets
// when the recording session ends or aborted.
// Owned by `game_window_contexts_`.
raw_ptr<GameDashboardContext, DanglingUntriaged> active_recording_context_ =
nullptr;
base::WeakPtrFactory<GameDashboardController> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_GAME_DASHBOARD_GAME_DASHBOARD_CONTROLLER_H_