From 885493cb204540cc0d918892ef5d4ba2b8285766 Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Thu, 28 Jan 2010 10:15:52 +0000 Subject: Store the originating target for a touch (i.e. calculated in touchstart) in a hash map, so that we can use that originating target as the target for future move/end/cancel events that that touch generates. This matches the behaviour that the iPhone exhibits. Change-Id: Iff5e29c795b8ae6128e67ad5d42a959b61f966f2 --- WebCore/page/EventHandler.cpp | 21 ++++++++++++++------- WebCore/page/EventHandler.h | 8 ++++++++ 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'WebCore') diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp index 51cf675..2563149 100644 --- a/WebCore/page/EventHandler.cpp +++ b/WebCore/page/EventHandler.cpp @@ -2595,6 +2595,20 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) int adjustedPageX = lroundf(pagePoint.x() / m_frame->pageZoomFactor()); int adjustedPageY = lroundf(pagePoint.y() / m_frame->pageZoomFactor()); + // ANDROID + // The touch event should act on the originating touch target, not the current target + // TODO: Upstream this fix to webkit.org (see webkit bug 34585) + int touchPointId = point.id(); + if (point.state() == PlatformTouchPoint::TouchPressed) + m_originatingTouchPointTargets.set(touchPointId, target); + + EventTarget* touchTarget = m_originatingTouchPointTargets.get(touchPointId).get(); + ASSERT(touchTarget); + + RefPtr touch = Touch::create(doc->frame(), touchTarget, touchPointId, + point.screenPos().x(), point.screenPos().y(), + adjustedPageX, adjustedPageY); + if ((event.type() == TouchStart #if PLATFORM(ANDROID) || event.type() == TouchDoubleTap @@ -2606,13 +2620,6 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) m_firstTouchPagePos = pagePoint; } - // ANDROID - // The touch event should act on m_touchEventTarget, not target - // TODO: Upstream this fix to webkit.org - RefPtr touch = Touch::create(doc->frame(), m_touchEventTarget.get(), point.id(), - point.screenPos().x(), point.screenPos().y(), - adjustedPageX, adjustedPageY); - if (point.state() == PlatformTouchPoint::TouchReleased) releasedTouches->append(touch); else if (point.state() == PlatformTouchPoint::TouchCancelled) diff --git a/WebCore/page/EventHandler.h b/WebCore/page/EventHandler.h index 861dce9..e871f61 100644 --- a/WebCore/page/EventHandler.h +++ b/WebCore/page/EventHandler.h @@ -37,12 +37,17 @@ class NSView; #endif +#if ENABLE(TOUCH_EVENTS) // ANDROID addition, needs to be upstreamed. (see webkit bug 34585) +#include +#endif + namespace WebCore { class AtomicString; class Clipboard; class Cursor; class Event; +class EventTarget; class FloatPoint; class Frame; class HitTestRequest; @@ -423,6 +428,9 @@ private: int m_activationEventNumber; #endif #if ENABLE(TOUCH_EVENTS) + // ANDROID fix to be upstreamed, see webkit bug 34585. + typedef HashMap > TouchTargetMap; + TouchTargetMap m_originatingTouchPointTargets; RefPtr m_touchEventTarget; IntPoint m_firstTouchScreenPos; IntPoint m_firstTouchPagePos; -- cgit v1.1 From 37ee8a08023fb2e5af82a4164797459e256c18e1 Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Thu, 11 Feb 2010 14:26:19 +0000 Subject: Fix the creation of the touchTargets list to match what the iPhone does and maintain compatability with existing apps like SuperPudu. touchTargets should always have at least one element and should be based on the target where the touch originated, not where it is now. This needs to be upstreamed to webkit. Change-Id: Ie4e6f65e77484e0eac6d0f239df9dd3a460e7bce --- WebCore/page/EventHandler.cpp | 65 +++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 18 deletions(-) (limited to 'WebCore') diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp index 2563149..ad29dc1 100644 --- a/WebCore/page/EventHandler.cpp +++ b/WebCore/page/EventHandler.cpp @@ -2567,6 +2567,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) RefPtr movedTouches = TouchList::create(); RefPtr targetTouches = TouchList::create(); RefPtr cancelTouches = TouchList::create(); + RefPtr stationaryTouches = TouchList::create(); const Vector& points = event.touchPoints(); AtomicString* eventName = 0; @@ -2609,6 +2610,17 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) point.screenPos().x(), point.screenPos().y(), adjustedPageX, adjustedPageY); + // touches should contain information about every touch currently on the screen. + if (point.state() != PlatformTouchPoint::TouchReleased) + touches->append(touch); + + // If it's a stationary touch, we don't want to process it further at the moment. + // We may add it to targetTouches later. + if (point.state() == PlatformTouchPoint::TouchStationary) { + stationaryTouches->append(touch); + continue; + } + if ((event.type() == TouchStart #if PLATFORM(ANDROID) || event.type() == TouchDoubleTap @@ -2620,21 +2632,45 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) m_firstTouchPagePos = pagePoint; } - if (point.state() == PlatformTouchPoint::TouchReleased) - releasedTouches->append(touch); - else if (point.state() == PlatformTouchPoint::TouchCancelled) - cancelTouches->append(touch); - else { - if (point.state() == PlatformTouchPoint::TouchPressed) - pressedTouches->append(touch); + // Check to see if this should be added to targetTouches. + // If we've got here then the touch is not stationary. If it's a release, it's no longer + // a touch on the screen so we don't want it in targetTouches. The first touch that gets + // to here defines the 'target' the touchTarget list uses. This seems arbitrary (much like + // checking !i to set m_touchEventTarget above?) but seems to yield compatible behaviour. + // + // FIXME: Is this really the correct semantics for the touchTargets list? The touch event + // spec is not clear to me. + if (point.state() != PlatformTouchPoint::TouchReleased) { + if (targetTouches->length() == 0) + targetTouches->append(touch); else { - touches->append(touch); - if (m_touchEventTarget == target) + if (touch->target() == targetTouches->item(0)->target()) targetTouches->append(touch); - if (point.state() == PlatformTouchPoint::TouchMoved) - movedTouches->append(touch); } } + + // Now build up the correct list for changedTouches. + if (point.state() == PlatformTouchPoint::TouchReleased) + releasedTouches->append(touch); + else if (point.state() == PlatformTouchPoint::TouchCancelled) + cancelTouches->append(touch); + else if (point.state() == PlatformTouchPoint::TouchPressed) + pressedTouches->append(touch); + else if (point.state() == PlatformTouchPoint::TouchMoved) + movedTouches->append(touch); + } + + // Add any stationary touches to targetTouches if they match the target. + EventTarget* targetTouchesTarget = 0; + if (targetTouches->length()) + targetTouchesTarget = targetTouches->item(0)->target(); + else + targetTouchesTarget = m_touchEventTarget.get(); + + for (int i = 0; i < stationaryTouches->length(); ++i) { + Touch* stationaryTouch = stationaryTouches->item(i); + if (stationaryTouch->target() == targetTouchesTarget) + targetTouches->append(stationaryTouch); } if (!m_touchEventTarget) @@ -2691,13 +2727,6 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) #endif } if (pressedTouches->length() > 0) { - // Add pressed touchpoints to touches and targetTouches - for (int i = 0; i < pressedTouches->length(); ++i) { - touches->append(pressedTouches->item(i)); - if (m_touchEventTarget == pressedTouches->item(i)->target()) - targetTouches->append(pressedTouches->item(i)); - } - #if PLATFORM(ANDROID) if (event.type() == TouchLongPress) { eventName = &eventNames().touchlongpressEvent; -- cgit v1.1 From 63f95120ca90887045131d7ecf183e171d5dbe5d Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Mon, 15 Feb 2010 17:00:16 +0000 Subject: Don't add something to a hash map and then get it out again immediately if we don't need to. Change-Id: Ic6718a7c23e8896f5bbbb5cadcc22aa9a3108530 --- WebCore/page/EventHandler.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'WebCore') diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp index ad29dc1..39fe724 100644 --- a/WebCore/page/EventHandler.cpp +++ b/WebCore/page/EventHandler.cpp @@ -2600,10 +2600,13 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) // The touch event should act on the originating touch target, not the current target // TODO: Upstream this fix to webkit.org (see webkit bug 34585) int touchPointId = point.id(); - if (point.state() == PlatformTouchPoint::TouchPressed) + EventTarget* touchTarget = 0; + if (point.state() == PlatformTouchPoint::TouchPressed) { m_originatingTouchPointTargets.set(touchPointId, target); + touchTarget = target; + } else + touchTarget = m_originatingTouchPointTargets.get(touchPointId).get(); - EventTarget* touchTarget = m_originatingTouchPointTargets.get(touchPointId).get(); ASSERT(touchTarget); RefPtr touch = Touch::create(doc->frame(), touchTarget, touchPointId, -- cgit v1.1