blob: 7f32ae0fcf1125a0eff83282e1a2a443dd73578c [file] [log] [blame]
[email protected]b4df9df2012-11-16 01:58:581// Copyright (c) 2012 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#include "content/browser/renderer_host/overscroll_controller.h"
6
[email protected]3aad43b2013-11-05 20:20:187#include "base/command_line.h"
[email protected]fc4b06d02013-10-23 20:47:118#include "base/logging.h"
[email protected]b4df9df2012-11-16 01:58:589#include "content/browser/renderer_host/overscroll_controller_delegate.h"
[email protected]1cd76c2d82012-11-29 07:36:4710#include "content/public/browser/overscroll_configuration.h"
[email protected]3aad43b2013-11-05 20:20:1811#include "content/public/common/content_switches.h"
dtapuska234bb4512016-12-19 21:46:1812#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
[email protected]b4df9df2012-11-16 01:58:5813
[email protected]180ef242013-11-07 06:50:4614using blink::WebInputEvent;
[email protected]a7f99f02013-08-29 14:15:1915
[email protected]3aad43b2013-11-05 20:20:1816namespace {
17
18bool IsScrollEndEffectEnabled() {
[email protected]479278702014-08-11 20:32:0919 return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
[email protected]3aad43b2013-11-05 20:20:1820 switches::kScrollEndEffect) == "1";
21}
22
dtapuska19ebfa512016-02-19 22:27:4023bool IsGestureEventFromTouchpad(const blink::WebInputEvent& event) {
Blink Reformat1c4d759e2017-04-09 16:34:5424 DCHECK(blink::WebInputEvent::IsGestureEventType(event.GetType()));
dtapuska19ebfa512016-02-19 22:27:4025 const blink::WebGestureEvent& gesture =
26 static_cast<const blink::WebGestureEvent&>(event);
Blink Reformat1c4d759e2017-04-09 16:34:5427 return gesture.source_device == blink::kWebGestureDeviceTouchpad;
dtapuska19ebfa512016-02-19 22:27:4028}
29
[email protected]3aad43b2013-11-05 20:20:1830} // namespace
31
[email protected]b4df9df2012-11-16 01:58:5832namespace content {
33
[email protected]fc4b06d02013-10-23 20:47:1134OverscrollController::OverscrollController()
35 : overscroll_mode_(OVERSCROLL_NONE),
[email protected]a4141642013-05-23 04:10:5836 scroll_state_(STATE_UNKNOWN),
[email protected]b4df9df2012-11-16 01:58:5837 overscroll_delta_x_(0.f),
38 overscroll_delta_y_(0.f),
dtapuskae7dd21de2016-06-09 13:41:5639 delegate_(NULL) {}
[email protected]b4df9df2012-11-16 01:58:5840
41OverscrollController::~OverscrollController() {
42}
43
dtapuska19ebfa512016-02-19 22:27:4044bool OverscrollController::ShouldProcessEvent(
45 const blink::WebInputEvent& event) {
Blink Reformat1c4d759e2017-04-09 16:34:5446 switch (event.GetType()) {
47 case blink::WebInputEvent::kMouseWheel:
dtapuska8c4dae12017-01-13 00:23:0648 return false;
Blink Reformat1c4d759e2017-04-09 16:34:5449 case blink::WebInputEvent::kGestureScrollBegin:
50 case blink::WebInputEvent::kGestureScrollUpdate:
51 case blink::WebInputEvent::kGestureScrollEnd: {
dtapuska8c4dae12017-01-13 00:23:0652 const blink::WebGestureEvent& gesture =
53 static_cast<const blink::WebGestureEvent&>(event);
mcnee19fd2492017-06-01 14:42:4354
55 // GestureScrollBegin and GestureScrollEnd events are created to wrap
56 // individual resent GestureScrollUpdates from a plugin. Hence these
57 // should not be used to indicate the beginning/end of the overscroll.
58 // TODO(mcnee): When we remove BrowserPlugin, delete this code.
59 // See crbug.com/533069
60 if (gesture.resending_plugin_id != -1 &&
61 event.GetType() != blink::WebInputEvent::kGestureScrollUpdate)
62 return false;
63
dtapuska8c4dae12017-01-13 00:23:0664 blink::WebGestureEvent::ScrollUnits scrollUnits;
Blink Reformat1c4d759e2017-04-09 16:34:5465 switch (event.GetType()) {
66 case blink::WebInputEvent::kGestureScrollBegin:
67 scrollUnits = gesture.data.scroll_begin.delta_hint_units;
dtapuska8c4dae12017-01-13 00:23:0668 break;
Blink Reformat1c4d759e2017-04-09 16:34:5469 case blink::WebInputEvent::kGestureScrollUpdate:
70 scrollUnits = gesture.data.scroll_update.delta_units;
dtapuska8c4dae12017-01-13 00:23:0671 break;
Blink Reformat1c4d759e2017-04-09 16:34:5472 case blink::WebInputEvent::kGestureScrollEnd:
73 scrollUnits = gesture.data.scroll_end.delta_units;
dtapuska8c4dae12017-01-13 00:23:0674 break;
75 default:
Blink Reformat1c4d759e2017-04-09 16:34:5476 scrollUnits = blink::WebGestureEvent::kPixels;
dtapuska8c4dae12017-01-13 00:23:0677 break;
dtapuska19ebfa512016-02-19 22:27:4078 }
dtapuska8c4dae12017-01-13 00:23:0679
Blink Reformat1c4d759e2017-04-09 16:34:5480 return scrollUnits == blink::WebGestureEvent::kPrecisePixels;
dtapuska19ebfa512016-02-19 22:27:4081 }
dtapuska8c4dae12017-01-13 00:23:0682 default:
83 break;
84 }
dtapuska19ebfa512016-02-19 22:27:4085 return true;
86}
87
[email protected]277857a2014-06-03 10:38:0188bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) {
dtapuska19ebfa512016-02-19 22:27:4089 if (!ShouldProcessEvent(event))
90 return false;
91
mfomitchev8a785bef2015-04-13 18:35:0592 bool reset_scroll_state = false;
93 if (scroll_state_ != STATE_UNKNOWN ||
94 overscroll_delta_x_ || overscroll_delta_y_) {
Blink Reformat1c4d759e2017-04-09 16:34:5495 switch (event.GetType()) {
96 case blink::WebInputEvent::kGestureScrollEnd:
dtapuska19ebfa512016-02-19 22:27:4097 // Avoid resetting the state on GestureScrollEnd generated
98 // from the touchpad since it is sent based on a timeout.
99 reset_scroll_state = !IsGestureEventFromTouchpad(event);
100 break;
101
Blink Reformat1c4d759e2017-04-09 16:34:54102 case blink::WebInputEvent::kGestureFlingStart:
mfomitchev8a785bef2015-04-13 18:35:05103 reset_scroll_state = true;
[email protected]b31beeb2013-06-17 15:54:27104 break;
105
Blink Reformat1c4d759e2017-04-09 16:34:54106 case blink::WebInputEvent::kMouseWheel: {
[email protected]180ef242013-11-07 06:50:46107 const blink::WebMouseWheelEvent& wheel =
108 static_cast<const blink::WebMouseWheelEvent&>(event);
Blink Reformat1c4d759e2017-04-09 16:34:54109 if (!wheel.has_precise_scrolling_deltas ||
110 wheel.phase == blink::WebMouseWheelEvent::kPhaseEnded ||
111 wheel.phase == blink::WebMouseWheelEvent::kPhaseCancelled) {
mfomitchev8a785bef2015-04-13 18:35:05112 reset_scroll_state = true;
[email protected]b31beeb2013-06-17 15:54:27113 }
114 break;
[email protected]a4141642013-05-23 04:10:58115 }
[email protected]b31beeb2013-06-17 15:54:27116
117 default:
Blink Reformat1c4d759e2017-04-09 16:34:54118 if (blink::WebInputEvent::IsMouseEventType(event.GetType()) ||
119 blink::WebInputEvent::IsKeyboardEventType(event.GetType())) {
mfomitchev8a785bef2015-04-13 18:35:05120 reset_scroll_state = true;
[email protected]b31beeb2013-06-17 15:54:27121 }
122 break;
[email protected]a4141642013-05-23 04:10:58123 }
124 }
125
mfomitchev8a785bef2015-04-13 18:35:05126 if (reset_scroll_state)
127 scroll_state_ = STATE_UNKNOWN;
128
[email protected]b4df9df2012-11-16 01:58:58129 if (DispatchEventCompletesAction(event)) {
130 CompleteAction();
[email protected]9f4f47e2012-11-20 02:21:43131
[email protected]277857a2014-06-03 10:38:01132 // Let the event be dispatched to the renderer.
133 return false;
[email protected]b4df9df2012-11-16 01:58:58134 }
135
136 if (overscroll_mode_ != OVERSCROLL_NONE && DispatchEventResetsState(event)) {
mfomitchev09f0d64a2017-03-02 19:40:07137 SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
[email protected]b4df9df2012-11-16 01:58:58138
139 // Let the event be dispatched to the renderer.
[email protected]277857a2014-06-03 10:38:01140 return false;
[email protected]b4df9df2012-11-16 01:58:58141 }
142
143 if (overscroll_mode_ != OVERSCROLL_NONE) {
[email protected]2422e5c2013-09-13 19:05:02144 // Consume the event only if it updates the overscroll state.
145 if (ProcessEventForOverscroll(event))
[email protected]277857a2014-06-03 10:38:01146 return true;
mfomitchev8a785bef2015-04-13 18:35:05147 } else if (reset_scroll_state) {
148 overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
[email protected]b4df9df2012-11-16 01:58:58149 }
150
mfomitchev8a785bef2015-04-13 18:35:05151
[email protected]277857a2014-06-03 10:38:01152 return false;
[email protected]b4df9df2012-11-16 01:58:58153}
154
[email protected]180ef242013-11-07 06:50:46155void OverscrollController::ReceivedEventACK(const blink::WebInputEvent& event,
[email protected]b4df9df2012-11-16 01:58:58156 bool processed) {
dtapuska19ebfa512016-02-19 22:27:40157 if (!ShouldProcessEvent(event))
158 return;
159
[email protected]a4141642013-05-23 04:10:58160 if (processed) {
161 // If a scroll event is consumed by the page, i.e. some content on the page
162 // has been scrolled, then there is not going to be an overscroll gesture,
163 // until the current scroll ends, and a new scroll gesture starts.
164 if (scroll_state_ == STATE_UNKNOWN &&
Blink Reformat1c4d759e2017-04-09 16:34:54165 (event.GetType() == blink::WebInputEvent::kMouseWheel ||
166 event.GetType() == blink::WebInputEvent::kGestureScrollUpdate)) {
[email protected]a4141642013-05-23 04:10:58167 scroll_state_ = STATE_CONTENT_SCROLLING;
168 }
[email protected]b4df9df2012-11-16 01:58:58169 return;
[email protected]a4141642013-05-23 04:10:58170 }
[email protected]b4df9df2012-11-16 01:58:58171 ProcessEventForOverscroll(event);
172}
173
[email protected]b31beeb2013-06-17 15:54:27174void OverscrollController::DiscardingGestureEvent(
[email protected]180ef242013-11-07 06:50:46175 const blink::WebGestureEvent& gesture) {
[email protected]b31beeb2013-06-17 15:54:27176 if (scroll_state_ != STATE_UNKNOWN &&
Blink Reformat1c4d759e2017-04-09 16:34:54177 (gesture.GetType() == blink::WebInputEvent::kGestureScrollEnd ||
178 gesture.GetType() == blink::WebInputEvent::kGestureFlingStart)) {
[email protected]b31beeb2013-06-17 15:54:27179 scroll_state_ = STATE_UNKNOWN;
180 }
181}
182
[email protected]b4df9df2012-11-16 01:58:58183void OverscrollController::Reset() {
184 overscroll_mode_ = OVERSCROLL_NONE;
185 overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
[email protected]a4141642013-05-23 04:10:58186 scroll_state_ = STATE_UNKNOWN;
[email protected]b4df9df2012-11-16 01:58:58187}
188
[email protected]63ad73832013-06-17 15:41:04189void OverscrollController::Cancel() {
mfomitchev09f0d64a2017-03-02 19:40:07190 SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
[email protected]63ad73832013-06-17 15:41:04191 overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
192 scroll_state_ = STATE_UNKNOWN;
193}
194
[email protected]b4df9df2012-11-16 01:58:58195bool OverscrollController::DispatchEventCompletesAction (
[email protected]180ef242013-11-07 06:50:46196 const blink::WebInputEvent& event) const {
[email protected]b4df9df2012-11-16 01:58:58197 if (overscroll_mode_ == OVERSCROLL_NONE)
198 return false;
199
200 // Complete the overscroll gesture if there was a mouse move or a scroll-end
201 // after the threshold.
Blink Reformat1c4d759e2017-04-09 16:34:54202 if (event.GetType() != blink::WebInputEvent::kMouseMove &&
203 event.GetType() != blink::WebInputEvent::kGestureScrollEnd &&
204 event.GetType() != blink::WebInputEvent::kGestureFlingStart)
[email protected]b4df9df2012-11-16 01:58:58205 return false;
206
dtapuska19ebfa512016-02-19 22:27:40207 // Avoid completing the action on GestureScrollEnd generated
208 // from the touchpad since it is sent based on a timeout not
209 // when the user has stopped interacting.
Blink Reformat1c4d759e2017-04-09 16:34:54210 if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd &&
dtapuska19ebfa512016-02-19 22:27:40211 IsGestureEventFromTouchpad(event))
212 return false;
213
[email protected]0da15c2d2013-10-30 16:47:20214 if (!delegate_)
215 return false;
216
[email protected]fc4b06d02013-10-23 20:47:11217 gfx::Rect bounds = delegate_->GetVisibleBounds();
[email protected]b4df9df2012-11-16 01:58:58218 if (bounds.IsEmpty())
219 return false;
220
Blink Reformat1c4d759e2017-04-09 16:34:54221 if (event.GetType() == blink::WebInputEvent::kGestureFlingStart) {
[email protected]6658c6a2013-01-23 23:42:22222 // Check to see if the fling is in the same direction of the overscroll.
[email protected]180ef242013-11-07 06:50:46223 const blink::WebGestureEvent gesture =
224 static_cast<const blink::WebGestureEvent&>(event);
[email protected]6658c6a2013-01-23 23:42:22225 switch (overscroll_mode_) {
226 case OVERSCROLL_EAST:
Blink Reformat1c4d759e2017-04-09 16:34:54227 if (gesture.data.fling_start.velocity_x < 0)
[email protected]6658c6a2013-01-23 23:42:22228 return false;
229 break;
230 case OVERSCROLL_WEST:
Blink Reformat1c4d759e2017-04-09 16:34:54231 if (gesture.data.fling_start.velocity_x > 0)
[email protected]6658c6a2013-01-23 23:42:22232 return false;
233 break;
234 case OVERSCROLL_NORTH:
Blink Reformat1c4d759e2017-04-09 16:34:54235 if (gesture.data.fling_start.velocity_y > 0)
[email protected]6658c6a2013-01-23 23:42:22236 return false;
237 break;
238 case OVERSCROLL_SOUTH:
Blink Reformat1c4d759e2017-04-09 16:34:54239 if (gesture.data.fling_start.velocity_y < 0)
[email protected]6658c6a2013-01-23 23:42:22240 return false;
241 break;
242 case OVERSCROLL_NONE:
[email protected]6658c6a2013-01-23 23:42:22243 NOTREACHED();
244 }
245 }
246
[email protected]b4df9df2012-11-16 01:58:58247 float ratio, threshold;
248 if (overscroll_mode_ == OVERSCROLL_WEST ||
[email protected]e42b1f82012-11-16 21:18:46249 overscroll_mode_ == OVERSCROLL_EAST) {
250 ratio = fabs(overscroll_delta_x_) / bounds.width();
[email protected]1cd76c2d82012-11-29 07:36:47251 threshold = GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE);
[email protected]b4df9df2012-11-16 01:58:58252 } else {
[email protected]e42b1f82012-11-16 21:18:46253 ratio = fabs(overscroll_delta_y_) / bounds.height();
[email protected]1cd76c2d82012-11-29 07:36:47254 threshold = GetOverscrollConfig(OVERSCROLL_CONFIG_VERT_THRESHOLD_COMPLETE);
[email protected]b4df9df2012-11-16 01:58:58255 }
[email protected]6658c6a2013-01-23 23:42:22256
[email protected]b4df9df2012-11-16 01:58:58257 return ratio >= threshold;
258}
259
260bool OverscrollController::DispatchEventResetsState(
[email protected]180ef242013-11-07 06:50:46261 const blink::WebInputEvent& event) const {
Blink Reformat1c4d759e2017-04-09 16:34:54262 switch (event.GetType()) {
263 case blink::WebInputEvent::kMouseWheel: {
[email protected]b16ac8202013-02-06 15:54:23264 // Only wheel events with precise deltas (i.e. from trackpad) contribute
265 // to the overscroll gesture.
[email protected]180ef242013-11-07 06:50:46266 const blink::WebMouseWheelEvent& wheel =
267 static_cast<const blink::WebMouseWheelEvent&>(event);
Blink Reformat1c4d759e2017-04-09 16:34:54268 return !wheel.has_precise_scrolling_deltas;
[email protected]b16ac8202013-02-06 15:54:23269 }
270
dtapuska19ebfa512016-02-19 22:27:40271 // Avoid resetting overscroll on GestureScrollBegin/End generated
272 // from the touchpad since it is sent based on a timeout.
Blink Reformat1c4d759e2017-04-09 16:34:54273 case blink::WebInputEvent::kGestureScrollBegin:
274 case blink::WebInputEvent::kGestureScrollEnd:
dtapuska19ebfa512016-02-19 22:27:40275 return !IsGestureEventFromTouchpad(event);
276
Blink Reformat1c4d759e2017-04-09 16:34:54277 case blink::WebInputEvent::kGestureScrollUpdate:
278 case blink::WebInputEvent::kGestureFlingCancel:
[email protected]b4df9df2012-11-16 01:58:58279 return false;
280
281 default:
[email protected]c4ddb5c42012-11-17 01:09:57282 // Touch events can arrive during an overscroll gesture initiated by
283 // touch-scrolling. These events should not reset the overscroll state.
Blink Reformat1c4d759e2017-04-09 16:34:54284 return !blink::WebInputEvent::IsTouchEventType(event.GetType());
[email protected]b4df9df2012-11-16 01:58:58285 }
286}
287
[email protected]2422e5c2013-09-13 19:05:02288bool OverscrollController::ProcessEventForOverscroll(
[email protected]180ef242013-11-07 06:50:46289 const blink::WebInputEvent& event) {
[email protected]2422e5c2013-09-13 19:05:02290 bool event_processed = false;
Blink Reformat1c4d759e2017-04-09 16:34:54291 switch (event.GetType()) {
292 case blink::WebInputEvent::kMouseWheel: {
[email protected]180ef242013-11-07 06:50:46293 const blink::WebMouseWheelEvent& wheel =
294 static_cast<const blink::WebMouseWheelEvent&>(event);
Blink Reformat1c4d759e2017-04-09 16:34:54295 if (!wheel.has_precise_scrolling_deltas)
[email protected]2422e5c2013-09-13 19:05:02296 break;
[email protected]bfab3d02014-08-20 03:16:55297 event_processed =
Blink Reformat1c4d759e2017-04-09 16:34:54298 ProcessOverscroll(wheel.delta_x * wheel.acceleration_ratio_x,
299 wheel.delta_y * wheel.acceleration_ratio_y, true);
[email protected]b4df9df2012-11-16 01:58:58300 break;
301 }
Blink Reformat1c4d759e2017-04-09 16:34:54302 case blink::WebInputEvent::kGestureScrollUpdate: {
[email protected]180ef242013-11-07 06:50:46303 const blink::WebGestureEvent& gesture =
304 static_cast<const blink::WebGestureEvent&>(event);
dtapuska19ebfa512016-02-19 22:27:40305 event_processed = ProcessOverscroll(
Blink Reformat1c4d759e2017-04-09 16:34:54306 gesture.data.scroll_update.delta_x,
307 gesture.data.scroll_update.delta_y,
308 gesture.source_device == blink::kWebGestureDeviceTouchpad);
[email protected]b4df9df2012-11-16 01:58:58309 break;
310 }
Blink Reformat1c4d759e2017-04-09 16:34:54311 case blink::WebInputEvent::kGestureFlingStart: {
[email protected]b4df9df2012-11-16 01:58:58312 const float kFlingVelocityThreshold = 1100.f;
[email protected]180ef242013-11-07 06:50:46313 const blink::WebGestureEvent& gesture =
314 static_cast<const blink::WebGestureEvent&>(event);
Blink Reformat1c4d759e2017-04-09 16:34:54315 float velocity_x = gesture.data.fling_start.velocity_x;
316 float velocity_y = gesture.data.fling_start.velocity_y;
[email protected]b4df9df2012-11-16 01:58:58317 if (fabs(velocity_x) > kFlingVelocityThreshold) {
318 if ((overscroll_mode_ == OVERSCROLL_WEST && velocity_x < 0) ||
319 (overscroll_mode_ == OVERSCROLL_EAST && velocity_x > 0)) {
320 CompleteAction();
[email protected]2422e5c2013-09-13 19:05:02321 event_processed = true;
[email protected]b4df9df2012-11-16 01:58:58322 break;
323 }
324 } else if (fabs(velocity_y) > kFlingVelocityThreshold) {
325 if ((overscroll_mode_ == OVERSCROLL_NORTH && velocity_y < 0) ||
326 (overscroll_mode_ == OVERSCROLL_SOUTH && velocity_y > 0)) {
327 CompleteAction();
[email protected]2422e5c2013-09-13 19:05:02328 event_processed = true;
[email protected]b4df9df2012-11-16 01:58:58329 break;
330 }
331 }
332
333 // Reset overscroll state if fling didn't complete the overscroll gesture.
mfomitchev09f0d64a2017-03-02 19:40:07334 SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
[email protected]b4df9df2012-11-16 01:58:58335 break;
336 }
337
338 default:
Blink Reformat1c4d759e2017-04-09 16:34:54339 DCHECK(blink::WebInputEvent::IsGestureEventType(event.GetType()) ||
340 blink::WebInputEvent::IsTouchEventType(event.GetType()))
341 << "Received unexpected event: " << event.GetType();
[email protected]b4df9df2012-11-16 01:58:58342 }
[email protected]2422e5c2013-09-13 19:05:02343 return event_processed;
[email protected]b4df9df2012-11-16 01:58:58344}
345
[email protected]bfab3d02014-08-20 03:16:55346bool OverscrollController::ProcessOverscroll(float delta_x,
[email protected]a7f99f02013-08-29 14:15:19347 float delta_y,
dtapuska19ebfa512016-02-19 22:27:40348 bool is_touchpad) {
[email protected]fa6db252013-07-26 03:38:20349 if (scroll_state_ != STATE_CONTENT_SCROLLING)
350 overscroll_delta_x_ += delta_x;
[email protected]b4df9df2012-11-16 01:58:58351 overscroll_delta_y_ += delta_y;
352
[email protected]fa6db252013-07-26 03:38:20353 float horiz_threshold = GetOverscrollConfig(
dtapuska19ebfa512016-02-19 22:27:40354 is_touchpad ? OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD
355 : OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
[email protected]fa6db252013-07-26 03:38:20356 float vert_threshold = GetOverscrollConfig(
357 OVERSCROLL_CONFIG_VERT_THRESHOLD_START);
358 if (fabs(overscroll_delta_x_) <= horiz_threshold &&
359 fabs(overscroll_delta_y_) <= vert_threshold) {
mfomitchev09f0d64a2017-03-02 19:40:07360 SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
[email protected]bfab3d02014-08-20 03:16:55361 return true;
[email protected]b4df9df2012-11-16 01:58:58362 }
363
[email protected]a23d04af2013-02-19 17:41:10364 // Compute the current overscroll direction. If the direction is different
365 // from the current direction, then always switch to no-overscroll mode first
366 // to make sure that subsequent scroll events go through to the page first.
367 OverscrollMode new_mode = OVERSCROLL_NONE;
[email protected]14749ddb2013-02-23 06:56:10368 const float kMinRatio = 2.5;
[email protected]fa6db252013-07-26 03:38:20369 if (fabs(overscroll_delta_x_) > horiz_threshold &&
370 fabs(overscroll_delta_x_) > fabs(overscroll_delta_y_) * kMinRatio)
[email protected]a23d04af2013-02-19 17:41:10371 new_mode = overscroll_delta_x_ > 0.f ? OVERSCROLL_EAST : OVERSCROLL_WEST;
[email protected]fa6db252013-07-26 03:38:20372 else if (fabs(overscroll_delta_y_) > vert_threshold &&
373 fabs(overscroll_delta_y_) > fabs(overscroll_delta_x_) * kMinRatio)
[email protected]a23d04af2013-02-19 17:41:10374 new_mode = overscroll_delta_y_ > 0.f ? OVERSCROLL_SOUTH : OVERSCROLL_NORTH;
375
[email protected]3aad43b2013-11-05 20:20:18376 // The vertical oversrcoll currently does not have any UX effects other then
377 // for the scroll end effect, so testing if it is enabled.
378 if ((new_mode == OVERSCROLL_SOUTH || new_mode == OVERSCROLL_NORTH) &&
379 !IsScrollEndEffectEnabled())
380 new_mode = OVERSCROLL_NONE;
381
mfomitchev09f0d64a2017-03-02 19:40:07382 if (overscroll_mode_ == OVERSCROLL_NONE) {
383 SetOverscrollMode(new_mode, is_touchpad ? OverscrollSource::TOUCHPAD
384 : OverscrollSource::TOUCHSCREEN);
385 } else if (new_mode != overscroll_mode_) {
386 SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE);
387 }
[email protected]fa6db252013-07-26 03:38:20388
389 if (overscroll_mode_ == OVERSCROLL_NONE)
[email protected]bfab3d02014-08-20 03:16:55390 return false;
[email protected]b4df9df2012-11-16 01:58:58391
392 // Tell the delegate about the overscroll update so that it can update
393 // the display accordingly (e.g. show history preview etc.).
[email protected]9f4f47e2012-11-20 02:21:43394 if (delegate_) {
395 // Do not include the threshold amount when sending the deltas to the
396 // delegate.
397 float delegate_delta_x = overscroll_delta_x_;
[email protected]fa6db252013-07-26 03:38:20398 if (fabs(delegate_delta_x) > horiz_threshold) {
[email protected]9f4f47e2012-11-20 02:21:43399 if (delegate_delta_x < 0)
[email protected]fa6db252013-07-26 03:38:20400 delegate_delta_x += horiz_threshold;
[email protected]9f4f47e2012-11-20 02:21:43401 else
[email protected]fa6db252013-07-26 03:38:20402 delegate_delta_x -= horiz_threshold;
[email protected]9f4f47e2012-11-20 02:21:43403 } else {
404 delegate_delta_x = 0.f;
405 }
406
407 float delegate_delta_y = overscroll_delta_y_;
[email protected]fa6db252013-07-26 03:38:20408 if (fabs(delegate_delta_y) > vert_threshold) {
[email protected]9f4f47e2012-11-20 02:21:43409 if (delegate_delta_y < 0)
[email protected]fa6db252013-07-26 03:38:20410 delegate_delta_y += vert_threshold;
[email protected]9f4f47e2012-11-20 02:21:43411 else
[email protected]fa6db252013-07-26 03:38:20412 delegate_delta_y -= vert_threshold;
[email protected]9f4f47e2012-11-20 02:21:43413 } else {
414 delegate_delta_y = 0.f;
415 }
[email protected]bfab3d02014-08-20 03:16:55416 return delegate_->OnOverscrollUpdate(delegate_delta_x, delegate_delta_y);
[email protected]9f4f47e2012-11-20 02:21:43417 }
[email protected]bfab3d02014-08-20 03:16:55418 return false;
[email protected]b4df9df2012-11-16 01:58:58419}
420
421void OverscrollController::CompleteAction() {
422 if (delegate_)
423 delegate_->OnOverscrollComplete(overscroll_mode_);
[email protected]e42b1f82012-11-16 21:18:46424 overscroll_mode_ = OVERSCROLL_NONE;
425 overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
[email protected]b4df9df2012-11-16 01:58:58426}
427
mfomitchev09f0d64a2017-03-02 19:40:07428void OverscrollController::SetOverscrollMode(OverscrollMode mode,
429 OverscrollSource source) {
[email protected]b4df9df2012-11-16 01:58:58430 if (overscroll_mode_ == mode)
431 return;
mfomitchev09f0d64a2017-03-02 19:40:07432
433 // If the mode changes to NONE, source is also NONE.
434 DCHECK(mode != OVERSCROLL_NONE || source == OverscrollSource::NONE);
435
[email protected]b4df9df2012-11-16 01:58:58436 OverscrollMode old_mode = overscroll_mode_;
437 overscroll_mode_ = mode;
438 if (overscroll_mode_ == OVERSCROLL_NONE)
439 overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
[email protected]a4141642013-05-23 04:10:58440 else
441 scroll_state_ = STATE_OVERSCROLLING;
[email protected]b4df9df2012-11-16 01:58:58442 if (delegate_)
mfomitchev09f0d64a2017-03-02 19:40:07443 delegate_->OnOverscrollModeChange(old_mode, overscroll_mode_, source);
[email protected]b4df9df2012-11-16 01:58:58444}
445
[email protected]b4df9df2012-11-16 01:58:58446} // namespace content