Bug 1878726 [wpt PR 44402] - [HitTestTransparency] Experimental status, a=testonly

Automatic update from web-platform-tests
[HitTestTransparency] Experimental status

The feature uses cc::HitTestOpacity::kTransparent for pointer-events:
none. The flag is first marked on paint chunks, then PendingLayer and
cc::Layer, by merging cc::HitTestOpacity from merged painted results.
The merge algorithm (which is already ready for HitTestOpaqueness)
can handle cases such as pointer-events:none with pointer-events:auto
descendants (which will be merged into cc::HitTestOpaqueness::kMixed).
cc::Layer::HitTestable() is now based on this flag for blink.

For test coverage, this CL also includes changes to make existing
tests pass or fix existing bugs with the feature:
- LayerTreeHostImpl::BuildHitTestData() now handles a SurfaceLayer
  with pointer-events:none even if it doesn't draw contents, to make
  CrossSiteSubframe/DragAndDropBrowserTest.CrossTabDrag/* pass.
- Correct hit test transparency for scrolling contents.
- Correct hit test transparency for frames under pointer-events:none
  container (b/323688987).
- Correct hit test transparency for scrollbar layers in boxes with
  pointer-events:none (b/324092420).
- New tests.

ClusterTelemetry job shows that it can reduce main thread scrolling (hit test or repaint) by 36% (kFailedHitTest by 40%,
kNonFastScrollableRegion by 67%) compared to HitTestOpaqueness only.

Bug: 40062957, 323688987, 324092420
Change-Id: I224c8e5f047ec27bf4c8957ae59643457cc9252e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5263065
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: Robert Flack <flackr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1258651}

--

wpt-commits: 742faa64b1b3cdad3384576d35340112067fa8f5
wpt-pr: 44402
This commit is contained in:
Xianzhu Wang 2024-02-12 08:42:23 +00:00 коммит произвёл moz-wptsync-bot
Родитель 8e2b935181
Коммит 745163053a
6 изменённых файлов: 315 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,57 @@
<!doctype html>
<meta charset=utf-8>
<title>pointer-events: none correctly targets scrolls</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<div style="pointer-events: none">
<iframe id="iframe"></iframe>
</div>
<div style="height: 200vh"></div>
<script>
promise_test(async (t) => {
let iframe = document.getElementById("iframe");
await new Promise((resolve) => {
iframe.onload = resolve;
iframe.srcdoc = `
<style>
#scroller {
overflow: auto;
height: 100px;
border: 2px solid blue;
}
.spacer {
height: 200vh;
}
</style>
<div id="scroller">
<div class="spacer"></div>
</div>
<div class="spacer"></div>
`;
});
let scrolled = new Promise((resolve) => {
let scrollers = [
window,
iframe.contentWindow,
iframe.contentDocument.getElementById("scroller")
];
let onscroll = (evt) => {
for (const scroller of scrollers) {
scroller.removeEventListener("scroll", onscroll);
}
resolve(evt.target.id || "root");
}
for (const scroller of scrollers) {
scroller.addEventListener("scroll", onscroll);
}
});
const actions = new test_driver.Actions().scroll(50, 50, 0, 50, { duration: 50 });
actions.send();
assert_equals(await scrolled, "root", "Incorrect element scrolled");
}, "Wheel-scroll over pointer-events: none scroller skips that scroller");
</script>

Просмотреть файл

@ -0,0 +1,53 @@
<!doctype html>
<meta charset=utf-8>
<title>pointer-events: none correctly targets scrolls</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<style>
body {
margin: 0;
}
#scroller {
overflow: auto;
width: 300px;
height: 300px;
border: 2px solid blue;
pointer-events: none;
}
.spacer {
height: 200vh;
}
</style>
<div id="scroller">
<div class="spacer"></div>
</div>
<div class="spacer"></div>
<script>
promise_test(async (t) => {
let scrolled = new Promise((resolve) => {
let scrollers = [window, document.getElementById("scroller")];
let onscroll = (evt) => {
for (const scroller of scrollers) {
scroller.removeEventListener("scroll", onscroll);
}
resolve(evt.target.id || "root");
}
for (const scroller of scrollers) {
scroller.addEventListener("scroll", onscroll);
}
});
// The cursor is expected on the scrollbar, but if it's not (e.g. if the
// scrollbar is overlay and isn't show), the test should still pass.
const actions = new test_driver.Actions().scroll(295, 200, 0, 50, { duration: 50 });
actions.send();
assert_equals(await scrolled, "root", "Incorrect element scrolled");
}, "Wheel-scroll over pointer-events: none scroller skips that scroller");
</script>

Просмотреть файл

@ -0,0 +1,58 @@
<!doctype html>
<meta charset=utf-8>
<title>pointer-events: none correctly targets scrolls</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<div style="pointer-events: none">
<iframe id="iframe"></iframe>
</div>
<div style="height: 200vh"></div>
<script>
promise_test(async (t) => {
let iframe = document.getElementById("iframe");
await new Promise((resolve) => {
iframe.onload = resolve;
iframe.srcdoc = `
<style>
#scroller {
overflow: auto;
height: 100px;
border: 2px solid blue;
will-change: scroll-position;
}
.spacer {
height: 200vh;
}
</style>
<div id="scroller">
<div class="spacer"></div>
</div>
<div class="spacer"></div>
`;
});
let scrolled = new Promise((resolve) => {
let scrollers = [
window,
iframe.contentWindow,
iframe.contentDocument.getElementById("scroller")
];
let onscroll = (evt) => {
for (const scroller of scrollers) {
scroller.removeEventListener("scroll", onscroll);
}
resolve(evt.target.id || "root");
}
for (const scroller of scrollers) {
scroller.addEventListener("scroll", onscroll);
}
});
const actions = new test_driver.Actions().scroll(50, 50, 0, 50, { duration: 50 });
actions.send();
assert_equals(await scrolled, "root", "Incorrect element scrolled");
}, "Wheel-scroll over pointer-events: none scroller skips that scroller");
</script>

Просмотреть файл

@ -0,0 +1,54 @@
<!doctype html>
<meta charset=utf-8>
<title>pointer-events: none correctly targets scrolls</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<style>
body {
margin: 0;
}
#scroller {
overflow: auto;
width: 300px;
height: 300px;
border: 2px solid blue;
pointer-events: none;
will-change: scroll-position;
}
.spacer {
height: 200vh;
}
</style>
<div id="scroller">
<div class="spacer"></div>
</div>
<div class="spacer"></div>
<script>
promise_test(async (t) => {
let scrolled = new Promise((resolve) => {
let scrollers = [window, document.getElementById("scroller")];
let onscroll = (evt) => {
for (const scroller of scrollers) {
scroller.removeEventListener("scroll", onscroll);
}
resolve(evt.target.id || "root");
}
for (const scroller of scrollers) {
scroller.addEventListener("scroll", onscroll);
}
});
// The cursor is expected on the scrollbar, but if it's not (e.g. if the
// scrollbar is overlay and isn't show), the test should still pass.
const actions = new test_driver.Actions().scroll(295, 200, 0, 50, { duration: 50 });
actions.send();
assert_equals(await scrolled, "root", "Incorrect element scrolled");
}, "Wheel-scroll over pointer-events: none scroller skips that scroller");
</script>

Просмотреть файл

@ -0,0 +1,47 @@
<!doctype html>
<meta charset=utf-8>
<title>pointer-events: none correctly targets scrolls</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<style>
#scroller {
overflow: auto;
height: 300px;
border: 2px solid blue;
pointer-events: none;
will-change: scroll-position;
}
.spacer {
height: 200vh;
}
</style>
<div id="scroller">
<div class="spacer"></div>
</div>
<div class="spacer"></div>
<script>
promise_test(async (t) => {
let scrolled = new Promise((resolve) => {
let scrollers = [window, document.getElementById("scroller")];
let onscroll = (evt) => {
for (const scroller of scrollers) {
scroller.removeEventListener("scroll", onscroll);
}
resolve(evt.target.id || "root");
}
for (const scroller of scrollers) {
scroller.addEventListener("scroll", onscroll);
}
});
const actions = new test_driver.Actions().scroll(50, 200, 0, 50, { duration: 50 });
actions.send();
assert_equals(await scrolled, "root", "Incorrect element scrolled");
}, "Wheel-scroll over pointer-events: none scroller skips that scroller");
</script>

Просмотреть файл

@ -0,0 +1,46 @@
<!doctype html>
<meta charset=utf-8>
<title>pointer-events: none correctly targets scrolls</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<style>
#scroller {
overflow: auto;
height: 300px;
border: 2px solid blue;
pointer-events: none;
}
.spacer {
height: 200vh;
}
</style>
<div id="scroller">
<div class="spacer"></div>
</div>
<div class="spacer"></div>
<script>
promise_test(async (t) => {
let scrolled = new Promise((resolve) => {
let scrollers = [window, document.getElementById("scroller")];
let onscroll = (evt) => {
for (const scroller of scrollers) {
scroller.removeEventListener("scroll", onscroll);
}
resolve(evt.target.id || "root");
}
for (const scroller of scrollers) {
scroller.addEventListener("scroll", onscroll);
}
});
const actions = new test_driver.Actions().scroll(50, 200, 0, 50, { duration: 50 });
actions.send();
assert_equals(await scrolled, "root", "Incorrect element scrolled");
}, "Wheel-scroll over pointer-events: none scroller skips that scroller");
</script>