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 |