Commit 577d916d authored by Rakina Zata Amni's avatar Rakina Zata Amni Committed by Commit Bot

[DL]: Make scrollIntoView() activate locked elements

When scrollIntoView was called on an element in locked subtree,
we will send the beforeactivate event and commit the locked ancestors.

Bug: 882663
Change-Id: I503bb6dc6c0cce9e5df53f52b432060a04680dfa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1528131
Commit-Queue: Rakina Zata Amni <rakina@chromium.org>
Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#642367}
parent 5d903b3a
...@@ -574,6 +574,7 @@ static ScrollAlignment ToPhysicalAlignment(const ScrollIntoViewOptions* options, ...@@ -574,6 +574,7 @@ static ScrollAlignment ToPhysicalAlignment(const ScrollIntoViewOptions* options,
} }
void Element::scrollIntoViewWithOptions(const ScrollIntoViewOptions* options) { void Element::scrollIntoViewWithOptions(const ScrollIntoViewOptions* options) {
ActivateDisplayLockIfNeeded();
GetDocument().EnsurePaintLocationDataValidForNode(this); GetDocument().EnsurePaintLocationDataValidForNode(this);
ScrollIntoViewNoVisualUpdate(options); ScrollIntoViewNoVisualUpdate(options);
} }
......
<!doctype HTML>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<style>
div {
contain: style layout;
}
</style>
<div id="outermost">
Outermost
<div id="outer">
Outer
<div id="inner">
Inner
<div id="innermost">
Innermost
</div>
</div>
</div>
</div>
<script>
'use strict';
function prepareTest() {
return Promise.all([
outer.displayLock.acquire({ timeout: Infinity, activatable: true }),
inner.displayLock.acquire({ timeout: Infinity, activatable: true })
]);
}
promise_test(() => {
return new Promise((resolve, reject) => {
prepareTest().then(() => {
assert_false(outermost.displayLock.locked);
assert_true(outer.displayLock.locked);
assert_true(inner.displayLock.locked);
assert_false(innermost.displayLock.locked);
let innerPromise = new Promise((resolve, reject) => {
inner.onbeforeactivate = (e) => {
assert_equals(e.activatedElement, innermost);
resolve();
}
});
let outerPromise = new Promise((resolve, reject) => {
outer.onbeforeactivate = (e) => {
assert_equals(e.activatedElement, innermost);
// Resolve if this is directly targeted to #outer,
// instead of bubbling here.
if (e.target == outer)
resolve();
}
});
let outermostPromise = new Promise((resolve, reject) => {
outermost.onbeforeactivate = (e) => {
assert_equals(e.activatedElement, innermost);
assert_not_equals(e.target, outermost);
// Resolve if this is targeted to #outer, which is
// dispatched after the event targeted to #inner.
if (e.target == outer)
resolve();
}
});
innermost.onbeforeactivate = reject;
// Navigating to element in locked subtree should fire beforeactivate
// on locked ancestors, but not itself.
innermost.scrollIntoView();
Promise.all([innerPromise, outerPromise, outermostPromise]).then(resolve);
});
});
}, "Activation through scrollIntoView fires beforeactivate on locked ancestor");
</script>
<!doctype HTML>
<style>
.spacer {
width: 150px;
height: 3000px;
background: lightblue;
}
#container {
contain: style layout;
width: 150px;
height: 150px;
background: lightgreen;
}
#target {
width: 100px;
height: 100px;
background: green;
}
</style>
<div class="spacer"></div>
<div id="container"><div id="target"></div></div>
<script>
// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
if (window.testRunner)
window.testRunner.waitUntilDone();
function notifyDone() {
if (window.testRunner)
window.testRunner.notifyDone();
}
function runTest() {
let container = document.getElementById("container");
document.getElementById("target").scrollIntoView();
requestAnimationFrame(notifyDone);
}
window.onload = () => { requestAnimationFrame(runTest); };
</script>
<!doctype HTML>
<style>
.spacer {
width: 150px;
height: 3000px;
background: lightblue;
}
#container {
contain: style layout;
width: 150px;
height: 150px;
background: lightgreen;
}
#target {
width: 100px;
height: 100px;
background: green;
}
</style>
<div class="spacer"></div>
<div id="container"><div id="target"></div></div>
<script>
if (window.testRunner)
window.testRunner.waitUntilDone();
function finishTest() {
if (window.testRunner)
window.testRunner.notifyDone();
}
function runTest() {
let container = document.getElementById("container");
container.displayLock.acquire({ timeout: Infinity, activatable: true }).then(() => {
document.getElementById("target").scrollIntoView();
requestAnimationFrame(finishTest);
});
}
window.onload = () => { requestAnimationFrame(runTest); };
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment