123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779 |
- // Copyright 2016 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "cc/input/browser_controls_offset_manager.h"
- #include <stdint.h>
- #include <algorithm>
- #include <utility>
- #include "base/check_op.h"
- #include "base/cxx17_backports.h"
- #include "base/memory/ptr_util.h"
- #include "cc/input/browser_controls_offset_manager_client.h"
- #include "cc/trees/layer_tree_impl.h"
- #include "components/viz/common/frame_sinks/begin_frame_args.h"
- #include "ui/gfx/animation/tween.h"
- #include "ui/gfx/geometry/transform.h"
- #include "ui/gfx/geometry/vector2d_f.h"
- namespace cc {
- namespace {
- // These constants were chosen empirically for their visually pleasant behavior.
- // Contact tedchoc@chromium.org for questions about changing these values.
- const int64_t kShowHideMaxDurationMs = 200;
- // TODO(sinansahin): Temporary value, pending UX guidance probably.
- const int64_t kHeightChangeDurationMs = 200;
- }
- // static
- 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();
- }
- 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_;
- }
- 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) {
- 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 the constraints have changed we need to inform Blink about it since
- // that'll affect main thread scrolling as well as layout.
- if (permitted_state_ != constraints) {
- constraint_changed_since_commit_ = true;
- client_->SetNeedsCommit();
- }
- permitted_state_ = constraints;
- // Don't do anything if it doesn't matter which state the controls are in.
- if (constraints == BrowserControlsState::kBoth &&
- current == BrowserControlsState::kBoth)
- return;
- // Don't do anything if there is no change in offset.
- float final_top_shown_ratio = 1.f;
- float final_bottom_shown_ratio = 1.f;
- AnimationDirection direction = AnimationDirection::SHOWING_CONTROLS;
- if (constraints == BrowserControlsState::kHidden ||
- current == BrowserControlsState::kHidden) {
- final_top_shown_ratio = TopControlsMinShownRatio();
- final_bottom_shown_ratio = BottomControlsMinShownRatio();
- direction = AnimationDirection::HIDING_CONTROLS;
- }
- if (final_top_shown_ratio == TopControlsShownRatio() &&
- final_bottom_shown_ratio == BottomControlsShownRatio()) {
- TRACE_EVENT_INSTANT0("cc", "Ratios Unchanged", TRACE_EVENT_SCOPE_THREAD);
- ResetAnimations();
- return;
- }
- // Don't do anything if the currently running animations end in our desired
- // state.
- 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)
- SetupAnimation(direction);
- else
- client_->SetCurrentBrowserControlsShownRatio(final_top_shown_ratio,
- final_bottom_shown_ratio);
- }
- 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;
- }
- // We continue to update both top and bottom controls even if one has a height
- // of 0 so that animations work properly. So here, we should preserve the
- // ratios even if the controls height is 0.
- 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) {
- // If the min-heights changed when the controls were at the min-height, the
- // shown ratios need to be snapped to the new min-shown-ratio to keep the
- // controls at the min height. If the controls were fully shown, we want to
- // keep them fully shown even after the heights changed. For any other
- // cases, we should update the shown ratio so the visible height remains the
- // same.
- if (TopControlsShownRatio() == OldTopControlsMinShownRatio())
- new_top_ratio = TopControlsMinShownRatio();
- else if (TopControlsShownRatio() == 1.f)
- new_top_ratio = 1.f;
- if (BottomControlsShownRatio() == OldBottomControlsMinShownRatio())
- new_bottom_ratio = BottomControlsMinShownRatio();
- else if (BottomControlsShownRatio() == 1.f)
- new_bottom_ratio = 1.f;
- }
- // Browser controls height change animations
- // If the browser controls heights (and/or min-heights) changed and need to be
- // animated, the setup is done here. All the animations done in this class
- // involve changing the shown ratios smoothly.
- //
- // There are several cases to handle:
- // 1- The controls shown ratio was at the minimum ratio
- // - If the min-height changed, we will run an animation from
- // old-min-height / new-total-height to new-min-height / new-total-height
- // - If the min-height didn't change, we should update the shown ratio to
- // min-height / new-total-height so that the controls keep the same
- // visible height and don't jump. No animation needed in this case.
- // 2- The controls shown ratio was at the highest ratio (should be 1 here)
- // - If the total height changed, we will run an animation from
- // old-total-height / new-total-height to 1.
- // - If the total height didn't change, we don't need to do anything.
- // 3- The controls shown ratio is between the minimum and the maximum.
- // - If an animation is running to the old min-height, start a new
- // animation to min-height / total-height.
- // - Otherwise don't start an animation. We're either animating the
- // controls to their expanded state, in which case we can let that
- // animation continue, or we're scrolling and no animation is needed.
- // Update the shown ratio so the visible height remains the same (see
- // new_{top,bottom}_ratio above).
- //
- // When this method is called as a result of a height change,
- // TopControlsHeight(), TopControlsMinHeight(), BottomControlsHeight(), and
- // BottomControlsMinHeight() will already be returning the new values.
- // However, the shown ratios aren't updated.
- bool top_controls_need_animation = animate_changes;
- bool bottom_controls_need_animation = animate_changes;
- // To handle the case where the min-height changes while we're animating to
- // the previous min-height, base our "are we at the minimum shown ratio"
- // check on the post-animation ratio if an animation is running, rather than
- // its current value.
- 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;
- // We can't animate if we don't have top controls.
- if (!TopControlsHeight()) {
- top_controls_need_animation = false;
- // If the top controls height changed when they were fully shown.
- } else if (TopControlsShownRatio() == 1.f &&
- TopControlsHeight() != old_top_height) {
- top_target_ratio = 1.f; // i.e. new_height / new_height
- // If the top controls min-height changed when they were at the minimum
- // shown ratio. For example, the min height changed from 0 to a positive
- // value while the top controls were completely hidden.
- } 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;
- // We can't animate if we don't have bottom controls.
- if (!BottomControlsHeight()) {
- bottom_controls_need_animation = false;
- // If the bottom controls height changed when they were fully shown.
- } else if (BottomControlsShownRatio() == 1.f &&
- BottomControlsHeight() != old_bottom_height) {
- bottom_target_ratio = 1.f; // i.e. new_height / new_height
- // If the bottom controls min-height changed when they were at the minimum
- // shown ratio.
- } 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;
- bottom_min_height_change_in_progress_ = true;
- SetBottomMinHeightOffsetAnimationRange(bottom_controls_min_height_offset_,
- BottomControlsMinHeight());
- }
- } else {
- bottom_controls_min_height_offset_ = BottomControlsMinHeight();
- }
- // We won't run any animations if the controls are in an in-between state.
- // Examples: a show/hide animation is running, shown ratio is some value
- // between min-shown-ratio and 1 because of a scroll event.
- UpdateOldBrowserControlsParams();
- client_->SetCurrentBrowserControlsShownRatio(new_top_ratio, new_bottom_ratio);
- }
- void BrowserControlsOffsetManager::ScrollBegin() {
- if (pinch_gesture_active_)
- return;
- ResetAnimations();
- ResetBaseline();
- }
- gfx::Vector2dF BrowserControlsOffsetManager::ScrollBy(
- const gfx::Vector2dF& pending_delta) {
- // If one or both of the top/bottom controls are showing, the shown ratio
- // needs to be computed.
- 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;
- // Scroll the page up before expanding the browser controls if
- // OnlyExpandTopControlsAtPageTop() returns true.
- float viewport_offset_y = client_->ViewportScrollOffset().y();
- if (client_->OnlyExpandTopControlsAtPageTop() && pending_delta.y() < 0 &&
- viewport_offset_y > 0) {
- // Reset the baseline so the controls will immediately begin to scroll
- // once we're at the top.
- ResetBaseline();
- // Only scroll the controls by the amount remaining after the page contents
- // have been scrolled to the top.
- accumulated_scroll_delta_ =
- std::min(0.f, pending_delta.y() + viewport_offset_y);
- } else {
- accumulated_scroll_delta_ += pending_delta.y();
- }
- // We want to base our calculations on top or bottom controls. After consuming
- // the scroll delta, we will calculate a shown ratio for the controls. The
- // top controls have the priority because they need to visually be in sync
- // with the web contents.
- 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_;
- // The top and bottom controls ratios can be calculated independently.
- // However, we want the (normalized) ratios to be equal when scrolling.
- // Having normalized ratios in this context means the top and bottom controls
- // reach the min and max ratios at the same time when scrolling or during
- // the usual show/hide animations, but they can have different shown ratios at
- // any time.
- 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 =
- (base::clamp(shown_ratio, min_ratio, 1.f) - min_ratio) /
- (1.f - min_ratio);
- // Even though the real shown ratios (shown height / total height) of the top
- // and bottom controls can be different, they share the same
- // relative/normalized ratio to keep them in sync.
- client_->SetCurrentBrowserControlsShownRatio(
- TopControlsMinShownRatio() +
- normalized_shown_ratio * (1.f - TopControlsMinShownRatio()),
- BottomControlsMinShownRatio() +
- normalized_shown_ratio * (1.f - BottomControlsMinShownRatio()));
- // If the controls are fully visible, treat the current position as the
- // new baseline even if the gesture didn't end.
- if (TopControlsShownRatio() == 1.f && BottomControlsShownRatio() == 1.f)
- ResetBaseline();
- ResetAnimations();
- // applied_delta will negate any scroll on the content if the top browser
- // controls are showing in favor of hiding the controls and resizing the
- // content. If the top controls have no height, the content should scroll
- // immediately.
- gfx::Vector2dF applied_delta(0.f, old_top_offset - ContentTopOffset());
- return pending_delta - applied_delta;
- }
- void BrowserControlsOffsetManager::ScrollEnd() {
- if (pinch_gesture_active_)
- return;
- StartAnimationIfNecessary();
- }
- void BrowserControlsOffsetManager::PinchBegin() {
- DCHECK(!pinch_gesture_active_);
- pinch_gesture_active_ = true;
- StartAnimationIfNecessary();
- }
- void BrowserControlsOffsetManager::PinchEnd() {
- DCHECK(pinch_gesture_active_);
- // Pinch{Begin,End} will always occur within the scope of Scroll{Begin,End},
- // so return to a state expected by the remaining scroll sequence.
- 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();
- absl::optional<float> new_top_ratio =
- top_controls_animation_.Tick(monotonic_time);
- if (!new_top_ratio.has_value())
- new_top_ratio = TopControlsShownRatio();
- absl::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_) {
- // The change in top offset may be larger than the min-height, resulting in
- // too low or too high |top_controls_min_height_offset_| values. So, we
- // should clamp it to a valid range.
- top_controls_min_height_offset_ =
- base::clamp(top_controls_min_height_offset_ + top_offset_delta,
- top_min_height_offset_animation_range_->first,
- top_min_height_offset_animation_range_->second);
- // Ticking the animation might reset it if it's at the final value.
- top_min_height_change_in_progress_ =
- top_controls_animation_.IsInitialized();
- }
- if (bottom_min_height_change_in_progress_) {
- // The change in bottom offset may be larger than the min-height, resulting
- // in too low or too high |bottom_controls_min_height_offset_| values. So,
- // we should clamp it to a valid range.
- bottom_controls_min_height_offset_ =
- base::clamp(bottom_controls_min_height_offset_ + bottom_offset_delta,
- bottom_min_height_offset_animation_range_->first,
- bottom_min_height_offset_animation_range_->second);
- // Ticking the animation might reset it if it's at the final value.
- bottom_min_height_change_in_progress_ =
- bottom_controls_animation_.IsInitialized();
- }
- 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() {
- // If the animation doesn't need to jump to the end, Animation::Reset() will
- // return |absl::nullopt|.
- absl::optional<float> top_ratio = top_controls_animation_.Reset();
- absl::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::NO_ANIMATION, direction);
- DCHECK(direction != AnimationDirection::HIDING_CONTROLS ||
- TopControlsShownRatio() > 0.f);
- DCHECK(direction != AnimationDirection::SHOWING_CONTROLS ||
- TopControlsShownRatio() < 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::HIDING_CONTROLS ? 0.f : 1.f;
- client_->SetCurrentBrowserControlsShownRatio(ratio, ratio);
- return;
- }
- // Providing artificially larger/smaller stop ratios to make the animation
- // faster if the start ratio is closer to stop ratio.
- const float max_stop_ratio =
- direction == AnimationDirection::SHOWING_CONTROLS ? 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,
- /*jump_to_end_on_reset=*/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,
- /*jump_to_end_on_reset=*/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_) {
- // If we're showing so much that the hide threshold won't trigger, show.
- SetupAnimation(AnimationDirection::SHOWING_CONTROLS);
- } else if (normalized_top_ratio <= controls_show_threshold_) {
- // If we're showing so little that the show threshold won't trigger, hide.
- SetupAnimation(AnimationDirection::HIDING_CONTROLS);
- } else {
- // If we could be either showing or hiding, we determine which one to
- // do based on whether or not the total scroll delta was moving up or
- // down.
- SetupAnimation(accumulated_scroll_delta_ <= 0.f
- ? AnimationDirection::SHOWING_CONTROLS
- : AnimationDirection::HIDING_CONTROLS);
- }
- }
- 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::SHOWING_CONTROLS
- : AnimationDirection::HIDING_CONTROLS;
- animation->Initialize(direction, start_ratio, stop_ratio,
- kHeightChangeDurationMs, /*jump_to_end_on_reset=*/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() {
- // No need to update the other two bool members as they aren't useful for this
- // class.
- 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));
- }
- // class Animation
- 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_));
- }
- absl::optional<float> BrowserControlsOffsetManager::Animation::Tick(
- base::TimeTicks monotonic_time) {
- if (!IsInitialized())
- return absl::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;
- }
- absl::optional<float> BrowserControlsOffsetManager::Animation::Reset() {
- auto ret = jump_to_end_on_reset_ ? absl::make_optional(base::clamp(
- stop_value_, min_value_, max_value_))
- : absl::nullopt;
- started_ = false;
- initialized_ = false;
- start_time_ = base::TimeTicks();
- start_value_ = 0.f;
- stop_time_ = base::TimeTicks();
- stop_value_ = 0.f;
- direction_ = AnimationDirection::NO_ANIMATION;
- 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::SHOWING_CONTROLS &&
- (value >= stop_value_ || value >= max_value_)) ||
- (direction_ == AnimationDirection::HIDING_CONTROLS &&
- (value <= stop_value_ || value <= min_value_));
- }
- float BrowserControlsOffsetManager::Animation::FinalValue() {
- return base::clamp(stop_value_, min_value_, max_value_);
- }
- } // namespace cc
|