File: multitask_menu_nudge_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 (173 lines) | stat: -rw-r--r-- 6,529 bytes parent folder | download | duplicates (6)
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
// Copyright 2022 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_UI_FRAME_MULTITASK_MENU_MULTITASK_MENU_NUDGE_CONTROLLER_H_
#define CHROMEOS_UI_FRAME_MULTITASK_MENU_MULTITASK_MENU_NUDGE_CONTROLLER_H_

#include <memory>

#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/clock.h"
#include "base/timer/timer.h"
#include "ui/aura/window_observer.h"
#include "ui/display/display_observer.h"
#include "ui/views/view.h"
#include "ui/views/widget/unique_widget_ptr.h"
#include "ui/views/widget/widget_observer.h"

class PrefRegistrySimple;

namespace ash {
class MultitaskMenuNudgeControllerTest;
class MultitaskMenuNudgeTest;
}

namespace ui {
class Layer;
}

namespace chromeos {

// Controller for showing the user education nudge for the multitask menu.
class COMPONENT_EXPORT(CHROMEOS_UI_FRAME) MultitaskMenuNudgeController
    : public aura::WindowObserver,
      public views::WidgetObserver,
      public display::DisplayObserver {
 public:
  // `tablet_mode` refers to the tablet state when the prefs are fetched. If
  // the state changes while fetching prefs, we do not show the nudge. The
  // callback may fail on lacros; in this case `values` will be null.
  // `shown_count` and `last_shown_time` are the values fetched from the pref
  // service regarding how many times the nudge has been shown, and when it was
  // last shown.
  struct PrefValues {
    int show_count;
    base::Time last_shown_time;
  };
  using GetPreferencesCallback =
      base::OnceCallback<void(bool tablet_mode,
                              std::optional<PrefValues> values)>;

  // A delegate to provide platform specific implementation (ash, lacros).
  class Delegate {
   public:
    virtual ~Delegate();

    virtual int GetTabletNudgeYOffset() const = 0;
    virtual void GetNudgePreferences(bool tablet_mode,
                                     GetPreferencesCallback callback) = 0;
    virtual void SetNudgePreferences(bool tablet_mode,
                                     int count,
                                     base::Time time) = 0;
    // Returns true if the user has logged in for the first time, or is a guest
    // user. We don't want to show the nudge in this case.
    virtual bool IsUserNewOrGuest() const;

   protected:
    Delegate();
  };

  MultitaskMenuNudgeController();
  MultitaskMenuNudgeController(const MultitaskMenuNudgeController&) = delete;
  MultitaskMenuNudgeController& operator=(const MultitaskMenuNudgeController&) =
      delete;
  ~MultitaskMenuNudgeController() override;

  static void RegisterProfilePrefs(PrefRegistrySimple* registry);

  // Attempts to show the nudge. Reads preferences and then calls
  // `OnGetPreferences()`.
  void MaybeShowNudge(aura::Window* window);
  void MaybeShowNudge(aura::Window* window, views::View* anchor_view);

  // Closes the widget and cleans up all pointers in this class.
  void DismissNudge();

  // Called when the menu is opened. Marks the pref as seen so it does not show
  // up again.
  void OnMenuOpened(bool tablet_mode);

  // aura::WindowObserver:
  void OnWindowParentChanged(aura::Window* window,
                             aura::Window* parent) override;
  void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
  void OnWindowTargetTransformChanging(
      aura::Window* window,
      const gfx::Transform& new_transform) override;
  void OnWindowStackingChanged(aura::Window* window) override;
  void OnWindowDestroying(aura::Window* window) override;

  // views::WidgetObserver:
  void OnWidgetBoundsChanged(views::Widget* widget,
                             const gfx::Rect& new_bounds) override;

  // display::DisplayObserver:
  void OnDisplayTabletStateChanged(display::TabletState state) override;

  static void SetSuppressNudgeForTesting(bool val);

 private:
  friend class ::ash::MultitaskMenuNudgeControllerTest;
  friend class ::ash::MultitaskMenuNudgeTest;

  // Used to control the clock in a test setting.
  static void SetOverrideClockForTesting(base::Clock* test_clock);

  // Callback function after fetching preferences. Shows the nudge if it can be
  // shown. The nudge can be shown if it hasn't been shown 3 times already, or
  // shown in the last 24 hours. `window` and `anchor_view` are the associated
  // window and the anchor for the nudge. `anchor_view` will be null in tablet
  // mode as the nudge shows in the top center of the window and is not anchored
  // to anything. `values` will return `std::nullopt` if fetching the pref
  // failed in lacros, it will return a value in ash.
  void OnGetPreferences(aura::Window* window,
                        views::View* anchor_view,
                        bool tablet_mode,
                        std::optional<PrefValues> values);

  // Runs when the nudge dismiss timer expires. Dismisses the nudge if it is
  // being shown.
  void OnDismissTimerEnded();

  // Dismisses the widget and pulse if `window_` is not visible, or if
  // `anchor_view_` is not drawn in clamshell mode. Otherwise updates the bounds
  // and reparents the two if necessary.
  void UpdateWidgetAndPulse();

  // The animation associated with `pulse_layer_`. Runs until `pulse_layer_` is
  // destroyed or `pulse_count` reaches 3.
  void PerformPulseAnimation(int pulse_count);

  // Dismisses the clamshell nudge at the end of the timer if it is still
  // visible. Tablet nudge is handled by the `TabletModeMultitaskCueController`
  // timer.
  base::OneShotTimer clamshell_nudge_dismiss_timer_;

  views::UniqueWidgetPtr nudge_widget_;
  std::unique_ptr<ui::Layer> pulse_layer_;

  // The time the nudge was shown. Null if it hasn't been shown this session.
  base::Time nudge_shown_time_;

  // The app window that the nudge is associated with.
  raw_ptr<aura::Window> window_ = nullptr;

  // The view that the nudge will be anchored to. It is the maximize or resize
  // button on `window_`'s frame. Null in tablet mode.
  raw_ptr<views::View> anchor_view_ = nullptr;

  base::ScopedObservation<aura::Window, aura::WindowObserver>
      window_observation_{this};
  base::ScopedObservation<views::Widget, views::WidgetObserver>
      widget_observation_{this};

  display::ScopedDisplayObserver display_observer_{this};

  base::WeakPtrFactory<MultitaskMenuNudgeController> weak_ptr_factory_{this};
};

}  // namespace chromeos

#endif  // CHROMEOS_UI_FRAME_MULTITASK_MENU_MULTITASK_MENU_NUDGE_CONTROLLER_H_