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
cc / input / browser_controls_offset_manager.h [blame]
// 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 CC_INPUT_BROWSER_CONTROLS_OFFSET_MANAGER_H_
#define CC_INPUT_BROWSER_CONTROLS_OFFSET_MANAGER_H_
#include <memory>
#include <optional>
#include <utility>
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/types/optional_ref.h"
#include "cc/input/browser_controls_offset_tags_info.h"
#include "cc/input/browser_controls_state.h"
#include "cc/layers/layer_impl.h"
#include "cc/trees/browser_controls_params.h"
#include "components/viz/common/quads/offset_tag.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/vector2d_f.h"
namespace cc {
class BrowserControlsOffsetManagerClient;
// Manages the position of the browser controls.
class CC_EXPORT BrowserControlsOffsetManager {
public:
enum class AnimationDirection {
kNoAnimation,
kShowingControls,
kHidingControls
};
static std::unique_ptr<BrowserControlsOffsetManager> Create(
BrowserControlsOffsetManagerClient* client,
float controls_show_threshold,
float controls_hide_threshold);
BrowserControlsOffsetManager(const BrowserControlsOffsetManager&) = delete;
virtual ~BrowserControlsOffsetManager();
BrowserControlsOffsetManager& operator=(const BrowserControlsOffsetManager&) =
delete;
// The offset from the window top to the top edge of the controls. Runs from 0
// (controls fully shown) to negative values (down is positive).
float ControlsTopOffset() const;
// The amount of offset of the web content area. Same as the current shown
// height of the browser controls.
float ContentTopOffset() const;
float TopControlsShownRatio() const;
float TopControlsHeight() const;
float TopControlsMinHeight() const;
int TopControlsHairlineHeight() const;
// The minimum shown ratio top controls can have.
float TopControlsMinShownRatio() const;
// The current top controls min-height. If the min-height is changing with an
// animation, this will return a value between the old min-height and the new
// min-height, which is equal to the current visible min-height. Otherwise,
// this will return the same value as |TopControlsMinHeight()|.
float TopControlsMinHeightOffset() const;
viz::OffsetTag ContentOffsetTag() const;
viz::OffsetTag TopControlsOffsetTag() const;
// The amount of offset of the web content area, calculating from the bottom.
// Same as the current shown height of the bottom controls.
float ContentBottomOffset() const;
// Similar to TopControlsHeight(), this method should return a static value.
// The current animated height should be acquired from ContentBottomOffset().
float BottomControlsHeight() const;
float BottomControlsMinHeight() const;
float BottomControlsShownRatio() const;
int BottomControlsAdditionalHeight() const;
// The minimum shown ratio bottom controls can have.
float BottomControlsMinShownRatio() const;
// The current bottom controls min-height. If the min-height is changing with
// an animation, this will return a value between the old min-height and the
// new min-height, which is equal to the current visible min-height.
// Otherwise, this will return the same value as |BottomControlsMinHeight()|.
float BottomControlsMinHeightOffset() const;
viz::OffsetTag BottomControlsOffsetTag() const;
// Valid shown ratio range for the top controls. The values will be (0, 1) if
// there is no animation running.
std::pair<float, float> TopControlsShownRatioRange();
// Valid shown ratio range for the bottom controls. The values will be (0, 1)
// if there is no animation running.
std::pair<float, float> BottomControlsShownRatioRange();
bool HasAnimation();
bool IsAnimatingToShowControls() const {
return top_controls_animation_.IsInitialized() &&
top_controls_animation_.Direction() ==
AnimationDirection::kShowingControls;
}
// See UpdateBrowserControlsState in
// third_party/blink/public/mojom/frame/frame.mojom
void UpdateBrowserControlsState(
BrowserControlsState constraints,
BrowserControlsState current,
bool animate,
base::optional_ref<const BrowserControlsOffsetTagsInfo> offset_tags_info);
// Return the browser control constraint that must be synced to the
// main renderer thread (to trigger viewport and related changes).
BrowserControlsState PullConstraintForMainThread(
bool* out_changed_since_commit);
// Called to notify this object that the control constraint has
// been pushed to the main thread. When a compositor commit does not
// happen the value pulled by the method above may not be synced;
// a call to this method notifies us that it has.
void NotifyConstraintSyncedToMainThread();
void OnBrowserControlsParamsChanged(bool animate_changes);
void ScrollBegin();
gfx::Vector2dF ScrollBy(const gfx::Vector2dF& pending_delta);
void ScrollEnd();
// The caller should ensure that |Pinch{Begin,End}| are called within
// the scope of |Scroll{Begin,End}|.
void PinchBegin();
void PinchEnd();
gfx::Vector2dF Animate(base::TimeTicks monotonic_time);
// Predict what the outer viewport container bounds delta will be as browser
// controls are shown or hidden during a scroll gesture before the Blink
// WebView is resized to reflect the new state.
double PredictViewportBoundsDelta(double current_bounds_delta,
gfx::Vector2dF scroll_distance);
void ResetAnimations();
protected:
BrowserControlsOffsetManager(BrowserControlsOffsetManagerClient* client,
float controls_show_threshold,
float controls_hide_threshold);
private:
class Animation;
void SetupAnimation(AnimationDirection direction);
void StartAnimationIfNecessary();
void ResetBaseline();
float OldTopControlsMinShownRatio();
float OldBottomControlsMinShownRatio();
void UpdateOldBrowserControlsParams();
void InitAnimationForHeightChange(Animation* animation,
float start_ratio,
float stop_ratio);
void SetTopMinHeightOffsetAnimationRange(float from, float to);
void SetBottomMinHeightOffsetAnimationRange(float from, float to);
// The client manages the lifecycle of this.
raw_ptr<BrowserControlsOffsetManagerClient> client_;
BrowserControlsState permitted_state_;
// Accumulated scroll delta since last baseline reset
float accumulated_scroll_delta_;
// Content offset when last baseline reset occurred.
float baseline_top_content_offset_;
float baseline_bottom_content_offset_;
// The percent height of the visible control such that it must be shown
// when the user stops the scroll.
float controls_show_threshold_;
// The percent height of the visible control such that it must be hidden
// when the user stops the scroll.
float controls_hide_threshold_;
bool pinch_gesture_active_;
// Used to track whether the constraint has changed and we need up reflect
// the changes to Blink.
bool constraint_changed_since_commit_;
// The old browser controls params that are used to figure out how to animate
// the height and min-height changes.
BrowserControlsParams old_browser_controls_params_;
// Whether a min-height change animation is in progress.
bool top_min_height_change_in_progress_;
bool bottom_min_height_change_in_progress_;
// Current top/bottom controls min-height.
float top_controls_min_height_offset_;
float bottom_controls_min_height_offset_;
// Top/bottom controls shadow height.
int top_controls_hairline_height_ = 0;
int bottom_controls_additional_height_ = 0;
// Minimum and maximum values |top_controls_min_height_offset_| can take
// during the current min-height change animation.
std::optional<std::pair<float, float>> top_min_height_offset_animation_range_;
// Minimum and maximum values |bottom_controls_min_height_offset_| can take
// during the current min-height change animation.
std::optional<std::pair<float, float>>
bottom_min_height_offset_animation_range_;
// Should ScrollEnd() animate the controls into view? This is used if there's
// a race between chrome starting an animation to show the controls while the
// user is doing a scroll gesture, which would cancel animations. We want to
// err on the side of showing the controls, so that the user realizes that
// they're an option. If we have started, but not yet completed an animation
// to show the controls when the scroll starts, or if one starts during the
// gesture, then we reorder the animation until after the scroll.
bool show_controls_when_scroll_completes_ = false;
// The tags used to accompany scroll offsets in the render frame's metadata.
// During surface aggregation, the layers with the same token will have the
// corresponding offsets applied.
viz::OffsetTag bottom_controls_offset_tag_;
viz::OffsetTag content_offset_tag_;
viz::OffsetTag top_controls_offset_tag_;
// Class that holds and manages the state of the controls animations.
class Animation {
public:
Animation();
// Whether the animation is initialized with a direction and start and stop
// values.
bool IsInitialized() const { return initialized_; }
AnimationDirection Direction() const { return direction_; }
void Initialize(AnimationDirection direction,
float start_value,
float stop_value,
int64_t duration,
bool jump_to_end_on_reset);
// Returns the animated value for the given monotonic time tick if the
// animation is initialized. Otherwise, returns |std::nullopt|.
std::optional<float> Tick(base::TimeTicks monotonic_time);
// Set the minimum and maximum values the animation can have.
void SetBounds(float min, float max);
// Reset the properties. If |skip_to_end_on_reset_| is false, this function
// will return |std::nullopt|. Otherwise, it will return the end value
// (clamped to min-max).
std::optional<float> Reset();
// Returns the value the animation will end on. This will be the stop_value
// passed to the constructor clamped by the currently configured bounds.
float FinalValue();
// Return the bounds.
float min_value() { return min_value_; }
float max_value() { return max_value_; }
private:
bool IsComplete(float value);
// Whether the animation is running.
bool started_ = false;
// Whether the animation is initialized by setting start and stop time and
// values.
bool initialized_ = false;
AnimationDirection direction_ = AnimationDirection::kNoAnimation;
// Monotonic start and stop times.
base::TimeTicks start_time_;
base::TimeTicks stop_time_;
// Animation duration.
base::TimeDelta duration_;
// Start and stop values.
float start_value_ = 0.f;
float stop_value_ = 0.f;
// Minimum and maximum values the animation can have, used to decide if the
// animation is complete.
float min_value_ = 0.f;
float max_value_ = 1.f;
// Whether to fast-forward to end when reset. It is still BCOM's
// responsibility to actually set the shown ratios using the value returned
// by ::Reset().
bool jump_to_end_on_reset_ = false;
};
Animation top_controls_animation_;
Animation bottom_controls_animation_;
};
} // namespace cc
#endif // CC_INPUT_BROWSER_CONTROLS_OFFSET_MANAGER_H_