#include "cc/input/browser_controls_offset_manager.h"
#include <stdint.h>
#include <algorithm>
#include <utility>
#if BUILDFLAG(IS_ARKWEB_EXT)
#include "arkweb/ohos_nweb_ex/build/features/features.h"
#endif
#include "base/check_op.h"
#include "base/memory/ptr_util.h"
#include "base/types/optional_ref.h"
#include "cc/input/browser_controls_offset_manager_client.h"
#include "cc/input/browser_controls_offset_tag_modifications.h"
#include "cc/input/browser_controls_state.h"
#include "cc/trees/layer_tree_impl.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/quads/offset_tag.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/geometry/vector2d_f.h"
#if BUILDFLAG(ARKWEB_EXT_TOPCONTROLS)
#include "arkweb/chromium_ext/content/public/common/content_switches_ext.h"
#include "base/command_line.h"
#endif
namespace cc {
namespace {
const int64_t kShowHideMaxDurationMs = 200;
const int64_t kHeightChangeDurationMs = 200;
}
std::unique_ptr<BrowserControlsOffsetManager>
BrowserControlsOffsetManager::Create(BrowserControlsOffsetManagerClient* client,
float controls_show_threshold,
float controls_hide_threshold) {
return base::WrapUnique(new BrowserControlsOffsetManager(
client, controls_show_threshold, controls_hide_threshold));
}
BrowserControlsOffsetManager::BrowserControlsOffsetManager(
BrowserControlsOffsetManagerClient* client,
float controls_show_threshold,
float controls_hide_threshold)
: client_(client),
permitted_state_(BrowserControlsState::kBoth),
accumulated_scroll_delta_(0.f),
baseline_top_content_offset_(0.f),
baseline_bottom_content_offset_(0.f),
controls_show_threshold_(controls_hide_threshold),
controls_hide_threshold_(controls_show_threshold),
pinch_gesture_active_(false),
constraint_changed_since_commit_(false),
top_min_height_change_in_progress_(false),
bottom_min_height_change_in_progress_(false),
top_controls_min_height_offset_(0.f),
bottom_controls_min_height_offset_(0.f) {
CHECK(client_);
UpdateOldBrowserControlsParams();
}
BrowserControlsOffsetManager::~BrowserControlsOffsetManager() = default;
float BrowserControlsOffsetManager::ControlsTopOffset() const {
return ContentTopOffset() - TopControlsHeight();
}
float BrowserControlsOffsetManager::ContentTopOffset() const {
return TopControlsHeight() > 0
? TopControlsShownRatio() * TopControlsHeight() : 0.0f;
}
float BrowserControlsOffsetManager::TopControlsShownRatio() const {
return client_->CurrentTopControlsShownRatio();
}
float BrowserControlsOffsetManager::TopControlsHeight() const {
return client_->TopControlsHeight();
}
float BrowserControlsOffsetManager::TopControlsMinHeight() const {
return client_->TopControlsMinHeight();
}
int BrowserControlsOffsetManager::TopControlsAdditionalHeight() const {
return offset_tag_modifications_.top_controls_additional_height;
}
int BrowserControlsOffsetManager::BottomControlsAdditionalHeight() const {
return offset_tag_modifications_.bottom_controls_additional_height;
}
viz::OffsetTag BrowserControlsOffsetManager::BottomControlsOffsetTag() const {
return offset_tag_modifications_.tags.bottom_controls_offset_tag;
}
viz::OffsetTag BrowserControlsOffsetManager::ContentOffsetTag() const {
return offset_tag_modifications_.tags.content_offset_tag;
}
viz::OffsetTag BrowserControlsOffsetManager::TopControlsOffsetTag() const {
return offset_tag_modifications_.tags.top_controls_offset_tag;
}
float BrowserControlsOffsetManager::TopControlsMinShownRatio() const {
return TopControlsHeight() ? TopControlsMinHeight() / TopControlsHeight()
: 0.f;
}
float BrowserControlsOffsetManager::BottomControlsHeight() const {
return client_->BottomControlsHeight();
}
float BrowserControlsOffsetManager::BottomControlsMinHeight() const {
return client_->BottomControlsMinHeight();
}
float BrowserControlsOffsetManager::BottomControlsMinShownRatio() const {
return BottomControlsHeight()
? BottomControlsMinHeight() / BottomControlsHeight()
: 0.f;
}
float BrowserControlsOffsetManager::ContentBottomOffset() const {
return BottomControlsHeight() > 0
? BottomControlsShownRatio() * BottomControlsHeight() : 0.0f;
}
float BrowserControlsOffsetManager::BottomControlsShownRatio() const {
return client_->CurrentBottomControlsShownRatio();
}
float BrowserControlsOffsetManager::TopControlsMinHeightOffset() const {
return top_controls_min_height_offset_;
}
float BrowserControlsOffsetManager::BottomControlsMinHeightOffset() const {
return bottom_controls_min_height_offset_;
}
bool BrowserControlsOffsetManager::HasOffsetTag() const {
return BottomControlsOffsetTag() || ContentOffsetTag() ||
TopControlsOffsetTag();
}
std::pair<float, float>
BrowserControlsOffsetManager::TopControlsShownRatioRange() {
if (top_controls_animation_.IsInitialized())
return std::make_pair(top_controls_animation_.min_value(),
top_controls_animation_.max_value());
return std::make_pair(0.f, 1.f);
}
std::pair<float, float>
BrowserControlsOffsetManager::BottomControlsShownRatioRange() {
if (bottom_controls_animation_.IsInitialized())
return std::make_pair(bottom_controls_animation_.min_value(),
bottom_controls_animation_.max_value());
return std::make_pair(0.f, 1.f);
}
void BrowserControlsOffsetManager::UpdateBrowserControlsState(
BrowserControlsState constraints,
BrowserControlsState current,
bool animate,
base::optional_ref<const BrowserControlsOffsetTagModifications>
offset_tag_modifications) {
DCHECK(!(constraints == BrowserControlsState::kShown &&
current == BrowserControlsState::kHidden));
DCHECK(!(constraints == BrowserControlsState::kHidden &&
current == BrowserControlsState::kShown));
TRACE_EVENT2("cc", "BrowserControlsOffsetManager::UpdateBrowserControlsState",
"constraints", static_cast<int>(constraints), "current",
static_cast<int>(current));
if (permitted_state_ != constraints) {
constraint_changed_since_commit_ = true;
client_->SetNeedsCommit();
}
permitted_state_ = constraints;
if (offset_tag_modifications.has_value()) {
offset_tag_modifications_ = offset_tag_modifications.value();
}
if (constraints == BrowserControlsState::kBoth &&
current == BrowserControlsState::kBoth)
return;
float final_top_shown_ratio = 1.f;
float final_bottom_shown_ratio = 1.f;
AnimationDirection direction = AnimationDirection::kShowingControls;
if (constraints == BrowserControlsState::kHidden ||
current == BrowserControlsState::kHidden) {
final_top_shown_ratio = TopControlsMinShownRatio();
final_bottom_shown_ratio = BottomControlsMinShownRatio();
direction = AnimationDirection::kHidingControls;
}
if (final_top_shown_ratio == TopControlsShownRatio() &&
final_bottom_shown_ratio == BottomControlsShownRatio()) {
TRACE_EVENT_INSTANT0("cc", "Ratios Unchanged", TRACE_EVENT_SCOPE_THREAD);
ResetAnimations();
return;
}
float animated_top_shown_ratio = top_controls_animation_.IsInitialized()
? top_controls_animation_.FinalValue()
: TopControlsShownRatio();
float animated_bottom_shown_ratio =
bottom_controls_animation_.IsInitialized()
? bottom_controls_animation_.FinalValue()
: BottomControlsShownRatio();
if (animated_top_shown_ratio == final_top_shown_ratio &&
animated_bottom_shown_ratio == final_bottom_shown_ratio) {
return;
}
ResetAnimations();
if (animate && direction == AnimationDirection::kShowingControls) {
show_controls_when_scroll_completes_ = true;
}
if (animate)
SetupAnimation(direction);
else
client_->SetCurrentBrowserControlsShownRatio(final_top_shown_ratio,
final_bottom_shown_ratio);
#if BUILDFLAG(ARKWEB_EXT_TOPCONTROLS) && BUILDFLAG(ARKWEB_FLING) && BUILDFLAG(ARKWEB_SLIDE)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableNwebExTopControls) &&
!animate) {
client_->SetupScrollBy();
}
#endif
}
BrowserControlsState BrowserControlsOffsetManager::PullConstraintForMainThread(
bool* out_changed_since_commit) {
DCHECK(out_changed_since_commit);
*out_changed_since_commit = constraint_changed_since_commit_;
return permitted_state_;
}
void BrowserControlsOffsetManager::NotifyConstraintSyncedToMainThread() {
constraint_changed_since_commit_ = false;
}
void BrowserControlsOffsetManager::OnBrowserControlsParamsChanged(
bool animate_changes) {
if (old_browser_controls_params_.top_controls_height == TopControlsHeight() &&
old_browser_controls_params_.top_controls_min_height ==
TopControlsMinHeight() &&
old_browser_controls_params_.bottom_controls_height ==
BottomControlsHeight() &&
old_browser_controls_params_.bottom_controls_min_height ==
BottomControlsMinHeight()) {
return;
}
float old_top_height = old_browser_controls_params_.top_controls_height;
float new_top_ratio =
TopControlsHeight()
? TopControlsShownRatio() * old_top_height / TopControlsHeight()
: TopControlsShownRatio();
float old_bottom_height = old_browser_controls_params_.bottom_controls_height;
float new_bottom_ratio = BottomControlsHeight()
? BottomControlsShownRatio() *
old_bottom_height / BottomControlsHeight()
: BottomControlsShownRatio();
if (!animate_changes) {
bool hide_controls = (permitted_state_ == BrowserControlsState::kHidden);
if (hide_controls) {
new_top_ratio = TopControlsMinShownRatio();
} else if (TopControlsShownRatio() == 1.f) {
new_top_ratio = 1.f;
} else if (TopControlsShownRatio() == OldTopControlsMinShownRatio()) {
new_top_ratio = TopControlsMinShownRatio();
}
if (hide_controls) {
new_bottom_ratio = BottomControlsMinShownRatio();
} else if (BottomControlsShownRatio() == 1.f) {
new_bottom_ratio = 1.f;
} else if (BottomControlsShownRatio() == OldBottomControlsMinShownRatio()) {
new_bottom_ratio = BottomControlsMinShownRatio();
}
}
bool top_controls_need_animation = animate_changes;
bool bottom_controls_need_animation = animate_changes;
float effective_top_shown_ratio = TopControlsShownRatio();
if (top_controls_animation_.IsInitialized()) {
effective_top_shown_ratio = top_controls_animation_.FinalValue();
}
float effective_bottom_shown_ratio = BottomControlsShownRatio();
if (bottom_controls_animation_.IsInitialized()) {
effective_bottom_shown_ratio = bottom_controls_animation_.FinalValue();
}
float top_target_ratio;
if (!TopControlsHeight()) {
top_controls_need_animation = false;
} else if (TopControlsShownRatio() == 1.f &&
TopControlsHeight() != old_top_height) {
top_target_ratio = 1.f;
} else if (effective_top_shown_ratio == OldTopControlsMinShownRatio() &&
TopControlsMinHeight() !=
old_browser_controls_params_.top_controls_min_height) {
top_target_ratio = TopControlsMinShownRatio();
} else {
top_controls_need_animation = false;
}
float bottom_target_ratio;
if (!BottomControlsHeight()) {
bottom_controls_need_animation = false;
} else if (BottomControlsShownRatio() == 1.f &&
BottomControlsHeight() != old_bottom_height) {
bottom_target_ratio = 1.f;
} else if (effective_bottom_shown_ratio == OldBottomControlsMinShownRatio() &&
BottomControlsMinHeight() !=
old_browser_controls_params_.bottom_controls_min_height) {
bottom_target_ratio = BottomControlsMinShownRatio();
} else {
bottom_controls_need_animation = false;
}
if (top_controls_need_animation) {
InitAnimationForHeightChange(&top_controls_animation_, new_top_ratio,
top_target_ratio);
if (old_browser_controls_params_.top_controls_min_height !=
TopControlsMinHeight()) {
top_controls_min_height_offset_ =
old_browser_controls_params_.top_controls_min_height;
top_min_height_change_in_progress_ = true;
SetTopMinHeightOffsetAnimationRange(top_controls_min_height_offset_,
TopControlsMinHeight());
}
} else {
top_controls_min_height_offset_ = TopControlsMinHeight();
}
if (bottom_controls_need_animation) {
InitAnimationForHeightChange(&bottom_controls_animation_, new_bottom_ratio,
bottom_target_ratio);
if (old_browser_controls_params_.bottom_controls_min_height !=
BottomControlsMinHeight()) {
bottom_controls_min_height_offset_ =
old_browser_controls_params_.bottom_controls_min_height;
int height_delta = BottomControlsHeight() - old_bottom_height;
int min_height_delta =
BottomControlsMinHeight() -
old_browser_controls_params_.bottom_controls_min_height;
if (min_height_delta > height_delta) {
bottom_controls_min_height_offset_ += min_height_delta - height_delta;
}
bottom_min_height_change_in_progress_ = true;
SetBottomMinHeightOffsetAnimationRange(bottom_controls_min_height_offset_,
BottomControlsMinHeight());
}
} else {
bottom_controls_min_height_offset_ = BottomControlsMinHeight();
}
UpdateOldBrowserControlsParams();
client_->SetCurrentBrowserControlsShownRatio(new_top_ratio, new_bottom_ratio);
}
void BrowserControlsOffsetManager::ScrollBegin() {
if (pinch_gesture_active_)
return;
show_controls_when_scroll_completes_ = IsAnimatingToShowControls();
ResetAnimations();
ResetBaseline();
}
gfx::Vector2dF BrowserControlsOffsetManager::ScrollBy(
const gfx::Vector2dF& pending_delta) {
if (!TopControlsHeight() && !BottomControlsHeight())
return pending_delta;
if (pinch_gesture_active_)
return pending_delta;
if ((permitted_state_ == BrowserControlsState::kShown &&
pending_delta.y() > 0) ||
(permitted_state_ == BrowserControlsState::kHidden &&
pending_delta.y() < 0))
return pending_delta;
float viewport_offset_y = client_->ViewportScrollOffset().y();
if (client_->OnlyExpandTopControlsAtPageTop() && pending_delta.y() < 0 &&
viewport_offset_y > 0) {
ResetBaseline();
accumulated_scroll_delta_ =
std::min(0.f, pending_delta.y() + viewport_offset_y);
} else {
accumulated_scroll_delta_ += pending_delta.y();
}
bool base_on_top_controls = TopControlsHeight();
float old_top_offset = ContentTopOffset();
float baseline_content_offset = base_on_top_controls
? baseline_top_content_offset_
: baseline_bottom_content_offset_;
float shown_ratio =
(baseline_content_offset - accumulated_scroll_delta_) /
(base_on_top_controls ? TopControlsHeight() : BottomControlsHeight());
float min_ratio = base_on_top_controls ? TopControlsMinShownRatio()
: BottomControlsMinShownRatio();
float normalized_shown_ratio;
if (min_ratio == 1.f) {
normalized_shown_ratio = 1.f;
} else {
normalized_shown_ratio =
(std::clamp(shown_ratio, min_ratio, 1.f) - min_ratio) /
(1.f - min_ratio);
}
client_->SetCurrentBrowserControlsShownRatio(
TopControlsMinShownRatio() +
normalized_shown_ratio * (1.f - TopControlsMinShownRatio()),
BottomControlsMinShownRatio() +
normalized_shown_ratio * (1.f - BottomControlsMinShownRatio()));
if (TopControlsShownRatio() == 1.f && BottomControlsShownRatio() == 1.f) {
ResetBaseline();
show_controls_when_scroll_completes_ = false;
}
ResetAnimations();
gfx::Vector2dF applied_delta(0.f, old_top_offset - ContentTopOffset());
return pending_delta - applied_delta;
}
void BrowserControlsOffsetManager::ScrollEnd() {
if (pinch_gesture_active_)
return;
if (show_controls_when_scroll_completes_ && TopControlsShownRatio() != 1.f) {
SetupAnimation(AnimationDirection::kShowingControls);
return;
}
StartAnimationIfNecessary();
}
void BrowserControlsOffsetManager::PinchBegin() {
DCHECK(!pinch_gesture_active_);
pinch_gesture_active_ = true;
StartAnimationIfNecessary();
}
void BrowserControlsOffsetManager::PinchEnd() {
DCHECK(pinch_gesture_active_);
pinch_gesture_active_ = false;
ScrollBegin();
}
gfx::Vector2dF BrowserControlsOffsetManager::Animate(
base::TimeTicks monotonic_time) {
if (!HasAnimation() || !client_->HaveRootScrollNode())
return gfx::Vector2dF();
float old_top_offset = ContentTopOffset();
float old_bottom_offset = ContentBottomOffset();
std::optional<float> new_top_ratio =
top_controls_animation_.Tick(monotonic_time);
if (!new_top_ratio.has_value())
new_top_ratio = TopControlsShownRatio();
std::optional<float> new_bottom_ratio =
bottom_controls_animation_.Tick(monotonic_time);
if (!new_bottom_ratio.has_value())
new_bottom_ratio = BottomControlsShownRatio();
client_->SetCurrentBrowserControlsShownRatio(new_top_ratio.value(),
new_bottom_ratio.value());
float top_offset_delta = ContentTopOffset() - old_top_offset;
float bottom_offset_delta = ContentBottomOffset() - old_bottom_offset;
if (top_min_height_change_in_progress_) {
top_controls_min_height_offset_ =
std::clamp(top_controls_min_height_offset_ + top_offset_delta,
top_min_height_offset_animation_range_->first,
top_min_height_offset_animation_range_->second);
top_min_height_change_in_progress_ =
top_controls_animation_.IsInitialized();
}
if (bottom_min_height_change_in_progress_) {
bottom_controls_min_height_offset_ =
std::clamp(bottom_controls_min_height_offset_ + bottom_offset_delta,
bottom_min_height_offset_animation_range_->first,
bottom_min_height_offset_animation_range_->second);
bottom_min_height_change_in_progress_ =
bottom_controls_animation_.IsInitialized();
if (!bottom_min_height_change_in_progress_) {
bottom_controls_min_height_offset_ = BottomControlsMinHeight();
}
}
gfx::Vector2dF scroll_delta(0.f, top_offset_delta);
return scroll_delta;
}
bool BrowserControlsOffsetManager::HasAnimation() {
return top_controls_animation_.IsInitialized() ||
bottom_controls_animation_.IsInitialized();
}
void BrowserControlsOffsetManager::ResetAnimations() {
std::optional<float> top_ratio = top_controls_animation_.Reset();
std::optional<float> bottom_ratio = bottom_controls_animation_.Reset();
if (top_ratio.has_value() || bottom_ratio.has_value()) {
client_->SetCurrentBrowserControlsShownRatio(
top_ratio.has_value() ? top_ratio.value() : TopControlsShownRatio(),
bottom_ratio.has_value() ? bottom_ratio.value()
: BottomControlsShownRatio());
if (top_min_height_change_in_progress_) {
DCHECK(top_ratio.has_value());
top_controls_min_height_offset_ = TopControlsMinHeight();
}
if (bottom_min_height_change_in_progress_) {
DCHECK(bottom_ratio.has_value());
bottom_controls_min_height_offset_ = BottomControlsMinHeight();
}
}
top_min_height_change_in_progress_ = false;
bottom_min_height_change_in_progress_ = false;
top_min_height_offset_animation_range_.reset();
bottom_min_height_offset_animation_range_.reset();
}
void BrowserControlsOffsetManager::SetupAnimation(
AnimationDirection direction) {
DCHECK_NE(AnimationDirection::kNoAnimation, direction);
DCHECK(direction != AnimationDirection::kHidingControls ||
TopControlsShownRatio() > 0.f || BottomControlsShownRatio() > 0.f);
DCHECK(direction != AnimationDirection::kShowingControls ||
TopControlsShownRatio() < 1.f || BottomControlsShownRatio() < 1.f);
if (top_controls_animation_.IsInitialized() &&
top_controls_animation_.Direction() == direction &&
bottom_controls_animation_.IsInitialized() &&
bottom_controls_animation_.Direction() == direction) {
return;
}
if (!TopControlsHeight() && !BottomControlsHeight()) {
float ratio = direction == AnimationDirection::kHidingControls ? 0.f : 1.f;
client_->SetCurrentBrowserControlsShownRatio(ratio, ratio);
return;
}
const float max_stop_ratio =
direction == AnimationDirection::kShowingControls ? 1 : -1;
float top_start_ratio = TopControlsShownRatio();
float top_stop_ratio = top_start_ratio + max_stop_ratio;
top_controls_animation_.Initialize(direction, top_start_ratio, top_stop_ratio,
kShowHideMaxDurationMs,
false);
top_controls_animation_.SetBounds(TopControlsMinShownRatio(), 1.f);
float bottom_start_ratio = BottomControlsShownRatio();
float bottom_stop_ratio = bottom_start_ratio + max_stop_ratio;
bottom_controls_animation_.Initialize(
direction, bottom_start_ratio, bottom_stop_ratio, kShowHideMaxDurationMs,
false);
bottom_controls_animation_.SetBounds(BottomControlsMinShownRatio(), 1.f);
client_->DidChangeBrowserControlsPosition();
}
void BrowserControlsOffsetManager::StartAnimationIfNecessary() {
if ((TopControlsShownRatio() == TopControlsMinShownRatio() ||
TopControlsShownRatio() == 1.f) &&
(BottomControlsShownRatio() == BottomControlsMinShownRatio() ||
BottomControlsShownRatio() == 1.f))
return;
float normalized_top_ratio =
(TopControlsShownRatio() - TopControlsMinShownRatio()) /
(1.f - TopControlsMinShownRatio());
if (normalized_top_ratio >= 1.f - controls_hide_threshold_) {
SetupAnimation(AnimationDirection::kShowingControls);
} else if (normalized_top_ratio <= controls_show_threshold_) {
SetupAnimation(AnimationDirection::kHidingControls);
} else {
SetupAnimation(accumulated_scroll_delta_ <= 0.f
? AnimationDirection::kShowingControls
: AnimationDirection::kHidingControls);
}
}
void BrowserControlsOffsetManager::ResetBaseline() {
accumulated_scroll_delta_ = 0.f;
baseline_top_content_offset_ = ContentTopOffset();
baseline_bottom_content_offset_ = ContentBottomOffset();
}
void BrowserControlsOffsetManager::InitAnimationForHeightChange(
Animation* animation,
float start_ratio,
float stop_ratio) {
AnimationDirection direction = start_ratio < stop_ratio
? AnimationDirection::kShowingControls
: AnimationDirection::kHidingControls;
animation->Initialize(direction, start_ratio, stop_ratio,
kHeightChangeDurationMs, true);
}
float BrowserControlsOffsetManager::OldTopControlsMinShownRatio() {
return old_browser_controls_params_.top_controls_height
? old_browser_controls_params_.top_controls_min_height /
old_browser_controls_params_.top_controls_height
: 0.f;
}
float BrowserControlsOffsetManager::OldBottomControlsMinShownRatio() {
return old_browser_controls_params_.bottom_controls_height
? old_browser_controls_params_.bottom_controls_min_height /
old_browser_controls_params_.bottom_controls_height
: 0.f;
}
void BrowserControlsOffsetManager::UpdateOldBrowserControlsParams() {
old_browser_controls_params_.top_controls_height = TopControlsHeight();
old_browser_controls_params_.top_controls_min_height = TopControlsMinHeight();
old_browser_controls_params_.bottom_controls_height = BottomControlsHeight();
old_browser_controls_params_.bottom_controls_min_height =
BottomControlsMinHeight();
}
void BrowserControlsOffsetManager::SetTopMinHeightOffsetAnimationRange(
float from,
float to) {
top_min_height_offset_animation_range_ =
std::make_pair(std::min(from, to), std::max(from, to));
}
void BrowserControlsOffsetManager::SetBottomMinHeightOffsetAnimationRange(
float from,
float to) {
bottom_min_height_offset_animation_range_ =
std::make_pair(std::min(from, to), std::max(from, to));
}
double BrowserControlsOffsetManager::PredictViewportBoundsDelta(
double current_bounds_delta,
gfx::Vector2dF scroll_distance) {
double adjustment = current_bounds_delta;
if (scroll_distance.y() > 0 && adjustment > 0) {
if (TopControlsShownRatio() < 1) {
adjustment += ContentTopOffset();
}
if (BottomControlsShownRatio() < 1) {
adjustment += ContentBottomOffset();
}
}
if (scroll_distance.y() < 0 && adjustment < 0) {
if (TopControlsShownRatio() > 0) {
adjustment -= TopControlsHeight() - ContentTopOffset();
}
if (BottomControlsShownRatio() > 0) {
adjustment -= BottomControlsHeight() - ContentBottomOffset();
}
}
return adjustment;
}
BrowserControlsOffsetManager::Animation::Animation() {}
void BrowserControlsOffsetManager::Animation::Initialize(
AnimationDirection direction,
float start_value,
float stop_value,
int64_t duration,
bool jump_to_end_on_reset) {
direction_ = direction;
start_value_ = start_value;
stop_value_ = stop_value;
duration_ = base::Milliseconds(duration);
initialized_ = true;
jump_to_end_on_reset_ = jump_to_end_on_reset;
SetBounds(std::min(start_value_, stop_value_),
std::max(start_value_, stop_value_));
}
std::optional<float> BrowserControlsOffsetManager::Animation::Tick(
base::TimeTicks monotonic_time) {
if (!IsInitialized())
return std::nullopt;
if (!started_) {
start_time_ = monotonic_time;
stop_time_ = start_time_ + duration_;
started_ = true;
}
float value = gfx::Tween::ClampedFloatValueBetween(
monotonic_time, start_time_, start_value_, stop_time_, stop_value_);
if (IsComplete(value)) {
value = FinalValue();
Reset();
}
return value;
}
void BrowserControlsOffsetManager::Animation::SetBounds(float min, float max) {
min_value_ = min;
max_value_ = max;
}
std::optional<float> BrowserControlsOffsetManager::Animation::Reset() {
auto ret =
jump_to_end_on_reset_
? std::make_optional(std::clamp(stop_value_, min_value_, max_value_))
: std::nullopt;
started_ = false;
initialized_ = false;
start_time_ = base::TimeTicks();
start_value_ = 0.f;
stop_time_ = base::TimeTicks();
stop_value_ = 0.f;
direction_ = AnimationDirection::kNoAnimation;
duration_ = base::TimeDelta();
min_value_ = 0.f;
max_value_ = 1.f;
jump_to_end_on_reset_ = false;
return ret;
}
bool BrowserControlsOffsetManager::Animation::IsComplete(float value) {
return (direction_ == AnimationDirection::kShowingControls &&
(value >= stop_value_ || value >= max_value_)) ||
(direction_ == AnimationDirection::kHidingControls &&
(value <= stop_value_ || value <= min_value_));
}
float BrowserControlsOffsetManager::Animation::FinalValue() {
return std::clamp(stop_value_, min_value_, max_value_);
}
}