mirror of
https://github.com/zebrajr/ladybird.git
synced 2025-12-06 00:19:53 +01:00
LibWeb: Fix partially selecting non-text nodes
Steps 4 and 5 were swapped since marking all the nodes between the start and end of the selection now also marks the end node as full, even if it should be marked as End. There could be extra logic to avoid marking it if it is a text node, but this seems easier. As a whole, this fixes partially selected non-text nodes. In such cases, where the selection starts or ends inside a node with descendants, it is impossible to just select from the start node to the end node since that would select all descendants of the start node and none of the end node. Previously, this was only half considered and only if the start node was a descendant of the end node.
This commit is contained in:
parent
66a36050bd
commit
80b629578e
|
|
@ -370,30 +370,30 @@ void ViewportPaintable::recompute_selection_states(DOM::Range& range)
|
|||
paintable->set_selection_state(SelectionState::Full);
|
||||
}
|
||||
|
||||
// 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 (is<DOM::Text>(*end_container))
|
||||
paintable->set_selection_state(SelectionState::End);
|
||||
else
|
||||
paintable->set_selection_state(SelectionState::Full);
|
||||
// 4. Mark the nodes between the start and end of the selection as Full.
|
||||
auto* start_at = start_container->child_at_index(range.start_offset());
|
||||
// If the start container has no child at that index, we need to start on the node right after the start container.
|
||||
if (!start_at) {
|
||||
if (auto* last_child = start_container->last_child()) {
|
||||
start_at = last_child->next_in_pre_order();
|
||||
} else {
|
||||
start_at = start_container->next_in_pre_order();
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Mark the nodes between start node and end node (in tree order) as Full.
|
||||
// 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)) {
|
||||
DOM::Node* stop_at = end_container->child_at_index(range.end_offset());
|
||||
// Only stop at the end container if it has no children that may need to be included.
|
||||
for (auto* node = start_at; node && (node != stop_at && !(node == end_container && !end_container->has_children())); node = node->next_in_pre_order(end_container)) {
|
||||
if (node->is_inert())
|
||||
continue;
|
||||
if (auto* paintable = node->paintable())
|
||||
paintable->set_selection_state(SelectionState::Full);
|
||||
}
|
||||
|
||||
// 5. Mark the selection end node as End if it is a text node.
|
||||
if (auto* paintable = end_container->paintable(); paintable && !range.end().node->is_inert() && is<DOM::Text>(*end_container)) {
|
||||
paintable->set_selection_state(SelectionState::End);
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewportPaintable::handle_mousewheel(Badge<EventHandler>, CSSPixelPoint, unsigned, unsigned, int, int)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
<img src="../images/selection-partial-nodes-ref.png">
|
||||
BIN
Tests/LibWeb/Screenshot/images/selection-partial-nodes-ref.png
Normal file
BIN
Tests/LibWeb/Screenshot/images/selection-partial-nodes-ref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
10
Tests/LibWeb/Screenshot/input/selection-partial-nodes.html
Normal file
10
Tests/LibWeb/Screenshot/input/selection-partial-nodes.html
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<meta name="fuzzy" content="maxDifference=0-1;totalPixels=0-250">
|
||||
<link rel="match" href="../expected/selection-partial-nodes-ref.html" />
|
||||
<div id="start">not selected <span>sel</span><span id="end">ected<span> and not selected</span></span></div>
|
||||
<script>
|
||||
let range = document.createRange();
|
||||
range.setStart(start, 1);
|
||||
range.setEnd(end, 1);
|
||||
window.getSelection().addRange(range);
|
||||
</script>
|
||||
Loading…
Reference in New Issue
Block a user