mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-13 11:39:43 +00:00
LibWeb: Fix selection when start node is inside end node
Some checks are pending
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Some checks are pending
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Fixes a regression introduced in
bc8870d019
(in a performant way this
time)
This commit is contained in:
parent
202c55bf28
commit
baf2063e31
Notes:
github-actions[bot]
2025-07-04 18:20:56 +00:00
Author: https://github.com/Psychpsyo
Commit: baf2063e31
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5290
Reviewed-by: https://github.com/gmta
Reviewed-by: https://github.com/kalenikaliaksandr ✅
6 changed files with 50 additions and 9 deletions
|
@ -362,19 +362,23 @@ void ViewportPaintable::recompute_selection_states(DOM::Range& range)
|
||||||
|
|
||||||
// 4. Mark the selection end node as End (if text) or Full (if anything else).
|
// 4. Mark the selection end node as End (if text) or Full (if anything else).
|
||||||
if (auto* paintable = end_container->paintable(); paintable && !range.end().node->is_inert()) {
|
if (auto* paintable = end_container->paintable(); paintable && !range.end().node->is_inert()) {
|
||||||
if (is<DOM::Text>(*end_container) || end_container->is_ancestor_of(start_container)) {
|
if (is<DOM::Text>(*end_container))
|
||||||
paintable->set_selection_state(SelectionState::End);
|
paintable->set_selection_state(SelectionState::End);
|
||||||
} else {
|
else
|
||||||
paintable->for_each_in_inclusive_subtree([&](auto& layout_node) {
|
paintable->set_selection_state(SelectionState::Full);
|
||||||
if (!layout_node.dom_node() || !layout_node.dom_node()->is_inert())
|
|
||||||
layout_node.set_selection_state(SelectionState::Full);
|
|
||||||
return TraversalDecision::Continue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Mark the nodes between start node and end node (in tree order) as Full.
|
// 5. Mark the nodes between start node and end node (in tree order) as Full.
|
||||||
for (auto* node = start_container->next_in_pre_order(); node && node != end_container; node = node->next_in_pre_order()) {
|
// NOTE: If the start node is a descendant of the end node, we cannot traverse from it to the end node since the end node is before it in tree order.
|
||||||
|
// Instead, we need to stop traversal somewhere inside the end node, or right after it.
|
||||||
|
DOM::Node* stop_at;
|
||||||
|
if (start_container->is_descendant_of(end_container)) {
|
||||||
|
stop_at = end_container->child_at_index(range.end_offset());
|
||||||
|
} else {
|
||||||
|
stop_at = end_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto* node = start_container->next_in_pre_order(); node && node != stop_at; node = node->next_in_pre_order(end_container)) {
|
||||||
if (node->is_inert())
|
if (node->is_inert())
|
||||||
continue;
|
continue;
|
||||||
if (auto* paintable = node->paintable())
|
if (auto* paintable = node->paintable())
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<img src="../images/selection-start-in-end-node-ref.png">
|
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="match" href="../expected/selection-start-in-end-node-ref.html" />
|
||||||
|
<!-- The space after the start node, as well as "NOT SELECTED" must not be selected. -->
|
||||||
|
<span id="end">End Node <span id="start">Start Node</span> </span>NOT SELECTED
|
||||||
|
<script>
|
||||||
|
let range = document.createRange();
|
||||||
|
range.setStart(start, 0);
|
||||||
|
range.setEnd(end, 2);
|
||||||
|
window.getSelection().addRange(range);
|
||||||
|
</script>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="match" href="../expected/selection-start-in-end-node-ref.html" />
|
||||||
|
<!-- here the end node contains the start node, as well as some further selected content and some non-selected content. -->
|
||||||
|
<span id="end">End Node <span id="start">Start</span> <span>Node</span> </span>NOT SELECTED
|
||||||
|
<script>
|
||||||
|
let range = document.createRange();
|
||||||
|
range.setStart(start, 0);
|
||||||
|
range.setEnd(end, 4);
|
||||||
|
window.getSelection().addRange(range);
|
||||||
|
</script>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="match" href="../expected/selection-start-in-end-node-ref.html" />
|
||||||
|
<!-- The text after the end node must not be selected. -->
|
||||||
|
<span id="end">End Node <span id="start">Start Node</span></span> NOT SELECTED
|
||||||
|
<script>
|
||||||
|
let range = document.createRange();
|
||||||
|
range.setStart(start, 0);
|
||||||
|
range.setEnd(end, 2);
|
||||||
|
window.getSelection().addRange(range);
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue