mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 1725493 - Make coalesced touchmove event could be up-to-date; r=smaug,sefeng
`mChanged` isn't propagated through IPC, so we end up never update the coalesced event. There can't be too many of touches, so it shouldn't be a performance issue if we just update all touches. Differential Revision: https://phabricator.services.mozilla.com/D122539
This commit is contained in:
parent
e8beefa0ac
commit
9a4b0f2c7f
@ -101,8 +101,7 @@
|
|||||||
ok(receivedSingleTouch, "Should've got single touch");
|
ok(receivedSingleTouch, "Should've got single touch");
|
||||||
ok(receivedMultiTouch, "Should've got multi touch");
|
ok(receivedMultiTouch, "Should've got multi touch");
|
||||||
|
|
||||||
opener.setTimeout("SimpleTest.finish()");
|
opener.finish();
|
||||||
|
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
189
dom/events/test/file_coalesce_touchmove_browserchild2.html
Normal file
189
dom/events/test/file_coalesce_touchmove_browserchild2.html
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||||
|
<title>touchmove coalescing</title>
|
||||||
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<script>
|
||||||
|
window.oncontextmenu = function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("touchstart", function(e) { e.preventDefault(); },
|
||||||
|
{ passive: false} );
|
||||||
|
|
||||||
|
var touchmoveEvents = [];
|
||||||
|
function touchmove(e) {
|
||||||
|
// Make touchmove handling slow
|
||||||
|
var start = performance.now();
|
||||||
|
while (performance.now() < (start + 5));
|
||||||
|
touchmoveEvents.push(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fireLotsOfSingleTouchMoves() {
|
||||||
|
var ret = new Promise(function(resolve) {
|
||||||
|
SpecialPowers.loadChromeScript(function() {
|
||||||
|
var element = this.actorParent.rootFrameLoader.ownerElement;
|
||||||
|
var rect = element.getBoundingClientRect();
|
||||||
|
var win = element.ownerDocument.defaultView;
|
||||||
|
var utils = win.windowUtils;
|
||||||
|
var x = rect.x + (rect.width / 2);
|
||||||
|
var y = Math.floor(rect.y + (rect.height / 4));
|
||||||
|
var endY = Math.floor(rect.y + ((rect.height / 4) * 2));
|
||||||
|
utils.sendTouchEvent("touchstart", [0], [x], [y], [1], [1], [0], [1],
|
||||||
|
0, false);
|
||||||
|
while (y != endY) {
|
||||||
|
utils.sendTouchEvent("touchmove", [0], [x], [y], [1], [1], [0], [1],
|
||||||
|
0, false);
|
||||||
|
++y;
|
||||||
|
}
|
||||||
|
utils.sendTouchEvent("touchend", [0], [x], [y], [1], [1], [0], [1],
|
||||||
|
0, false);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
touchmoveEvents = [];
|
||||||
|
window.addEventListener("touchmove", touchmove, true);
|
||||||
|
window.addEventListener("touchend", function(e) {
|
||||||
|
window.removeEventListener("touchmove", touchmove, true);
|
||||||
|
resolve(touchmoveEvents);
|
||||||
|
}, {once: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fireTwoSingleTouches() {
|
||||||
|
var ret = new Promise(function(resolve) {
|
||||||
|
SpecialPowers.loadChromeScript(function() {
|
||||||
|
var element = this.actorParent.rootFrameLoader.ownerElement;
|
||||||
|
var rect = element.getBoundingClientRect();
|
||||||
|
var win = element.ownerDocument.defaultView;
|
||||||
|
var utils = win.windowUtils;
|
||||||
|
var x = rect.x + (rect.width / 2);
|
||||||
|
var startY = Math.floor(rect.y + (rect.height / 4));
|
||||||
|
var endY = Math.floor(rect.y + ((rect.height / 4) * 2));
|
||||||
|
utils.sendTouchEvent("touchstart", [0], [x], [startY], [1], [1], [0],
|
||||||
|
[1], 0, false);
|
||||||
|
utils.sendTouchEvent("touchmove", [0], [x], [startY], [1], [1], [0],
|
||||||
|
[1], 0, false);
|
||||||
|
utils.sendTouchEvent("touchmove", [0], [x], [startY + 1], [1], [1], [0],
|
||||||
|
[1], 0, false);
|
||||||
|
utils.sendTouchEvent("touchend", [0], [x], [endY], [1], [1], [0],
|
||||||
|
[1], 0, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
touchmoveEvents = [];
|
||||||
|
window.addEventListener("touchmove", touchmove, true);
|
||||||
|
window.addEventListener("touchend", function(e) {
|
||||||
|
window.removeEventListener("touchmove", touchmove, true);
|
||||||
|
resolve(touchmoveEvents);
|
||||||
|
}, {once: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fireLotsOfMultiTouchMoves() {
|
||||||
|
var ret = new Promise(function(resolve) {
|
||||||
|
SpecialPowers.loadChromeScript(function() {
|
||||||
|
var element = this.actorParent.rootFrameLoader.ownerElement;
|
||||||
|
var rect = element.getBoundingClientRect();
|
||||||
|
var win = element.ownerDocument.defaultView;
|
||||||
|
var utils = win.windowUtils;
|
||||||
|
var x = rect.x + (rect.width / 2);
|
||||||
|
var startY = Math.floor(rect.y + (rect.height / 4));
|
||||||
|
var endY = Math.floor(rect.y + ((rect.height / 4) * 2));
|
||||||
|
utils.sendTouchEvent("touchstart", [0, 1], [x, x + 1],
|
||||||
|
[startY, startY + 1], [1, 1], [1, 1], [0, 0],
|
||||||
|
[1, 1], 0, false);
|
||||||
|
while (startY != endY) {
|
||||||
|
utils.sendTouchEvent("touchmove", [0, 1], [x, x + 1],
|
||||||
|
[startY, startY + 1], [1, 1], [1, 1], [0, 0],
|
||||||
|
[1, 1], 0, false);
|
||||||
|
++startY;
|
||||||
|
}
|
||||||
|
utils.sendTouchEvent("touchend", [0, 1], [x, x + 1], [endY, endY + 1],
|
||||||
|
[1, 1], [1, 1], [0, 0], [1, 1], 0, false);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
touchmoveEvents = [];
|
||||||
|
window.addEventListener("touchmove", touchmove, true);
|
||||||
|
window.addEventListener("touchend", function(e) {
|
||||||
|
window.removeEventListener("touchmove", touchmove, true);
|
||||||
|
resolve(touchmoveEvents);
|
||||||
|
}, {once: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function disableCoalescing() {
|
||||||
|
return SpecialPowers.pushPrefEnv({"set": [["dom.events.compress.touchmove",
|
||||||
|
false],
|
||||||
|
["dom.events.coalesce.touchmove",
|
||||||
|
false]]});
|
||||||
|
}
|
||||||
|
|
||||||
|
function enableCoalescing() {
|
||||||
|
return SpecialPowers.pushPrefEnv({"set": [["dom.events.compress.touchmove",
|
||||||
|
false],
|
||||||
|
["dom.events.coalesce.touchmove",
|
||||||
|
true]]});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runTests() {
|
||||||
|
document.body.clientTop; // Flush layout
|
||||||
|
|
||||||
|
await disableCoalescing();
|
||||||
|
var touchMovesWithoutCoalescing = await fireLotsOfSingleTouchMoves();
|
||||||
|
await enableCoalescing();
|
||||||
|
var touchMovesWithCoalescing = await fireLotsOfSingleTouchMoves();
|
||||||
|
opener.ok(touchMovesWithoutCoalescing.length > touchMovesWithCoalescing.length,
|
||||||
|
"Coalescing should reduce the number of touchmove events");
|
||||||
|
opener.isDeeply(touchMovesWithoutCoalescing.shift().touches,
|
||||||
|
touchMovesWithCoalescing.shift().touches,
|
||||||
|
"Shouldn't have coalesced the initial touchmove");
|
||||||
|
opener.isDeeply(touchMovesWithoutCoalescing.pop().touches,
|
||||||
|
touchMovesWithCoalescing.pop().touches,
|
||||||
|
"The last touchmove event should be up-to-date");
|
||||||
|
|
||||||
|
await disableCoalescing();
|
||||||
|
var twoTouchMovesWithoutCoalescing = await fireTwoSingleTouches();
|
||||||
|
await enableCoalescing();
|
||||||
|
var twoTouchMovesWithCoalescing = await fireTwoSingleTouches();
|
||||||
|
opener.is(twoTouchMovesWithoutCoalescing.length, 2,
|
||||||
|
"Should have got two touchmoves");
|
||||||
|
opener.is(twoTouchMovesWithoutCoalescing.length,
|
||||||
|
twoTouchMovesWithCoalescing.length,
|
||||||
|
"Shouldn't have coalesced the touchmove.");
|
||||||
|
|
||||||
|
await disableCoalescing();
|
||||||
|
var multiTouchMovesWithoutCoalescing = await fireLotsOfMultiTouchMoves();
|
||||||
|
await enableCoalescing();
|
||||||
|
var multiTouchMovesWithCoalescing = await fireLotsOfMultiTouchMoves();
|
||||||
|
opener.ok(multiTouchMovesWithoutCoalescing.length > multiTouchMovesWithCoalescing.length,
|
||||||
|
"Coalescing should reduce the number of multitouch touchmove events");
|
||||||
|
opener.isDeeply(multiTouchMovesWithoutCoalescing.shift().touches,
|
||||||
|
multiTouchMovesWithCoalescing.shift().touches,
|
||||||
|
"Shouldn't have coalesced the initial multitouch touchmove event");
|
||||||
|
opener.isDeeply(multiTouchMovesWithoutCoalescing.pop().touches,
|
||||||
|
multiTouchMovesWithCoalescing.pop().touches,
|
||||||
|
"The last multitouch touchmove event should be up-to-date");
|
||||||
|
|
||||||
|
opener.finish();
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["dom.w3c_touch_events.enabled", true]]},
|
||||||
|
runTests);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body style="height: 100vh;" onload="SimpleTest.waitForFocus(init);">
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -14,12 +14,12 @@
|
|||||||
window.addEventListener("touchstart", function(e) { e.preventDefault(); },
|
window.addEventListener("touchstart", function(e) { e.preventDefault(); },
|
||||||
{ passive: false} );
|
{ passive: false} );
|
||||||
|
|
||||||
var touchmoveCount = 0;
|
var touchmoveEvents = [];
|
||||||
function touchmove() {
|
function touchmove(e) {
|
||||||
// Make touchmove handling slow
|
// Make touchmove handling slow
|
||||||
var start = performance.now();
|
var start = performance.now();
|
||||||
while (performance.now() < (start + 10));
|
while (performance.now() < (start + 10));
|
||||||
++touchmoveCount;
|
touchmoveEvents.push(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fireLotsOfSingleTouchMoves() {
|
async function fireLotsOfSingleTouchMoves() {
|
||||||
@ -44,11 +44,11 @@
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
touchmoveCount = 0;
|
touchmoveEvents = [];
|
||||||
window.addEventListener("touchmove", touchmove, true);
|
window.addEventListener("touchmove", touchmove, true);
|
||||||
window.addEventListener("touchend", function(e) {
|
window.addEventListener("touchend", function(e) {
|
||||||
window.removeEventListener("touchmove", touchmove, true);
|
window.removeEventListener("touchmove", touchmove, true);
|
||||||
resolve(touchmoveCount);
|
resolve(touchmoveEvents);
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -75,11 +75,11 @@
|
|||||||
[1], 0, false);
|
[1], 0, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
touchmoveCount = 0;
|
touchmoveEvents = [];
|
||||||
window.addEventListener("touchmove", touchmove, true);
|
window.addEventListener("touchmove", touchmove, true);
|
||||||
window.addEventListener("touchend", function(e) {
|
window.addEventListener("touchend", function(e) {
|
||||||
window.removeEventListener("touchmove", touchmove, true);
|
window.removeEventListener("touchmove", touchmove, true);
|
||||||
resolve(touchmoveCount);
|
resolve(touchmoveEvents);
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -110,58 +110,71 @@
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
touchmoveCount = 0;
|
touchmoveEvents = [];
|
||||||
window.addEventListener("touchmove", touchmove, true);
|
window.addEventListener("touchmove", touchmove, true);
|
||||||
window.addEventListener("touchend", function(e) {
|
window.addEventListener("touchend", function(e) {
|
||||||
window.removeEventListener("touchmove", touchmove, true);
|
window.removeEventListener("touchmove", touchmove, true);
|
||||||
resolve(touchmoveCount);
|
resolve(touchmoveEvents);
|
||||||
}, {once: true});
|
}, {once: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
function disableCoalescing() {
|
function disableIPCCompression() {
|
||||||
return SpecialPowers.pushPrefEnv({"set": [["dom.events.compress.touchmove",
|
return SpecialPowers.pushPrefEnv({"set": [["dom.events.compress.touchmove",
|
||||||
false],
|
false],
|
||||||
["dom.events.coalesce.touchmove",
|
["dom.events.coalesce.touchmove",
|
||||||
false]]});
|
false]]});
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableCoalescing() {
|
function enableIPCCompression() {
|
||||||
return SpecialPowers.pushPrefEnv({"set": [["dom.events.compress.touchmove",
|
return SpecialPowers.pushPrefEnv({"set": [["dom.events.compress.touchmove",
|
||||||
true],
|
true],
|
||||||
["dom.events.coalesce.touchmove",
|
["dom.events.coalesce.touchmove",
|
||||||
true]]});
|
false]]});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runTests() {
|
async function runTests() {
|
||||||
document.body.clientTop; // Flush layout
|
document.body.clientTop; // Flush layout
|
||||||
|
|
||||||
await disableCoalescing();
|
await disableIPCCompression();
|
||||||
var touchMovesWithoutCoalescing = await fireLotsOfSingleTouchMoves();
|
var touchMovesWithoutCoalescing = await fireLotsOfSingleTouchMoves();
|
||||||
await enableCoalescing();
|
await enableIPCCompression();
|
||||||
var touchMovesWithCoalescing = await fireLotsOfSingleTouchMoves();
|
var touchMovesWithCoalescing = await fireLotsOfSingleTouchMoves();
|
||||||
opener.ok(touchMovesWithoutCoalescing > touchMovesWithCoalescing,
|
opener.ok(touchMovesWithoutCoalescing.length > touchMovesWithCoalescing.length,
|
||||||
"Coalescing should reduce the number of touchmove events");
|
"Coalescing should reduce the number of touchmove events");
|
||||||
|
opener.isDeeply(touchMovesWithoutCoalescing.shift().touches,
|
||||||
|
touchMovesWithCoalescing.shift().touches,
|
||||||
|
"Shouldn't have coalesced the initial touchmove");
|
||||||
|
opener.isDeeply(touchMovesWithoutCoalescing.pop().touches,
|
||||||
|
touchMovesWithCoalescing.pop().touches,
|
||||||
|
"The last touchmove event should be up-to-date");
|
||||||
|
|
||||||
await disableCoalescing();
|
await disableIPCCompression();
|
||||||
var twoTouchMovesWithoutCoalescing = await fireTwoSingleTouches();
|
var twoTouchMovesWithoutCoalescing = await fireTwoSingleTouches();
|
||||||
await enableCoalescing();
|
await enableIPCCompression();
|
||||||
var twoTouchMovesWithCoalescing = await fireTwoSingleTouches();
|
var twoTouchMovesWithCoalescing = await fireTwoSingleTouches();
|
||||||
opener.is(twoTouchMovesWithoutCoalescing, 2,
|
opener.is(twoTouchMovesWithoutCoalescing.length, 2,
|
||||||
"Should have got two touchmoves");
|
"Should have got two touchmoves");
|
||||||
opener.is(twoTouchMovesWithoutCoalescing, twoTouchMovesWithCoalescing,
|
opener.is(twoTouchMovesWithoutCoalescing.length,
|
||||||
"Shouldn't have coalesced the initial touchmove.");
|
twoTouchMovesWithCoalescing.length,
|
||||||
|
"Shouldn't have coalesced the touchmove.");
|
||||||
|
|
||||||
await disableCoalescing();
|
await disableIPCCompression();
|
||||||
var multiTouchMovesWithoutCoalescing = await fireLotsOfMultiTouchMoves();
|
var multiTouchMovesWithoutCoalescing = await fireLotsOfMultiTouchMoves();
|
||||||
await enableCoalescing();
|
await enableIPCCompression();
|
||||||
var multiTouchMovesWithCoalescing = await fireLotsOfMultiTouchMoves();
|
var multiTouchMovesWithCoalescing = await fireLotsOfMultiTouchMoves();
|
||||||
opener.ok(multiTouchMovesWithoutCoalescing > multiTouchMovesWithCoalescing,
|
opener.ok(multiTouchMovesWithoutCoalescing.length > multiTouchMovesWithCoalescing.length,
|
||||||
"Coalescing should reduce the number of multitouch touchmove events");
|
"Coalescing should reduce the number of multitouch touchmove events");
|
||||||
|
opener.isDeeply(multiTouchMovesWithoutCoalescing.shift().touches,
|
||||||
|
multiTouchMovesWithCoalescing.shift().touches,
|
||||||
|
"Shouldn't have coalesced the initial multitouch touchmove event");
|
||||||
|
opener.isDeeply(multiTouchMovesWithoutCoalescing.pop().touches,
|
||||||
|
multiTouchMovesWithCoalescing.pop().touches,
|
||||||
|
"The last multitouch touchmove event should be up-to-date");
|
||||||
|
|
||||||
opener.finish_ipc();
|
opener.finish();
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +137,7 @@ skip-if =
|
|||||||
support-files =
|
support-files =
|
||||||
file_coalesce_touchmove_ipc.html
|
file_coalesce_touchmove_ipc.html
|
||||||
file_coalesce_touchmove_browserchild.html
|
file_coalesce_touchmove_browserchild.html
|
||||||
|
file_coalesce_touchmove_browserchild2.html
|
||||||
skip-if = debug #In order to be able to test touchmoves, the test needs to synthesize touchstart in a way which asserts
|
skip-if = debug #In order to be able to test touchmoves, the test needs to synthesize touchstart in a way which asserts
|
||||||
[test_deviceSensor.html]
|
[test_deviceSensor.html]
|
||||||
[test_bug812744.html]
|
[test_bug812744.html]
|
||||||
|
@ -8,15 +8,27 @@
|
|||||||
<script>
|
<script>
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
function finish_ipc() {
|
let tests = [
|
||||||
window.open("file_coalesce_touchmove_browserchild.html");
|
"file_coalesce_touchmove_ipc.html",
|
||||||
|
"file_coalesce_touchmove_browserchild.html",
|
||||||
|
"file_coalesce_touchmove_browserchild2.html",
|
||||||
|
];
|
||||||
|
|
||||||
|
function finish() {
|
||||||
|
info("finish");
|
||||||
|
if (tests.length) {
|
||||||
|
SimpleTest.executeSoon(run);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
function start() {
|
function run() {
|
||||||
window.open("file_coalesce_touchmove_ipc.html");
|
info(`run ${tests[0]}`);
|
||||||
|
window.open(tests.shift());
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="start();">
|
<body onload="run();">
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -28,11 +28,12 @@ void CoalescedTouchData::Coalesce(const WidgetTouchEvent& aEvent,
|
|||||||
MOZ_ASSERT(mCoalescedInputEvent->mInputSource == aEvent.mInputSource);
|
MOZ_ASSERT(mCoalescedInputEvent->mInputSource == aEvent.mInputSource);
|
||||||
|
|
||||||
for (const RefPtr<Touch>& touch : aEvent.mTouches) {
|
for (const RefPtr<Touch>& touch : aEvent.mTouches) {
|
||||||
if (touch->mChanged) {
|
// Get the same touch in the original event
|
||||||
// Get the same touch in the original event
|
RefPtr<Touch> sameTouch = GetTouch(touch->Identifier());
|
||||||
RefPtr<Touch> sameTouch = GetTouch(touch->Identifier());
|
// The checks in CoalescedTouchData::CanCoalesce ensure it should never
|
||||||
sameTouch->SetSameAs(touch);
|
// be null.
|
||||||
}
|
MOZ_ASSERT(sameTouch);
|
||||||
|
sameTouch->SetSameAs(touch);
|
||||||
}
|
}
|
||||||
|
|
||||||
mCoalescedInputEvent->mTimeStamp = aEvent.mTimeStamp;
|
mCoalescedInputEvent->mTimeStamp = aEvent.mTimeStamp;
|
||||||
|
Loading…
Reference in New Issue
Block a user