blob: e00d7fb09daf4cb453c55967a50afde602a8fef0 [file] [log] [blame]
// 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 "core/frame/BrowserControls.h"
#include <algorithm> // for std::min and std::max
#include "core/frame/VisualViewport.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "platform/geometry/FloatSize.h"
namespace blink {
BrowserControls::BrowserControls(const Page& page)
: page_(&page),
top_height_(0),
bottom_height_(0),
shown_ratio_(0),
baseline_content_offset_(0),
accumulated_scroll_delta_(0),
shrink_viewport_(false),
permitted_state_(kWebBrowserControlsBoth) {}
void BrowserControls::Trace(blink::Visitor* visitor) {
visitor->Trace(page_);
}
void BrowserControls::ScrollBegin() {
ResetBaseline();
}
FloatSize BrowserControls::ScrollBy(FloatSize pending_delta) {
if ((permitted_state_ == kWebBrowserControlsShown &&
pending_delta.Height() > 0) ||
(permitted_state_ == kWebBrowserControlsHidden &&
pending_delta.Height() < 0))
return pending_delta;
if (top_height_ == 0 && bottom_height_ == 0)
return pending_delta;
float height = top_height_;
if (!top_height_)
height = bottom_height_;
// If there is no top height, base calculations off bottom height.
float old_offset = top_height_ ? ContentOffset() : BottomContentOffset();
float page_scale = page_->GetVisualViewport().Scale();
// Update accumulated vertical scroll and apply it to browser controls
// Compute scroll delta in viewport space by applying page scale
accumulated_scroll_delta_ += pending_delta.Height() * page_scale;
float new_content_offset =
baseline_content_offset_ - accumulated_scroll_delta_;
SetShownRatio(new_content_offset / height);
// Reset baseline when controls are fully visible
if (shown_ratio_ == 1)
ResetBaseline();
// Clamp and use the expected content offset so that we don't return
// spurrious remaining scrolls due to the imprecision of the shownRatio.
new_content_offset = std::min(new_content_offset, height);
new_content_offset = std::max(new_content_offset, 0.f);
// We negate the difference because scrolling down (positive delta) causes
// browser controls to hide (negative offset difference).
FloatSize applied_delta(
0, top_height_ ? (old_offset - new_content_offset) / page_scale : 0);
return pending_delta - applied_delta;
}
void BrowserControls::ResetBaseline() {
accumulated_scroll_delta_ = 0;
baseline_content_offset_ =
top_height_ ? ContentOffset() : BottomContentOffset();
}
float BrowserControls::UnreportedSizeAdjustment() {
return (shrink_viewport_ ? top_height_ : 0) - ContentOffset();
}
float BrowserControls::ContentOffset() {
return shown_ratio_ * top_height_;
}
float BrowserControls::BottomContentOffset() {
return shown_ratio_ * bottom_height_;
}
void BrowserControls::SetShownRatio(float shown_ratio) {
shown_ratio = std::min(shown_ratio, 1.f);
shown_ratio = std::max(shown_ratio, 0.f);
if (shown_ratio_ == shown_ratio)
return;
shown_ratio_ = shown_ratio;
page_->GetChromeClient().DidUpdateBrowserControls();
}
void BrowserControls::UpdateConstraintsAndState(
WebBrowserControlsState constraints,
WebBrowserControlsState current,
bool animate) {
permitted_state_ = constraints;
DCHECK(!(constraints == kWebBrowserControlsShown &&
current == kWebBrowserControlsHidden));
DCHECK(!(constraints == kWebBrowserControlsHidden &&
current == kWebBrowserControlsShown));
// If the change should be animated, let the impl thread drive the change.
// Otherwise, immediately set the shown ratio so we don't have to wait for
// a commit from the impl thread.
if (animate)
return;
if (constraints == kWebBrowserControlsBoth &&
current == kWebBrowserControlsBoth)
return;
if (constraints == kWebBrowserControlsHidden ||
current == kWebBrowserControlsHidden)
SetShownRatio(0.f);
else
SetShownRatio(1.f);
}
void BrowserControls::SetHeight(float top_height,
float bottom_height,
bool shrink_viewport) {
if (top_height_ == top_height && shrink_viewport_ == shrink_viewport &&
bottom_height_ == bottom_height) {
return;
}
top_height_ = top_height;
bottom_height_ = bottom_height;
shrink_viewport_ = shrink_viewport;
page_->GetChromeClient().DidUpdateBrowserControls();
}
} // namespace blink