| Index: Source/core/page/EventHandler.cpp
|
| diff --git a/Source/core/page/EventHandler.cpp b/Source/core/page/EventHandler.cpp
|
| index d26cd614a18903911ad11f4746158ee73bb540f4..f97079e68754f5e22c0bd6f4e9f23afdce63f9c2 100644
|
| --- a/Source/core/page/EventHandler.cpp
|
| +++ b/Source/core/page/EventHandler.cpp
|
| @@ -45,6 +45,7 @@
|
| #include "core/events/EventPath.h"
|
| #include "core/events/KeyboardEvent.h"
|
| #include "core/events/MouseEvent.h"
|
| +#include "core/events/PointerEvent.h"
|
| #include "core/events/TextEvent.h"
|
| #include "core/events/TouchEvent.h"
|
| #include "core/events/WheelEvent.h"
|
| @@ -237,6 +238,7 @@ EventHandler::EventHandler(LocalFrame* frame)
|
| , m_mouseDownTimestamp(0)
|
| , m_widgetIsLatched(false)
|
| , m_touchPressed(false)
|
| + , m_primaryPointerId(0)
|
| , m_scrollGestureHandlingNode(nullptr)
|
| , m_lastGestureScrollOverWidget(false)
|
| , m_maxMouseMovedDuration(0)
|
| @@ -317,6 +319,7 @@ void EventHandler::clear()
|
| m_scrollbarHandlingScrollGesture = nullptr;
|
| m_maxMouseMovedDuration = 0;
|
| m_touchPressed = false;
|
| + m_primaryPointerId = 0;
|
| m_mouseDownMayStartSelect = false;
|
| m_mouseDownMayStartDrag = false;
|
| m_lastShowPressTimestamp = 0;
|
| @@ -3776,7 +3779,7 @@ void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setL
|
| }
|
| }
|
|
|
| -static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State state)
|
| +static const AtomicString& touchEventNameForTouchPointState(PlatformTouchPoint::State state)
|
| {
|
| switch (state) {
|
| case PlatformTouchPoint::TouchReleased:
|
| @@ -3795,6 +3798,25 @@ static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State
|
| }
|
| }
|
|
|
| +static 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:
|
| + // TouchStationary state is not converted to touch events, so fall through to assert.
|
| + default:
|
| + ASSERT_NOT_REACHED();
|
| + return emptyAtom;
|
| + }
|
| +}
|
| +
|
| HitTestResult EventHandler::hitTestResultInFrame(LocalFrame* frame, const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType)
|
| {
|
| HitTestResult result(HitTestRequest(hitType), point);
|
| @@ -3816,10 +3838,9 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
|
|
|
| const Vector<PlatformTouchPoint>& points = event.touchPoints();
|
|
|
| - unsigned i;
|
| bool freshTouchEvents = true;
|
| bool allTouchReleased = true;
|
| - for (i = 0; i < points.size(); ++i) {
|
| + for (unsigned i = 0; i < points.size(); ++i) {
|
| const PlatformTouchPoint& point = points[i];
|
| if (point.state() != PlatformTouchPoint::TouchPressed)
|
| freshTouchEvents = false;
|
| @@ -3853,7 +3874,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
|
| }
|
|
|
| // First do hit tests for any new touch points.
|
| - for (i = 0; i < points.size(); ++i) {
|
| + for (unsigned i = 0; i < points.size(); ++i) {
|
| const PlatformTouchPoint& point = points[i];
|
|
|
| // Touch events implicitly capture to the touched node, and don't change
|
| @@ -3888,6 +3909,10 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
|
| ASSERT(m_touchSequenceDocument->frame()->view());
|
| }
|
|
|
| + // If it is the first TouchPressed we have seen so far, we will consider it primary.
|
| + if (!m_primaryPointerId)
|
| + m_primaryPointerId = point.id();
|
| +
|
| // Ideally we'd ASSERT(!m_targetForTouchID.contains(point.id())
|
| // since we shouldn't get a touchstart for a touch that's already
|
| // down. However EventSender allows this to be violated and there's
|
| @@ -3904,6 +3929,10 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
|
|
|
| m_touchPressed = !allTouchReleased;
|
|
|
| + unsigned lastPrimaryPointerId = m_primaryPointerId;
|
| + if (allTouchReleased)
|
| + m_primaryPointerId = 0;
|
| +
|
| // If there's no document receiving touch events, or no handlers on the
|
| // document set to receive the events, then we can skip all the rest of
|
| // this work.
|
| @@ -3938,7 +3967,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
|
| EventTargetSet m_targets;
|
| } changedTouches[PlatformTouchPoint::TouchStateEnd];
|
|
|
| - for (i = 0; i < points.size(); ++i) {
|
| + for (unsigned i = 0; i < points.size(); ++i) {
|
| const PlatformTouchPoint& point = points[i];
|
| PlatformTouchPoint::State pointState = point.state();
|
| RefPtrWillBeRawPtr<EventTarget> touchTarget = nullptr;
|
| @@ -4031,20 +4060,59 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
|
| m_touchSequenceUserGestureToken.clear();
|
| }
|
|
|
| - // Now iterate the changedTouches list and m_targets within it, sending
|
| - // events to the targets as required.
|
| bool swallowedEvent = false;
|
| +
|
| + if (RuntimeEnabledFeatures::pointerEventEnabled()) {
|
| + // Iterate the changedTouches list and m_targets within it, sending PointerEvents
|
| + // to the targets as required.
|
| + for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) {
|
| + if (!changedTouches[state].m_touches)
|
| + continue;
|
| +
|
| + const AtomicString& eventName(pointerEventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state)));
|
| + const EventTargetSet& targetsForState = changedTouches[state].m_targets;
|
| +
|
| + for (const RefPtrWillBeMember<EventTarget>& eventTarget : targetsForState) {
|
| + EventTarget* pointerEventTarget = eventTarget.get();
|
| + TouchList* touchesForTarget = touchesByTarget.get(pointerEventTarget);
|
| + for (unsigned i = 0; i < touchesForTarget->length(); i++) {
|
| + Touch* touch = touchesForTarget->item(i);
|
| +
|
| + PointerEventInit pointerEventInit;
|
| + pointerEventInit.setPointerId(touch->identifier());
|
| + pointerEventInit.setWidth(touch->radiusX());
|
| + pointerEventInit.setHeight(touch->radiusY());
|
| + pointerEventInit.setPressure(touch->force());
|
| + pointerEventInit.setTiltX(0.0);
|
| + pointerEventInit.setTiltY(0.0);
|
| + pointerEventInit.setPointerType(eventName);
|
| + pointerEventInit.setIsPrimary(lastPrimaryPointerId == touch->identifier());
|
| +
|
| + RefPtrWillBeRawPtr<PointerEvent> pointerEvent = PointerEvent::create(eventName, pointerEventInit);
|
| + pointerEventTarget->toNode()->dispatchPointerEvent(pointerEvent.get());
|
| + swallowedEvent = swallowedEvent || pointerEvent->defaultPrevented() || pointerEvent->defaultHandled();
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Skip firing TouchEvent's if any PointerEvent was consumed.
|
| + if (swallowedEvent)
|
| + return true;
|
| + }
|
| +
|
| + // Now iterate the changedTouches list and m_targets within it, sending
|
| + // TouchEvents to the targets as required.
|
| for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) {
|
| if (!changedTouches[state].m_touches)
|
| continue;
|
|
|
| - const AtomicString& stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state)));
|
| + const AtomicString& eventName(touchEventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state)));
|
| const EventTargetSet& targetsForState = changedTouches[state].m_targets;
|
| for (const RefPtrWillBeMember<EventTarget>& eventTarget : targetsForState) {
|
| EventTarget* touchEventTarget = eventTarget.get();
|
| RefPtrWillBeRawPtr<TouchEvent> touchEvent = TouchEvent::create(
|
| touches.get(), touchesByTarget.get(touchEventTarget), changedTouches[state].m_touches.get(),
|
| - stateName, touchEventTarget->toNode()->document().domWindow(),
|
| + eventName, touchEventTarget->toNode()->document().domWindow(),
|
| event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.cancelable(), event.causesScrollingIfUncanceled(), event.timestamp());
|
| touchEventTarget->toNode()->dispatchTouchEvent(touchEvent.get());
|
| swallowedEvent = swallowedEvent || touchEvent->defaultPrevented() || touchEvent->defaultHandled();
|
|
|