mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1340085 - [Pointer Event] Stop firing pointer events after firing eTouchCancel. f=smaug. r=kats
--HG-- extra : rebase_source : 95539f13dd0316cb4c01382a4c0213b00dcb64b0
This commit is contained in:
parent
da577361e9
commit
f3b56f1a20
@ -368,7 +368,7 @@ APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
|
||||
aApzResponse == nsEventStatus_eConsumeDoDefault &&
|
||||
gfxPrefs::PointerEventsEnabled()) {
|
||||
WidgetTouchEvent cancelEvent(aEvent);
|
||||
cancelEvent.mMessage = eTouchCancel;
|
||||
cancelEvent.mMessage = eTouchPointerCancel;
|
||||
cancelEvent.mFlags.mCancelable = false; // mMessage != eTouchCancel;
|
||||
for (uint32_t i = 0; i < cancelEvent.mTouches.Length(); ++i) {
|
||||
if (mozilla::dom::Touch* touch = cancelEvent.mTouches[i]) {
|
||||
|
@ -7026,6 +7026,7 @@ DispatchPointerFromMouseOrTouch(PresShell* aShell,
|
||||
pointerMessage = ePointerDown;
|
||||
break;
|
||||
case eTouchCancel:
|
||||
case eTouchPointerCancel:
|
||||
pointerMessage = ePointerCancel;
|
||||
break;
|
||||
default:
|
||||
@ -7034,7 +7035,7 @@ DispatchPointerFromMouseOrTouch(PresShell* aShell,
|
||||
|
||||
for (uint32_t i = 0; i < touchEvent->mTouches.Length(); ++i) {
|
||||
mozilla::dom::Touch* touch = touchEvent->mTouches[i];
|
||||
if (!touch || !touch->convertToPointer) {
|
||||
if (!TouchManager::ShouldConvertTouchToPointer(touch, touchEvent)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,8 @@ TouchManager::PreHandleEvent(WidgetEvent* aEvent,
|
||||
touch->mChanged = true;
|
||||
}
|
||||
touch->mMessage = aEvent->mMessage;
|
||||
TouchInfo info = { touch, GetNonAnonymousAncestor(touch->mTarget) };
|
||||
TouchInfo info = { touch, GetNonAnonymousAncestor(touch->mTarget),
|
||||
true };
|
||||
sCaptureTouchList->Put(id, info);
|
||||
}
|
||||
break;
|
||||
@ -247,6 +248,26 @@ TouchManager::PreHandleEvent(WidgetEvent* aEvent,
|
||||
AppendToTouchList(&touches);
|
||||
break;
|
||||
}
|
||||
case eTouchPointerCancel: {
|
||||
// Don't generate pointer events by touch events after eTouchPointerCancel
|
||||
// is received.
|
||||
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
|
||||
WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
|
||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
||||
Touch* touch = touches[i];
|
||||
if (!touch) {
|
||||
continue;
|
||||
}
|
||||
int32_t id = touch->Identifier();
|
||||
TouchInfo info;
|
||||
if (!sCaptureTouchList->Get(id, &info)) {
|
||||
continue;
|
||||
}
|
||||
info.mConvertToPointer = false;
|
||||
sCaptureTouchList->Put(id, info);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -290,4 +311,24 @@ TouchManager::GetCapturedTouch(int32_t aId)
|
||||
return touch.forget();
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
TouchManager::ShouldConvertTouchToPointer(const Touch* aTouch,
|
||||
const WidgetTouchEvent* aEvent)
|
||||
{
|
||||
if (!aTouch || !aTouch->convertToPointer) {
|
||||
return false;
|
||||
}
|
||||
TouchInfo info;
|
||||
if (!sCaptureTouchList->Get(aTouch->Identifier(), &info)) {
|
||||
// This check runs before the TouchManager has the touch registered in its
|
||||
// touch list. It's because we dispatching pointer events before handling
|
||||
// touch events. So we convert eTouchStart to pointerdown even it's not
|
||||
// registered.
|
||||
// Check WidgetTouchEvent::mMessage because Touch::mMessage is assigned when
|
||||
// pre-handling touch events.
|
||||
return aEvent->mMessage == eTouchStart;
|
||||
}
|
||||
return info.mConvertToPointer;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -40,7 +40,8 @@ public:
|
||||
static already_AddRefed<nsIContent> GetAnyCapturedTouchTarget();
|
||||
static bool HasCapturedTouch(int32_t aId);
|
||||
static already_AddRefed<dom::Touch> GetCapturedTouch(int32_t aId);
|
||||
|
||||
static bool ShouldConvertTouchToPointer(const dom::Touch* aTouch,
|
||||
const WidgetTouchEvent* aEvent);
|
||||
private:
|
||||
void EvictTouches();
|
||||
static void EvictTouchPoint(RefPtr<dom::Touch>& aTouch,
|
||||
@ -54,6 +55,7 @@ private:
|
||||
{
|
||||
RefPtr<mozilla::dom::Touch> mTouch;
|
||||
nsCOMPtr<nsIContent> mNonAnonymousTarget;
|
||||
bool mConvertToPointer;
|
||||
};
|
||||
static nsDataHashtable<nsUint32HashKey, TouchInfo>* sCaptureTouchList;
|
||||
};
|
||||
|
@ -114,44 +114,58 @@ function runTests() {
|
||||
var touchCancelTriggered = 0;
|
||||
var pointerCancelTriggered = 0;
|
||||
|
||||
d0.onmousedown = function(e) {
|
||||
mouseDownTriggered = 1;
|
||||
is(pointerDownTriggered , 1, "Mouse event must be triggered after pointer event!");
|
||||
};
|
||||
d0.ontouchstart = function(e) {
|
||||
touchDownTriggered = 1;
|
||||
is(touchDownTriggered , 1, "Touch event must be triggered after pointer event!");
|
||||
}
|
||||
d0.ontouchcancel = function(e) {
|
||||
touchCancelTriggered = 1;
|
||||
is(pointerCancelTriggered, 1, "Touch cancel event must be triggered after pointer event!");
|
||||
}
|
||||
d0.onpointerdown = function(e) {
|
||||
pointerDownTriggered = 1;
|
||||
is(mouseDownTriggered, 0, "Pointer event must be triggered before mouse event!");
|
||||
is(touchDownTriggered, 0, "Pointer event must be triggered before touch event!");
|
||||
};
|
||||
d0.addEventListener("pointercancel", function(ev) {
|
||||
is(ev.pointerId, 0, "Correct default pointerId");
|
||||
is(ev.bubbles, true, "bubbles should be true");
|
||||
is(ev.cancelable, false, "pointercancel cancelable should be false ");
|
||||
pointerCancelTriggered = 1;
|
||||
is(touchCancelTriggered, 0, "Pointer event must be triggered before touch event!");
|
||||
// Test pointer event generated from mouse event
|
||||
d0.addEventListener("mousedown", (e) => {
|
||||
++mouseDownTriggered;
|
||||
is(pointerDownTriggered , mouseDownTriggered, "Mouse event must be triggered after pointer event!");
|
||||
}, {once: true});
|
||||
|
||||
d0.addEventListener("pointerdown", (e) => {
|
||||
++pointerDownTriggered;
|
||||
is(pointerDownTriggered, mouseDownTriggered + 1, "Pointer event must be triggered before mouse event!");
|
||||
}, {once: true});
|
||||
|
||||
// Test pointer event generated from mouse event
|
||||
synthesizeMouse(d1, 3, 3, { type: "mousemove"});
|
||||
synthesizeMouse(d1, 3, 3, { type: "mousedown"});
|
||||
synthesizeMouse(d1, 3, 3, { type: "mouseup"});
|
||||
|
||||
// Test pointer event generated from touch event
|
||||
pointerDownTriggered = 0;
|
||||
mouseDownTriggered = 0;
|
||||
pointerDownTriggered = 0;
|
||||
|
||||
d0.addEventListener("touchstart", (e) => {
|
||||
++touchDownTriggered;
|
||||
is(pointerDownTriggered, touchDownTriggered, "Touch event must be triggered after pointer event!");
|
||||
}, {once: true});
|
||||
|
||||
d0.addEventListener("mousedown", (e) => {
|
||||
++mouseDownTriggered;
|
||||
is(pointerDownTriggered , mouseDownTriggered, "Mouse event must be triggered after pointer event!");
|
||||
}, {once: true});
|
||||
|
||||
d0.addEventListener("pointerdown", (e) => {
|
||||
++pointerDownTriggered;
|
||||
is(pointerDownTriggered, touchDownTriggered + 1, "Pointer event must be triggered before mouse event!");
|
||||
is(pointerDownTriggered, mouseDownTriggered + 1, "Pointer event must be triggered before mouse event!");
|
||||
}, {once: true});
|
||||
|
||||
d0.addEventListener("touchcancel", (e) => {
|
||||
++touchCancelTriggered;
|
||||
is(pointerCancelTriggered, touchCancelTriggered, "Touch cancel event must be triggered after pointer event!");
|
||||
}, {once: true});
|
||||
|
||||
d0.addEventListener("pointercancel", function(ev) {
|
||||
is(ev.pointerId, 0, "Correct default pointerId");
|
||||
is(ev.bubbles, true, "bubbles should be true");
|
||||
is(ev.cancelable, false, "pointercancel cancelable should be false ");
|
||||
++pointerCancelTriggered;
|
||||
is(pointerCancelTriggered, touchCancelTriggered + 1, "Pointer event must be triggered before touch event!");
|
||||
}, {once: true});
|
||||
|
||||
var cwu = SpecialPowers.getDOMWindowUtils(window);
|
||||
var event1 = getTouchEventForTarget(d1, cwu, 0);
|
||||
sendTouchEvent(cwu, "touchmove", event1, 0);
|
||||
sendTouchEvent(cwu, "touchstart", event1, 0);
|
||||
sendTouchEvent(cwu, "touchmove", event1, 0);
|
||||
// Test Touch to Pointer Cancel
|
||||
sendTouchEvent(cwu, "touchcancel", event1, 0);
|
||||
|
||||
@ -228,6 +242,7 @@ function runTests() {
|
||||
};
|
||||
|
||||
synthesizeMouse(d1, 3, 3, { type: "mousemove"});
|
||||
sendTouchEvent(cwu, "touchstart", getTouchEventForTarget(d3, cwu, 3), 0);
|
||||
sendTouchEvent(cwu, "touchmove", getTouchEventForTarget(d3, cwu, 3), 0);
|
||||
is(touchPointerEnterLeaveCount, 1, "Wrong touch enterLeave count for!");
|
||||
is(mousePointerEnterLeaveCount, 2, "Wrong mouse enterLeave count for!");
|
||||
@ -291,8 +306,8 @@ function runTests() {
|
||||
is(e.pointerType, "mouse", "Wrong Pointer type, should be mouse type");
|
||||
}
|
||||
pointerOutTriggeredForCancelEvent = 1;
|
||||
};
|
||||
d1.onpointerleave = function(e) {
|
||||
};
|
||||
d1.onpointerleave = function(e) {
|
||||
is(pointerOutTriggeredForCancelEvent, 1, "Pointer Out must be dispatched bedore Pointer leave");
|
||||
if (pointerLeaveTriggeredForCancelEvent == 0) {
|
||||
is(e.pointerId, 3, "Wrong Pointer type, should be id from Touch event");
|
||||
|
@ -398,6 +398,7 @@ NS_EVENT_MESSAGE(eTouchStart)
|
||||
NS_EVENT_MESSAGE(eTouchMove)
|
||||
NS_EVENT_MESSAGE(eTouchEnd)
|
||||
NS_EVENT_MESSAGE(eTouchCancel)
|
||||
NS_EVENT_MESSAGE(eTouchPointerCancel)
|
||||
|
||||
// Pointerlock DOM API
|
||||
NS_EVENT_MESSAGE(ePointerLockChange)
|
||||
|
@ -439,7 +439,8 @@ WidgetEvent::IsAllowedToDispatchDOMEvent() const
|
||||
return wheelEvent->mDeltaX != 0.0 || wheelEvent->mDeltaY != 0.0 ||
|
||||
wheelEvent->mDeltaZ != 0.0;
|
||||
}
|
||||
|
||||
case eTouchEventClass:
|
||||
return mMessage != eTouchPointerCancel;
|
||||
// Following events are handled in EventStateManager, so, we don't need to
|
||||
// dispatch DOM event for them into the DOM tree.
|
||||
case eQueryContentEventClass:
|
||||
|
Loading…
Reference in New Issue
Block a user