| 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 |