| 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/PointerEventManager.h" | 5 #include "core/input/PointerEventManager.h" |
| 6 | 6 |
| 7 #include "core/dom/ElementTraversal.h" | 7 #include "core/dom/ElementTraversal.h" |
| 8 #include "core/dom/UserGestureIndicator.h" | 8 #include "core/dom/UserGestureIndicator.h" |
| 9 #include "core/dom/shadow/FlatTreeTraversal.h" | 9 #include "core/dom/shadow/FlatTreeTraversal.h" |
| 10 #include "core/events/MouseEvent.h" | 10 #include "core/events/MouseEvent.h" |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 bool new_touch_sequence = true; | 287 bool new_touch_sequence = true; |
| 288 for (unsigned i = 0; i < event.touches_length; ++i) { | 288 for (unsigned i = 0; i < event.touches_length; ++i) { |
| 289 if (event.touches[i].state != WebTouchPoint::kStatePressed) { | 289 if (event.touches[i].state != WebTouchPoint::kStatePressed) { |
| 290 new_touch_sequence = false; | 290 new_touch_sequence = false; |
| 291 break; | 291 break; |
| 292 } | 292 } |
| 293 } | 293 } |
| 294 if (new_touch_sequence) | 294 if (new_touch_sequence) |
| 295 UnblockTouchPointers(); | 295 UnblockTouchPointers(); |
| 296 | 296 |
| 297 // Do any necessary hit-tests and compute the event targets for all pointers | 297 // Do the first point target calculation to create the user gesture. |
| 298 // in the event. | 298 EventHandlingUtil::PointerEventTarget first_pointer_event_target; |
| 299 HeapVector<TouchEventManager::TouchInfo> touch_infos; | 299 if (event.touches_length) { |
| 300 ComputeTouchTargets(event, touch_infos); | 300 first_pointer_event_target = |
| 301 ComputePointerEventTarget(event.TouchPointInRootFrame(0)); |
| 302 } |
| 301 | 303 |
| 302 // Any finger lifting is a user gesture only when it wasn't associated with a | 304 // Any finger lifting is a user gesture only when it wasn't associated with a |
| 303 // scroll. | 305 // scroll. |
| 304 // https://docs.google.com/document/d/1oF1T3O7_E4t1PYHV6gyCwHxOi3ystm0eSL5xZu7
nvOg/edit# | 306 // https://docs.google.com/document/d/1oF1T3O7_E4t1PYHV6gyCwHxOi3ystm0eSL5xZu7
nvOg/edit# |
| 305 // Re-use the same UserGesture for touchend and pointerup (but not for the | 307 // Re-use the same UserGesture for touchend and pointerup (but not for the |
| 306 // mouse events generated by GestureTap). | 308 // mouse events generated by GestureTap). |
| 307 // For the rare case of multi-finger scenarios spanning documents, it | 309 // For the rare case of multi-finger scenarios spanning documents, it |
| 308 // seems extremely unlikely to matter which document the gesture is | 310 // seems extremely unlikely to matter which document the gesture is |
| 309 // associated with so just pick the first finger. | 311 // associated with so just pick the first finger. |
| 310 RefPtr<UserGestureToken> possible_gesture_token; | 312 RefPtr<UserGestureToken> possible_gesture_token; |
| 311 if (event.GetType() == WebInputEvent::kTouchEnd && | 313 if (event.GetType() == WebInputEvent::kTouchEnd && |
| 312 !in_canceled_state_for_pointer_type_touch_ && !touch_infos.IsEmpty() && | 314 !in_canceled_state_for_pointer_type_touch_ && event.touches_length && |
| 313 touch_infos[0].target_frame) { | 315 first_pointer_event_target.target_frame) { |
| 314 possible_gesture_token = | 316 possible_gesture_token = UserGestureToken::Create( |
| 315 UserGestureToken::Create(touch_infos[0].target_frame->GetDocument()); | 317 first_pointer_event_target.target_frame->GetDocument()); |
| 316 } | 318 } |
| 317 UserGestureIndicator holder(possible_gesture_token); | 319 UserGestureIndicator holder(possible_gesture_token); |
| 318 | 320 |
| 319 DispatchTouchPointerEvents(event, coalesced_events, touch_infos); | 321 HeapVector<EventHandlingUtil::PointerEventTarget> pointer_event_targets; |
| 322 |
| 323 for (unsigned touch_point_idx = 0; touch_point_idx < event.touches_length; |
| 324 ++touch_point_idx) { |
| 325 // Do any necessary hit-tests and compute the event targets for all pointers |
| 326 // in the event. |
| 327 const auto& touch_point = event.TouchPointInRootFrame(touch_point_idx); |
| 328 EventHandlingUtil::PointerEventTarget pointer_event_target = |
| 329 touch_point_idx ? ComputePointerEventTarget(touch_point) |
| 330 : first_pointer_event_target; |
| 331 pointer_event_targets.push_back(pointer_event_target); |
| 332 |
| 333 DispatchTouchPointerEvent( |
| 334 touch_point, pointer_event_target, |
| 335 GetCoalescedPoints(coalesced_events, touch_point.id), |
| 336 static_cast<WebInputEvent::Modifiers>(event.GetModifiers()), |
| 337 event.TimeStampSeconds(), event.unique_touch_event_id); |
| 338 } |
| 320 | 339 |
| 321 return touch_event_manager_->HandleTouchEvent(event, coalesced_events, | 340 return touch_event_manager_->HandleTouchEvent(event, coalesced_events, |
| 322 touch_infos); | 341 pointer_event_targets); |
| 323 } | 342 } |
| 324 | 343 |
| 325 void PointerEventManager::ComputeTouchTargets( | 344 EventHandlingUtil::PointerEventTarget |
| 326 const WebTouchEvent& event, | 345 PointerEventManager::ComputePointerEventTarget( |
| 327 HeapVector<TouchEventManager::TouchInfo>& touch_infos) { | 346 const WebTouchPoint& touch_point) { |
| 328 for (unsigned touch_point = 0; touch_point < event.touches_length; | 347 EventHandlingUtil::PointerEventTarget pointer_event_target; |
| 329 ++touch_point) { | |
| 330 TouchEventManager::TouchInfo touch_info; | |
| 331 touch_info.point = event.TouchPointInRootFrame(touch_point); | |
| 332 | 348 |
| 333 int pointer_id = pointer_event_factory_.GetPointerEventId(touch_info.point); | 349 int pointer_id = pointer_event_factory_.GetPointerEventId(touch_point); |
| 334 // Do the hit test either when the touch first starts or when the touch | 350 // Do the hit test either when the touch first starts or when the touch |
| 335 // is not captured. |m_pendingPointerCaptureTarget| indicates the target | 351 // is not captured. |m_pendingPointerCaptureTarget| indicates the target |
| 336 // that will be capturing this event. |m_pointerCaptureTarget| may not | 352 // that will be capturing this event. |m_pointerCaptureTarget| may not |
| 337 // have this target yet since the processing of that will be done right | 353 // have this target yet since the processing of that will be done right |
| 338 // before firing the event. | 354 // before firing the event. |
| 339 if (touch_info.point.state == WebTouchPoint::kStatePressed || | 355 if (touch_point.state == WebTouchPoint::kStatePressed || |
| 340 !pending_pointer_capture_target_.Contains(pointer_id)) { | 356 !pending_pointer_capture_target_.Contains(pointer_id)) { |
| 341 HitTestRequest::HitTestRequestType hit_type = | 357 HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kTouchEvent | |
| 342 HitTestRequest::kTouchEvent | HitTestRequest::kReadOnly | | 358 HitTestRequest::kReadOnly | |
| 343 HitTestRequest::kActive; | 359 HitTestRequest::kActive; |
| 344 LayoutPoint page_point = LayoutPoint(frame_->View()->RootFrameToContents( | 360 LayoutPoint page_point = LayoutPoint( |
| 345 touch_info.point.PositionInWidget())); | 361 frame_->View()->RootFrameToContents(touch_point.PositionInWidget())); |
| 346 HitTestResult hit_test_tesult = | 362 HitTestResult hit_test_tesult = |
| 347 frame_->GetEventHandler().HitTestResultAtPoint(page_point, hit_type); | 363 frame_->GetEventHandler().HitTestResultAtPoint(page_point, hit_type); |
| 348 Node* node = hit_test_tesult.InnerNode(); | 364 Node* node = hit_test_tesult.InnerNode(); |
| 349 if (node) { | 365 if (node) { |
| 350 touch_info.target_frame = node->GetDocument().GetFrame(); | 366 pointer_event_target.target_frame = node->GetDocument().GetFrame(); |
| 351 if (isHTMLCanvasElement(node)) { | 367 if (isHTMLCanvasElement(node)) { |
| 352 HitTestCanvasResult* hit_test_canvas_result = | 368 HitTestCanvasResult* hit_test_canvas_result = |
| 353 toHTMLCanvasElement(node)->GetControlAndIdIfHitRegionExists( | 369 toHTMLCanvasElement(node)->GetControlAndIdIfHitRegionExists( |
| 354 hit_test_tesult.PointInInnerNodeFrame()); | 370 hit_test_tesult.PointInInnerNodeFrame()); |
| 355 if (hit_test_canvas_result->GetControl()) | 371 if (hit_test_canvas_result->GetControl()) |
| 356 node = hit_test_canvas_result->GetControl(); | 372 node = hit_test_canvas_result->GetControl(); |
| 357 touch_info.region = hit_test_canvas_result->GetId(); | 373 pointer_event_target.region = hit_test_canvas_result->GetId(); |
| 358 } | |
| 359 // TODO(crbug.com/612456): We need to investigate whether pointer | |
| 360 // events should go to text nodes or not. If so we need to | |
| 361 // update the mouse code as well. Also this logic looks similar | |
| 362 // to the one in TouchEventManager. We should be able to | |
| 363 // refactor it better after this investigation. | |
| 364 if (node->IsTextNode()) | |
| 365 node = FlatTreeTraversal::Parent(*node); | |
| 366 touch_info.touch_node = node; | |
| 367 } | 374 } |
| 368 } else { | 375 // TODO(crbug.com/612456): We need to investigate whether pointer |
| 369 // Set the target of pointer event to the captured node as this | 376 // events should go to text nodes or not. If so we need to |
| 370 // pointer is captured otherwise it would have gone to the if block | 377 // update the mouse code as well. Also this logic looks similar |
| 371 // and perform a hit-test. | 378 // to the one in TouchEventManager. We should be able to |
| 372 touch_info.touch_node = | 379 // refactor it better after this investigation. |
| 373 pending_pointer_capture_target_.at(pointer_id)->ToNode(); | 380 if (node->IsTextNode()) |
| 374 touch_info.target_frame = touch_info.touch_node->GetDocument().GetFrame(); | 381 node = FlatTreeTraversal::Parent(*node); |
| 382 pointer_event_target.target_node = node; |
| 375 } | 383 } |
| 376 | 384 } else { |
| 377 touch_infos.push_back(touch_info); | 385 // Set the target of pointer event to the captured node as this |
| 386 // pointer is captured otherwise it would have gone to the if block |
| 387 // and perform a hit-test. |
| 388 pointer_event_target.target_node = |
| 389 pending_pointer_capture_target_.at(pointer_id)->ToNode(); |
| 390 pointer_event_target.target_frame = |
| 391 pointer_event_target.target_node->GetDocument().GetFrame(); |
| 378 } | 392 } |
| 393 return pointer_event_target; |
| 379 } | 394 } |
| 380 | 395 |
| 381 void PointerEventManager::DispatchTouchPointerEvents( | 396 void PointerEventManager::DispatchTouchPointerEvent( |
| 382 const WebTouchEvent& event, | 397 const WebTouchPoint& touch_point, |
| 383 const Vector<WebTouchEvent>& coalesced_events, | 398 const EventHandlingUtil::PointerEventTarget& pointer_event_target, |
| 384 HeapVector<TouchEventManager::TouchInfo>& touch_infos) { | 399 const Vector<std::pair<WebTouchPoint, TimeTicks>>& coalesced_events, |
| 400 WebInputEvent::Modifiers modifiers, |
| 401 double timestamp, |
| 402 uint32_t unique_touch_event_id) { |
| 385 // Iterate through the touch points, sending PointerEvents to the targets as | 403 // Iterate through the touch points, sending PointerEvents to the targets as |
| 386 // required. | 404 // required. |
| 387 for (auto touch_info : touch_infos) { | 405 // Do not send pointer events for stationary touches or null targetFrame |
| 388 const WebTouchPoint& touch_point = touch_info.point; | 406 if (pointer_event_target.target_node && pointer_event_target.target_frame && |
| 389 // Do not send pointer events for stationary touches or null targetFrame | 407 touch_point.state != WebTouchPoint::kStateStationary && |
| 390 if (touch_info.touch_node && touch_info.target_frame && | 408 !in_canceled_state_for_pointer_type_touch_) { |
| 391 touch_point.state != WebTouchPoint::kStateStationary && | 409 PointerEvent* pointer_event = pointer_event_factory_.Create( |
| 392 !in_canceled_state_for_pointer_type_touch_) { | 410 touch_point, coalesced_events, |
| 393 PointerEvent* pointer_event = pointer_event_factory_.Create( | 411 static_cast<WebInputEvent::Modifiers>(modifiers), |
| 394 touch_point, GetCoalescedPoints(coalesced_events, touch_point.id), | 412 TimeTicks::FromSeconds(timestamp), pointer_event_target.target_frame, |
| 395 static_cast<WebInputEvent::Modifiers>(event.GetModifiers()), | 413 pointer_event_target.target_node |
| 396 TimeTicks::FromSeconds(event.TimeStampSeconds()), | 414 ? pointer_event_target.target_node->GetDocument().domWindow() |
| 397 touch_info.target_frame, | 415 : nullptr); |
| 398 touch_info.touch_node | |
| 399 ? touch_info.touch_node->GetDocument().domWindow() | |
| 400 : nullptr); | |
| 401 | 416 |
| 402 WebInputEventResult result = | 417 WebInputEventResult result = |
| 403 SendTouchPointerEvent(touch_info.touch_node, pointer_event); | 418 SendTouchPointerEvent(pointer_event_target.target_node, pointer_event); |
| 404 | 419 |
| 405 // If a pointerdown has been canceled, queue the unique id to allow | 420 // If a pointerdown has been canceled, queue the unique id to allow |
| 406 // suppressing mouse events from gesture events. For mouse events | 421 // suppressing mouse events from gesture events. For mouse events |
| 407 // fired from GestureTap & GestureLongPress (which are triggered by | 422 // fired from GestureTap & GestureLongPress (which are triggered by |
| 408 // single touches only), it is enough to queue the ids only for | 423 // single touches only), it is enough to queue the ids only for |
| 409 // primary pointers. | 424 // primary pointers. |
| 410 // TODO(mustaq): What about other cases (e.g. GestureTwoFingerTap)? | 425 // TODO(mustaq): What about other cases (e.g. GestureTwoFingerTap)? |
| 411 if (result != WebInputEventResult::kNotHandled && | 426 if (result != WebInputEventResult::kNotHandled && |
| 412 pointer_event->type() == EventTypeNames::pointerdown && | 427 pointer_event->type() == EventTypeNames::pointerdown && |
| 413 pointer_event->isPrimary()) { | 428 pointer_event->isPrimary()) { |
| 414 touch_ids_for_canceled_pointerdowns_.push_back( | 429 touch_ids_for_canceled_pointerdowns_.push_back(unique_touch_event_id); |
| 415 event.unique_touch_event_id); | |
| 416 } | |
| 417 } | 430 } |
| 418 } | 431 } |
| 419 } | 432 } |
| 420 | 433 |
| 421 WebInputEventResult PointerEventManager::SendTouchPointerEvent( | 434 WebInputEventResult PointerEventManager::SendTouchPointerEvent( |
| 422 EventTarget* target, | 435 EventTarget* target, |
| 423 PointerEvent* pointer_event) { | 436 PointerEvent* pointer_event) { |
| 424 if (in_canceled_state_for_pointer_type_touch_) | 437 if (in_canceled_state_for_pointer_type_touch_) |
| 425 return WebInputEventResult::kNotHandled; | 438 return WebInputEventResult::kNotHandled; |
| 426 | 439 |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 if (first_id > unique_touch_event_id) | 745 if (first_id > unique_touch_event_id) |
| 733 return false; | 746 return false; |
| 734 touch_ids_for_canceled_pointerdowns_.TakeFirst(); | 747 touch_ids_for_canceled_pointerdowns_.TakeFirst(); |
| 735 if (first_id == unique_touch_event_id) | 748 if (first_id == unique_touch_event_id) |
| 736 return true; | 749 return true; |
| 737 } | 750 } |
| 738 return false; | 751 return false; |
| 739 } | 752 } |
| 740 | 753 |
| 741 } // namespace blink | 754 } // namespace blink |
| OLD | NEW |