Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1523)

Unified Diff: Source/core/page/EventHandler.cpp

Issue 1144313003: Added PointerEvent firing on touch events. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Fixed the gyp rule for nuked ThreadLocalEventNames.h Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« Source/core/page/EventHandler.h ('K') | « Source/core/page/EventHandler.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/page/EventHandler.cpp
diff --git a/Source/core/page/EventHandler.cpp b/Source/core/page/EventHandler.cpp
index 6cfb5ac4da40857cf04b2ad674cc0e7b2891759a..8e842b41eee0e3edbeee93b75b5f52fe75e9edb0 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"
@@ -244,11 +245,13 @@ EventHandler::EventHandler(LocalFrame* frame)
, m_lastShowPressTimestamp(0)
, m_deltaConsumedForScrollSequence(false)
{
+ m_primaryIdByPointerType.clear();
}
EventHandler::~EventHandler()
{
ASSERT(!m_fakeMouseMoveEventTimer.isActive());
+ m_primaryIdByPointerType.clear();
}
DEFINE_TRACE(EventHandler)
@@ -316,6 +319,7 @@ void EventHandler::clear()
m_scrollbarHandlingScrollGesture = nullptr;
m_maxMouseMovedDuration = 0;
m_touchPressed = false;
+ m_primaryIdByPointerType.clear();
m_mouseDownMayStartSelect = false;
m_mouseDownMayStartDrag = false;
m_lastShowPressTimestamp = 0;
@@ -3777,7 +3781,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:
@@ -3796,6 +3800,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.
Rick Byers 2015/06/11 04:14:56 remove incorrect (and otherwise fairly useless) co
mustaq 2015/06/12 16:05:23 Done.
+ default:
+ ASSERT_NOT_REACHED();
+ return emptyAtom;
+ }
+}
+
HitTestResult EventHandler::hitTestResultInFrame(LocalFrame* frame, const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType)
{
HitTestResult result(HitTestRequest(hitType), point);
@@ -3815,13 +3838,14 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
{
TRACE_EVENT0("blink", "EventHandler::handleTouchEvent");
+ const String& PointerTypeTouch("touch");
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;
if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled)
@@ -3854,7 +3878,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
@@ -3916,30 +3940,18 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
return false;
}
- // Build up the lists to use for the 'touches', 'targetTouches' and
- // 'changedTouches' attributes in the JS event. See
- // http://www.w3.org/TR/touch-events/#touchevent-interface for how these
- // lists fit together.
-
- // Holds the complete set of touches on the screen.
- RefPtrWillBeRawPtr<TouchList> touches = TouchList::create();
-
- // A different view on the 'touches' list above, filtered and grouped by
- // event target. Used for the 'targetTouches' list in the JS event.
- using TargetTouchesHeapMap = WillBeHeapHashMap<EventTarget*, RefPtrWillBeMember<TouchList>>;
- TargetTouchesHeapMap touchesByTarget;
-
- // Array of touches per state, used to assemble the 'changedTouches' list.
- using EventTargetSet = WillBeHeapHashSet<RefPtrWillBeMember<EventTarget>>;
- struct {
- // The touches corresponding to the particular change state this struct
- // instance represents.
- RefPtrWillBeMember<TouchList> m_touches;
- // Set of targets involved in m_touches.
- EventTargetSet m_targets;
- } changedTouches[PlatformTouchPoint::TouchStateEnd];
-
- for (i = 0; i < points.size(); ++i) {
+ // Compute and store the common info used by both PointerEvent and TouchEvent.
+ using TouchInfo = struct {
Rick Byers 2015/06/11 04:14:56 curious: how is this syntax different from the sim
mustaq 2015/06/12 16:05:24 I need to use 'typedef struct {...} TouchInfo' her
Rick Byers 2015/06/16 17:25:38 Ah, cool - thanks!
+ EventTarget* touchTarget;
+ LocalFrame* targetFrame;
+ FloatPoint adjustedPagePoint;
+ FloatSize adjustedRadius;
+ bool knownTarget;
+ bool consumed;
+ };
+ Vector<TouchInfo> touchInfos(points.size());
+
+ for (unsigned i = 0; i < points.size(); ++i) {
const PlatformTouchPoint& point = points[i];
PlatformTouchPoint::State pointState = point.state();
RefPtrWillBeRawPtr<EventTarget> touchTarget = nullptr;
@@ -3988,21 +4000,127 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
// pagePoint should always be in the target element's document coordinates.
FloatPoint pagePoint = targetFrame->view()->rootFrameToContents(point.pos());
-
float scaleFactor = 1.0f / targetFrame->pageZoomFactor();
FloatPoint adjustedPagePoint = pagePoint.scaledBy(scaleFactor);
Rick Byers 2015/06/11 04:14:56 kind of silly to create these locals just to assig
mustaq 2015/06/12 16:05:24 Done.
FloatSize adjustedRadius = point.radius().scaledBy(scaleFactor);
+ TouchInfo& touchInfo = touchInfos[i];
+ touchInfo.touchTarget = touchTarget.get();
+ touchInfo.targetFrame = targetFrame;
+ touchInfo.adjustedPagePoint = adjustedPagePoint;
+ touchInfo.adjustedRadius = adjustedRadius;
+ touchInfo.knownTarget = knownTarget;
+ touchInfo.consumed = false;
+ }
+
+ if (RuntimeEnabledFeatures::pointerEventEnabled()) {
Rick Byers 2015/06/11 04:14:56 could some of this be factored out to another func
mustaq 2015/06/12 16:05:23 Done.
+ bool hasPrimaryIdForTouch = m_primaryIdByPointerType.contains(PointerTypeTouch);
+ unsigned primaryIdForTouch = hasPrimaryIdForTouch? m_primaryIdByPointerType.get(PointerTypeTouch) : 0;
Rick Byers 2015/06/11 04:14:56 nit: space before ?
mustaq 2015/06/12 16:05:24 Done.
+
+ // Iterate through the touch points, sending PointerEvents to the targets as required.
+ for (unsigned i = 0; i < points.size(); ++i) {
+ const PlatformTouchPoint& point = points[i];
+ TouchInfo& touchInfo = touchInfos[i];
+
+ const PlatformTouchPoint::State pointState = point.state();
+ const AtomicString& eventName(pointerEventNameForTouchPointState(pointState));
USE eero AT chromium.org 2015/06/11 11:12:42 This does not handle correctly touch points whose
mustaq 2015/06/12 16:05:23 Done.
+
+ if (pointState == PlatformTouchPoint::TouchPressed && !hasPrimaryIdForTouch) {
+ primaryIdForTouch = point.id();
+ m_primaryIdByPointerType.set(PointerTypeTouch, primaryIdForTouch);
+ hasPrimaryIdForTouch = true;
+ }
+
+ bool isEnterOrLeave = false;
+ bool isCancelable = !(isEnterOrLeave || pointState == PlatformTouchPoint::TouchCancelled);
+ bool isBubbling = !isEnterOrLeave;
+
+ PointerEventInit pointerEventInit;
+ pointerEventInit.setPointerId(point.id());
+ pointerEventInit.setWidth(touchInfo.adjustedRadius.width());
+ pointerEventInit.setHeight(touchInfo.adjustedRadius.height());
+ pointerEventInit.setPressure(point.force());
+ pointerEventInit.setTiltX(0.0);
+ pointerEventInit.setTiltY(0.0);
+ pointerEventInit.setPointerType(PointerTypeTouch);
+ pointerEventInit.setIsPrimary(hasPrimaryIdForTouch && primaryIdForTouch == point.id());
+ pointerEventInit.setScreenX(point.screenPos().x());
+ pointerEventInit.setScreenY(point.screenPos().y());
+ pointerEventInit.setClientX(0);
+ pointerEventInit.setClientY(0);
Rick Byers 2015/06/11 04:14:56 These are wrong - it should have client co-ordinat
mustaq 2015/06/12 16:05:23 Done.
+ pointerEventInit.setMovementX(0);
+ pointerEventInit.setMovementY(0);
+ pointerEventInit.setButton(0);
+ pointerEventInit.setButtons(0);
Rick Byers 2015/06/11 04:14:56 This is wrong, should be 1 http://w3c.github.io/po
mustaq 2015/06/12 16:05:23 Done.
+ pointerEventInit.setRelatedTarget(nullptr);
+
+ pointerEventInit.setCtrlKey(event.ctrlKey());
+ pointerEventInit.setShiftKey(event.shiftKey());
+ pointerEventInit.setAltKey(event.altKey());
+ pointerEventInit.setMetaKey(event.metaKey());
+
+ pointerEventInit.setBubbles(isBubbling);
+ pointerEventInit.setCancelable(isCancelable);
+
+ RefPtrWillBeRawPtr<PointerEvent> pointerEvent = PointerEvent::create(eventName, pointerEventInit);
+ touchInfo.touchTarget->toNode()->dispatchPointerEvent(pointerEvent.get());
+ touchInfo.consumed = pointerEvent->defaultPrevented() || pointerEvent->defaultHandled();
+ }
+
+ if (allTouchReleased)
+ m_primaryIdByPointerType.remove(PointerTypeTouch);
Rick Byers 2015/06/11 04:14:56 This logic deserves a test (at first I thought it
mustaq 2015/06/12 16:05:23 Done.
mustaq 2015/06/12 20:37:18 Just discovered that Chrome reuses 'retired' point
+ }
+
+ bool swallowedEvent = false;
+
+ // Build up the lists to use for the 'touches', 'targetTouches' and
+ // 'changedTouches' attributes in the JS event. See
+ // http://www.w3.org/TR/touch-events/#touchevent-interface for how these
+ // lists fit together.
+
+ // Holds the complete set of touches on the screen.
+ RefPtrWillBeRawPtr<TouchList> touches = TouchList::create();
+
+ // A different view on the 'touches' list above, filtered and grouped by
+ // event target. Used for the 'targetTouches' list in the JS event.
+ using TargetTouchesHeapMap = WillBeHeapHashMap<EventTarget*, RefPtrWillBeMember<TouchList>>;
+ TargetTouchesHeapMap touchesByTarget;
+
+ // Array of touches per state, used to assemble the 'changedTouches' list.
+ using EventTargetSet = WillBeHeapHashSet<RefPtrWillBeMember<EventTarget>>;
+ struct {
+ // The touches corresponding to the particular change state this struct
+ // instance represents.
+ RefPtrWillBeMember<TouchList> m_touches;
+ // Set of targets involved in m_touches.
+ EventTargetSet m_targets;
+ } changedTouches[PlatformTouchPoint::TouchStateEnd];
+
+ for (unsigned i = 0; i < points.size(); ++i) {
+ const PlatformTouchPoint& point = points[i];
+ const TouchInfo& touchInfo = touchInfos[i];
+ PlatformTouchPoint::State pointState = point.state();
+
+ if (touchInfo.consumed)
+ continue;
+
RefPtrWillBeRawPtr<Touch> touch = Touch::create(
- targetFrame, touchTarget.get(), point.id(), point.screenPos(), adjustedPagePoint, adjustedRadius, point.rotationAngle(), point.force());
+ touchInfo.targetFrame,
+ touchInfo.touchTarget,
+ point.id(),
+ point.screenPos(),
+ touchInfo.adjustedPagePoint,
+ touchInfo.adjustedRadius,
+ point.rotationAngle(),
+ point.force());
// Ensure this target's touch list exists, even if it ends up empty, so
// it can always be passed to TouchEvent::Create below.
- TargetTouchesHeapMap::iterator targetTouchesIterator = touchesByTarget.find(touchTarget.get());
+ TargetTouchesHeapMap::iterator targetTouchesIterator = touchesByTarget.find(touchInfo.touchTarget);
if (targetTouchesIterator == touchesByTarget.end()) {
- touchesByTarget.set(touchTarget.get(), TouchList::create());
- targetTouchesIterator = touchesByTarget.find(touchTarget.get());
+ touchesByTarget.set(touchInfo.touchTarget, TouchList::create());
+ targetTouchesIterator = touchesByTarget.find(touchInfo.touchTarget);
}
// touches and targetTouches should only contain information about
@@ -4019,12 +4137,12 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
// never be in the changedTouches list so we do not handle them
// explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609
// for further discussion about the TouchStationary state.
- if (pointState != PlatformTouchPoint::TouchStationary && knownTarget) {
+ if (pointState != PlatformTouchPoint::TouchStationary && touchInfo.knownTarget) {
ASSERT(pointState < PlatformTouchPoint::TouchStateEnd);
if (!changedTouches[pointState].m_touches)
changedTouches[pointState].m_touches = TouchList::create();
changedTouches[pointState].m_touches->append(touch);
- changedTouches[pointState].m_targets.add(touchTarget);
+ changedTouches[pointState].m_targets.add(touchInfo.touchTarget);
}
}
if (allTouchReleased) {
@@ -4032,20 +4150,19 @@ 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;
+ // Now iterate through 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();
« Source/core/page/EventHandler.h ('K') | « Source/core/page/EventHandler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698