mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-28 11:49:44 +00:00
LibWeb: Skip update_associated_selection()
when there's no selection
This change fixes at least two issues: - `update_associated_selection()` is responsible for selectionchange dispatch, and we were incorrectly dispatching this event on ranges that were not associated with a selection. - `Range::get_client_rects()` was using `update_associated_selection()` to refresh the selection state in the paintable tree for the current range, but since a range might not be associated with a selection, this could make the painted selection reflect the state of an arbitrary range instead of the actual selection range. Fixes a bug on Discord where any text typed into the message input would get selected.
This commit is contained in:
parent
69074a3841
commit
5874b7a76f
Notes:
github-actions[bot]
2025-07-03 20:17:46 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: 5874b7a76f
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5292
Reviewed-by: https://github.com/gmta ✅
5 changed files with 73 additions and 12 deletions
|
@ -3,6 +3,7 @@
|
|||
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022-2023, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2024-2025, Jelle Raaijmakers <jelle@ladybird.org>
|
||||
* Copyright (c) 2024-2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -99,6 +100,9 @@ void Range::set_associated_selection(Badge<Selection::Selection>, GC::Ptr<Select
|
|||
|
||||
void Range::update_associated_selection()
|
||||
{
|
||||
if (!m_associated_selection)
|
||||
return;
|
||||
|
||||
auto& document = m_start_container->document();
|
||||
if (auto* viewport = document.paintable()) {
|
||||
viewport->recompute_selection_states(*this);
|
||||
|
@ -1143,7 +1147,6 @@ GC::Ref<Geometry::DOMRectList> Range::get_client_rects()
|
|||
return Geometry::DOMRectList::create(realm(), {});
|
||||
|
||||
start_container()->document().update_layout(DOM::UpdateLayoutReason::RangeGetClientRects);
|
||||
update_associated_selection();
|
||||
Vector<GC::Root<Geometry::DOMRect>> rects;
|
||||
// FIXME: take Range collapsed into consideration
|
||||
// 2. Iterate the node included in Range
|
||||
|
@ -1159,6 +1162,15 @@ GC::Ref<Geometry::DOMRectList> Range::get_client_rects()
|
|||
end_node = *end_node->child_at_index(m_end_offset - 1);
|
||||
}
|
||||
for (GC::Ptr<Node> node = start_node; node && node != end_node->next_in_pre_order(); node = node->next_in_pre_order()) {
|
||||
auto selection_state = Painting::Paintable::SelectionState::Full;
|
||||
if (node == start_node && node == end_node) {
|
||||
selection_state = Painting::Paintable::SelectionState::StartAndEnd;
|
||||
} else if (node == start_node) {
|
||||
selection_state = Painting::Paintable::SelectionState::Start;
|
||||
} else if (node == end_node) {
|
||||
selection_state = Painting::Paintable::SelectionState::End;
|
||||
}
|
||||
|
||||
auto node_type = static_cast<NodeType>(node->node_type());
|
||||
if (node_type == NodeType::ELEMENT_NODE) {
|
||||
// 1. For each element selected by the range, whose parent is not selected by the range, include the border
|
||||
|
@ -1181,7 +1193,7 @@ GC::Ref<Geometry::DOMRectList> Range::get_client_rects()
|
|||
auto const& paintable_lines = static_cast<Painting::PaintableWithLines const&>(*containing_block);
|
||||
auto fragments = paintable_lines.fragments();
|
||||
for (auto frag = fragments.begin(); frag != fragments.end(); frag++) {
|
||||
auto rect = frag->range_rect(start_offset(), end_offset());
|
||||
auto rect = frag->range_rect(selection_state, start_offset(), end_offset());
|
||||
if (rect.is_empty())
|
||||
continue;
|
||||
rects.append(Geometry::DOMRect::create(realm(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue