Source code
Revision control
Copy as Markdown
Other Tools
<!DOCTYPE html>
<html id="html">
<title>Test for making sure that an instant scroll update on the main-thread is reflected to displayport</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="apz_test_utils.js"></script>
<script src="apz_test_native_event_utils.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/paint_listener.js"></script>
<style>
html {
overflow: scroll;
scrollbar-width: none;
}
</style>
<body>
<div style="height: 50000px"></div>
</body>
<script>
// Displayport alignment multiplier calculation; see AsyncPanZoomController::GetDisplayportAlignmentMultiplier
function GetDisplayportAlignmentMultiplier(aBaseHeight) {
let multiplier = 1;
let baseHeight = aBaseHeight;
while (baseHeight > 500) {
baseHeight /= 2;
multiplier *= 2;
if (multiplier >= 8) {
break;
}
}
return multiplier;
}
async function test() {
const resolution = await getResolution();
const deviceScale = window.devicePixelRatio;
// Invoke scrollToVisual to diverge the visual scroll offset from the
// layout scroll offset.
const utils = SpecialPowers.getDOMWindowUtils(window);
utils.scrollToVisual(0, 1000,
utils.UPDATE_TYPE_MAIN_THREAD,
utils.SCROLL_MODE_INSTANT);
await promiseApzFlushedRepaints();
const initialVisualOffset = visualViewport.offsetTop;
info(`The visualViewport.offsetTop is now ${visualViewport.offsetTop}`);
ok(visualViewport.offsetTop > 0, `The visual viewport has scrolled`);
info(`The visualViewport.pageTop is now ${visualViewport.pageTop}`);
const initialScrollY = window.scrollY;
info(`The window.scrollY is now ${window.scrollY}`);
ok(window.scrollY > 0, `The layout viewport has scrolled`);
is(initialScrollY + initialVisualOffset, 1000,
"The visual scroll offset + the layout scroll offset should equal to 1000");
// Start in a requestAnimationFrame callback so that awaiting an additional
// requestAnimationFrame callback should result a paint.
await promiseFrame();
const currentTime = document.timeline.currentTime;
// Do an instant relative scroll operation on the main-thread.
// NOTE: Until the next paint this scroll position update will not be sent
// to APZ.
window.scrollBy(0, 1000);
// Wait a frame so that a paint should have happened.
await promiseFrame();
// Make sure now that refresh driver's time has advanced.
ok(document.timeline.currentTime > currentTime,
`${document.timeline.currentTime} > ${currentTime}`);
// Displayport margins calculation; see DisplayPortMargins::GetRelativeToLayoutViewport
const margin = initialVisualOffset * resolution * deviceScale;
const clientHeightInScreen = document.documentElement.clientHeight * deviceScale;
const multiplier = GetDisplayportAlignmentMultiplier(clientHeightInScreen);
// These calculations need to be same as the ones in GetDisplayPortFromMarginsData().
const currentScrollPosition = initialScrollY + 1000;
const currentScrollPositionInScreen = currentScrollPosition * resolution * deviceScale;
const notAlignedDisplayportPosition = currentScrollPositionInScreen + margin;
const displayportAlignment = 128 * multiplier;
const alignedDisplayportPosition =
displayportAlignment * Math.floor(notAlignedDisplayportPosition / displayportAlignment);
let displayport = getLastContentDisplayportFor(document.documentElement.id);
isfuzzy(displayport.y,
(alignedDisplayportPosition - currentScrollPositionInScreen) / (resolution * deviceScale),
1.0, // getLastContentDisplayportFor returns rounded interger values.
"The displayport y should be reflecting the instant scroll distance");
}
// Scale 2.0x to diverge the visual scroll offset from the layout scroll
// offset by calling nsIDOMWindowUtils.scrollToVisual.
SpecialPowers.DOMWindowUtils.setResolutionAndScaleTo(2.0);
waitUntilApzStable()
.then(test)
.then(subtestDone, subtestFailed);
</script>
</html>