Skip to content

Commit

Permalink
[css-pseudo] Fix text selection and drag-and-drop for pseudo-elements
Browse files Browse the repository at this point in the history
Before this patch, if you had a tree like

  <div><div::before>abc</div::before>def</div>

and you tried to select "bc", Chromium would end up selecting "ef" in
some cases. Similarly, trying to drag a text and drop it between "bc",
would end up inserting the text between "ef".

This patch fixes the problem, now trying to select "bc" won't select
anything. And dropping some text between "bc" will insert it between
the "cd".

BUG=1051685

TEST=external/wpt/css/css-pseudo/text-selection.html
TEST=fast/css-generated-content/drag-and-drop.html

The 2nd test is internal because I didn't manage to properly simulate
drag and drop using testdriver.js

Change-Id: Iedd594b46022ed434bdb1462232c717ec08f5304
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2047287
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Commit-Queue: Oriol Brufau <obrufau@igalia.com>
Cr-Commit-Position: refs/heads/master@{#741909}
  • Loading branch information
Loirooriol authored and chromium-wpt-export-bot committed Feb 17, 2020
1 parent 0ffd351 commit 410f5ec
Showing 1 changed file with 87 additions and 0 deletions.
87 changes: 87 additions & 0 deletions css/css-pseudo/text-selection.html
@@ -0,0 +1,87 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Pseudo-Elements Test: Text selection</title>
<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#treelike">
<link rel="help" href="https://drafts.csswg.org/css-ui/#user-interaction">
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
<meta name="assert" content="This test checks that text in a ::before or ::marker pseudo-element can't be selected." />
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
<style>
.test {
font: 10px/1 Ahem;
margin-left: 200px;
}
#before::before {
content: "::before";
display: inline-block;
margin-left: -80px;
}
#marker {
display: list-item;
list-style-type: "::marker";
}
#before-marker::before {
content: "";
display: list-item;
list-style-type: "::marker";
height: 0;
}
</style>
<div class="test" id="before"><span>helloworld</span></div>
<div class="test" id="marker"><span>helloworld</span></div>
<div class="test" id="before-marker"><span>helloworld</span></div>
<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>
<script>
function createSelection(element, start, end, step) {
getSelection().empty();
step = Math.abs(step);
const actions = new test_driver.Actions();
actions.pointerMove(start, 0, {origin: element});
actions.pointerDown();
if (start < end) {
for (let x = start + step; x < end; x += step)
actions.pointerMove(x, 0, {origin: element});
} else {
for (let x = start - step; x > end; x -= step)
actions.pointerMove(x, 0, {origin: element});
}
actions.pointerMove(end, 0, {origin: element});
actions.pointerUp();
return actions.send();
}
(async function() {
setup({ explicit_done: true });
for (let target of document.querySelectorAll(".test")) {
const contents = target.querySelector("span");
const text = contents.firstChild;
const s = getSelection();

// Create a selection that starts in the middle of the element contents
// and ends in the middle of the pseudo-element
await createSelection(contents, 0, -90, 10);
test(function(t) {
assert_equals(s.toString(), "hello", "toString");
assert_equals(s.anchorNode, text, "anchorNode");
assert_equals(s.anchorOffset, 5, "anchorOffset");
assert_equals(s.focusNode, text, "focusNode");
assert_equals(s.focusOffset, 0, "focusOffset");
}, "Selection ending in ::" + target.id);

// Create a selection that starts and ends inside the pseudo-element.
await createSelection(contents, -80, -110, 10);
test(function(t) {
assert_equals(s.toString(), "", "toString");
assert_in_array(s.anchorNode, [text, null], "anchorNode");
assert_equals(s.anchorOffset, 0, "anchorOffset");
assert_in_array(s.focusNode, [text, null], "focusNode");
assert_equals(s.focusOffset, 0, "focusOffset");
}, "Selection contained in ::" + target.id);
}
done();
})();
</script>

0 comments on commit 410f5ec

Please sign in to comment.