OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/input/input_handler_proxy.h" | 5 #include "content/renderer/input/input_handler_proxy.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "content/common/input/did_overscroll_params.h" | 12 #include "content/common/input/did_overscroll_params.h" |
13 #include "content/common/input/web_input_event_traits.h" | 13 #include "content/common/input/web_input_event_traits.h" |
14 #include "content/public/common/content_switches.h" | 14 #include "content/public/common/content_switches.h" |
15 #include "content/renderer/input/input_handler_proxy_client.h" | 15 #include "content/renderer/input/input_handler_proxy_client.h" |
| 16 #include "content/renderer/input/input_scroll_elasticity_controller.h" |
16 #include "third_party/WebKit/public/platform/Platform.h" | 17 #include "third_party/WebKit/public/platform/Platform.h" |
17 #include "third_party/WebKit/public/web/WebInputEvent.h" | 18 #include "third_party/WebKit/public/web/WebInputEvent.h" |
18 #include "ui/events/latency_info.h" | 19 #include "ui/events/latency_info.h" |
19 #include "ui/gfx/frame_time.h" | 20 #include "ui/gfx/frame_time.h" |
20 #include "ui/gfx/geometry/point_conversions.h" | 21 #include "ui/gfx/geometry/point_conversions.h" |
21 | 22 |
22 using blink::WebFloatPoint; | 23 using blink::WebFloatPoint; |
23 using blink::WebFloatSize; | 24 using blink::WebFloatSize; |
24 using blink::WebGestureEvent; | 25 using blink::WebGestureEvent; |
25 using blink::WebInputEvent; | 26 using blink::WebInputEvent; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 gesture_scroll_on_impl_thread_(false), | 155 gesture_scroll_on_impl_thread_(false), |
155 gesture_pinch_on_impl_thread_(false), | 156 gesture_pinch_on_impl_thread_(false), |
156 fling_may_be_active_on_main_thread_(false), | 157 fling_may_be_active_on_main_thread_(false), |
157 disallow_horizontal_fling_scroll_(false), | 158 disallow_horizontal_fling_scroll_(false), |
158 disallow_vertical_fling_scroll_(false), | 159 disallow_vertical_fling_scroll_(false), |
159 has_fling_animation_started_(false) { | 160 has_fling_animation_started_(false) { |
160 DCHECK(client); | 161 DCHECK(client); |
161 input_handler_->BindToClient(this); | 162 input_handler_->BindToClient(this); |
162 smooth_scroll_enabled_ = CommandLine::ForCurrentProcess()->HasSwitch( | 163 smooth_scroll_enabled_ = CommandLine::ForCurrentProcess()->HasSwitch( |
163 switches::kEnableSmoothScrolling); | 164 switches::kEnableSmoothScrolling); |
| 165 |
| 166 #if defined(OS_MACOSX) |
| 167 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 168 switches::kEnableThreadedEventHandlingMac)) { |
| 169 scroll_elasticity_controller_.reset(new InputScrollElasticityController( |
| 170 input_handler_->GetScrollElasticityHelper())); |
| 171 } |
| 172 #endif |
164 } | 173 } |
165 | 174 |
166 InputHandlerProxy::~InputHandlerProxy() {} | 175 InputHandlerProxy::~InputHandlerProxy() {} |
167 | 176 |
168 void InputHandlerProxy::WillShutdown() { | 177 void InputHandlerProxy::WillShutdown() { |
169 input_handler_ = NULL; | 178 input_handler_ = NULL; |
170 client_->WillShutdown(); | 179 client_->WillShutdown(); |
| 180 if (scroll_elasticity_controller_) |
| 181 scroll_elasticity_controller_->WillShutdown(); |
171 } | 182 } |
172 | 183 |
173 InputHandlerProxy::EventDisposition | 184 InputHandlerProxy::EventDisposition |
174 InputHandlerProxy::HandleInputEventWithLatencyInfo( | 185 InputHandlerProxy::HandleInputEventWithLatencyInfo( |
175 const WebInputEvent& event, | 186 const WebInputEvent& event, |
176 ui::LatencyInfo* latency_info) { | 187 ui::LatencyInfo* latency_info) { |
177 DCHECK(input_handler_); | 188 DCHECK(input_handler_); |
178 | 189 |
179 SendScrollLatencyUma(event, *latency_info); | 190 SendScrollLatencyUma(event, *latency_info); |
180 | 191 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 CancelCurrentFling(); | 280 CancelCurrentFling(); |
270 } | 281 } |
271 break; | 282 break; |
272 } | 283 } |
273 | 284 |
274 return DID_NOT_HANDLE; | 285 return DID_NOT_HANDLE; |
275 } | 286 } |
276 | 287 |
277 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel( | 288 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel( |
278 const WebMouseWheelEvent& wheel_event) { | 289 const WebMouseWheelEvent& wheel_event) { |
| 290 InputHandlerProxy::EventDisposition result = DID_NOT_HANDLE; |
| 291 cc::InputHandlerScrollResult scroll_result; |
| 292 |
279 if (wheel_event.scrollByPage) { | 293 if (wheel_event.scrollByPage) { |
280 // TODO(jamesr): We don't properly handle scroll by page in the compositor | 294 // TODO(jamesr): We don't properly handle scroll by page in the compositor |
281 // thread, so punt it to the main thread. http://crbug.com/236639 | 295 // thread, so punt it to the main thread. http://crbug.com/236639 |
282 return DID_NOT_HANDLE; | 296 result = DID_NOT_HANDLE; |
283 } | 297 } else if (wheel_event.modifiers & WebInputEvent::ControlKey) { |
284 if (wheel_event.modifiers & WebInputEvent::ControlKey) { | |
285 // Wheel events involving the control key never trigger scrolling, only | 298 // Wheel events involving the control key never trigger scrolling, only |
286 // event handlers. Forward to the main thread. | 299 // event handlers. Forward to the main thread. |
287 return DID_NOT_HANDLE; | 300 result = DID_NOT_HANDLE; |
288 } | 301 } else if (smooth_scroll_enabled_) { |
289 if (smooth_scroll_enabled_) { | |
290 cc::InputHandler::ScrollStatus scroll_status = | 302 cc::InputHandler::ScrollStatus scroll_status = |
291 input_handler_->ScrollAnimated( | 303 input_handler_->ScrollAnimated( |
292 gfx::Point(wheel_event.x, wheel_event.y), | 304 gfx::Point(wheel_event.x, wheel_event.y), |
293 gfx::Vector2dF(-wheel_event.deltaX, -wheel_event.deltaY)); | 305 gfx::Vector2dF(-wheel_event.deltaX, -wheel_event.deltaY)); |
294 switch (scroll_status) { | 306 switch (scroll_status) { |
295 case cc::InputHandler::ScrollStarted: | 307 case cc::InputHandler::ScrollStarted: |
296 return DID_HANDLE; | 308 result = DID_HANDLE; |
| 309 break; |
297 case cc::InputHandler::ScrollIgnored: | 310 case cc::InputHandler::ScrollIgnored: |
298 return DROP_EVENT; | 311 result = DROP_EVENT; |
299 default: | 312 default: |
300 return DID_NOT_HANDLE; | 313 result = DID_NOT_HANDLE; |
| 314 break; |
| 315 } |
| 316 } else { |
| 317 cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin( |
| 318 gfx::Point(wheel_event.x, wheel_event.y), cc::InputHandler::Wheel); |
| 319 switch (scroll_status) { |
| 320 case cc::InputHandler::ScrollStarted: { |
| 321 TRACE_EVENT_INSTANT2( |
| 322 "input", "InputHandlerProxy::handle_input wheel scroll", |
| 323 TRACE_EVENT_SCOPE_THREAD, "deltaX", -wheel_event.deltaX, "deltaY", |
| 324 -wheel_event.deltaY); |
| 325 gfx::Point scroll_point(wheel_event.x, wheel_event.y); |
| 326 gfx::Vector2dF scroll_delta(-wheel_event.deltaX, -wheel_event.deltaY); |
| 327 scroll_result = input_handler_->ScrollBy(scroll_point, scroll_delta); |
| 328 HandleOverscroll(scroll_point, scroll_result); |
| 329 input_handler_->ScrollEnd(); |
| 330 result = scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT; |
| 331 break; |
| 332 } |
| 333 case cc::InputHandler::ScrollIgnored: |
| 334 // TODO(jamesr): This should be DROP_EVENT, but in cases where we fail |
| 335 // to properly sync scrollability it's safer to send the event to the |
| 336 // main thread. Change back to DROP_EVENT once we have synchronization |
| 337 // bugs sorted out. |
| 338 result = DID_NOT_HANDLE; |
| 339 break; |
| 340 case cc::InputHandler::ScrollUnknown: |
| 341 case cc::InputHandler::ScrollOnMainThread: |
| 342 result = DID_NOT_HANDLE; |
| 343 break; |
| 344 case cc::InputHandler::ScrollStatusCount: |
| 345 NOTREACHED(); |
| 346 break; |
301 } | 347 } |
302 } | 348 } |
303 cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin( | 349 |
304 gfx::Point(wheel_event.x, wheel_event.y), cc::InputHandler::Wheel); | 350 // Send the event and its disposition to the elasticity controller to update |
305 switch (scroll_status) { | 351 // the over-scroll animation. If the event is to be handled on the main |
306 case cc::InputHandler::ScrollStarted: { | 352 // thread, the event and its disposition will be sent to the elasticity |
307 TRACE_EVENT_INSTANT2( | 353 // controller after being handled on the main thread. |
308 "input", | 354 if (scroll_elasticity_controller_ && result != DID_NOT_HANDLE) { |
309 "InputHandlerProxy::handle_input wheel scroll", | 355 // Note that the call to the elasticity controller is made asynchronously, |
310 TRACE_EVENT_SCOPE_THREAD, | 356 // to minimize divergence between main thread and impl thread event |
311 "deltaX", | 357 // handling paths. |
312 -wheel_event.deltaX, | 358 base::MessageLoop::current()->PostTask( |
313 "deltaY", | 359 FROM_HERE, |
314 -wheel_event.deltaY); | 360 base::Bind(&InputScrollElasticityController::ObserveWheelEventAndResult, |
315 gfx::Point scroll_point(wheel_event.x, wheel_event.y); | 361 scroll_elasticity_controller_->GetWeakPtr(), wheel_event, |
316 gfx::Vector2dF scroll_delta(-wheel_event.deltaX, -wheel_event.deltaY); | 362 scroll_result)); |
317 cc::InputHandlerScrollResult scroll_result = input_handler_->ScrollBy( | |
318 scroll_point, scroll_delta); | |
319 HandleOverscroll(scroll_point, scroll_result); | |
320 input_handler_->ScrollEnd(); | |
321 return scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT; | |
322 } | |
323 case cc::InputHandler::ScrollIgnored: | |
324 // TODO(jamesr): This should be DROP_EVENT, but in cases where we fail | |
325 // to properly sync scrollability it's safer to send the event to the | |
326 // main thread. Change back to DROP_EVENT once we have synchronization | |
327 // bugs sorted out. | |
328 return DID_NOT_HANDLE; | |
329 case cc::InputHandler::ScrollUnknown: | |
330 case cc::InputHandler::ScrollOnMainThread: | |
331 return DID_NOT_HANDLE; | |
332 case cc::InputHandler::ScrollStatusCount: | |
333 NOTREACHED(); | |
334 break; | |
335 } | 363 } |
336 return DID_NOT_HANDLE; | 364 return result; |
337 } | 365 } |
338 | 366 |
339 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollBegin( | 367 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollBegin( |
340 const WebGestureEvent& gesture_event) { | 368 const WebGestureEvent& gesture_event) { |
341 DCHECK(!gesture_scroll_on_impl_thread_); | 369 DCHECK(!gesture_scroll_on_impl_thread_); |
342 #ifndef NDEBUG | 370 #ifndef NDEBUG |
343 DCHECK(!expect_scroll_update_end_); | 371 DCHECK(!expect_scroll_update_end_); |
344 expect_scroll_update_end_ = true; | 372 expect_scroll_update_end_ = true; |
345 #endif | 373 #endif |
346 cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin( | 374 cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin( |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 const blink::WebGestureEvent& event) { | 660 const blink::WebGestureEvent& event) { |
633 TRACE_EVENT_INSTANT0("input", | 661 TRACE_EVENT_INSTANT0("input", |
634 "InputHandlerProxy::ExtendBoostedFlingTimeout", | 662 "InputHandlerProxy::ExtendBoostedFlingTimeout", |
635 TRACE_EVENT_SCOPE_THREAD); | 663 TRACE_EVENT_SCOPE_THREAD); |
636 deferred_fling_cancel_time_seconds_ = | 664 deferred_fling_cancel_time_seconds_ = |
637 event.timeStampSeconds + kFlingBoostTimeoutDelaySeconds; | 665 event.timeStampSeconds + kFlingBoostTimeoutDelaySeconds; |
638 last_fling_boost_event_ = event; | 666 last_fling_boost_event_ = event; |
639 } | 667 } |
640 | 668 |
641 void InputHandlerProxy::Animate(base::TimeTicks time) { | 669 void InputHandlerProxy::Animate(base::TimeTicks time) { |
| 670 if (scroll_elasticity_controller_) |
| 671 scroll_elasticity_controller_->Animate(time); |
| 672 |
642 if (!fling_curve_) | 673 if (!fling_curve_) |
643 return; | 674 return; |
644 | 675 |
645 double monotonic_time_sec = InSecondsF(time); | 676 double monotonic_time_sec = InSecondsF(time); |
646 | 677 |
647 if (deferred_fling_cancel_time_seconds_ && | 678 if (deferred_fling_cancel_time_seconds_ && |
648 monotonic_time_sec > deferred_fling_cancel_time_seconds_) { | 679 monotonic_time_sec > deferred_fling_cancel_time_seconds_) { |
649 CancelCurrentFling(); | 680 CancelCurrentFling(); |
650 return; | 681 return; |
651 } | 682 } |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 // trigger a scroll, e.g., with a trivial time delta between fling updates. | 888 // trigger a scroll, e.g., with a trivial time delta between fling updates. |
858 // Return true in this case to prevent early fling termination. | 889 // Return true in this case to prevent early fling termination. |
859 if (std::abs(clipped_increment.width) < kScrollEpsilon && | 890 if (std::abs(clipped_increment.width) < kScrollEpsilon && |
860 std::abs(clipped_increment.height) < kScrollEpsilon) | 891 std::abs(clipped_increment.height) < kScrollEpsilon) |
861 return true; | 892 return true; |
862 | 893 |
863 return did_scroll; | 894 return did_scroll; |
864 } | 895 } |
865 | 896 |
866 } // namespace content | 897 } // namespace content |
OLD | NEW |