From 76bab908127f1eb0bae849e2abc7ca263c9b3a98 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Thu, 14 Aug 2025 12:48:06 -0400 Subject: [PATCH] LibWeb: Use rendered text to find word boundaries when double-clicking This effectively reverts da26941b505ea3a2aab1dae99c3a6d648f4222a9. 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. --- Libraries/LibWeb/Page/EventHandler.cpp | 7 +++++-- .../Text/expected/selection-on-rendered-text.txt | 1 + .../LibWeb/Text/input/selection-on-rendered-text.html | 11 +++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/selection-on-rendered-text.txt create mode 100644 Tests/LibWeb/Text/input/selection-on-rendered-text.html diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp index 203c5453443..b0706841a31 100644 --- a/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Libraries/LibWeb/Page/EventHandler.cpp @@ -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()) { diff --git a/Tests/LibWeb/Text/expected/selection-on-rendered-text.txt b/Tests/LibWeb/Text/expected/selection-on-rendered-text.txt new file mode 100644 index 00000000000..70b7a952e95 --- /dev/null +++ b/Tests/LibWeb/Text/expected/selection-on-rendered-text.txt @@ -0,0 +1 @@ +Selected range: 6 - 11 diff --git a/Tests/LibWeb/Text/input/selection-on-rendered-text.html b/Tests/LibWeb/Text/input/selection-on-rendered-text.html new file mode 100644 index 00000000000..5907ebb3bf7 --- /dev/null +++ b/Tests/LibWeb/Text/input/selection-on-rendered-text.html @@ -0,0 +1,11 @@ + + +

Lorem ipsum dolor sit amet

+