Chromium Code Reviews| Index: third_party/WebKit/Source/core/events/PointerEventManager.cpp |
| diff --git a/third_party/WebKit/Source/core/events/PointerEventManager.cpp b/third_party/WebKit/Source/core/events/PointerEventManager.cpp |
| index 3b6414415c80268e86bd483b1aa5feb68b7f78e5..89daa2c60da882dfe17112cb77dc5cf16b5689d8 100644 |
| --- a/third_party/WebKit/Source/core/events/PointerEventManager.cpp |
| +++ b/third_party/WebKit/Source/core/events/PointerEventManager.cpp |
| @@ -3,6 +3,7 @@ |
| // found in the LICENSE file. |
| #include "core/events/PointerEventManager.h" |
| +#include "core/dom/shadow/ComposedTreeTraversal.h" |
| namespace blink { |
| @@ -26,6 +27,37 @@ const char* pointerTypeNameForWebPointPointerType(WebPointerProperties::PointerT |
| return ""; |
| } |
| +const AtomicString& pointerEventNameForTouchPointState(PlatformTouchPoint::State state) |
| +{ |
| + switch (state) { |
| + case PlatformTouchPoint::TouchReleased: |
| + return EventTypeNames::pointerup; |
| + case PlatformTouchPoint::TouchCancelled: |
| + return EventTypeNames::pointercancel; |
| + case PlatformTouchPoint::TouchPressed: |
| + return EventTypeNames::pointerdown; |
| + case PlatformTouchPoint::TouchMoved: |
| + return EventTypeNames::pointermove; |
| + case PlatformTouchPoint::TouchStationary: |
| + // Fall through to default |
| + default: |
| + ASSERT_NOT_REACHED(); |
| + return emptyAtom; |
| + } |
| +} |
| + |
| +bool isInDocument(EventTarget *n) |
| +{ |
| + return n && n->toNode() && n->toNode()->inDocument(); |
| +} |
| + |
| +void sendPointerEventToTarget(EventTarget *target, |
| + PassRefPtrWillBeRawPtr<PointerEvent> pointerevent) |
| +{ |
| + if (isInDocument(target)) |
| + target->dispatchEvent(pointerevent); |
| +} |
| + |
| } // namespace |
| const PointerEventManager::MappedId PointerEventManager::s_invalidId = 0; |
| @@ -89,7 +121,8 @@ PassRefPtrWillBeRawPtr<PointerEvent> PointerEventManager::create(const AtomicStr |
| return PointerEvent::create(type, pointerEventInit); |
| } |
| -PassRefPtrWillBeRawPtr<PointerEvent> PointerEventManager::create(const AtomicString& type, |
| +PassRefPtrWillBeRawPtr<PointerEvent> PointerEventManager::create( |
| + const AtomicString& type, |
| const PlatformTouchPoint& touchPoint, PlatformEvent::Modifiers modifiers, |
| const double width, const double height, |
| const double clientX, const double clientY) |
| @@ -126,8 +159,152 @@ PassRefPtrWillBeRawPtr<PointerEvent> PointerEventManager::create(const AtomicStr |
| return PointerEvent::create(type, pointerEventInit); |
| } |
| +PassRefPtrWillBeRawPtr<PointerEvent> PointerEventManager::create( |
| + PassRefPtrWillBeRawPtr<PointerEvent> pointerevent, |
| + const AtomicString& type, |
| + PassRefPtrWillBeRawPtr<EventTarget> relatedTarget) |
| +{ |
| + PointerEventInit pointerEventInit; |
| + |
| + pointerEventInit.setPointerId(pointerevent->pointerId()); |
| + pointerEventInit.setPointerType(pointerevent->pointerType()); |
| + pointerEventInit.setIsPrimary(pointerevent->isPrimary()); |
| + pointerEventInit.setWidth(pointerevent->width()); |
| + pointerEventInit.setHeight(pointerevent->height()); |
| + pointerEventInit.setTiltX(pointerevent->tiltX()); |
| + pointerEventInit.setTiltY(pointerevent->tiltY()); |
| + pointerEventInit.setScreenX(pointerevent->screenX()); |
| + pointerEventInit.setScreenY(pointerevent->screenY()); |
| + pointerEventInit.setClientX(pointerevent->clientX()); |
| + pointerEventInit.setClientY(pointerevent->clientY()); |
| + pointerEventInit.setButton(pointerevent->button()); |
| + pointerEventInit.setButtons(pointerevent->buttons()); |
| + pointerEventInit.setPressure(pointerevent->pressure()); |
| -PassRefPtrWillBeRawPtr<PointerEvent> PointerEventManager::createPointerCancel(const PlatformTouchPoint& touchPoint) |
| + pointerEventInit.setBubbles(type != EventTypeNames::pointerenter |
| + && type != EventTypeNames::pointerleave); |
| + pointerEventInit.setCancelable(type != EventTypeNames::pointerenter |
| + && type != EventTypeNames::pointerleave |
| + && type != EventTypeNames::pointercancel); |
| + |
| + return PointerEvent::create(type, pointerEventInit); |
| +} |
| + |
| +void PointerEventManager::sendNodeTransitionEvents( |
|
mustaq
2016/02/08 17:01:34
This duplication looks bad. All you need here is a
Navid Zolghadr
2016/02/10 16:25:29
Done.
|
| + EventTarget* exitedTarget, EventTarget* enteredTarget, |
| + PassRefPtrWillBeRawPtr<PointerEvent> pointerEvent) |
| +{ |
| + if (exitedTarget == enteredTarget) |
| + return; |
| + |
| + if (!RuntimeEnabledFeatures::pointerEventEnabled()) |
| + return; |
| + |
| + // Create lists of all exited/entered ancestors, locate the common ancestor |
| + WillBeHeapVector<RefPtrWillBeMember<Node>, 32> exitedAncestors; |
| + WillBeHeapVector<RefPtrWillBeMember<Node>, 32> enteredAncestors; |
| + if (isInDocument(exitedTarget)) { |
| + Node* exitedNode = exitedTarget->toNode(); |
| + exitedNode->updateDistribution(); |
| + for (Node* node = exitedNode; node; node = ComposedTreeTraversal::parent(*node)) |
| + exitedAncestors.append(node); |
| + } |
| + if (isInDocument(enteredTarget)) { |
| + Node* enteredNode = enteredTarget->toNode(); |
| + enteredNode->updateDistribution(); |
| + for (Node* node = enteredNode; node; node = ComposedTreeTraversal::parent(*node)) |
| + enteredAncestors.append(node); |
| + } |
| + |
| + size_t exitedAncestorIndex = exitedAncestors.size(); |
| + size_t enteredAncestorIndex = enteredAncestors.size(); |
| + if (!exitedAncestors.isEmpty() && !enteredAncestors.isEmpty()) { |
| + for (size_t i = exitedAncestors.size(), j = enteredAncestors.size(); i>0 && j>0; j--, i--) { |
| + if (exitedAncestors[i-1] == enteredAncestors[j-1]) { |
| + exitedAncestorIndex = i-1; |
| + enteredAncestorIndex = j-1; |
| + } else { |
| + break; |
| + } |
| + } |
| + } |
| + |
| + // Dispatch pointerout |
| + sendPointerEventToTarget(exitedTarget, |
| + create(pointerEvent, EventTypeNames::pointerout, enteredTarget)); |
| + |
| + // Dispatch pointerleave events, in child-to-parent order |
| + for (size_t i = 0; i < exitedAncestorIndex; i++) { |
| + sendPointerEventToTarget(exitedAncestors[i].get(), |
| + create(pointerEvent, EventTypeNames::pointerleave, enteredTarget)); |
| + } |
| + |
| + // Dispatch pointerover |
| + sendPointerEventToTarget(enteredTarget, |
| + create(pointerEvent, EventTypeNames::pointerover, exitedTarget)); |
| + |
| + // Dispatch pointerenter events, in parent-to-child order. |
| + for (size_t j = enteredAncestorIndex; j > 0; j--) { |
| + sendPointerEventToTarget(enteredAncestors[j-1].get(), |
| + create(pointerEvent, EventTypeNames::pointerenter, exitedTarget)); |
| + } |
| +} |
| + |
| +void PointerEventManager::setNodeUnderPointer( |
| + PassRefPtrWillBeRawPtr<PointerEvent> pointerevent, EventTarget* target) |
| +{ |
| + if (m_nodeUnderPointer.contains(pointerevent->pointerId())) { |
| + sendNodeTransitionEvents(m_nodeUnderPointer.get( |
| + pointerevent->pointerId()), target, pointerevent); |
| + if (!target) |
| + m_nodeUnderPointer.remove(pointerevent->pointerId()); |
| + else |
| + m_nodeUnderPointer.set(pointerevent->pointerId(), target); |
| + } else if (target) { |
| + sendNodeTransitionEvents(nullptr, target, pointerevent); |
| + m_nodeUnderPointer.add(pointerevent->pointerId(), target); |
| + } |
| +} |
| + |
| +void PointerEventManager::sendTouchCancelPointerEvent(PassRefPtrWillBeRawPtr<EventTarget> target, |
| + const PlatformTouchPoint& point) |
| +{ |
| + RefPtrWillBeRawPtr<PointerEvent> pointerEvent = |
| + createPointerCancel(point); |
| + |
| + // TODO(nzolghadr): crbug.com/579553 dealing with implicit touch capturing vs pointer event capturing |
| + target->dispatchEvent(pointerEvent.get()); |
| + |
| + remove(pointerEvent); |
| + setNodeUnderPointer(pointerEvent, nullptr); |
| +} |
| + |
| +bool PointerEventManager::sendTouchPointerEvent( |
| + PassRefPtrWillBeRawPtr<EventTarget> target, |
| + const PlatformTouchPoint& touchPoint, PlatformEvent::Modifiers modifiers, |
| + const double width, const double height, |
| + const double clientX, const double clientY) |
| +{ |
| + RefPtrWillBeRawPtr<PointerEvent> pointerEvent = create( |
| + pointerEventNameForTouchPointState(touchPoint.state()), |
| + touchPoint, modifiers, width, height, clientX, clientY); |
| + |
| + setNodeUnderPointer(pointerEvent, target); |
| + |
| + // TODO(nzolghadr): crbug.com/579553 dealing with implicit touch capturing vs pointer event capturing |
| + target->dispatchEvent(pointerEvent.get()); |
| + |
| + if (touchPoint.state() == PlatformTouchPoint::TouchReleased |
| + || touchPoint.state() == PlatformTouchPoint::TouchCancelled) { |
| + remove(pointerEvent); |
| + setNodeUnderPointer(pointerEvent, nullptr); |
| + } |
| + |
| + return pointerEvent->defaultPrevented() || pointerEvent->defaultHandled(); |
| +} |
| + |
| +PassRefPtrWillBeRawPtr<PointerEvent> PointerEventManager::createPointerCancel( |
| + const PlatformTouchPoint& touchPoint) |
| { |
| PointerEventInit pointerEventInit; |
| @@ -149,6 +326,11 @@ PointerEventManager::~PointerEventManager() |
| clear(); |
| } |
| +DEFINE_TRACE(PointerEventManager) |
| +{ |
| + visitor->trace(m_nodeUnderPointer); |
| +} |
| + |
| void PointerEventManager::clear() |
| { |
| for (int type = 0; type <= toInt(WebPointerProperties::PointerType::LastEntry); type++) { |
| @@ -157,6 +339,7 @@ void PointerEventManager::clear() |
| } |
| m_idMapping.clear(); |
| m_idReverseMapping.clear(); |
| + m_nodeUnderPointer.clear(); |
| // Always add mouse pointer in initialization and never remove it. |
| // No need to add it to m_idMapping as it is not going to be used with the existing APIs |