зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1863194 - Do not terminate wheel transaction on browsing context change. r=hiro,smaug,webdriver-reviewers,Sasha
We should continue to use a wheel transaction for wheel events when the browsing context changes from the current context. Avoiding the override of the event target with the current wheel transaction can halt a page scroll when the mouse moves over content in a different presentation context. Differential Revision: https://phabricator.services.mozilla.com/D205495
This commit is contained in:
Родитель
eb8068f09a
Коммит
455ab11833
|
@ -0,0 +1,146 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<title>A scroll over an iframe should not terminate the wheel transaction</title>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
height: 250vh;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#spacer {
|
||||
height: 50px;
|
||||
width: 100vw;
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
#subframe {
|
||||
width: 80vw;
|
||||
height: 60vh;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="spacer"></div>
|
||||
<iframe id="subframe">
|
||||
</iframe>
|
||||
</body>
|
||||
<script>
|
||||
const searchParams = new URLSearchParams(location.search);
|
||||
|
||||
async function scrollWithPan() {
|
||||
await NativePanHandler.promiseNativePanEvent(
|
||||
document.scrollingElement,
|
||||
50,
|
||||
30,
|
||||
0,
|
||||
NativePanHandler.delta,
|
||||
NativePanHandler.beginPhase,
|
||||
);
|
||||
|
||||
await NativePanHandler.promiseNativePanEvent(
|
||||
document.scrollingElement,
|
||||
50,
|
||||
30,
|
||||
0,
|
||||
NativePanHandler.delta,
|
||||
NativePanHandler.updatePhase,
|
||||
);
|
||||
|
||||
await NativePanHandler.promiseNativePanEvent(
|
||||
document.scrollingElement,
|
||||
50,
|
||||
30,
|
||||
0,
|
||||
NativePanHandler.delta,
|
||||
NativePanHandler.endPhase,
|
||||
);
|
||||
}
|
||||
|
||||
async function scrollWithWheel() {
|
||||
await promiseMoveMouseAndScrollWheelOver(document.scrollingElement, 50, 30,
|
||||
false, 100);
|
||||
}
|
||||
|
||||
async function test() {
|
||||
let iframeURL =
|
||||
SimpleTest.getTestFileURL("helper_scroll_over_subframe_child.html");
|
||||
|
||||
switch (searchParams.get("oop")) {
|
||||
case "true":
|
||||
iframeURL = iframeURL.replace(window.location.origin, "https://example.com/");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const iframeLoadPromise = promiseOneEvent(subframe, "load", null);
|
||||
subframe.src = iframeURL;
|
||||
await iframeLoadPromise;
|
||||
|
||||
await SpecialPowers.spawn(subframe, [], async () => {
|
||||
await content.wrappedJSObject.waitUntilApzStable();
|
||||
await SpecialPowers.contentTransformsReceived(content);
|
||||
});
|
||||
|
||||
let childWindowReceivedWheelEvent = false;
|
||||
|
||||
window.addEventListener("message", e => {
|
||||
if (e.data == "child-received-wheel-event") {
|
||||
childWindowReceivedWheelEvent = true;
|
||||
}
|
||||
});
|
||||
|
||||
await SpecialPowers.spawn(subframe, [], () => {
|
||||
let target = content.document.getElementById("target")
|
||||
target.style.backgroundColor = "green";
|
||||
content.getComputedStyle(target).backgroundColor;
|
||||
target.addEventListener("wheel", () => {
|
||||
target.style.backgroundColor = "red";
|
||||
content.getComputedStyle(target).backgroundColor;
|
||||
});
|
||||
return new Promise(resolve => resolve());
|
||||
});
|
||||
|
||||
await promiseFrame();
|
||||
|
||||
let transformEndPromise = promiseTransformEnd();
|
||||
|
||||
// Scroll over the iframe
|
||||
switch (searchParams.get("scroll")) {
|
||||
case "wheel":
|
||||
await scrollWithWheel();
|
||||
break;
|
||||
case "pan":
|
||||
await scrollWithPan();
|
||||
break;
|
||||
default:
|
||||
ok(false, "Unsupported scroll value: " + searchParams.get("scroll"));
|
||||
break;
|
||||
}
|
||||
|
||||
await transformEndPromise;
|
||||
|
||||
// Wait an extra frame to ensure any message from the child has
|
||||
// extra time to be sent to the parent.
|
||||
await promiseFrame();
|
||||
|
||||
let res = await SpecialPowers.spawn(subframe, [], () => {
|
||||
let target = content.document.getElementById("target")
|
||||
return target.style.backgroundColor;
|
||||
});
|
||||
|
||||
await promiseFrame();
|
||||
|
||||
// We should not have fired a wheel event to the element in the iframe
|
||||
ok(!childWindowReceivedWheelEvent, "Child window should not receive wheel events");
|
||||
is(res, "green", "OOP iframe does not halt user scroll of parent");
|
||||
}
|
||||
waitUntilApzStable().then(test).then(subtestDone, subtestFailed);
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script src="apz_test_utils.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#target {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: blue;
|
||||
overflow: scroll;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="target">
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
window.addEventListener("wheel", () => {
|
||||
window.parent.postMessage("child-received-wheel-event", "*");
|
||||
});
|
||||
</script>
|
||||
</html>
|
|
@ -20,6 +20,13 @@ var prefs = [
|
|||
["mousewheel.transaction.timeout", 0],
|
||||
];
|
||||
|
||||
var wheel_transaction_prefs = [
|
||||
["dom.event.wheel-event-groups.enabled", true],
|
||||
["mousewheel.transaction.timeout", 10000],
|
||||
["apz.test.mac.synth_wheel_input", true],
|
||||
...getSmoothScrollPrefs("wheel"),
|
||||
];
|
||||
|
||||
// For helper_scroll_over_scrollbar, we need to set a pref to force
|
||||
// layerization of the scrollbar track to reproduce the bug being fixed.
|
||||
// Otherwise, the bug only manifests with overlay scrollbars on macOS,
|
||||
|
@ -48,6 +55,10 @@ var subtests = [
|
|||
prefs: [["general.smoothScroll", false],
|
||||
["apz.test.mac.synth_wheel_input", true]]},
|
||||
{"file": "helper_scroll_anchoring_on_wheel.html", prefs: smoothness_prefs},
|
||||
{"file": "helper_scroll_over_subframe.html?scroll=wheel", prefs: wheel_transaction_prefs},
|
||||
{"file": "helper_scroll_over_subframe.html?oop=true&scroll=wheel", prefs: wheel_transaction_prefs},
|
||||
{"file": "helper_scroll_over_subframe.html?scroll=pan", prefs: wheel_transaction_prefs},
|
||||
{"file": "helper_scroll_over_subframe.html?oop=true&scroll=pan", prefs: wheel_transaction_prefs},
|
||||
];
|
||||
|
||||
subtests.push(...buildRelativeScrollSmoothnessVariants("wheel", ["scrollBy", "scrollTo", "scrollTop"]));
|
||||
|
|
|
@ -12100,13 +12100,6 @@ void PresShell::EventHandler::EventTargetData::UpdateWheelEventTarget(
|
|||
return;
|
||||
}
|
||||
|
||||
// If the browsing context is no longer the same as the context of the
|
||||
// current wheel transaction, do not override the event target.
|
||||
if (!groupFrame->PresContext() || !groupFrame->PresShell() ||
|
||||
groupFrame->PresContext() != GetPresContext()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If dom.event.wheel-event-groups.enabled is set and whe have a stored
|
||||
// event target from the wheel transaction, override the event target.
|
||||
SetFrameAndComputePresShellAndContent(groupFrame, aGUIEvent);
|
||||
|
|
|
@ -34,6 +34,10 @@ class InputModule extends WindowGlobalBiDiModule {
|
|||
const actionChain = lazy.action.Chain.fromJSON(this.#actionState, actions);
|
||||
|
||||
await actionChain.dispatch(this.#actionState, this.messageHandler.window);
|
||||
|
||||
// Terminate the current wheel transaction if there is one. Wheel
|
||||
// transactions should not live longer than a single action chain.
|
||||
ChromeUtils.endWheelTransaction();
|
||||
}
|
||||
|
||||
async releaseActions() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче