File: game_mode_controller.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (165 lines) | stat: -rw-r--r-- 6,403 bytes parent folder | download | duplicates (7)
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_