1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_ 6 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_ 7 8 #include "base/macros.h" 9 #include "cc/input/overscroll_behavior.h" 10 #include "cc/input/scroll_elasticity_helper.h" 11 #include "third_party/blink/public/common/input/web_gesture_event.h" 12 #include "third_party/blink/public/common/input/web_input_event.h" 13 #include "third_party/blink/renderer/platform/platform_export.h" 14 15 /* 16 * Copyright (C) 2011 Apple Inc. All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * 27 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 29 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 37 * THE POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 namespace cc { 41 struct InputHandlerScrollResult; 42 } // namespace cc 43 44 namespace blink { 45 // This serves as a base class for handling overscroll. Most of the basic 46 // overscroll functionality is contained in this class. The customization 47 // details like the stretch distance, the bounce animations etc will be 48 // implemented by the subclasses. 49 class PLATFORM_EXPORT ElasticOverscrollController { 50 public: 51 explicit ElasticOverscrollController(cc::ScrollElasticityHelper* helper); 52 virtual ~ElasticOverscrollController() = default; 53 54 // These methods that are "real" should only be called if the associated event 55 // is not a synthetic phase change, e.g. generated by the MouseWheelEventQueue 56 // or FlingController. Otherwise, calling them will disrupt elastic scrolling. 57 void ObserveRealScrollBegin(bool enter_momentum, bool leave_momentum); 58 void ObserveScrollUpdate(const gfx::Vector2dF& event_delta, 59 const gfx::Vector2dF& unused_scroll_delta, 60 const base::TimeTicks& event_timestamp, 61 const cc::OverscrollBehavior overscroll_behavior, 62 bool has_momentum); 63 void ObserveRealScrollEnd(const base::TimeTicks event_timestamp); 64 65 // Update the overscroll state based a gesture event that has been processed. 66 // Note that this assumes that all events are coming from a single input 67 // device. If the user simultaneously uses multiple input devices, Cocoa may 68 // not correctly pass all the gesture begin and end events. In this case, 69 // this class may disregard some scrolls that come in at unexpected times. 70 void ObserveGestureEventAndResult( 71 const blink::WebGestureEvent& gesture_event, 72 const cc::InputHandlerScrollResult& scroll_result); 73 74 void Animate(base::TimeTicks time); 75 void ReconcileStretchAndScroll(); 76 static std::unique_ptr<ElasticOverscrollController> Create( 77 cc::ScrollElasticityHelper* helper); 78 79 protected: 80 virtual void DidEnterMomentumAnimatedState() = 0; 81 82 // The parameter "delta" is the difference between the time "Animate" is 83 // called and momentum_animation_start_time_. Using this information, the 84 // stretch amount for a scroller is determined. This is how the bounce 85 // animation basically "ticks". 86 virtual gfx::Vector2d StretchAmountForTimeDelta( 87 const base::TimeDelta& delta) const = 0; 88 89 // Maps the distance the user has scrolled past the boundary into the distance 90 // to actually scroll the elastic scroller. 91 virtual gfx::Vector2d StretchAmountForAccumulatedOverscroll( 92 const gfx::Vector2dF& accumulated_overscroll) const = 0; 93 94 // Does the inverse of StretchAmountForAccumulatedOverscroll. As in, takes in 95 // the bounce distance and calculates how much is actually overscrolled. 96 virtual gfx::Vector2d AccumulatedOverscrollForStretchAmount( 97 const gfx::Vector2dF& stretch_amount) const = 0; 98 scroll_bounds()99 gfx::Size scroll_bounds() const { return helper_->ScrollBounds(); } scroll_velocity()100 gfx::Vector2dF scroll_velocity() const { return scroll_velocity_; } 101 102 // TODO (arakeri): Need to be cleared when we leave MomentumAnimated. 103 // Momentum animation state. This state is valid only while the state is 104 // MomentumAnimated, and is initialized in EnterStateMomentumAnimated. 105 gfx::Vector2dF momentum_animation_initial_stretch_; 106 gfx::Vector2dF momentum_animation_initial_velocity_; 107 108 private: 109 FRIEND_TEST_ALL_PREFIXES(ElasticOverscrollControllerBezierTest, 110 VerifyBackwardAnimationTick); 111 FRIEND_TEST_ALL_PREFIXES(ElasticOverscrollControllerBezierTest, 112 VerifyForwardAnimationTick); 113 FRIEND_TEST_ALL_PREFIXES(ElasticOverscrollControllerBezierTest, 114 VerifyForwardAnimationIsNotPlayed); 115 FRIEND_TEST_ALL_PREFIXES(ElasticOverscrollControllerBezierTest, 116 VerifyInitialStretchDelta); 117 118 enum State { 119 // The initial state, during which the overscroll amount is zero and 120 // there are no active or momentum scroll events coming in. This state 121 // is briefly returned to between the active and momentum phases of a 122 // scroll (if there is no overscroll). 123 kStateInactive, 124 // The state between receiving PhaseBegan/MayBegin and PhaseEnd/Cancelled, 125 // corresponding to the period during which the user has fingers on the 126 // trackpad. The overscroll amount is updated as input events are received. 127 // When PhaseEnd is received, the state transitions to Inactive if there is 128 // no overscroll and MomentumAnimated if there is non-zero overscroll. 129 kStateActiveScroll, 130 // The state between receiving a momentum PhaseBegan and PhaseEnd, while 131 // there is no overscroll. The overscroll amount is updated as input events 132 // are received. If the overscroll is ever non-zero then the state 133 // immediately transitions to kStateMomentumAnimated. 134 kStateMomentumScroll, 135 // The state while the overscroll amount is updated by an animation. If 136 // the user places fingers on the trackpad (a PhaseMayBegin is received) 137 // then the state transition to kStateActiveScroll. Otherwise the state 138 // transitions to Inactive when the overscroll amount becomes zero. 139 kStateMomentumAnimated, 140 }; 141 142 void UpdateVelocity(const gfx::Vector2dF& event_delta, 143 const base::TimeTicks& event_timestamp); 144 void Overscroll(const gfx::Vector2dF& overscroll_delta); 145 void EnterStateMomentumAnimated( 146 const base::TimeTicks& triggering_event_timestamp); 147 void EnterStateInactive(); 148 149 // Returns true if |direction| is pointing in a direction in which it is not 150 // possible to scroll any farther horizontally (or vertically). It is only in 151 // this circumstance that an overscroll in that direction may begin. 152 bool PinnedHorizontally(float direction) const; 153 bool PinnedVertically(float direction) const; 154 155 // Whether or not the content of the page is scrollable horizontaly (or 156 // vertically). 157 bool CanScrollHorizontally() const; 158 bool CanScrollVertically() const; 159 160 base::TimeTicks momentum_animation_start_time_; 161 cc::ScrollElasticityHelper* helper_; 162 State state_; 163 164 // If there is no overscroll, require a minimum overscroll delta before 165 // starting the rubber-band effect. Track the amount of scrolling that has 166 // has occurred but has not yet caused rubber-band stretching in 167 // |pending_overscroll_delta_|. 168 gfx::Vector2dF pending_overscroll_delta_; 169 170 // Maintain a calculation of the velocity of the scroll, based on the input 171 // scroll delta divide by the time between input events. Track this velocity 172 // in |scroll_velocity| and the previous input event timestamp for finite 173 // differencing in |last_scroll_event_timestamp_|. 174 gfx::Vector2dF scroll_velocity_; 175 base::TimeTicks last_scroll_event_timestamp_; 176 177 // The force of the rubber-band spring. This is equal to the cumulative sum 178 // of all overscroll offsets since entering a non-Inactive state. This is 179 // reset to zero only when entering the Inactive state. 180 gfx::Vector2dF stretch_scroll_force_; 181 182 bool received_overscroll_update_; 183 cc::OverscrollBehavior overscroll_behavior_; 184 }; 185 186 } // namespace blink 187 188 #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_INPUT_ELASTIC_OVERSCROLL_CONTROLLER_H_ 189