File: ink_drop_host.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (300 lines) | stat: -rw-r--r-- 11,582 bytes parent folder | download | duplicates (3)
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_VIEWS_ANIMATION_INK_DROP_HOST_H_
#define UI_VIEWS_ANIMATION_INK_DROP_HOST_H_

#include <memory>
#include <variant>

#include "base/memory/raw_ptr.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/color/color_id.h"
#include "ui/color/color_provider.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/animation/ink_drop_event_handler.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"

namespace ui {
class Layer;
class LocatedEvent;
}  // namespace ui

namespace views {

class InkDrop;
class InkDropHighlight;
class InkDropImpl;
class InkDropMask;
class InkDropRipple;
enum class InkDropState;

namespace test {
class InkDropHostTestApi;
}  // namespace test

// TODO(crbug.com/40613900): Rename this type and move this header. Also
// consider if InkDropHost should be what implements the InkDrop interface and
// have that be the public interface. The current division of labor is roughly
// as follows:
// * InkDropHost manages an InkDrop and is responsible for a lot of its
//   configuration and creating the parts of the InkDrop.
// * InkDrop manages the parts of the ink-drop effect once it's up and running.
// * InkDropRipple is a ripple effect that usually triggers as a result of
//   clicking or activating the button / similar which hosts this.
// * InkDropHighlight manages the hover/focus highlight layer.
// TODO(pbos): See if this can be the only externally visible surface for an
// ink-drop effect, and rename this InkDrop, or consolidate with InkDrop.
class VIEWS_EXPORT InkDropHost {
 public:
  // Used in SetMode() to specify whether the ink drop effect is enabled
  // or not for the view. In case of having an ink drop, it also specifies
  // whether the default event handler for the ink drop should be installed or
  // the subclass will handle ink drop events itself.
  enum class InkDropMode {
    OFF,
    ON,
    ON_NO_GESTURE_HANDLER,
    ON_NO_ANIMATE,
  };

  explicit InkDropHost(View* host);
  InkDropHost(const InkDropHost&) = delete;
  InkDropHost& operator=(const InkDropHost&) = delete;
  virtual ~InkDropHost();

  // Returns a configured InkDrop. To override default behavior call
  // SetCreateInkDropCallback().
  std::unique_ptr<InkDrop> CreateInkDrop();

  // Replace CreateInkDrop() behavior.
  void SetCreateInkDropCallback(
      base::RepeatingCallback<std::unique_ptr<InkDrop>()> callback);

  // Creates and returns the visual effect used for press. Used by InkDropImpl
  // instances.
  std::unique_ptr<InkDropRipple> CreateInkDropRipple() const;

  // Replaces CreateInkDropRipple() behavior.
  void SetCreateRippleCallback(
      base::RepeatingCallback<std::unique_ptr<InkDropRipple>()> callback);

  // Returns the point of the |last_ripple_triggering_event_| if it was a
  // LocatedEvent, otherwise the center point of the local bounds is returned.
  // This is nominally used by the InkDropRipple.
  gfx::Point GetInkDropCenterBasedOnLastEvent() const;

  // Creates and returns the visual effect used for hover and focus. Used by
  // InkDropImpl instances. To override behavior call
  // SetCreateHighlightCallback().
  std::unique_ptr<InkDropHighlight> CreateInkDropHighlight() const;

  // Replaces CreateInkDropHighlight() behavior.
  void SetCreateHighlightCallback(
      base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()> callback);

  // Callback replacement of CreateInkDropMask().
  // TODO(pbos): Investigate removing this. It currently is only used by
  // PieMenuView.
  void SetCreateMaskCallback(
      base::RepeatingCallback<std::unique_ptr<InkDropMask>()> callback);

  // Toggles ink drop attention state on/off. If set on, a pulsing highlight
  // is shown, prompting users to interact with `host_view_`.
  // Called by components that want to call into user's attention, e.g. IPH.
  void ToggleAttentionState(bool attention_on);

  // Returns the base color for the ink drop.
  SkColor GetBaseColor() const;

  // Sets the base color of the ink drop. If `SetBaseColor` is called, the
  // effect of previous calls to `SetBaseColorId` and `SetBaseColorCallback` is
  // overwritten and vice versa.
  // TODO(crbug.com/40230665): Replace SetBaseColor with SetBaseColorId.
  void SetBaseColor(SkColor color);
  void SetBaseColorId(ui::ColorId color_id);
  // Callback version of `GetBaseColor`. If possible, prefer using
  // `SetBaseColor` or `SetBaseColorId`.
  void SetBaseColorCallback(base::RepeatingCallback<SkColor()> callback);

  // Toggle to enable/disable an InkDrop on this View.  Descendants can override
  // CreateInkDropHighlight() and CreateInkDropRipple() to change the look/feel
  // of the InkDrop.
  //
  // TODO(bruthig): Add an easier mechanism than overriding functions to allow
  // subclasses/clients to specify the flavor of ink drop.
  void SetMode(InkDropMode ink_drop_mode);
  InkDropMode GetMode() const;

  // Set whether the ink drop layers should be placed into the region above or
  // below the view layer. The default is kBelow;
  void SetLayerRegion(LayerRegion region);
  LayerRegion GetLayerRegion() const;

  void SetVisibleOpacity(float visible_opacity);
  float GetVisibleOpacity() const;

  void SetHighlightOpacity(std::optional<float> opacity);

  void SetSmallCornerRadius(int small_radius);
  int GetSmallCornerRadius() const;

  void SetLargeCornerRadius(int large_radius);
  int GetLargeCornerRadius() const;

  // Animates |ink_drop_| to the desired |ink_drop_state|. Caches |event| as the
  // last_ripple_triggering_event().
  //
  // *** NOTE ***: |event| has been plumbed through on a best effort basis for
  // the purposes of centering ink drop ripples on located Events.  Thus nullptr
  // has been used by clients who do not have an Event instance available to
  // them.
  void AnimateToState(InkDropState state, const ui::LocatedEvent* event);

  // Returns true if an ink drop instance has been created.
  bool HasInkDrop() const;

  // Provides public access to |ink_drop_| so that factory methods can configure
  // the inkdrop. Implements lazy initialization of |ink_drop_| so as to avoid
  // virtual method calls during construction since subclasses should be able to
  // call SetMode() during construction.
  InkDrop* GetInkDrop();

  // Returns whether the ink drop should be considered "highlighted" (in or
  // animating into "highlight visible" steady state).
  bool GetHighlighted() const;

  base::CallbackListSubscription AddHighlightedChangedCallback(
      base::RepeatingClosure callback);

  // Should be called by InkDrop implementations when their highlight state
  // changes, to trigger the corresponding property change notification here.
  void OnInkDropHighlightedChanged();

  // Methods called by InkDrop for attaching its layer.
  // TODO(pbos): Investigate using direct calls on View::AddLayerToRegion.
  void AddInkDropLayer(ui::Layer* ink_drop_layer);
  void RemoveInkDropLayer(ui::Layer* ink_drop_layer);

  // Size used by default for the SquareInkDropRipple.
  static constexpr gfx::Size kDefaultSquareInkDropSize = gfx::Size(24, 24);

  // Returns a large scaled size used by SquareInkDropRipple and Highlight.
  static gfx::Size GetLargeSize(gfx::Size small_size);

  // Creates a SquareInkDropRipple centered on |center_point|.
  std::unique_ptr<InkDropRipple> CreateSquareRipple(
      const gfx::Point& center_point,
      const gfx::Size& size = kDefaultSquareInkDropSize) const;

  View* host_view() { return host_view_; }
  const View* host_view() const { return host_view_; }
  bool in_attention_state_for_testing() const { return in_attention_state_; }

 private:
  friend class test::InkDropHostTestApi;

  class ViewLayerTransformObserver : public ViewObserver {
   public:
    ViewLayerTransformObserver(InkDropHost* ink_drop_host, View* host);
    ~ViewLayerTransformObserver() override;

    void OnViewLayerTransformed(View* observed_view) override;

   private:
    base::ScopedObservation<View, ViewObserver> observation_{this};
    const raw_ptr<InkDropHost> ink_drop_host_;
  };

  class InkDropHostEventHandlerDelegate : public InkDropEventHandler::Delegate {
   public:
    explicit InkDropHostEventHandlerDelegate(InkDropHost* host);

    // InkDropEventHandler::Delegate:
    InkDrop* GetInkDrop() override;
    bool HasInkDrop() const override;

    bool SupportsGestureEvents() const override;

   private:
    // The host.
    const raw_ptr<InkDropHost> ink_drop_host_;
  };

  const InkDropEventHandler* GetEventHandler() const;
  InkDropEventHandler* GetEventHandler();

  // This generates a mask for the InkDrop.
  std::unique_ptr<views::InkDropMask> CreateInkDropMask() const;

  // Adds a clip rect on the root layer of the ink drop impl. This is a more
  // performant alternative to using circles or rectangle mask layers. Returns
  // true if a clip was added.
  bool AddInkDropClip(ui::Layer* ink_drop_layer);

  // Initializes and sets a mask on `ink_drop_layer`. This will not run if
  // AddInkDropClip() succeeds in the default implementation of
  // AddInkDropLayer().
  void InstallInkDropMask(ui::Layer* ink_drop_layer);

  const raw_ptr<View> host_view_;

  // Defines what type of |ink_drop_| to create.
  InkDropMode ink_drop_mode_ = views::InkDropHost::InkDropMode::OFF;

  // Into which region should the ink drop layers be placed.
  LayerRegion layer_region_ = LayerRegion::kBelow;

  // Used to observe View and inform the InkDrop of host-transform changes.
  ViewLayerTransformObserver host_view_transform_observer_;

  // Should not be accessed directly. Use GetInkDrop() instead.
  std::unique_ptr<InkDrop> ink_drop_;

  // Intentionally declared after |ink_drop_| so that it doesn't access a
  // destroyed |ink_drop_| during destruction.
  InkDropHostEventHandlerDelegate ink_drop_event_handler_delegate_;
  InkDropEventHandler ink_drop_event_handler_;

  float ink_drop_visible_opacity_ = 0.175f;

  // The color of the ripple and hover.
  std::variant<SkColor, ui::ColorId, base::RepeatingCallback<SkColor()>>
      ink_drop_base_color_ = gfx::kPlaceholderColor;

  // TODO(pbos): Audit call sites to make sure highlight opacity is either
  // always set or using the default value. Then make this a non-optional float.
  std::optional<float> ink_drop_highlight_opacity_;

  // Radii used for the SquareInkDropRipple.
  int ink_drop_small_corner_radius_ = 2;
  int ink_drop_large_corner_radius_ = 4;

  std::unique_ptr<views::InkDropMask> ink_drop_mask_;

  base::RepeatingCallback<std::unique_ptr<InkDrop>()> create_ink_drop_callback_;
  base::RepeatingCallback<std::unique_ptr<InkDropRipple>()>
      create_ink_drop_ripple_callback_;
  base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()>
      create_ink_drop_highlight_callback_;

  base::RepeatingCallback<std::unique_ptr<InkDropMask>()>
      create_ink_drop_mask_callback_;

  base::RepeatingClosureList highlighted_changed_callbacks_;

  // Attention is a state we apply on Buttons' ink drop when we want to draw
  // users' attention to this button and prompt users' interaction.
  // It consists of two visual effects: a default light blue color and a pulsing
  // effect. Current use case is IPH. Go to chrome://user-education-internals
  // and press e.g. IPH_TabSearch to see the effects.
  bool in_attention_state_ = false;
};

}  // namespace views

#endif  // UI_VIEWS_ANIMATION_INK_DROP_HOST_H_