Bug 1931968 [wpt PR 49236] - [focus] Make mouse focus use flat tree parent, a=testonly

Automatic update from web-platform-tests
[focus] Make mouse focus use flat tree parent

This is an updated version of patch:
https://crrev.com/c/1514433

Currently, mouse-triggered event will traverse up parentOrShadowHost
to find fallback element to receive mouse focus. This doesn't make sense
for slotted content, where we expect the parent to receive focus to be
the assigned slot. This is fixed by traversing using the Flat Tree.

In the DOM spec for the Dispatch algorithm [1]:

"If isActivationEvent is true, event’s bubbles attribute is true,
activationTarget is null, and parent has activation behavior, then set
activationTarget to parent."

The parent is found using the get the parent algorithm [2]:
"A node’s get the parent algorithm, given an event, returns the node’s
assigned slot, if node is assigned; otherwise node’s parent."

Previously, this patch was reverted because it broke the text selection
in DevTools Network panel, which uses slots. This is fixed by
updating FrameSelection to use flat tree traversal to find parent.

The change is behind flag MouseFocusFlatTreeParent.

[1] https://dom.spec.whatwg.org/#concept-event-dispatch
[2] https://dom.spec.whatwg.org/#get-the-parent

Change-Id: Ibfeaebab0dce4817c34b447f540e784b12b9ab56
Bug: 41420461
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6004068
Auto-Submit: Di Zhang <dizhangg@chromium.org>
Commit-Queue: David Baron <dbaron@chromium.org>
Reviewed-by: David Baron <dbaron@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1384575}

--

wpt-commits: 8c7d2bc8f83d8a38e51178ce132f3eed17275b8b
wpt-pr: 49236
This commit is contained in:
Di Zhang 2024-11-19 09:52:03 +00:00 committed by moz-wptsync-bot
parent d5155e8e84
commit e4e37992cd

View File

@ -0,0 +1,73 @@
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<link rel="help" href="crbug.com/41420461">
<div id='normalDiv' tabindex='0'><span id='normalSpan'>Text to click and select</span></div>
<div id='container'><span id='slottedSpan'>Slotted text to click and select</span></div>
<script>
function clickOn(element) {
const actions = new test_driver.Actions();
actions.pointerMove(5, 5, {origin: element});
actions.pointerDown();
actions.pointerUp();
return actions.send();
}
function selectText(element) {
getSelection().empty();
const actions = new test_driver.Actions();
actions.pointerMove(0, 0, {origin: element});
actions.pointerDown();
actions.pointerMove(50, 0, {origin: element});
actions.pointerUp();
return actions.send();
}
let sr = container.attachShadow({ mode: 'open' });
sr.innerHTML = '<div id="shadowDiv" tabindex="0"><slot></slot></div>';
promise_test(async () => {
await clickOn(normalSpan);
assert_equals(document.activeElement, normalDiv);
await clickOn(slottedSpan);
assert_equals(document.activeElement, container);
assert_equals(sr.activeElement, sr.getElementById('shadowDiv'));
}, 'Clicking on non-focusable slot inside focusable div will make the flat-tree focusable ancestor get focused');
promise_test(async () => {
let selection = getSelection();
await selectText(normalSpan);
assert_equals(document.activeElement, normalDiv);
assert_equals(selection.anchorNode, normalSpan.firstChild);
assert_greater_than(selection.toString().length, 0);
await selectText(slottedSpan);
assert_equals(document.activeElement, container);
assert_equals(sr.activeElement, sr.getElementById('shadowDiv'));
assert_equals(selection.anchorNode, slottedSpan.firstChild);
assert_greater_than(selection.toString().length, 0);
}, 'Select on non-focusable slot inside focusable div will select text');
promise_test(async () => {
let selection = getSelection();
// Reset selection
await clickOn(normalSpan);
container.setAttribute('contenteditable', true);
await selectText(slottedSpan);
assert_equals(document.activeElement, container);
assert_equals(sr.activeElement, null, 'focus is on contenteditable container only');
assert_equals(selection.anchorNode, slottedSpan.firstChild);
assert_greater_than(selection.toString().length, 0);
container.removeAttribute('contenteditable');
}, 'Select on non-focusable non-editable slot in a contenteditable shadow DOM and inside focusable div will select text');
</script>