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/DocumentUserGestureToken.h" | 7 #include "core/dom/DocumentUserGestureToken.h" |
8 #include "core/dom/ElementTraversal.h" | 8 #include "core/dom/ElementTraversal.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" |
11 #include "core/frame/FrameView.h" | 11 #include "core/frame/FrameView.h" |
12 #include "core/frame/UseCounter.h" | 12 #include "core/frame/UseCounter.h" |
13 #include "core/html/HTMLCanvasElement.h" | 13 #include "core/html/HTMLCanvasElement.h" |
14 #include "core/input/EventHandler.h" | 14 #include "core/input/EventHandler.h" |
15 #include "core/input/EventHandlingUtil.h" | 15 #include "core/input/EventHandlingUtil.h" |
16 #include "core/input/MouseEventManager.h" | 16 #include "core/input/MouseEventManager.h" |
17 #include "core/input/TouchActionUtil.h" | 17 #include "core/input/TouchActionUtil.h" |
18 #include "core/layout/HitTestCanvasResult.h" | 18 #include "core/layout/HitTestCanvasResult.h" |
19 #include "core/page/ChromeClient.h" | 19 #include "core/page/ChromeClient.h" |
20 #include "core/page/Page.h" | 20 #include "core/page/Page.h" |
21 #include "platform/PlatformTouchEvent.h" | 21 #include "public/platform/WebTouchEvent.h" |
22 | 22 |
23 namespace blink { | 23 namespace blink { |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 size_t toPointerTypeIndex(WebPointerProperties::PointerType t) { | 27 size_t toPointerTypeIndex(WebPointerProperties::PointerType t) { |
28 return static_cast<size_t>(t); | 28 return static_cast<size_t>(t); |
29 } | 29 } |
30 | 30 |
31 bool isInDocument(EventTarget* n) { | 31 bool isInDocument(EventTarget* n) { |
32 return n && n->toNode() && n->toNode()->isConnected(); | 32 return n && n->toNode() && n->toNode()->isConnected(); |
33 } | 33 } |
34 | 34 |
35 Vector<PlatformTouchPoint> getCoalescedPoints( | 35 Vector<WebTouchPoint> getCoalescedPoints( |
36 const Vector<PlatformTouchEvent>& coalescedEvents, | 36 const Vector<WebTouchEvent>& coalescedEvents, |
37 int id) { | 37 int id) { |
38 Vector<PlatformTouchPoint> relatedPoints; | 38 Vector<WebTouchPoint> relatedPoints; |
39 for (const auto& touchEvent : coalescedEvents) { | 39 for (const auto& touchEvent : coalescedEvents) { |
40 for (auto& point : touchEvent.touchPoints()) { | 40 for (unsigned i = 0; i < touchEvent.touchesLength; ++i) { |
41 // TODO(nzolghadr): Need to filter out stationary points | 41 // TODO(nzolghadr): Need to filter out stationary points |
42 if (point.id() == id) | 42 if (touchEvent.touches[i].id == id) |
43 relatedPoints.push_back(point); | 43 relatedPoints.push_back(touchEvent.touchPointInRootFrame(i)); |
44 } | 44 } |
45 } | 45 } |
46 return relatedPoints; | 46 return relatedPoints; |
47 } | 47 } |
48 | 48 |
49 } // namespace | 49 } // namespace |
50 | 50 |
51 PointerEventManager::PointerEventManager(LocalFrame& frame, | 51 PointerEventManager::PointerEventManager(LocalFrame& frame, |
52 MouseEventManager& mouseEventManager) | 52 MouseEventManager& mouseEventManager) |
53 : m_frame(frame), | 53 : m_frame(frame), |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 | 263 |
264 removePointer(pointerEvent); | 264 removePointer(pointerEvent); |
265 } | 265 } |
266 } | 266 } |
267 | 267 |
268 void PointerEventManager::unblockTouchPointers() { | 268 void PointerEventManager::unblockTouchPointers() { |
269 m_inCanceledStateForPointerTypeTouch = false; | 269 m_inCanceledStateForPointerTypeTouch = false; |
270 } | 270 } |
271 | 271 |
272 WebInputEventResult PointerEventManager::handleTouchEvents( | 272 WebInputEventResult PointerEventManager::handleTouchEvents( |
273 const PlatformTouchEvent& event, | 273 const WebTouchEvent& event, |
274 const Vector<PlatformTouchEvent>& coalescedEvents) { | 274 const Vector<WebTouchEvent>& coalescedEvents) { |
275 if (event.type() == PlatformEvent::TouchScrollStarted) { | 275 if (event.type() == WebInputEvent::TouchScrollStarted) { |
276 blockTouchPointers(); | 276 blockTouchPointers(); |
277 return WebInputEventResult::HandledSystem; | 277 return WebInputEventResult::HandledSystem; |
278 } | 278 } |
279 | 279 |
280 bool newTouchSequence = true; | 280 bool newTouchSequence = true; |
281 for (const auto& touchPoint : event.touchPoints()) { | 281 for (unsigned i = 0; i < event.touchesLength; ++i) { |
282 if (touchPoint.state() != PlatformTouchPoint::TouchPressed) { | 282 if (event.touches[i].state != WebTouchPoint::StatePressed) { |
283 newTouchSequence = false; | 283 newTouchSequence = false; |
284 break; | 284 break; |
285 } | 285 } |
286 } | 286 } |
287 if (newTouchSequence) | 287 if (newTouchSequence) |
288 unblockTouchPointers(); | 288 unblockTouchPointers(); |
289 | 289 |
290 // Do any necessary hit-tests and compute the event targets for all pointers | 290 // Do any necessary hit-tests and compute the event targets for all pointers |
291 // in the event. | 291 // in the event. |
292 HeapVector<TouchEventManager::TouchInfo> touchInfos; | 292 HeapVector<TouchEventManager::TouchInfo> touchInfos; |
293 computeTouchTargets(event, touchInfos); | 293 computeTouchTargets(event, touchInfos); |
294 | 294 |
295 // Any finger lifting is a user gesture only when it wasn't associated with a | 295 // Any finger lifting is a user gesture only when it wasn't associated with a |
296 // scroll. | 296 // scroll. |
297 // https://docs.google.com/document/d/1oF1T3O7_E4t1PYHV6gyCwHxOi3ystm0eSL5xZu7
nvOg/edit# | 297 // https://docs.google.com/document/d/1oF1T3O7_E4t1PYHV6gyCwHxOi3ystm0eSL5xZu7
nvOg/edit# |
298 // Re-use the same UserGesture for touchend and pointerup (but not for the | 298 // Re-use the same UserGesture for touchend and pointerup (but not for the |
299 // mouse events generated by GestureTap). | 299 // mouse events generated by GestureTap). |
300 // For the rare case of multi-finger scenarios spanning documents, it | 300 // For the rare case of multi-finger scenarios spanning documents, it |
301 // seems extremely unlikely to matter which document the gesture is | 301 // seems extremely unlikely to matter which document the gesture is |
302 // associated with so just pick the first finger. | 302 // associated with so just pick the first finger. |
303 RefPtr<UserGestureToken> possibleGestureToken; | 303 RefPtr<UserGestureToken> possibleGestureToken; |
304 if (event.type() == PlatformEvent::TouchEnd && | 304 if (event.type() == WebInputEvent::TouchEnd && |
305 !m_inCanceledStateForPointerTypeTouch && !touchInfos.isEmpty() && | 305 !m_inCanceledStateForPointerTypeTouch && !touchInfos.isEmpty() && |
306 touchInfos[0].targetFrame) { | 306 touchInfos[0].targetFrame) { |
307 possibleGestureToken = | 307 possibleGestureToken = |
308 DocumentUserGestureToken::create(touchInfos[0].targetFrame->document()); | 308 DocumentUserGestureToken::create(touchInfos[0].targetFrame->document()); |
309 } | 309 } |
310 UserGestureIndicator holder(possibleGestureToken); | 310 UserGestureIndicator holder(possibleGestureToken); |
311 | 311 |
312 dispatchTouchPointerEvents(event, coalescedEvents, touchInfos); | 312 dispatchTouchPointerEvents(event, coalescedEvents, touchInfos); |
313 | 313 |
314 return m_touchEventManager->handleTouchEvent(event, touchInfos); | 314 return m_touchEventManager->handleTouchEvent(event, touchInfos); |
315 } | 315 } |
316 | 316 |
317 void PointerEventManager::computeTouchTargets( | 317 void PointerEventManager::computeTouchTargets( |
318 const PlatformTouchEvent& event, | 318 const WebTouchEvent& event, |
319 HeapVector<TouchEventManager::TouchInfo>& touchInfos) { | 319 HeapVector<TouchEventManager::TouchInfo>& touchInfos) { |
320 for (const auto& touchPoint : event.touchPoints()) { | 320 for (unsigned touchPoint = 0; touchPoint < event.touchesLength; |
| 321 ++touchPoint) { |
321 TouchEventManager::TouchInfo touchInfo; | 322 TouchEventManager::TouchInfo touchInfo; |
322 touchInfo.point = touchPoint; | 323 touchInfo.point = event.touchPointInRootFrame(touchPoint); |
323 | 324 |
324 int pointerId = | 325 int pointerId = m_pointerEventFactory.getPointerEventId(touchInfo.point); |
325 m_pointerEventFactory.getPointerEventId(touchPoint.pointerProperties()); | |
326 // Do the hit test either when the touch first starts or when the touch | 326 // Do the hit test either when the touch first starts or when the touch |
327 // is not captured. |m_pendingPointerCaptureTarget| indicates the target | 327 // is not captured. |m_pendingPointerCaptureTarget| indicates the target |
328 // that will be capturing this event. |m_pointerCaptureTarget| may not | 328 // that will be capturing this event. |m_pointerCaptureTarget| may not |
329 // have this target yet since the processing of that will be done right | 329 // have this target yet since the processing of that will be done right |
330 // before firing the event. | 330 // before firing the event. |
331 if (touchInfo.point.state() == PlatformTouchPoint::TouchPressed || | 331 if (touchInfo.point.state == WebTouchPoint::StatePressed || |
332 !m_pendingPointerCaptureTarget.contains(pointerId)) { | 332 !m_pendingPointerCaptureTarget.contains(pointerId)) { |
333 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent | | 333 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent | |
334 HitTestRequest::ReadOnly | | 334 HitTestRequest::ReadOnly | |
335 HitTestRequest::Active; | 335 HitTestRequest::Active; |
336 LayoutPoint pagePoint = LayoutPoint( | 336 LayoutPoint pagePoint = LayoutPoint( |
337 m_frame->view()->rootFrameToContents(touchInfo.point.pos())); | 337 m_frame->view()->rootFrameToContents(touchInfo.point.position)); |
338 HitTestResult hitTestTesult = | 338 HitTestResult hitTestTesult = |
339 m_frame->eventHandler().hitTestResultAtPoint(pagePoint, hitType); | 339 m_frame->eventHandler().hitTestResultAtPoint(pagePoint, hitType); |
340 Node* node = hitTestTesult.innerNode(); | 340 Node* node = hitTestTesult.innerNode(); |
341 if (node) { | 341 if (node) { |
342 touchInfo.targetFrame = node->document().frame(); | 342 touchInfo.targetFrame = node->document().frame(); |
343 if (isHTMLCanvasElement(node)) { | 343 if (isHTMLCanvasElement(node)) { |
344 HitTestCanvasResult* hitTestCanvasResult = | 344 HitTestCanvasResult* hitTestCanvasResult = |
345 toHTMLCanvasElement(node)->getControlAndIdIfHitRegionExists( | 345 toHTMLCanvasElement(node)->getControlAndIdIfHitRegionExists( |
346 hitTestTesult.pointInInnerNodeFrame()); | 346 hitTestTesult.pointInInnerNodeFrame()); |
347 if (hitTestCanvasResult->getControl()) | 347 if (hitTestCanvasResult->getControl()) |
(...skipping 16 matching lines...) Expand all Loading... |
364 touchInfo.touchNode = | 364 touchInfo.touchNode = |
365 m_pendingPointerCaptureTarget.get(pointerId)->toNode(); | 365 m_pendingPointerCaptureTarget.get(pointerId)->toNode(); |
366 touchInfo.targetFrame = touchInfo.touchNode->document().frame(); | 366 touchInfo.targetFrame = touchInfo.touchNode->document().frame(); |
367 } | 367 } |
368 | 368 |
369 touchInfos.push_back(touchInfo); | 369 touchInfos.push_back(touchInfo); |
370 } | 370 } |
371 } | 371 } |
372 | 372 |
373 void PointerEventManager::dispatchTouchPointerEvents( | 373 void PointerEventManager::dispatchTouchPointerEvents( |
374 const PlatformTouchEvent& event, | 374 const WebTouchEvent& event, |
375 const Vector<PlatformTouchEvent>& coalescedEvents, | 375 const Vector<WebTouchEvent>& coalescedEvents, |
376 HeapVector<TouchEventManager::TouchInfo>& touchInfos) { | 376 HeapVector<TouchEventManager::TouchInfo>& touchInfos) { |
377 // Iterate through the touch points, sending PointerEvents to the targets as | 377 // Iterate through the touch points, sending PointerEvents to the targets as |
378 // required. | 378 // required. |
379 for (auto touchInfo : touchInfos) { | 379 for (auto touchInfo : touchInfos) { |
380 const PlatformTouchPoint& touchPoint = touchInfo.point; | 380 const WebTouchPoint& touchPoint = touchInfo.point; |
381 // Do not send pointer events for stationary touches or null targetFrame | 381 // Do not send pointer events for stationary touches or null targetFrame |
382 if (touchInfo.touchNode && touchInfo.targetFrame && | 382 if (touchInfo.touchNode && touchInfo.targetFrame && |
383 touchPoint.state() != PlatformTouchPoint::TouchStationary && | 383 touchPoint.state != WebTouchPoint::StateStationary && |
384 !m_inCanceledStateForPointerTypeTouch) { | 384 !m_inCanceledStateForPointerTypeTouch) { |
385 PointerEvent* pointerEvent = m_pointerEventFactory.create( | 385 PointerEvent* pointerEvent = m_pointerEventFactory.create( |
386 touchPoint, getCoalescedPoints(coalescedEvents, touchPoint.id()), | 386 touchPoint, getCoalescedPoints(coalescedEvents, touchPoint.id), |
387 event.getModifiers(), touchInfo.targetFrame, | 387 static_cast<WebInputEvent::Modifiers>(event.modifiers()), |
| 388 touchInfo.targetFrame, |
388 touchInfo.touchNode ? touchInfo.touchNode->document().domWindow() | 389 touchInfo.touchNode ? touchInfo.touchNode->document().domWindow() |
389 : nullptr); | 390 : nullptr); |
390 | 391 |
391 WebInputEventResult result = | 392 WebInputEventResult result = |
392 sendTouchPointerEvent(touchInfo.touchNode, pointerEvent); | 393 sendTouchPointerEvent(touchInfo.touchNode, pointerEvent); |
393 | 394 |
394 // If a pointerdown has been canceled, queue the unique id to allow | 395 // If a pointerdown has been canceled, queue the unique id to allow |
395 // suppressing mouse events from gesture events. For mouse events | 396 // suppressing mouse events from gesture events. For mouse events |
396 // fired from GestureTap & GestureLongPress (which are triggered by | 397 // fired from GestureTap & GestureLongPress (which are triggered by |
397 // single touches only), it is enough to queue the ids only for | 398 // single touches only), it is enough to queue the ids only for |
398 // primary pointers. | 399 // primary pointers. |
399 // TODO(mustaq): What about other cases (e.g. GestureTwoFingerTap)? | 400 // TODO(mustaq): What about other cases (e.g. GestureTwoFingerTap)? |
400 if (result != WebInputEventResult::NotHandled && | 401 if (result != WebInputEventResult::NotHandled && |
401 pointerEvent->type() == EventTypeNames::pointerdown && | 402 pointerEvent->type() == EventTypeNames::pointerdown && |
402 pointerEvent->isPrimary()) { | 403 pointerEvent->isPrimary()) { |
403 m_touchIdsForCanceledPointerdowns.append(event.uniqueTouchEventId()); | 404 m_touchIdsForCanceledPointerdowns.append(event.uniqueTouchEventId); |
404 } | 405 } |
405 } | 406 } |
406 } | 407 } |
407 } | 408 } |
408 | 409 |
409 WebInputEventResult PointerEventManager::sendTouchPointerEvent( | 410 WebInputEventResult PointerEventManager::sendTouchPointerEvent( |
410 EventTarget* target, | 411 EventTarget* target, |
411 PointerEvent* pointerEvent) { | 412 PointerEvent* pointerEvent) { |
412 if (m_inCanceledStateForPointerTypeTouch) | 413 if (m_inCanceledStateForPointerTypeTouch) |
413 return WebInputEventResult::NotHandled; | 414 return WebInputEventResult::NotHandled; |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 if (firstId > uniqueTouchEventId) | 693 if (firstId > uniqueTouchEventId) |
693 return false; | 694 return false; |
694 m_touchIdsForCanceledPointerdowns.takeFirst(); | 695 m_touchIdsForCanceledPointerdowns.takeFirst(); |
695 if (firstId == uniqueTouchEventId) | 696 if (firstId == uniqueTouchEventId) |
696 return true; | 697 return true; |
697 } | 698 } |
698 return false; | 699 return false; |
699 } | 700 } |
700 | 701 |
701 } // namespace blink | 702 } // namespace blink |
OLD | NEW |