OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "core/input/TouchEventManager.h" | 5 #include "core/input/TouchEventManager.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
9 #include "core/events/TouchEvent.h" | 9 #include "core/events/TouchEvent.h" |
10 #include "core/frame/Deprecation.h" | 10 #include "core/frame/Deprecation.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 return g_empty_atom; | 54 return g_empty_atom; |
55 } | 55 } |
56 } | 56 } |
57 | 57 |
58 enum TouchEventDispatchResultType { | 58 enum TouchEventDispatchResultType { |
59 kUnhandledTouches, // Unhandled touch events. | 59 kUnhandledTouches, // Unhandled touch events. |
60 kHandledTouches, // Handled touch events. | 60 kHandledTouches, // Handled touch events. |
61 kTouchEventDispatchResultTypeMax, | 61 kTouchEventDispatchResultTypeMax, |
62 }; | 62 }; |
63 | 63 |
64 bool IsTouchSequenceStart(const WebTouchEvent& event) { | 64 bool IsTouchSequenceStart(const Vector<WebCoalescedPointerEvent>& event) { |
65 if (!event.touches_length) | 65 if (!event.size()) |
66 return false; | 66 return false; |
67 if (event.GetType() != WebInputEvent::kTouchStart) | 67 for (size_t i = 0; i < event.size(); ++i) { |
68 return false; | 68 if (event[i].first.action != |
69 for (size_t i = 0; i < event.touches_length; ++i) { | 69 WebPointerProperties::PointerAction::kPointerDown) |
70 if (event.touches[i].state != blink::WebTouchPoint::kStatePressed) | |
71 return false; | 70 return false; |
72 } | 71 } |
73 return true; | 72 return true; |
74 } | 73 } |
75 | 74 |
76 // Defining this class type local to dispatchTouchEvents() and annotating | 75 // Defining this class type local to dispatchTouchEvents() and annotating |
77 // it with STACK_ALLOCATED(), runs into MSVC(VS 2013)'s C4822 warning | 76 // it with STACK_ALLOCATED(), runs into MSVC(VS 2013)'s C4822 warning |
78 // that the local class doesn't provide a local definition for 'operator new'. | 77 // that the local class doesn't provide a local definition for 'operator new'. |
79 // Which it intentionally doesn't and shouldn't. | 78 // Which it intentionally doesn't and shouldn't. |
80 // | 79 // |
(...skipping 29 matching lines...) Expand all Loading... |
110 current_touch_action_ = kTouchActionAuto; | 109 current_touch_action_ = kTouchActionAuto; |
111 } | 110 } |
112 | 111 |
113 DEFINE_TRACE(TouchEventManager) { | 112 DEFINE_TRACE(TouchEventManager) { |
114 visitor->Trace(frame_); | 113 visitor->Trace(frame_); |
115 visitor->Trace(touch_sequence_document_); | 114 visitor->Trace(touch_sequence_document_); |
116 visitor->Trace(target_for_touch_id_); | 115 visitor->Trace(target_for_touch_id_); |
117 } | 116 } |
118 | 117 |
119 WebInputEventResult TouchEventManager::DispatchTouchEvents( | 118 WebInputEventResult TouchEventManager::DispatchTouchEvents( |
120 const WebTouchEvent& event, | 119 const Vector<WebCoalescedPointerEvent>& event, |
121 const HeapVector<TouchInfo>& touch_infos, | 120 const HeapVector<TouchInfo>& touch_infos, |
122 bool all_touches_released) { | 121 bool all_touches_released) { |
123 // Build up the lists to use for the |touches|, |targetTouches| and | 122 // Build up the lists to use for the |touches|, |targetTouches| and |
124 // |changedTouches| attributes in the JS event. See | 123 // |changedTouches| attributes in the JS event. See |
125 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these | 124 // http://www.w3.org/TR/touch-events/#touchevent-interface for how these |
126 // lists fit together. | 125 // lists fit together. |
127 | 126 |
128 if (event.GetType() == WebInputEvent::kTouchEnd || | 127 if (event.size() > 1 || |
129 event.GetType() == WebInputEvent::kTouchCancel || | 128 event[0].first.action == |
130 event.touches_length > 1) { | 129 WebPointerProperties::PointerAction::kPointerUp || |
| 130 event[0].first.action == |
| 131 WebPointerProperties::PointerAction::kPointerCancel) { |
131 suppressing_touchmoves_within_slop_ = false; | 132 suppressing_touchmoves_within_slop_ = false; |
132 } | 133 } |
133 | 134 |
134 if (suppressing_touchmoves_within_slop_ && | 135 if (suppressing_touchmoves_within_slop_ && |
135 event.GetType() == WebInputEvent::kTouchMove) { | 136 event[0].first.action == |
136 if (!event.moved_beyond_slop_region) | 137 WebPointerProperties::PointerAction::kPointerMove) { |
| 138 if (!event[0].first.moved_beyond_slop_region) |
137 return WebInputEventResult::kHandledSuppressed; | 139 return WebInputEventResult::kHandledSuppressed; |
138 suppressing_touchmoves_within_slop_ = false; | 140 suppressing_touchmoves_within_slop_ = false; |
139 } | 141 } |
140 | 142 |
141 // Holds the complete set of touches on the screen. | 143 // Holds the complete set of touches on the screen. |
142 TouchList* touches = TouchList::Create(); | 144 TouchList* touches = TouchList::Create(); |
143 | 145 |
144 // A different view on the 'touches' list above, filtered and grouped by | 146 // A different view on the 'touches' list above, filtered and grouped by |
145 // event target. Used for the |targetTouches| list in the JS event. | 147 // event target. Used for the |targetTouches| list in the JS event. |
146 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>; | 148 using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 } | 197 } |
196 } | 198 } |
197 | 199 |
198 if (all_touches_released) { | 200 if (all_touches_released) { |
199 touch_sequence_document_.Clear(); | 201 touch_sequence_document_.Clear(); |
200 current_touch_action_ = kTouchActionAuto; | 202 current_touch_action_ = kTouchActionAuto; |
201 } | 203 } |
202 | 204 |
203 WebInputEventResult event_result = WebInputEventResult::kNotHandled; | 205 WebInputEventResult event_result = WebInputEventResult::kNotHandled; |
204 | 206 |
| 207 // Only for setting it inside TouchEvent for compatibility. |
| 208 WebTouchEvent web_touch_event; |
| 209 for (size_t i = 0; i < event.size(); i++) { |
| 210 const auto& touch_pointer_event = event[0].first; |
| 211 WebTouchPoint touch_point; |
| 212 // WebPointerProperties attributes |
| 213 touch_point.id = touch_pointer_event.id; |
| 214 touch_point.force = touch_pointer_event.force; |
| 215 touch_point.tilt_x = touch_pointer_event.tilt_x; |
| 216 touch_point.tilt_y = touch_pointer_event.tilt_y; |
| 217 touch_point.tangential_pressure = touch_pointer_event.tangential_pressure; |
| 218 touch_point.twist = touch_pointer_event.twist; |
| 219 touch_point.button = touch_pointer_event.button; |
| 220 touch_point.pointer_type = touch_pointer_event.pointer_type; |
| 221 touch_point.movement_x = touch_pointer_event.movement_x; |
| 222 touch_point.movement_y = touch_pointer_event.movement_y; |
| 223 // WebTouchPoint attributes |
| 224 touch_point.rotation_angle = touch_pointer_event.rotation_angle; |
| 225 |
| 226 web_touch_event.touches[web_touch_event.touches_length++] = touch_point; |
| 227 } |
| 228 // WebInutEvent attributes |
| 229 web_touch_event.SetFrameScale(event[0].first.FrameScale()); |
| 230 web_touch_event.SetFrameTranslate(event[0].first.FrameTranslate()); |
| 231 web_touch_event.SetTimeStampSeconds(event[0].first.TimeStampSeconds()); |
| 232 web_touch_event.SetType(event[0].first.GetType()); |
| 233 web_touch_event.SetModifiers(event[0].first.GetModifiers()); |
| 234 // WebTouchEvent attributes |
| 235 web_touch_event.dispatch_type = event[0].first.dispatch_type; |
| 236 web_touch_event.moved_beyond_slop_region = |
| 237 event[0].first.moved_beyond_slop_region; |
| 238 web_touch_event.touch_start_or_first_touch_move = |
| 239 event[0].first.touch_start_or_first_touch_move; |
| 240 |
205 // Now iterate through the |changedTouches| list and |m_targets| within it, | 241 // Now iterate through the |changedTouches| list and |m_targets| within it, |
206 // sending TouchEvents to the targets as required. | 242 // sending TouchEvents to the targets as required. |
207 for (unsigned state = 0; state <= WebTouchPoint::kStateMax; ++state) { | 243 for (unsigned state = 0; state <= WebTouchPoint::kStateMax; ++state) { |
208 if (!changed_touches[state].touches_) | 244 if (!changed_touches[state].touches_) |
209 continue; | 245 continue; |
210 | 246 |
211 const AtomicString& event_name(TouchEventNameForTouchPointState( | 247 const AtomicString& event_name(TouchEventNameForTouchPointState( |
212 static_cast<WebTouchPoint::State>(state))); | 248 static_cast<WebTouchPoint::State>(state))); |
| 249 |
213 for (const auto& event_target : changed_touches[state].targets_) { | 250 for (const auto& event_target : changed_touches[state].targets_) { |
214 EventTarget* touch_event_target = event_target; | 251 EventTarget* touch_event_target = event_target; |
215 TouchEvent* touch_event = TouchEvent::Create( | 252 TouchEvent* touch_event = TouchEvent::Create( |
216 event, touches, touches_by_target.at(touch_event_target), | 253 web_touch_event, touches, touches_by_target.at(touch_event_target), |
217 changed_touches[state].touches_.Get(), event_name, | 254 changed_touches[state].touches_.Get(), event_name, |
218 touch_event_target->ToNode()->GetDocument().domWindow(), | 255 touch_event_target->ToNode()->GetDocument().domWindow(), |
219 current_touch_action_); | 256 current_touch_action_); |
220 | 257 |
221 DispatchEventResult dom_dispatch_result = | 258 DispatchEventResult dom_dispatch_result = |
222 touch_event_target->DispatchEvent(touch_event); | 259 touch_event_target->DispatchEvent(touch_event); |
223 | 260 |
224 // Only report for top level documents with a single touch on | 261 // Only report for top level documents with a single touch on |
225 // touch-start or the first touch-move. | 262 // touch-start or the first touch-move. |
226 if (event.touch_start_or_first_touch_move && touch_infos.size() == 1 && | 263 if (touch_infos.size() == 1 && |
| 264 event[0].first.touch_start_or_first_touch_move && |
227 frame_->IsMainFrame()) { | 265 frame_->IsMainFrame()) { |
228 // Record the disposition and latency of touch starts and first touch | 266 // Record the disposition and latency of touch starts and first touch |
229 // moves before and after the page is fully loaded respectively. | 267 // moves before and after the page is fully loaded respectively. |
230 int64_t latency_in_micros = | 268 int64_t latency_in_micros = |
231 (TimeTicks::Now() - | 269 (TimeTicks::Now() - |
232 TimeTicks::FromSeconds(event.TimeStampSeconds())) | 270 TimeTicks::FromSeconds(event[0].first.TimeStampSeconds())) |
233 .InMicroseconds(); | 271 .InMicroseconds(); |
234 if (event.IsCancelable()) { | 272 if (event[0].first.IsCancelable()) { |
235 if (frame_->GetDocument()->IsLoadCompleted()) { | 273 if (frame_->GetDocument()->IsLoadCompleted()) { |
236 DEFINE_STATIC_LOCAL(EnumerationHistogram, | 274 DEFINE_STATIC_LOCAL(EnumerationHistogram, |
237 touch_dispositions_after_page_load_histogram, | 275 touch_dispositions_after_page_load_histogram, |
238 ("Event.Touch.TouchDispositionsAfterPageLoad", | 276 ("Event.Touch.TouchDispositionsAfterPageLoad", |
239 kTouchEventDispatchResultTypeMax)); | 277 kTouchEventDispatchResultTypeMax)); |
240 touch_dispositions_after_page_load_histogram.Count( | 278 touch_dispositions_after_page_load_histogram.Count( |
241 (dom_dispatch_result != DispatchEventResult::kNotCanceled) | 279 (dom_dispatch_result != DispatchEventResult::kNotCanceled) |
242 ? kHandledTouches | 280 ? kHandledTouches |
243 : kUnhandledTouches); | 281 : kUnhandledTouches); |
244 | 282 |
(...skipping 21 matching lines...) Expand all Loading... |
266 touch_dispositions_outside_fling_histogram, | 304 touch_dispositions_outside_fling_histogram, |
267 ("Event.Touch.TouchDispositionsOutsideFling2", | 305 ("Event.Touch.TouchDispositionsOutsideFling2", |
268 kTouchEventDispatchResultTypeMax)); | 306 kTouchEventDispatchResultTypeMax)); |
269 touch_dispositions_outside_fling_histogram.Count( | 307 touch_dispositions_outside_fling_histogram.Count( |
270 (dom_dispatch_result != DispatchEventResult::kNotCanceled) | 308 (dom_dispatch_result != DispatchEventResult::kNotCanceled) |
271 ? kHandledTouches | 309 ? kHandledTouches |
272 : kUnhandledTouches); | 310 : kUnhandledTouches); |
273 } | 311 } |
274 | 312 |
275 // Report the touch disposition when there is an active fling animation. | 313 // Report the touch disposition when there is an active fling animation. |
276 if (event.dispatch_type == | 314 if (event[0].first.dispatch_type == |
277 WebInputEvent::kListenersForcedNonBlockingDueToFling) { | 315 WebInputEvent::kListenersForcedNonBlockingDueToFling) { |
278 DEFINE_STATIC_LOCAL(EnumerationHistogram, | 316 DEFINE_STATIC_LOCAL(EnumerationHistogram, |
279 touch_dispositions_during_fling_histogram, | 317 touch_dispositions_during_fling_histogram, |
280 ("Event.Touch.TouchDispositionsDuringFling2", | 318 ("Event.Touch.TouchDispositionsDuringFling2", |
281 kTouchEventDispatchResultTypeMax)); | 319 kTouchEventDispatchResultTypeMax)); |
282 touch_dispositions_during_fling_histogram.Count( | 320 touch_dispositions_during_fling_histogram.Count( |
283 touch_event->PreventDefaultCalledOnUncancelableEvent() | 321 touch_event->PreventDefaultCalledOnUncancelableEvent() |
284 ? kHandledTouches | 322 ? kHandledTouches |
285 : kUnhandledTouches); | 323 : kUnhandledTouches); |
286 } | 324 } |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 touch_info.content_point = page_point.ScaledBy(scale_factor); | 481 touch_info.content_point = page_point.ScaledBy(scale_factor); |
444 touch_info.adjusted_radius = | 482 touch_info.adjusted_radius = |
445 FloatSize(touch_info.point.radius_x, touch_info.point.radius_y) | 483 FloatSize(touch_info.point.radius_x, touch_info.point.radius_y) |
446 .ScaledBy(scale_factor); | 484 .ScaledBy(scale_factor); |
447 touch_info.known_target = known_target; | 485 touch_info.known_target = known_target; |
448 touch_info.region = region_id; | 486 touch_info.region = region_id; |
449 } | 487 } |
450 } | 488 } |
451 | 489 |
452 bool TouchEventManager::ReHitTestTouchPointsIfNeeded( | 490 bool TouchEventManager::ReHitTestTouchPointsIfNeeded( |
453 const WebTouchEvent& event, | 491 const Vector<WebCoalescedPointerEvent>& event, |
454 HeapVector<TouchInfo>& touch_infos) { | 492 HeapVector<TouchInfo>& touch_infos) { |
455 bool new_touch_sequence = true; | 493 bool new_touch_sequence = true; |
456 bool all_touches_released = true; | 494 bool all_touches_released = true; |
457 | 495 |
458 for (unsigned i = 0; i < event.touches_length; ++i) { | 496 for (size_t i = 0; i < event.size(); ++i) { |
459 WebTouchPoint::State state = event.touches[i].state; | 497 WebPointerProperties::PointerAction action = event[i].first.action; |
460 if (state != WebTouchPoint::kStatePressed) | 498 if (action != WebPointerProperties::PointerAction::kPointerDown) |
461 new_touch_sequence = false; | 499 new_touch_sequence = false; |
462 if (state != WebTouchPoint::kStateReleased && | 500 if (action != WebPointerProperties::PointerAction::kPointerUp && |
463 state != WebTouchPoint::kStateCancelled) | 501 action != WebPointerProperties::PointerAction::kPointerCancel) |
464 all_touches_released = false; | 502 all_touches_released = false; |
465 } | 503 } |
466 if (new_touch_sequence) { | 504 if (new_touch_sequence) { |
467 // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should | 505 // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should |
468 // have cleared the active document when we saw the last release. But we | 506 // have cleared the active document when we saw the last release. But we |
469 // have some tests that violate this, ClusterFuzz could trigger it, and | 507 // have some tests that violate this, ClusterFuzz could trigger it, and |
470 // there may be cases where the browser doesn't reliably release all | 508 // there may be cases where the browser doesn't reliably release all |
471 // touches. http://crbug.com/345372 tracks this. | 509 // touches. http://crbug.com/345372 tracks this. |
472 touch_sequence_document_.Clear(); | 510 touch_sequence_document_.Clear(); |
473 } | 511 } |
(...skipping 23 matching lines...) Expand all Loading... |
497 } | 535 } |
498 return false; | 536 return false; |
499 } | 537 } |
500 | 538 |
501 SetAllPropertiesOfTouchInfos(touch_infos); | 539 SetAllPropertiesOfTouchInfos(touch_infos); |
502 | 540 |
503 return true; | 541 return true; |
504 } | 542 } |
505 | 543 |
506 WebInputEventResult TouchEventManager::HandleTouchEvent( | 544 WebInputEventResult TouchEventManager::HandleTouchEvent( |
507 const WebTouchEvent& event, | 545 const Vector<WebCoalescedPointerEvent>& event, |
508 HeapVector<TouchInfo>& touch_infos) { | 546 HeapVector<TouchInfo>& touch_infos) { |
509 if (!ReHitTestTouchPointsIfNeeded(event, touch_infos)) | 547 if (!ReHitTestTouchPointsIfNeeded(event, touch_infos)) |
510 return WebInputEventResult::kNotHandled; | 548 return WebInputEventResult::kNotHandled; |
511 | 549 |
512 bool all_touches_released = true; | 550 bool all_touches_released = true; |
513 for (unsigned i = 0; i < event.touches_length; ++i) { | 551 for (size_t i = 0; i < event.size(); ++i) { |
514 WebTouchPoint::State state = event.touches[i].state; | 552 WebPointerProperties::PointerAction action = event[i].first.action; |
515 if (state != WebTouchPoint::kStateReleased && | 553 if (action != WebPointerProperties::PointerAction::kPointerUp && |
516 state != WebTouchPoint::kStateCancelled) | 554 action != WebPointerProperties::PointerAction::kPointerCancel) |
517 all_touches_released = false; | 555 all_touches_released = false; |
518 } | 556 } |
519 | 557 |
520 return DispatchTouchEvents(event, touch_infos, all_touches_released); | 558 return DispatchTouchEvents(event, touch_infos, all_touches_released); |
521 } | 559 } |
522 | 560 |
523 bool TouchEventManager::IsAnyTouchActive() const { | 561 bool TouchEventManager::IsAnyTouchActive() const { |
524 return touch_pressed_; | 562 return touch_pressed_; |
525 } | 563 } |
526 | 564 |
527 } // namespace blink | 565 } // namespace blink |
OLD | NEW |