Bug 1947470 - Do MoveInsideAndClamp for the given position:fixed rectangle to avoid unexpected scrolling. r=dlrobertson
For safety, both of helper_scrollIntoView_bug1950744.html and helper_scrollIntoView_bug1950744-2.html run with layout.scroll_fixed_content_into_view_visually=true and layout.scroll_fixed_content_into_view_visually=false because these tests should NOT cause any scrolling regardless of the pref value. Differential Revision: https://phabricator.services.mozilla.com/D243735
This commit is contained in:
@@ -33,17 +33,16 @@
|
|||||||
<input type="text" id="name" />
|
<input type="text" id="name" />
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
const isAndroid = getPlatform() == "android";
|
|
||||||
async function test() {
|
async function test() {
|
||||||
is(window.scrollY, 0, "The initial scroll offset should be 0");
|
is(window.scrollY, 0, "The initial scroll offset should be 0");
|
||||||
is(visualViewport.scale, 1.0, "The document should not get scaled");
|
is(visualViewport.scale, 1.0, "The document should not get scaled");
|
||||||
is(visualViewport.pageTop, 0, "The initial visual viewport pageTop should be 0");
|
is(visualViewport.pageTop, 0, "The initial visual viewport pageTop should be 0");
|
||||||
|
|
||||||
visualViewport.addEventListener("scroll", () => {
|
visualViewport.addEventListener("scroll", () => {
|
||||||
ok(isAndroid, "Any VisualViewport scroll event should not be observed");
|
ok(false, "Any VisualViewport scroll event should not be observed");
|
||||||
});
|
});
|
||||||
window.addEventListener("scroll", () => {
|
window.addEventListener("scroll", () => {
|
||||||
ok(isAndroid, "Any scroll event should not be observed");
|
ok(false, "Any scroll event should not be observed");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Scroll to the input element inside a position:fixed element.
|
// Scroll to the input element inside a position:fixed element.
|
||||||
@@ -55,13 +54,8 @@ async function test() {
|
|||||||
await promiseFrame();
|
await promiseFrame();
|
||||||
await promiseFrame();
|
await promiseFrame();
|
||||||
|
|
||||||
if (isAndroid) {
|
is(visualViewport.pageTop, 0, "The visual viewport pageTop should be zero");
|
||||||
todo_is(visualViewport.pageTop, 0, "The visual viewport pageTop should be zero");
|
is(window.scrollY, 0, "The scroll offset should be zero");
|
||||||
todo_is(window.scrollY, 0, "The scroll offset should be zero");
|
|
||||||
} else {
|
|
||||||
is(visualViewport.pageTop, 0, "The visual viewport pageTop should be zero");
|
|
||||||
is(window.scrollY, 0, "The scroll offset should be zero");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
waitUntilApzStable()
|
waitUntilApzStable()
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
<div id="target"></div>
|
<div id="target"></div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
const isAndroid = getPlatform() == "android";
|
|
||||||
async function test() {
|
async function test() {
|
||||||
is(window.scrollY, 0, "The initial scroll offset should be 0");
|
is(window.scrollY, 0, "The initial scroll offset should be 0");
|
||||||
is(visualViewport.scale, 1.0, "The document should not get scaled");
|
is(visualViewport.scale, 1.0, "The document should not get scaled");
|
||||||
@@ -43,10 +42,10 @@ async function test() {
|
|||||||
await scrollendPromise;
|
await scrollendPromise;
|
||||||
|
|
||||||
visualViewport.addEventListener("scroll", () => {
|
visualViewport.addEventListener("scroll", () => {
|
||||||
ok(isAndroid, "Any VisualViewport scroll event should not be observed");
|
ok(false, "Any VisualViewport scroll event should not be observed");
|
||||||
});
|
});
|
||||||
window.addEventListener("scroll", () => {
|
window.addEventListener("scroll", () => {
|
||||||
ok(isAndroid, "Any scroll event should not be observed");
|
ok(false, "Any scroll event should not be observed");
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelector("#target").scrollIntoView();
|
document.querySelector("#target").scrollIntoView();
|
||||||
@@ -57,11 +56,7 @@ async function test() {
|
|||||||
await promiseFrame();
|
await promiseFrame();
|
||||||
await promiseFrame();
|
await promiseFrame();
|
||||||
|
|
||||||
if (isAndroid) {
|
is(window.scrollY, 2000, "The scroll offset should stay at 2000px");
|
||||||
todo_is(window.scrollY, 2000, "The scroll offset should stay at 2000px");
|
|
||||||
} else {
|
|
||||||
is(window.scrollY, 2000, "The scroll offset should stay at 2000px");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
waitUntilApzStable()
|
waitUntilApzStable()
|
||||||
|
|||||||
@@ -15,8 +15,22 @@ var subtests = [
|
|||||||
"prefs": [...prefs,
|
"prefs": [...prefs,
|
||||||
["layout.scroll_fixed_content_into_view_visually", true]]
|
["layout.scroll_fixed_content_into_view_visually", true]]
|
||||||
},
|
},
|
||||||
{"file": "helper_scrollIntoView_bug1950744.html", prefs},
|
{"file": "helper_scrollIntoView_bug1950744.html",
|
||||||
{"file": "helper_scrollIntoView_bug1950744-2.html", prefs},
|
"prefs": [...prefs,
|
||||||
|
["layout.scroll_fixed_content_into_view_visually", false]]
|
||||||
|
},
|
||||||
|
{"file": "helper_scrollIntoView_bug1950744.html",
|
||||||
|
"prefs": [...prefs,
|
||||||
|
["layout.scroll_fixed_content_into_view_visually", true]]
|
||||||
|
},
|
||||||
|
{"file": "helper_scrollIntoView_bug1950744-2.html",
|
||||||
|
"prefs": [...prefs,
|
||||||
|
["layout.scroll_fixed_content_into_view_visually", false]]
|
||||||
|
},
|
||||||
|
{"file": "helper_scrollIntoView_bug1950744-2.html",
|
||||||
|
"prefs": [...prefs,
|
||||||
|
["layout.scroll_fixed_content_into_view_visually", true]]
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isApzEnabled()) {
|
if (isApzEnabled()) {
|
||||||
|
|||||||
@@ -3856,18 +3856,31 @@ void PresShell::ScrollFrameIntoVisualViewport(Maybe<nsPoint>& aDestination,
|
|||||||
|
|
||||||
const nsSize visualViewportSize =
|
const nsSize visualViewportSize =
|
||||||
rootScrollContainer->GetVisualViewportSize();
|
rootScrollContainer->GetVisualViewportSize();
|
||||||
|
|
||||||
|
const nsSize layoutViewportSize = root->GetLayoutViewportSize();
|
||||||
|
const nsRect layoutViewport = nsRect(nsPoint(), layoutViewportSize);
|
||||||
|
// `positon:fixed` element are attached/fixed to the ViewportFrame, which is
|
||||||
|
// the parent of the root scroll container frame, thus what we need here is
|
||||||
|
// the visible area of the position:fixed element inside the root scroll
|
||||||
|
// container frame.
|
||||||
|
// For example, if the top left position of the fixed element is (-100,
|
||||||
|
// -100), it's outside of the scrollable range either in the layout viewport
|
||||||
|
// or the visual viewport. Likewise, if the right bottom position of the
|
||||||
|
// fixed element is (110vw, 110vh), it's also outside of the scrollable
|
||||||
|
// range.
|
||||||
|
const nsRect clampedPositionFixedRect =
|
||||||
|
aPositionFixedRect.MoveInsideAndClamp(layoutViewport);
|
||||||
// If the position:fixed element is already inside the visual viewport, we
|
// If the position:fixed element is already inside the visual viewport, we
|
||||||
// don't need to scroll visually.
|
// don't need to scroll visually.
|
||||||
if (aPositionFixedRect.y >= 0 &&
|
if (clampedPositionFixedRect.y >= 0 &&
|
||||||
aPositionFixedRect.YMost() <= visualViewportSize.height &&
|
clampedPositionFixedRect.YMost() <= visualViewportSize.height &&
|
||||||
aPositionFixedRect.x >= 0 &&
|
clampedPositionFixedRect.x >= 0 &&
|
||||||
aPositionFixedRect.XMost() <= visualViewportSize.width) {
|
clampedPositionFixedRect.XMost() <= visualViewportSize.width) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the position:fixed element is totally outside of the the layout
|
// If the position:fixed element is totally outside of the the layout
|
||||||
// viewport, it will never be in the viewport.
|
// viewport, it will never be in the viewport.
|
||||||
const nsSize layoutViewportSize = root->GetLayoutViewportSize();
|
|
||||||
if (!NeedToVisuallyScroll(layoutViewportSize, aPositionFixedRect)) {
|
if (!NeedToVisuallyScroll(layoutViewportSize, aPositionFixedRect)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user