blob: 3e96465b2e2c0a23232303a92e6ebbb2437368eb [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2012 The Chromium Authors
[email protected]b4df9df2012-11-16 01:58:582// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_RENDERER_HOST_OVERSCROLL_CONTROLLER_H_
6#define CONTENT_BROWSER_RENDERER_HOST_OVERSCROLL_CONTROLLER_H_
7
Arthur Sonzognic686e8f2024-01-11 08:36:378#include <optional>
9
Daniel Cheng224569ee2018-04-25 05:45:0610#include "base/time/time.h"
Mohsen Izadi80189412018-03-22 17:10:1811#include "cc/input/overscroll_behavior.h"
mcnee19fd2492017-06-01 14:42:4312#include "content/common/content_export.h"
Dave Tapuska129cef82019-12-19 16:36:4813#include "third_party/blink/public/common/input/web_gesture_event.h"
14#include "third_party/blink/public/common/input/web_input_event.h"
Sandra Suncbd6da42018-01-05 15:29:3615#include "ui/events/blink/did_overscroll_params.h"
[email protected]b4df9df2012-11-16 01:58:5816
17namespace content {
18
[email protected]b4df9df2012-11-16 01:58:5819class OverscrollControllerDelegate;
Mohsen Izadi9830436c2017-12-21 18:02:4620class OverscrollControllerTest;
21class RenderWidgetHostViewAuraOverscrollTest;
[email protected]b4df9df2012-11-16 01:58:5822
[email protected]888878e82013-07-24 22:49:4023// Indicates the direction that the scroll is heading in relative to the screen,
24// with the top being NORTH.
[email protected]b4df9df2012-11-16 01:58:5825enum OverscrollMode {
26 OVERSCROLL_NONE,
27 OVERSCROLL_NORTH,
28 OVERSCROLL_SOUTH,
29 OVERSCROLL_WEST,
mfomitchev27e68f6e2015-04-14 15:18:1430 OVERSCROLL_EAST
[email protected]b4df9df2012-11-16 01:58:5831};
32
mfomitchev09f0d64a2017-03-02 19:40:0733// Indicates the source device that was used to trigger the overscroll gesture.
34enum class OverscrollSource {
35 NONE,
36 TOUCHPAD,
37 TOUCHSCREEN,
38};
39
[email protected]b4df9df2012-11-16 01:58:5840// When a page is scrolled beyond the scrollable region, it will trigger an
41// overscroll gesture. This controller receives the events that are dispatched
42// to the renderer, and the ACKs of events, and updates the overscroll gesture
43// status accordingly.
Mohsen Izadi9830436c2017-12-21 18:02:4644// Exported for testing.
Jose Dapena Pazdb116c02017-11-28 15:58:2145class CONTENT_EXPORT OverscrollController {
[email protected]b4df9df2012-11-16 01:58:5846 public:
Jose Dapena Pazdb116c02017-11-28 15:58:2147 OverscrollController();
Peter Boström828b9022021-09-21 02:28:4348
49 OverscrollController(const OverscrollController&) = delete;
50 OverscrollController& operator=(const OverscrollController&) = delete;
51
Jose Dapena Pazdb116c02017-11-28 15:58:2152 virtual ~OverscrollController();
[email protected]b4df9df2012-11-16 01:58:5853
54 // This must be called when dispatching any event from the
55 // RenderWidgetHostView so that the state of the overscroll gesture can be
[email protected]277857a2014-06-03 10:38:0156 // updated properly. Returns true if the event was handled, in which case
57 // further processing should cease.
58 bool WillHandleEvent(const blink::WebInputEvent& event);
[email protected]b4df9df2012-11-16 01:58:5859
Sandra Suncbd6da42018-01-05 15:29:3660 // This is called whenever an overscroll event is generated on the renderer
61 // side. This is called before ReceivedEventAck. The params contains an
62 // OverscrollBehavior that can prevent overscroll navigation.
63 void OnDidOverscroll(const ui::DidOverscrollParams& params);
64
[email protected]b4df9df2012-11-16 01:58:5865 // This must be called when the ACK for any event comes in. This updates the
66 // overscroll gesture status as appropriate.
Kevin McNee2b9fb072019-12-04 00:36:2367 void ReceivedEventACK(const blink::WebInputEvent& event, bool processed);
[email protected]b4df9df2012-11-16 01:58:5868
69 OverscrollMode overscroll_mode() const { return overscroll_mode_; }
70
Robert Flackc3670192021-03-30 16:18:0971 void set_delegate(base::WeakPtr<OverscrollControllerDelegate> delegate) {
[email protected]b4df9df2012-11-16 01:58:5872 delegate_ = delegate;
73 }
74
75 // Resets internal states.
76 void Reset();
77
[email protected]63ad73832013-06-17 15:41:0478 // Cancels any in-progress overscroll (and calls OnOverscrollModeChange on the
79 // delegate if necessary), and resets internal states.
80 void Cancel();
81
[email protected]b4df9df2012-11-16 01:58:5882 private:
Mohsen Izadi9830436c2017-12-21 18:02:4683 friend class OverscrollControllerTest;
[email protected]277857a2014-06-03 10:38:0184 friend class RenderWidgetHostViewAuraOverscrollTest;
[email protected]b4df9df2012-11-16 01:58:5885
[email protected]a4141642013-05-23 04:10:5886 // Different scrolling states.
Mohsen Izadi9830436c2017-12-21 18:02:4687 enum class ScrollState {
88 NONE,
89
90 // Either a mouse-wheel or a gesture-scroll-update event is consumed by the
91 // renderer in which case no overscroll should be initiated until the end of
92 // the user interaction.
93 CONTENT_CONSUMING,
94
95 // Overscroll controller has initiated overscrolling and will consume all
96 // subsequent gesture-scroll-update events, preventing them from being
97 // forwarded to the renderer.
98 OVERSCROLLING,
[email protected]a4141642013-05-23 04:10:5899 };
100
[email protected]b4df9df2012-11-16 01:58:58101 // Returns true if the event indicates that the in-progress overscroll gesture
102 // can now be completed.
chaopeng1d469b02018-04-05 15:41:07103 bool DispatchEventCompletesAction(const blink::WebInputEvent& event) const;
[email protected]b4df9df2012-11-16 01:58:58104
105 // Returns true to indicate that dispatching the event should reset the
106 // overscroll gesture status.
[email protected]180ef242013-11-07 06:50:46107 bool DispatchEventResetsState(const blink::WebInputEvent& event) const;
[email protected]b4df9df2012-11-16 01:58:58108
[email protected]2422e5c2013-09-13 19:05:02109 // Processes an event to update the internal state for overscroll. Returns
110 // true if the state is updated, false otherwise.
[email protected]180ef242013-11-07 06:50:46111 bool ProcessEventForOverscroll(const blink::WebInputEvent& event);
[email protected]b4df9df2012-11-16 01:58:58112
113 // Processes horizontal overscroll. This can update both the overscroll mode
114 // and the over scroll amount (i.e. |overscroll_mode_|, |overscroll_delta_x_|
[email protected]bfab3d02014-08-20 03:16:55115 // and |overscroll_delta_y_|). Returns true if overscroll was handled by the
116 // delegate.
chaopeng9736c522018-05-08 18:32:27117 bool ProcessOverscroll(float delta_x,
118 float delta_y,
119 bool is_touchpad,
120 bool is_inertial);
[email protected]b4df9df2012-11-16 01:58:58121
122 // Completes the desired action from the current gesture.
123 void CompleteAction();
124
mfomitchev09f0d64a2017-03-02 19:40:07125 // Sets the overscroll mode and triggers callback in the delegate when
126 // appropriate. When a new overscroll is started (i.e. when |new_mode| is not
127 // equal to OVERSCROLL_NONE), |source| will be set to the device that
128 // triggered the overscroll gesture.
129 void SetOverscrollMode(OverscrollMode new_mode, OverscrollSource source);
[email protected]b4df9df2012-11-16 01:58:58130
chaopenga7585d792018-04-10 18:02:38131 // Whether this inertial event should be filtered out by the controller.
132 bool ShouldIgnoreInertialEvent(const blink::WebInputEvent& event) const;
133
dtapuska19ebfa512016-02-19 22:27:40134 // Whether this event should be processed or not handled by the controller.
135 bool ShouldProcessEvent(const blink::WebInputEvent& event);
136
Mohsen Izadi50180f392017-09-08 19:29:12137 // Helper function to reset |scroll_state_| and |locked_mode_|.
138 void ResetScrollState();
139
Mohsen Izadi80189412018-03-22 17:10:18140 // Current value of overscroll-behavior CSS property for the root element of
141 // the page.
142 cc::OverscrollBehavior behavior_;
143
[email protected]b4df9df2012-11-16 01:58:58144 // The current state of overscroll gesture.
Mohsen Izadi38795d5d2017-06-30 17:10:48145 OverscrollMode overscroll_mode_ = OVERSCROLL_NONE;
146
Mohsen Izadif589f4b2017-08-24 02:55:48147 // When set to something other than OVERSCROLL_NONE, the overscroll cannot
148 // switch to any other mode, except to OVERSCROLL_NONE. This is set when an
149 // overscroll is started until the touch sequence is completed.
150 OverscrollMode locked_mode_ = OVERSCROLL_NONE;
151
Mohsen Izadi38795d5d2017-06-30 17:10:48152 // Source of the current overscroll gesture.
153 OverscrollSource overscroll_source_ = OverscrollSource::NONE;
[email protected]b4df9df2012-11-16 01:58:58154
Mohsen Izadi9830436c2017-12-21 18:02:46155 // Current scrolling state.
156 ScrollState scroll_state_ = ScrollState::NONE;
[email protected]a4141642013-05-23 04:10:58157
[email protected]b4df9df2012-11-16 01:58:58158 // The amount of overscroll in progress. These values are invalid when
159 // |overscroll_mode_| is set to OVERSCROLL_NONE.
Mohsen Izadi38795d5d2017-06-30 17:10:48160 float overscroll_delta_x_ = 0.f;
161 float overscroll_delta_y_ = 0.f;
[email protected]b4df9df2012-11-16 01:58:58162
163 // The delegate that receives the overscroll updates. The delegate is not
164 // owned by this controller.
Robert Flackc3670192021-03-30 16:18:09165 base::WeakPtr<OverscrollControllerDelegate> delegate_;
[email protected]b4df9df2012-11-16 01:58:58166
chaopeng1d469b02018-04-05 15:41:07167 // A inertial scroll (fling) event may complete an overscroll gesture and
chaopeng9736c522018-05-08 18:32:27168 // navigate to a new page or cancel the overscroll animation. In both cases
169 // inertial scroll can continue to generate scroll-update events. These events
170 // need to be ignored.
chaopeng1d469b02018-04-05 15:41:07171 bool ignore_following_inertial_events_ = false;
172
Mohsen Izadi5a6583512018-04-23 18:31:19173 // Specifies whether last overscroll was ignored, either due to a command line
174 // flag or because cool off period had not passed.
175 bool overscroll_ignored_ = false;
176
Daniel Cheng224569ee2018-04-25 05:45:06177 // Timestamp for the end of the last ignored scroll sequence.
178 base::TimeTicks last_ignored_scroll_time_;
Mohsen Izadi5a6583512018-04-23 18:31:19179
180 // Time between the end of the last ignored scroll sequence and the beginning
Daniel Cheng224569ee2018-04-25 05:45:06181 // of the current one.
182 base::TimeDelta time_since_last_ignored_scroll_;
Mohsen Izadi5a6583512018-04-23 18:31:19183
chaopeng9736c522018-05-08 18:32:27184 // On Windows, we don't generate the inertial events (fling) but receive them
185 // from Win API. In some cases, we get a long tail of inertial events for a
186 // couple of seconds. The overscroll animation feels like stuck in these
187 // cases. So we only process 0.3 second inertial events then cancel the
188 // overscroll if it is not completed yet.
189 // Timestamp for the first inertial event (fling) in current stream.
Arthur Sonzognic686e8f2024-01-11 08:36:37190 std::optional<base::TimeTicks> first_inertial_event_time_;
[email protected]b4df9df2012-11-16 01:58:58191};
192
193} // namespace content
194
195#endif // CONTENT_BROWSER_RENDERER_HOST_OVERSCROLL_CONTROLLER_H_