Bug 1016481 - Prevent dispatching a click when the touch-end event is cancelled. r=smaug r=botond

This commit is contained in:
Kartikaya Gupta 2014-07-17 22:24:23 -04:00
parent bf8666cf6d
commit ac6718b01f
4 changed files with 30 additions and 7 deletions

View File

@ -427,7 +427,7 @@ function testPreventDefault() {
[{ name: "touchstart", prevent: false },
{ name: "touchmove", prevent: false },
{ name: "touchmove", prevent: false },
{ name: "touchend", prevent: false, doPrevent: true }]
{ name: "touchend", prevent: true, doPrevent: true }]
];
var dotest = function(aTest) {

View File

@ -729,6 +729,7 @@ TabChild::TabChild(nsIContentChild* aManager, const TabContext& aContext, uint32
, mOrientation(eScreenOrientation_PortraitPrimary)
, mUpdateHitRegion(false)
, mPendingTouchPreventedResponse(false)
, mTouchEndIsClick(Unknown)
, mIgnoreKeyPressEvent(false)
, mActiveElementManager(new ActiveElementManager())
, mHasValidInnerSize(false)
@ -1804,6 +1805,10 @@ TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid&
return true;
}
if (mTouchEndIsClick == IsNotClick) {
return true;
}
LayoutDevicePoint currentPoint = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid) * mWidget->GetDefaultScale();;
MessageLoop::current()->PostDelayedTask(
@ -1894,7 +1899,7 @@ TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
}
case APZStateChange::EndTouch:
{
mActiveElementManager->HandleTouchEnd(aArg);
mTouchEndIsClick = (aArg ? IsClick : IsNotClick);
break;
}
default:
@ -2113,6 +2118,7 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
localEvent.mFlags.mMultipleActionsPrevented;
switch (aEvent.message) {
case NS_TOUCH_START: {
mTouchEndIsClick = Unknown;
if (mPendingTouchPreventedResponse) {
// We can enter here if we get two TOUCH_STARTs in a row and didn't
// respond to the first one. Respond to it now.
@ -2128,9 +2134,17 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
break;
}
case NS_TOUCH_MOVE:
case NS_TOUCH_END:
case NS_TOUCH_CANCEL: {
if (isTouchPrevented && mTouchEndIsClick == IsClick) {
mTouchEndIsClick = IsNotClick;
}
// fall through
case NS_TOUCH_CANCEL:
if (mTouchEndIsClick != Unknown) {
mActiveElementManager->HandleTouchEnd(mTouchEndIsClick == IsClick);
}
// fall through
case NS_TOUCH_MOVE: {
if (mPendingTouchPreventedResponse) {
MOZ_ASSERT(aGuid == mPendingTouchPreventedGuid);
SendContentReceivedTouch(mPendingTouchPreventedGuid, isTouchPrevented);

View File

@ -591,6 +591,13 @@ private:
ScrollableLayerGuid mPendingTouchPreventedGuid;
void FireSingleTapEvent(LayoutDevicePoint aPoint);
enum ClickState {
Unknown,
IsClick,
IsNotClick
};
ClickState mTouchEndIsClick;
bool mIgnoreKeyPressEvent;
nsRefPtr<ActiveElementManager> mActiveElementManager;
bool mHasValidInnerSize;

View File

@ -7831,9 +7831,11 @@ PresShell::DispatchTouchEvent(WidgetEvent* aEvent,
bool aTouchIsNew)
{
// calling preventDefault on touchstart or the first touchmove for a
// point prevents mouse events
bool canPrevent = aEvent->message == NS_TOUCH_START ||
(aEvent->message == NS_TOUCH_MOVE && aTouchIsNew);
// point prevents mouse events. calling it on the touchend should
// prevent click dispatching.
bool canPrevent = (aEvent->message == NS_TOUCH_START) ||
(aEvent->message == NS_TOUCH_MOVE && aTouchIsNew) ||
(aEvent->message == NS_TOUCH_END);
bool preventDefault = false;
nsEventStatus tmpStatus = nsEventStatus_eIgnore;
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();