blob: 0115078698b24816428b68ca873a1bfbeae0618c [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 "third_party/blink/renderer/core/page/scrolling/viewport_scroll_callback.h"
#include "third_party/blink/renderer/core/frame/browser_controls.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/page/scrolling/overscroll_controller.h"
#include "third_party/blink/renderer/core/page/scrolling/scroll_state.h"
#include "third_party/blink/renderer/core/scroll/scrollable_area.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
namespace blink {
ViewportScrollCallback::ViewportScrollCallback(
BrowserControls* browser_controls,
OverscrollController* overscroll_controller,
RootFrameViewport& root_frame_viewport)
: browser_controls_(browser_controls),
overscroll_controller_(overscroll_controller),
root_frame_viewport_(&root_frame_viewport) {}
ViewportScrollCallback::~ViewportScrollCallback() = default;
void ViewportScrollCallback::Trace(blink::Visitor* visitor) {
visitor->Trace(browser_controls_);
visitor->Trace(overscroll_controller_);
visitor->Trace(root_frame_viewport_);
ScrollStateCallback::Trace(visitor);
}
bool ViewportScrollCallback::ShouldScrollBrowserControls(
const ScrollOffset& delta,
ScrollGranularity granularity) const {
if (granularity != kScrollByPixel && granularity != kScrollByPrecisePixel)
return false;
if (!root_frame_viewport_)
return false;
ScrollOffset max_scroll = root_frame_viewport_->MaximumScrollOffset();
ScrollOffset scroll_offset = root_frame_viewport_->GetScrollOffset();
// Always give the delta to the browser controls if the scroll is in
// the direction to show the browser controls. If it's in the
// direction to hide the browser controls, only give the delta to the
// browser controls when the frame can scroll.
return delta.Height() < 0 || scroll_offset.Height() < max_scroll.Height();
}
bool ViewportScrollCallback::ScrollBrowserControls(ScrollState& state) {
// Scroll browser controls.
if (browser_controls_) {
if (state.isBeginning())
browser_controls_->ScrollBegin();
FloatSize delta(state.deltaX(), state.deltaY());
ScrollGranularity granularity =
ScrollGranularity(static_cast<int>(state.deltaGranularity()));
if (ShouldScrollBrowserControls(delta, granularity)) {
FloatSize remaining_delta = browser_controls_->ScrollBy(delta);
FloatSize consumed = delta - remaining_delta;
state.ConsumeDeltaNative(consumed.Width(), consumed.Height());
return !consumed.IsZero();
}
}
return false;
}
void ViewportScrollCallback::Invoke(ScrollState* state) {
DCHECK(state);
if (!root_frame_viewport_)
return;
bool browser_controls_did_scroll = ScrollBrowserControls(*state);
ScrollResult result = PerformNativeScroll(*state);
// We consider browser controls movement to be scrolling.
result.did_scroll_y |= browser_controls_did_scroll;
// Handle Overscroll.
if (overscroll_controller_) {
FloatPoint position(state->positionX(), state->positionY());
FloatSize velocity(state->velocityX(), state->velocityY());
overscroll_controller_->HandleOverscroll(result, position, velocity);
}
}
void ViewportScrollCallback::SetScroller(ScrollableArea* scroller) {
DCHECK(scroller);
root_frame_viewport_->SetLayoutViewport(*scroller);
}
ScrollResult ViewportScrollCallback::PerformNativeScroll(ScrollState& state) {
DCHECK(root_frame_viewport_);
FloatSize delta(state.deltaX(), state.deltaY());
ScrollGranularity granularity =
ScrollGranularity(static_cast<int>(state.deltaGranularity()));
ScrollResult result = root_frame_viewport_->UserScroll(granularity, delta);
// The viewport consumes everything.
// TODO(bokan): This isn't actually consuming everything but doing so breaks
// the main thread pull-to-refresh action. crbug.com/607210.
state.ConsumeDeltaNative(delta.Width() - result.unused_scroll_delta_x,
delta.Height() - result.unused_scroll_delta_y);
return result;
}
} // namespace blink