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
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_ASH_COMPONENTS_GAME_MODE_GAME_MODE_CONTROLLER_H_
#define CHROMEOS_ASH_COMPONENTS_GAME_MODE_GAME_MODE_CONTROLLER_H_
#include "ash/wm/window_state.h"
#include "ash/wm/window_state_observer.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
#include "base/timer/elapsed_timer.h"
#include "base/timer/timer.h"
#include "chromeos/ash/components/dbus/resourced/resourced_client.h"
#include "ui/aura/client/focus_change_observer.h"
#include "ui/aura/client/focus_client.h"
namespace game_mode {
namespace {
using GameMode = ash::ResourcedClient::GameMode;
typedef base::RepeatingCallback<void(GameMode, ash::WindowState*)>
NotifySetGameModeCallback;
} // namespace
inline constexpr char kTimeInGameModeHistogramName[] =
"GameMode.TimeInGameMode.Borealis";
inline constexpr char kGameModeResultHistogramName[] =
"GameMode.Result.Borealis";
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class GameModeResult {
kAttempted = 0,
kFailed = 1,
kMaxValue = kFailed,
};
// When a Borealis game app game enters full screen, game mode is
// enabled. Game Mode is actually enabled as a result of multiple sets of
// criteria being fulfilled, each checked in sequence. The GameModeController
// additionally exposes an Observer interface which allows clients to subscribe
// to changes in the game mode state.
//
// When one criteria set is met, a new criteria object is constructed which
// is responsible for checking the next criteria, and is owned by the prior
// criteria object. An owner destroys its direct and indirect owned (subsequent)
// criteria objects as soon as itself becomes invalid.
//
// The criteria objects are constructed in this order:
//
// Criteria object Conditions checked Causes invalidation (x)
// -----------------------------------------------------------------------------
// GameModeController Window is focused
// WindowTracker * Window is fullscreen Window is destroyed
// GameModeEnabler ** None
//
// (x) Indicates the responsible criteria object makes itself inactive and
// discards its child criteria, if any.
// * WindowTracker is responsible for determining the type of window
// ** GameModeEnabler starts game mode on construction, and stops game mode on
// destruction.
//
// More concretely, this is the logical flow:
//
// +"GameMode off"+<---------------------------------------------+
// | ^ focus focus ^
// | | lost lost |
// V focused | Y |
// "Watch focus"------->"Watch state"--------->"Game window?"---->"GameMode on"
// ^ full | |
// | screen'd | N fullscreen |
// | V lost V
// "GameMode off"<------------------------------------+
//
class GameModeController : public aura::client::FocusChangeObserver {
public:
GameModeController();
GameModeController(const GameModeController&) = delete;
GameModeController& operator=(const GameModeController&) = delete;
~GameModeController() override;
// Overridden from FocusChangeObserver
void OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) override;
// Maintains GameMode in an ON state until destroyed.
class GameModeEnabler {
public:
// |window_state| indicates the window which currently meets the criteria to
// enable game mode.
GameModeEnabler(ash::WindowState* window_state,
NotifySetGameModeCallback notify_set_game_mode_callback);
~GameModeEnabler();
// Updates the window which is causing the game mode to be enabled, and
// notifies observers.
void SetWindowState(ash::WindowState* window_state);
private:
static void OnSetGameMode(std::optional<GameMode> refresh_of,
std::optional<GameMode> previous);
void RefreshGameMode();
// Used to determine if it's the first instance of game mode failing.
static bool should_record_failure;
base::RepeatingTimer timer_;
base::ElapsedTimer began_;
// Not owned. |window_state_| is observed by the WindowTracker which owns
// this GameModeEnabler, and this enabler will always be destroyed before
// the window is destroyed.
raw_ptr<ash::WindowState> window_state_;
const NotifySetGameModeCallback notify_set_game_mode_callback_;
};
class WindowTracker : public ash::WindowStateObserver,
public aura::WindowObserver {
public:
WindowTracker(ash::WindowState* window_state,
std::unique_ptr<WindowTracker> previous_focused,
NotifySetGameModeCallback notify_set_game_mode_callback);
~WindowTracker() override;
// Overridden from WindowObserver
void OnWindowDestroying(aura::Window* window) override;
// Overridden from WindowStateObserver
void OnPostWindowStateTypeChange(
ash::WindowState* window_state,
chromeos::WindowStateType old_type) override;
void UpdateGameModeStatus(ash::WindowState* window_state);
private:
base::ScopedObservation<ash::WindowState, ash::WindowStateObserver>
window_state_observer_{this};
base::ScopedObservation<aura::Window, aura::WindowObserver>
window_observer_{this};
std::unique_ptr<GameModeEnabler> game_mode_enabler_;
const NotifySetGameModeCallback notify_set_game_mode_callback_;
};
using GameModeChangedCallback =
base::RepeatingCallback<void(aura::Window*, GameMode)>;
void set_game_mode_changed_callback(GameModeChangedCallback callback) {
callback_ = callback;
}
void NotifySetGameMode(GameMode game_mode, ash::WindowState* window_state);
private:
std::unique_ptr<WindowTracker> focused_;
GameModeChangedCallback callback_;
};
} // namespace game_mode
#endif // CHROMEOS_ASH_COMPONENTS_GAME_MODE_GAME_MODE_CONTROLLER_H_
|