LibWeb: Use rendered text to find word boundaries when double-clicking

This effectively reverts da26941b50.

When the user double-clicks a word on screen, they are interacting with
the rendered text, which has e.g. whitespace collapsing applied. If we
acquire word boundaries from the raw text, the resulting selection is
not right.

We still have issues with acquiring the right selection via APIs such as
`document.getSelection`. The offsets computed here are effectively then
applied to the raw text. But this issue is present all over EventHandler
and this patch at least makes the selection visually accurate.
This commit is contained in:
Timothy Flynn 2025-08-14 12:48:06 -04:00 committed by Alexander Kalenik
commit 76bab90812
Notes: github-actions[bot] 2025-08-14 17:37:55 +00:00
3 changed files with 17 additions and 2 deletions

View file

@ -981,8 +981,11 @@ EventResult EventHandler::handle_doubleclick(CSSPixelPoint viewport_position, CS
if (hit_dom_node.is_password_input()) {
next_boundary = hit_dom_node.length_in_utf16_code_units();
} else {
previous_boundary = hit_dom_node.word_segmenter().previous_boundary(result->index_in_node, Unicode::Segmenter::Inclusive::Yes).value_or(0);
next_boundary = hit_dom_node.word_segmenter().next_boundary(result->index_in_node).value_or(hit_dom_node.length());
auto& segmenter = word_segmenter();
segmenter.set_segmented_text(hit_paintable.text_for_rendering());
previous_boundary = segmenter.previous_boundary(result->index_in_node, Unicode::Segmenter::Inclusive::Yes).value_or(0);
next_boundary = segmenter.next_boundary(result->index_in_node).value_or(hit_dom_node.length());
}
if (auto* target = document.active_input_events_target()) {

View file

@ -0,0 +1 @@
Selected range: 6 - 11

View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<script src="include.js"></script>
<p id="text">Lorem ipsum dolor sit amet</p>
<script>
test(() => {
internals.doubleclick(85, 20);
const selection = document.getSelection().getRangeAt(0);
println(`Selected range: ${selection.startOffset} - ${selection.endOffset}`);
});
</script>