Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1157)

Unified Diff: content/renderer/input/input_scroll_elasticity_controller.cc

Issue 1415953004: Move content/renderer input handling for web input events to ui (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/input/input_scroll_elasticity_controller.cc
diff --git a/content/renderer/input/input_scroll_elasticity_controller.cc b/content/renderer/input/input_scroll_elasticity_controller.cc
deleted file mode 100644
index 00d078ff76c84ddb3b870c1ac0dd107bcaec0353..0000000000000000000000000000000000000000
--- a/content/renderer/input/input_scroll_elasticity_controller.cc
+++ /dev/null
@@ -1,410 +0,0 @@
-// Copyright 2014 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 "content/renderer/input/input_scroll_elasticity_controller.h"
-
-#include <math.h>
-
-#include "base/bind.h"
-#include "cc/input/input_handler.h"
-#include "ui/gfx/geometry/vector2d_conversions.h"
-
-// InputScrollElasticityController is based on
-// WebKit/Source/platform/mac/InputScrollElasticityController.mm
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-namespace content {
-
-namespace {
-
-const float kScrollVelocityZeroingTimeout = 0.10f;
-const float kRubberbandMinimumRequiredDeltaBeforeStretch = 10;
-
-const float kRubberbandStiffness = 20;
-const float kRubberbandAmplitude = 0.31f;
-const float kRubberbandPeriod = 1.6f;
-
-// For these functions which compute the stretch amount, always return a
-// rounded value, instead of a floating-point value. The reason for this is
-// that Blink's scrolling can become erratic with fractional scroll amounts (in
-// particular, if you have a scroll offset of 0.5, Blink will never actually
-// bring that value back to 0, which breaks the logic used to determine if a
-// layer is pinned in a direction).
-
-gfx::Vector2d StretchAmountForTimeDelta(const gfx::Vector2dF& initial_position,
- const gfx::Vector2dF& initial_velocity,
- float elapsed_time) {
- // Compute the stretch amount at a given time after some initial conditions.
- // Do this by first computing an intermediary position given the initial
- // position, initial velocity, time elapsed, and no external forces. Then
- // take the intermediary position and damp it towards zero by multiplying
- // against a negative exponential.
- float amplitude = kRubberbandAmplitude;
- float period = kRubberbandPeriod;
- float critical_dampening_factor =
- expf((-elapsed_time * kRubberbandStiffness) / period);
-
- return gfx::ToRoundedVector2d(gfx::ScaleVector2d(
- initial_position +
- gfx::ScaleVector2d(initial_velocity, elapsed_time * amplitude),
- critical_dampening_factor));
-}
-
-gfx::Vector2d StretchAmountForReboundDelta(const gfx::Vector2dF& delta) {
- float stiffness = std::max(kRubberbandStiffness, 1.0f);
- return gfx::ToRoundedVector2d(gfx::ScaleVector2d(delta, 1.0f / stiffness));
-}
-
-gfx::Vector2d StretchScrollForceForStretchAmount(const gfx::Vector2dF& delta) {
- return gfx::ToRoundedVector2d(
- gfx::ScaleVector2d(delta, kRubberbandStiffness));
-}
-
-} // namespace
-
-InputScrollElasticityController::InputScrollElasticityController(
- cc::ScrollElasticityHelper* helper)
- : helper_(helper),
- state_(kStateInactive),
- momentum_animation_reset_at_next_frame_(false),
- weak_factory_(this) {
-}
-
-InputScrollElasticityController::~InputScrollElasticityController() {
-}
-
-base::WeakPtr<InputScrollElasticityController>
-InputScrollElasticityController::GetWeakPtr() {
- if (helper_)
- return weak_factory_.GetWeakPtr();
- return base::WeakPtr<InputScrollElasticityController>();
-}
-
-void InputScrollElasticityController::ObserveWheelEventAndResult(
- const blink::WebMouseWheelEvent& wheel_event,
- const cc::InputHandlerScrollResult& scroll_result) {
- // We should only get PhaseMayBegin or PhaseBegan events while in the
- // Inactive or MomentumAnimated states, but in case we get bad input (e.g,
- // abbreviated by tab-switch), always re-set the state to ActiveScrolling
- // when those events are received.
- if (wheel_event.phase == blink::WebMouseWheelEvent::PhaseMayBegin ||
- wheel_event.phase == blink::WebMouseWheelEvent::PhaseBegan) {
- scroll_velocity = gfx::Vector2dF();
- last_scroll_event_timestamp_ = base::TimeTicks();
- state_ = kStateActiveScroll;
- pending_overscroll_delta_ = gfx::Vector2dF();
- return;
- }
-
- gfx::Vector2dF event_delta(-wheel_event.deltaX, -wheel_event.deltaY);
- base::TimeTicks event_timestamp =
- base::TimeTicks() +
- base::TimeDelta::FromSecondsD(wheel_event.timeStampSeconds);
- switch (state_) {
- case kStateInactive: {
- // The PhaseMayBegin and PhaseBegan cases are handled at the top of the
- // function.
- if (wheel_event.momentumPhase == blink::WebMouseWheelEvent::PhaseBegan)
- state_ = kStateMomentumScroll;
- break;
- }
- case kStateActiveScroll:
- if (wheel_event.phase == blink::WebMouseWheelEvent::PhaseChanged) {
- UpdateVelocity(event_delta, event_timestamp);
- Overscroll(event_delta, scroll_result.unused_scroll_delta);
- } else if (wheel_event.phase == blink::WebMouseWheelEvent::PhaseEnded ||
- wheel_event.phase ==
- blink::WebMouseWheelEvent::PhaseCancelled) {
- if (helper_->StretchAmount().IsZero()) {
- EnterStateInactive();
- } else {
- EnterStateMomentumAnimated(event_timestamp);
- }
- }
- break;
- case kStateMomentumScroll:
- if (wheel_event.momentumPhase ==
- blink::WebMouseWheelEvent::PhaseChanged) {
- UpdateVelocity(event_delta, event_timestamp);
- Overscroll(event_delta, scroll_result.unused_scroll_delta);
- if (!helper_->StretchAmount().IsZero()) {
- EnterStateMomentumAnimated(event_timestamp);
- }
- } else if (wheel_event.momentumPhase ==
- blink::WebMouseWheelEvent::PhaseEnded) {
- EnterStateInactive();
- }
- case kStateMomentumAnimated:
- // The PhaseMayBegin and PhaseBegan cases are handled at the top of the
- // function.
- break;
- }
-}
-
-void InputScrollElasticityController::UpdateVelocity(
- const gfx::Vector2dF& event_delta,
- const base::TimeTicks& event_timestamp) {
- float time_delta =
- (event_timestamp - last_scroll_event_timestamp_).InSecondsF();
- if (time_delta < kScrollVelocityZeroingTimeout && time_delta > 0) {
- scroll_velocity = gfx::Vector2dF(event_delta.x() / time_delta,
- event_delta.y() / time_delta);
- } else {
- scroll_velocity = gfx::Vector2dF();
- }
- last_scroll_event_timestamp_ = event_timestamp;
-}
-
-void InputScrollElasticityController::Overscroll(
- const gfx::Vector2dF& input_delta,
- const gfx::Vector2dF& overscroll_delta) {
- // The effect can be dynamically disabled by setting disallowing user
- // scrolling. When disabled, disallow active or momentum overscrolling, but
- // allow any current overscroll to animate back.
- if (!helper_->IsUserScrollable())
- return;
-
- gfx::Vector2dF adjusted_overscroll_delta =
- pending_overscroll_delta_ + overscroll_delta;
- pending_overscroll_delta_ = gfx::Vector2dF();
-
- // Only allow one direction to overscroll at a time, and slightly prefer
- // scrolling vertically by applying the equal case to delta_y.
- if (fabsf(input_delta.y()) >= fabsf(input_delta.x()))
- adjusted_overscroll_delta.set_x(0);
- else
- adjusted_overscroll_delta.set_y(0);
-
- // Don't allow overscrolling in a direction where scrolling is possible.
- if (!PinnedHorizontally(adjusted_overscroll_delta.x()))
- adjusted_overscroll_delta.set_x(0);
- if (!PinnedVertically(adjusted_overscroll_delta.y())) {
- adjusted_overscroll_delta.set_y(0);
- }
-
- // Require a minimum of 10 units of overscroll before starting the rubber-band
- // stretch effect, so that small stray motions don't trigger it. If that
- // minimum isn't met, save what remains in |pending_overscroll_delta_| for
- // the next event.
- gfx::Vector2dF old_stretch_amount = helper_->StretchAmount();
- gfx::Vector2dF stretch_scroll_force_delta;
- if (old_stretch_amount.x() != 0 ||
- fabsf(adjusted_overscroll_delta.x()) >=
- kRubberbandMinimumRequiredDeltaBeforeStretch) {
- stretch_scroll_force_delta.set_x(adjusted_overscroll_delta.x());
- } else {
- pending_overscroll_delta_.set_x(adjusted_overscroll_delta.x());
- }
- if (old_stretch_amount.y() != 0 ||
- fabsf(adjusted_overscroll_delta.y()) >=
- kRubberbandMinimumRequiredDeltaBeforeStretch) {
- stretch_scroll_force_delta.set_y(adjusted_overscroll_delta.y());
- } else {
- pending_overscroll_delta_.set_y(adjusted_overscroll_delta.y());
- }
-
- // Update the stretch amount according to the spring equations.
- if (stretch_scroll_force_delta.IsZero())
- return;
- stretch_scroll_force_ += stretch_scroll_force_delta;
- gfx::Vector2dF new_stretch_amount =
- StretchAmountForReboundDelta(stretch_scroll_force_);
- helper_->SetStretchAmount(new_stretch_amount);
-}
-
-void InputScrollElasticityController::EnterStateInactive() {
- DCHECK_NE(kStateInactive, state_);
- DCHECK(helper_->StretchAmount().IsZero());
- state_ = kStateInactive;
- stretch_scroll_force_ = gfx::Vector2dF();
-}
-
-void InputScrollElasticityController::EnterStateMomentumAnimated(
- const base::TimeTicks& triggering_event_timestamp) {
- DCHECK_NE(kStateMomentumAnimated, state_);
- state_ = kStateMomentumAnimated;
-
- momentum_animation_start_time_ = triggering_event_timestamp;
- momentum_animation_initial_stretch_ = helper_->StretchAmount();
- momentum_animation_initial_velocity_ = scroll_velocity;
- momentum_animation_reset_at_next_frame_ = false;
-
- // Similarly to the logic in Overscroll, prefer vertical scrolling to
- // horizontal scrolling.
- if (fabsf(momentum_animation_initial_velocity_.y()) >=
- fabsf(momentum_animation_initial_velocity_.x()))
- momentum_animation_initial_velocity_.set_x(0);
-
- if (!CanScrollHorizontally())
- momentum_animation_initial_velocity_.set_x(0);
-
- if (!CanScrollVertically())
- momentum_animation_initial_velocity_.set_y(0);
-
- helper_->RequestAnimate();
-}
-
-void InputScrollElasticityController::Animate(base::TimeTicks time) {
- if (state_ != kStateMomentumAnimated)
- return;
-
- if (momentum_animation_reset_at_next_frame_) {
- momentum_animation_start_time_ = time;
- momentum_animation_initial_stretch_ = helper_->StretchAmount();
- momentum_animation_initial_velocity_ = gfx::Vector2dF();
- momentum_animation_reset_at_next_frame_ = false;
- }
-
- float time_delta =
- std::max((time - momentum_animation_start_time_).InSecondsF(), 0.0);
-
- gfx::Vector2dF old_stretch_amount = helper_->StretchAmount();
- gfx::Vector2dF new_stretch_amount = StretchAmountForTimeDelta(
- momentum_animation_initial_stretch_, momentum_animation_initial_velocity_,
- time_delta);
- gfx::Vector2dF stretch_delta = new_stretch_amount - old_stretch_amount;
-
- // If the new stretch amount is near zero, set it directly to zero and enter
- // the inactive state.
- if (fabs(new_stretch_amount.x()) < 1 && fabs(new_stretch_amount.y()) < 1) {
- helper_->SetStretchAmount(gfx::Vector2dF());
- EnterStateInactive();
- return;
- }
-
- // If we are not pinned in the direction of the delta, then the delta is only
- // allowed to decrease the existing stretch -- it cannot increase a stretch
- // until it is pinned.
- if (!PinnedHorizontally(stretch_delta.x())) {
- if (stretch_delta.x() > 0 && old_stretch_amount.x() < 0)
- stretch_delta.set_x(std::min(stretch_delta.x(), -old_stretch_amount.x()));
- else if (stretch_delta.x() < 0 && old_stretch_amount.x() > 0)
- stretch_delta.set_x(std::max(stretch_delta.x(), -old_stretch_amount.x()));
- else
- stretch_delta.set_x(0);
- }
- if (!PinnedVertically(stretch_delta.y())) {
- if (stretch_delta.y() > 0 && old_stretch_amount.y() < 0)
- stretch_delta.set_y(std::min(stretch_delta.y(), -old_stretch_amount.y()));
- else if (stretch_delta.y() < 0 && old_stretch_amount.y() > 0)
- stretch_delta.set_y(std::max(stretch_delta.y(), -old_stretch_amount.y()));
- else
- stretch_delta.set_y(0);
- }
- new_stretch_amount = old_stretch_amount + stretch_delta;
-
- stretch_scroll_force_ =
- StretchScrollForceForStretchAmount(new_stretch_amount);
- helper_->SetStretchAmount(new_stretch_amount);
- helper_->RequestAnimate();
-}
-
-bool InputScrollElasticityController::PinnedHorizontally(
- float direction) const {
- gfx::ScrollOffset scroll_offset = helper_->ScrollOffset();
- gfx::ScrollOffset max_scroll_offset = helper_->MaxScrollOffset();
- if (direction < 0)
- return scroll_offset.x() <= 0;
- if (direction > 0)
- return scroll_offset.x() >= max_scroll_offset.x();
- return false;
-}
-
-bool InputScrollElasticityController::PinnedVertically(float direction) const {
- gfx::ScrollOffset scroll_offset = helper_->ScrollOffset();
- gfx::ScrollOffset max_scroll_offset = helper_->MaxScrollOffset();
- if (direction < 0)
- return scroll_offset.y() <= 0;
- if (direction > 0)
- return scroll_offset.y() >= max_scroll_offset.y();
- return false;
-}
-
-bool InputScrollElasticityController::CanScrollHorizontally() const {
- return helper_->MaxScrollOffset().x() > 0;
-}
-
-bool InputScrollElasticityController::CanScrollVertically() const {
- return helper_->MaxScrollOffset().y() > 0;
-}
-
-void InputScrollElasticityController::ReconcileStretchAndScroll() {
- gfx::Vector2dF stretch = helper_->StretchAmount();
- if (stretch.IsZero())
- return;
-
- gfx::ScrollOffset scroll_offset = helper_->ScrollOffset();
- gfx::ScrollOffset max_scroll_offset = helper_->MaxScrollOffset();
-
- // Compute stretch_adjustment which will be added to |stretch| and subtracted
- // from the |scroll_offset|.
- gfx::Vector2dF stretch_adjustment;
- if (stretch.x() < 0 && scroll_offset.x() > 0) {
- stretch_adjustment.set_x(
- std::min(-stretch.x(), static_cast<float>(scroll_offset.x())));
- }
- if (stretch.x() > 0 && scroll_offset.x() < max_scroll_offset.x()) {
- stretch_adjustment.set_x(std::max(
- -stretch.x(),
- static_cast<float>(scroll_offset.x() - max_scroll_offset.x())));
- }
- if (stretch.y() < 0 && scroll_offset.y() > 0) {
- stretch_adjustment.set_y(
- std::min(-stretch.y(), static_cast<float>(scroll_offset.y())));
- }
- if (stretch.y() > 0 && scroll_offset.y() < max_scroll_offset.y()) {
- stretch_adjustment.set_y(std::max(
- -stretch.y(),
- static_cast<float>(scroll_offset.y() - max_scroll_offset.y())));
- }
-
- if (stretch_adjustment.IsZero())
- return;
-
- gfx::Vector2dF new_stretch_amount = stretch + stretch_adjustment;
- helper_->ScrollBy(-stretch_adjustment);
- helper_->SetStretchAmount(new_stretch_amount);
-
- // Update the internal state for the active scroll or animation to avoid
- // discontinuities.
- switch (state_) {
- case kStateActiveScroll:
- stretch_scroll_force_ =
- StretchScrollForceForStretchAmount(new_stretch_amount);
- break;
- case kStateMomentumAnimated:
- momentum_animation_reset_at_next_frame_ = true;
- break;
- default:
- // These cases should not be hit because the stretch must be zero in the
- // Inactive and MomentumScroll states.
- NOTREACHED();
- break;
- }
-}
-
-} // namespace content

Powered by Google App Engine
This is Rietveld 408576698