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

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 primary pointer id on reuse, for each type of Pointers. 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
Index: Source/core/page/EventHandler.cpp
diff --git a/Source/core/page/EventHandler.cpp b/Source/core/page/EventHandler.cpp
index 6cfb5ac4da40857cf04b2ad674cc0e7b2891759a..bbd388b6de36c6ed75d77153ec28b28d7e4ad79f 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"
@@ -316,6 +317,7 @@ void EventHandler::clear()
m_scrollbarHandlingScrollGesture = nullptr;
m_maxMouseMovedDuration = 0;
m_touchPressed = false;
+ m_pointerIdManager.clear();
m_mouseDownMayStartSelect = false;
m_mouseDownMayStartDrag = false;
m_lastShowPressTimestamp = 0;
@@ -3777,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:
@@ -3789,7 +3791,26 @@ static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State
case PlatformTouchPoint::TouchMoved:
return EventTypeNames::touchmove;
case PlatformTouchPoint::TouchStationary:
- // TouchStationary state is not converted to touch events, so fall through to assert.
+ // Fall through to default
+ default:
+ ASSERT_NOT_REACHED();
+ return emptyAtom;
+ }
+}
+
+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:
+ // Fall through to default
default:
ASSERT_NOT_REACHED();
return emptyAtom;
@@ -3811,17 +3832,75 @@ HitTestResult EventHandler::hitTestResultInFrame(LocalFrame* frame, const Layout
return result;
}
+void EventHandler::handlePointerEventsFromTouchEvent(const PlatformTouchEvent& event,
+ const Vector<PlatformTouchPoint>& points, Vector<TouchInfo>& touchInfos)
+{
+ const String& PointerTypeStrForTouch("touch");
+
+ // 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];
Rick Byers 2015/06/16 17:25:39 would it be a little cleaner to stick the Platform
mustaq 2015/06/16 20:18:43 Done.
+
+ unsigned pointerId = point.id();
+ const PlatformTouchPoint::State pointState = point.state();
+
+ if (pointState == PlatformTouchPoint::TouchStationary)
+ continue;
+ bool pointerReleasedOrCancelled =
+ pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled;
+ const AtomicString& eventName(pointerEventNameForTouchPointState(pointState));
+
+ if (pointState == PlatformTouchPoint::TouchPressed)
+ m_pointerIdManager.add(PointerIdManager::PointerTypeTouch, pointerId);
+
+ bool isEnterOrLeave = false;
+ bool isCancelable = !(isEnterOrLeave || pointState == PlatformTouchPoint::TouchCancelled);
+ bool isBubbling = !isEnterOrLeave;
Rick Byers 2015/06/16 17:25:39 nit isCancelable and isBubbling local variables on
mustaq 2015/06/16 20:18:43 Done.
+
+ PointerEventInit pointerEventInit;
+ pointerEventInit.setPointerId(pointerId);
+ pointerEventInit.setWidth(touchInfo.adjustedRadius.width());
+ pointerEventInit.setHeight(touchInfo.adjustedRadius.height());
+ pointerEventInit.setPressure(point.force());
+ pointerEventInit.setPointerType(PointerTypeStrForTouch);
+ pointerEventInit.setIsPrimary(m_pointerIdManager.isPrimary(PointerIdManager::PointerTypeTouch, pointerId));
+ pointerEventInit.setScreenX(point.screenPos().x());
+ pointerEventInit.setScreenY(point.screenPos().y());
+ pointerEventInit.setClientX(touchInfo.adjustedPagePoint.x());
+ pointerEventInit.setClientY(touchInfo.adjustedPagePoint.y());
+ pointerEventInit.setButton(0);
+ pointerEventInit.setButtons(pointerReleasedOrCancelled ? 0 : 1);
+
+ 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();
+
+ // Remove the released/cancelled id at the end to correctly determine primary id above.
+ if (pointerReleasedOrCancelled)
+ m_pointerIdManager.remove(PointerIdManager::PointerTypeTouch, pointerId);
+ }
+}
+
bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
{
TRACE_EVENT0("blink", "EventHandler::handleTouchEvent");
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 +3933,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 +3995,10 @@ 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];
+ // Compute and store the common info used by both PointerEvent and TouchEvent.
+ Vector<TouchInfo> touchInfos(points.size());
- 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;
@@ -3988,21 +4047,69 @@ 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);
- FloatSize adjustedRadius = point.radius().scaledBy(scaleFactor);
+ TouchInfo& touchInfo = touchInfos[i];
+ touchInfo.touchTarget = touchTarget.get();
+ touchInfo.targetFrame = targetFrame;
+ touchInfo.adjustedPagePoint = pagePoint.scaledBy(scaleFactor);
+ touchInfo.adjustedRadius = point.radius().scaledBy(scaleFactor);
+ touchInfo.knownTarget = knownTarget;
+ touchInfo.consumed = false;
+ }
+
+ if (RuntimeEnabledFeatures::pointerEventEnabled())
+ handlePointerEventsFromTouchEvent(event, points, touchInfos);
Rick Byers 2015/06/16 17:25:39 nit: dispatchPointerEventsForTouchEvent? We're no
mustaq 2015/06/16 20:18:43 Done.
+
+ bool swallowedEvent = false;
+
Rick Byers 2015/06/16 17:25:39 now that we have this TouchInfo, perhaps we should
mustaq 2015/06/16 20:18:43 Done, thanks for observing this. A quick thought:
Rick Byers 2015/06/18 17:40:07 Yes, I think it's right but ideally would get some
mustaq 2015/06/18 18:20:53 Done.
+ // 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 +4126,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 +4139,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/events/PointerEventUtils.cpp ('K') | « Source/core/page/EventHandler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698