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 "ui/events/blink/input_handler_proxy.h" | 5 #include "ui/events/blink/input_handler_proxy.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 using blink::WebGestureEvent; | 28 using blink::WebGestureEvent; |
29 using blink::WebInputEvent; | 29 using blink::WebInputEvent; |
30 using blink::WebMouseEvent; | 30 using blink::WebMouseEvent; |
31 using blink::WebMouseWheelEvent; | 31 using blink::WebMouseWheelEvent; |
32 using blink::WebPoint; | 32 using blink::WebPoint; |
33 using blink::WebTouchEvent; | 33 using blink::WebTouchEvent; |
34 using blink::WebTouchPoint; | 34 using blink::WebTouchPoint; |
35 | 35 |
36 namespace { | 36 namespace { |
37 | 37 |
| 38 const int32_t kEventDispositionUndefined = -1; |
| 39 |
38 // Maximum time between a fling event's timestamp and the first |Animate| call | 40 // Maximum time between a fling event's timestamp and the first |Animate| call |
39 // for the fling curve to use the fling timestamp as the initial animation time. | 41 // for the fling curve to use the fling timestamp as the initial animation time. |
40 // Two frames allows a minor delay between event creation and the first animate. | 42 // Two frames allows a minor delay between event creation and the first animate. |
41 const double kMaxSecondsFromFlingTimestampToFirstAnimate = 2. / 60.; | 43 const double kMaxSecondsFromFlingTimestampToFirstAnimate = 2. / 60.; |
42 | 44 |
43 // Threshold for determining whether a fling scroll delta should have caused the | 45 // Threshold for determining whether a fling scroll delta should have caused the |
44 // client to scroll. | 46 // client to scroll. |
45 const float kScrollEpsilon = 0.1f; | 47 const float kScrollEpsilon = 0.1f; |
46 | 48 |
47 // Minimum fling velocity required for the active fling and new fling for the | 49 // Minimum fling velocity required for the active fling and new fling for the |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 #ifndef NDEBUG | 222 #ifndef NDEBUG |
221 expect_scroll_update_end_(false), | 223 expect_scroll_update_end_(false), |
222 #endif | 224 #endif |
223 gesture_scroll_on_impl_thread_(false), | 225 gesture_scroll_on_impl_thread_(false), |
224 gesture_pinch_on_impl_thread_(false), | 226 gesture_pinch_on_impl_thread_(false), |
225 fling_may_be_active_on_main_thread_(false), | 227 fling_may_be_active_on_main_thread_(false), |
226 disallow_horizontal_fling_scroll_(false), | 228 disallow_horizontal_fling_scroll_(false), |
227 disallow_vertical_fling_scroll_(false), | 229 disallow_vertical_fling_scroll_(false), |
228 has_fling_animation_started_(false), | 230 has_fling_animation_started_(false), |
229 smooth_scroll_enabled_(false), | 231 smooth_scroll_enabled_(false), |
230 uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()) { | 232 uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()), |
| 233 use_gesture_events_for_mouse_wheel_(true), |
| 234 touch_start_result_(kEventDispositionUndefined) { |
231 DCHECK(client); | 235 DCHECK(client); |
232 input_handler_->BindToClient(this); | 236 input_handler_->BindToClient(this); |
233 cc::ScrollElasticityHelper* scroll_elasticity_helper = | 237 cc::ScrollElasticityHelper* scroll_elasticity_helper = |
234 input_handler_->CreateScrollElasticityHelper(); | 238 input_handler_->CreateScrollElasticityHelper(); |
235 if (scroll_elasticity_helper) { | 239 if (scroll_elasticity_helper) { |
236 scroll_elasticity_controller_.reset( | 240 scroll_elasticity_controller_.reset( |
237 new InputScrollElasticityController(scroll_elasticity_helper)); | 241 new InputScrollElasticityController(scroll_elasticity_helper)); |
238 } | 242 } |
239 } | 243 } |
240 | 244 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 case WebInputEvent::GestureFlingCancel: | 340 case WebInputEvent::GestureFlingCancel: |
337 if (CancelCurrentFling()) | 341 if (CancelCurrentFling()) |
338 return DID_HANDLE; | 342 return DID_HANDLE; |
339 else if (!fling_may_be_active_on_main_thread_) | 343 else if (!fling_may_be_active_on_main_thread_) |
340 return DROP_EVENT; | 344 return DROP_EVENT; |
341 return DID_NOT_HANDLE; | 345 return DID_NOT_HANDLE; |
342 | 346 |
343 case WebInputEvent::TouchStart: | 347 case WebInputEvent::TouchStart: |
344 return HandleTouchStart(static_cast<const WebTouchEvent&>(event)); | 348 return HandleTouchStart(static_cast<const WebTouchEvent&>(event)); |
345 | 349 |
| 350 case WebInputEvent::TouchMove: |
| 351 return HandleTouchMove(static_cast<const WebTouchEvent&>(event)); |
| 352 |
| 353 case WebInputEvent::TouchEnd: |
| 354 return HandleTouchEnd(static_cast<const WebTouchEvent&>(event)); |
| 355 |
346 case WebInputEvent::MouseMove: { | 356 case WebInputEvent::MouseMove: { |
347 const WebMouseEvent& mouse_event = | 357 const WebMouseEvent& mouse_event = |
348 static_cast<const WebMouseEvent&>(event); | 358 static_cast<const WebMouseEvent&>(event); |
349 // TODO(tony): Ignore when mouse buttons are down? | 359 // TODO(tony): Ignore when mouse buttons are down? |
350 // TODO(davemoore): This should never happen, but bug #326635 showed some | 360 // TODO(davemoore): This should never happen, but bug #326635 showed some |
351 // surprising crashes. | 361 // surprising crashes. |
352 CHECK(input_handler_); | 362 CHECK(input_handler_); |
353 input_handler_->MouseMoveAt(gfx::Point(mouse_event.x, mouse_event.y)); | 363 input_handler_->MouseMoveAt(gfx::Point(mouse_event.x, mouse_event.y)); |
354 return DID_NOT_HANDLE; | 364 return DID_NOT_HANDLE; |
355 } | 365 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 #if defined(OS_MACOSX) | 429 #if defined(OS_MACOSX) |
420 // Mac does not smooth scroll wheel events (crbug.com/574283). | 430 // Mac does not smooth scroll wheel events (crbug.com/574283). |
421 return false; | 431 return false; |
422 #else | 432 #else |
423 return smooth_scroll_enabled_ && !event.hasPreciseScrollingDeltas; | 433 return smooth_scroll_enabled_ && !event.hasPreciseScrollingDeltas; |
424 #endif | 434 #endif |
425 } | 435 } |
426 | 436 |
427 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel( | 437 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel( |
428 const WebMouseWheelEvent& wheel_event) { | 438 const WebMouseWheelEvent& wheel_event) { |
| 439 if (use_gesture_events_for_mouse_wheel_) { |
| 440 cc::EventListenerProperties properties = |
| 441 input_handler_->GetEventListenerProperties( |
| 442 cc::EventListenerClass::kMouseWheel); |
| 443 switch (properties) { |
| 444 case cc::EventListenerProperties::kPassive: |
| 445 return DID_HANDLE_NON_BLOCKING; |
| 446 case cc::EventListenerProperties::kBlockingAndPassive: |
| 447 case cc::EventListenerProperties::kBlocking: |
| 448 return DID_NOT_HANDLE; |
| 449 case cc::EventListenerProperties::kNone: |
| 450 return DROP_EVENT; |
| 451 default: |
| 452 NOTREACHED(); |
| 453 return DROP_EVENT; |
| 454 } |
| 455 } |
| 456 return ScrollByMouseWheel(wheel_event); |
| 457 } |
| 458 |
| 459 InputHandlerProxy::EventDisposition InputHandlerProxy::ScrollByMouseWheel( |
| 460 const WebMouseWheelEvent& wheel_event) { |
429 InputHandlerProxy::EventDisposition result = DID_NOT_HANDLE; | 461 InputHandlerProxy::EventDisposition result = DID_NOT_HANDLE; |
430 cc::InputHandlerScrollResult scroll_result; | 462 cc::InputHandlerScrollResult scroll_result; |
431 | 463 |
432 // TODO(ccameron): The rail information should be pushed down into | 464 // TODO(ccameron): The rail information should be pushed down into |
433 // InputHandler. | 465 // InputHandler. |
434 gfx::Vector2dF scroll_delta( | 466 gfx::Vector2dF scroll_delta( |
435 wheel_event.railsMode != WebInputEvent::RailsModeVertical | 467 wheel_event.railsMode != WebInputEvent::RailsModeVertical |
436 ? -wheel_event.deltaX | 468 ? -wheel_event.deltaX |
437 : 0, | 469 : 0, |
438 wheel_event.railsMode != WebInputEvent::RailsModeHorizontal | 470 wheel_event.railsMode != WebInputEvent::RailsModeHorizontal |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 return DID_NOT_HANDLE; | 759 return DID_NOT_HANDLE; |
728 } | 760 } |
729 return DROP_EVENT; | 761 return DROP_EVENT; |
730 } | 762 } |
731 } | 763 } |
732 return DID_NOT_HANDLE; | 764 return DID_NOT_HANDLE; |
733 } | 765 } |
734 | 766 |
735 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchStart( | 767 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchStart( |
736 const blink::WebTouchEvent& touch_event) { | 768 const blink::WebTouchEvent& touch_event) { |
| 769 EventDisposition result = DROP_EVENT; |
737 for (size_t i = 0; i < touch_event.touchesLength; ++i) { | 770 for (size_t i = 0; i < touch_event.touchesLength; ++i) { |
738 if (touch_event.touches[i].state != WebTouchPoint::StatePressed) | 771 if (touch_event.touches[i].state != WebTouchPoint::StatePressed) |
739 continue; | 772 continue; |
740 if (input_handler_->DoTouchEventsBlockScrollAt( | 773 if (input_handler_->DoTouchEventsBlockScrollAt( |
741 gfx::Point(touch_event.touches[i].position.x, | 774 gfx::Point(touch_event.touches[i].position.x, |
742 touch_event.touches[i].position.y))) { | 775 touch_event.touches[i].position.y))) { |
743 // TODO(rbyers): We should consider still sending the touch events to | 776 result = DID_NOT_HANDLE; |
744 // main asynchronously (crbug.com/455539). | 777 break; |
745 return DID_NOT_HANDLE; | |
746 } | 778 } |
747 } | 779 } |
748 return DROP_EVENT; | 780 |
| 781 // If |result| is DROP_EVENT it wasn't processed above. |
| 782 if (result == DROP_EVENT) { |
| 783 switch (input_handler_->GetEventListenerProperties( |
| 784 cc::EventListenerClass::kTouch)) { |
| 785 case cc::EventListenerProperties::kPassive: |
| 786 result = DID_HANDLE_NON_BLOCKING; |
| 787 break; |
| 788 case cc::EventListenerProperties::kBlocking: |
| 789 // The touch area rects above already have checked whether it hits |
| 790 // a blocking region. Since it does not the event can be dropped. |
| 791 result = DROP_EVENT; |
| 792 break; |
| 793 case cc::EventListenerProperties::kBlockingAndPassive: |
| 794 // There is at least one passive listener that needs to possibly |
| 795 // be notified so it can't be dropped. |
| 796 result = DID_HANDLE_NON_BLOCKING; |
| 797 break; |
| 798 case cc::EventListenerProperties::kNone: |
| 799 result = DROP_EVENT; |
| 800 break; |
| 801 default: |
| 802 NOTREACHED(); |
| 803 result = DROP_EVENT; |
| 804 break; |
| 805 } |
| 806 } |
| 807 |
| 808 // Merge |touch_start_result_| and |result| so the result has the highest |
| 809 // priority value according to the sequence; (DROP_EVENT, |
| 810 // DID_HANDLE_NON_BLOCKING, DID_NOT_HANDLE). |
| 811 if (touch_start_result_ == kEventDispositionUndefined || |
| 812 touch_start_result_ == DROP_EVENT || result == DID_NOT_HANDLE) |
| 813 touch_start_result_ = result; |
| 814 |
| 815 return result; |
| 816 } |
| 817 |
| 818 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchMove( |
| 819 const blink::WebTouchEvent& touch_event) { |
| 820 if (touch_start_result_ != kEventDispositionUndefined) |
| 821 return static_cast<EventDisposition>(touch_start_result_); |
| 822 return DID_NOT_HANDLE; |
| 823 } |
| 824 |
| 825 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchEnd( |
| 826 const blink::WebTouchEvent& touch_event) { |
| 827 if (touch_event.touchesLength == 1) |
| 828 touch_start_result_ = kEventDispositionUndefined; |
| 829 return DID_NOT_HANDLE; |
749 } | 830 } |
750 | 831 |
751 bool InputHandlerProxy::FilterInputEventForFlingBoosting( | 832 bool InputHandlerProxy::FilterInputEventForFlingBoosting( |
752 const WebInputEvent& event) { | 833 const WebInputEvent& event) { |
753 if (!WebInputEvent::isGestureEventType(event.type)) | 834 if (!WebInputEvent::isGestureEventType(event.type)) |
754 return false; | 835 return false; |
755 | 836 |
756 if (!fling_curve_) { | 837 if (!fling_curve_) { |
757 DCHECK(!deferred_fling_cancel_time_seconds_); | 838 DCHECK(!deferred_fling_cancel_time_seconds_); |
758 return false; | 839 return false; |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 // flings always go through the normal InputHandler. | 1163 // flings always go through the normal InputHandler. |
1083 if (synchronous_input_handler_ && | 1164 if (synchronous_input_handler_ && |
1084 input_handler_->IsCurrentlyScrollingInnerViewport()) | 1165 input_handler_->IsCurrentlyScrollingInnerViewport()) |
1085 synchronous_input_handler_->SetNeedsSynchronousAnimateInput(); | 1166 synchronous_input_handler_->SetNeedsSynchronousAnimateInput(); |
1086 else | 1167 else |
1087 input_handler_->SetNeedsAnimateInput(); | 1168 input_handler_->SetNeedsAnimateInput(); |
1088 } | 1169 } |
1089 | 1170 |
1090 bool InputHandlerProxy::TouchpadFlingScroll( | 1171 bool InputHandlerProxy::TouchpadFlingScroll( |
1091 const WebFloatSize& increment) { | 1172 const WebFloatSize& increment) { |
1092 WebMouseWheelEvent synthetic_wheel; | 1173 InputHandlerProxy::EventDisposition disposition; |
1093 synthetic_wheel.type = WebInputEvent::MouseWheel; | 1174 cc::EventListenerProperties properties = |
1094 synthetic_wheel.timeStampSeconds = InSecondsF(base::TimeTicks::Now()); | 1175 input_handler_->GetEventListenerProperties( |
1095 synthetic_wheel.deltaX = increment.width; | 1176 cc::EventListenerClass::kMouseWheel); |
1096 synthetic_wheel.deltaY = increment.height; | 1177 switch (properties) { |
1097 synthetic_wheel.hasPreciseScrollingDeltas = true; | 1178 case cc::EventListenerProperties::kPassive: |
1098 synthetic_wheel.x = fling_parameters_.point.x; | 1179 disposition = DID_HANDLE_NON_BLOCKING; |
1099 synthetic_wheel.y = fling_parameters_.point.y; | 1180 break; |
1100 synthetic_wheel.globalX = fling_parameters_.globalPoint.x; | 1181 case cc::EventListenerProperties::kBlocking: |
1101 synthetic_wheel.globalY = fling_parameters_.globalPoint.y; | 1182 disposition = DID_NOT_HANDLE; |
1102 synthetic_wheel.modifiers = fling_parameters_.modifiers; | 1183 break; |
| 1184 case cc::EventListenerProperties::kNone: { |
| 1185 WebMouseWheelEvent synthetic_wheel; |
| 1186 synthetic_wheel.type = WebInputEvent::MouseWheel; |
| 1187 synthetic_wheel.timeStampSeconds = InSecondsF(base::TimeTicks::Now()); |
| 1188 synthetic_wheel.deltaX = increment.width; |
| 1189 synthetic_wheel.deltaY = increment.height; |
| 1190 synthetic_wheel.hasPreciseScrollingDeltas = true; |
| 1191 synthetic_wheel.x = fling_parameters_.point.x; |
| 1192 synthetic_wheel.y = fling_parameters_.point.y; |
| 1193 synthetic_wheel.globalX = fling_parameters_.globalPoint.x; |
| 1194 synthetic_wheel.globalY = fling_parameters_.globalPoint.y; |
| 1195 synthetic_wheel.modifiers = fling_parameters_.modifiers; |
1103 | 1196 |
1104 InputHandlerProxy::EventDisposition disposition = | 1197 disposition = ScrollByMouseWheel(synthetic_wheel); |
1105 HandleInputEvent(synthetic_wheel); | 1198 break; |
| 1199 } |
| 1200 default: |
| 1201 NOTREACHED(); |
| 1202 return false; |
| 1203 } |
| 1204 |
1106 switch (disposition) { | 1205 switch (disposition) { |
1107 case DID_HANDLE: | 1206 case DID_HANDLE: |
1108 return true; | 1207 return true; |
1109 case DROP_EVENT: | 1208 case DROP_EVENT: |
1110 break; | 1209 break; |
| 1210 case DID_HANDLE_NON_BLOCKING: |
| 1211 // TODO(dtapuska): Process the fling on the compositor thread |
| 1212 // but post the events to the main thread; for now just pass it to the |
| 1213 // main thread. |
1111 case DID_NOT_HANDLE: | 1214 case DID_NOT_HANDLE: |
1112 TRACE_EVENT_INSTANT0("input", | 1215 TRACE_EVENT_INSTANT0("input", |
1113 "InputHandlerProxy::scrollBy::AbortFling", | 1216 "InputHandlerProxy::scrollBy::AbortFling", |
1114 TRACE_EVENT_SCOPE_THREAD); | 1217 TRACE_EVENT_SCOPE_THREAD); |
1115 // If we got a DID_NOT_HANDLE, that means we need to deliver wheels on the | 1218 // If we got a DID_NOT_HANDLE, that means we need to deliver wheels on the |
1116 // main thread. In this case we need to schedule a commit and transfer the | 1219 // main thread. In this case we need to schedule a commit and transfer the |
1117 // fling curve over to the main thread and run the rest of the wheels from | 1220 // fling curve over to the main thread and run the rest of the wheels from |
1118 // there. This can happen when flinging a page that contains a scrollable | 1221 // there. This can happen when flinging a page that contains a scrollable |
1119 // subarea that we can't scroll on the thread if the fling starts outside | 1222 // subarea that we can't scroll on the thread if the fling starts outside |
1120 // the subarea but then is flung "under" the pointer. | 1223 // the subarea but then is flung "under" the pointer. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1188 // trigger a scroll, e.g., with a trivial time delta between fling updates. | 1291 // trigger a scroll, e.g., with a trivial time delta between fling updates. |
1189 // Return true in this case to prevent early fling termination. | 1292 // Return true in this case to prevent early fling termination. |
1190 if (std::abs(clipped_increment.width) < kScrollEpsilon && | 1293 if (std::abs(clipped_increment.width) < kScrollEpsilon && |
1191 std::abs(clipped_increment.height) < kScrollEpsilon) | 1294 std::abs(clipped_increment.height) < kScrollEpsilon) |
1192 return true; | 1295 return true; |
1193 | 1296 |
1194 return did_scroll; | 1297 return did_scroll; |
1195 } | 1298 } |
1196 | 1299 |
1197 } // namespace ui | 1300 } // namespace ui |
OLD | NEW |