mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-07 00:29:15 +00:00
LibWeb: Improve caret positioning behavior inside fragments
When clicking on a glyph or starting a selection on it, we would use the glyph's offset/index as the position which represents the left side of the glyph, or the position between the glyph and the glyph before it. Instead of looking at which glyph is under the mouse pointer, look at which glyph boundary is closer. Now, if you click to the right of a glyph (but still on that glyph), it correctly selects the next glyph's offset as the position.
This commit is contained in:
parent
408165d2f4
commit
dbbdf2cebc
Notes:
github-actions[bot]
2025-06-13 13:09:58 +00:00
Author: https://github.com/gmta
Commit: dbbdf2cebc
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5067
Reviewed-by: https://github.com/tcl3
Reviewed-by: https://github.com/trflynn89
4 changed files with 18 additions and 22 deletions
|
@ -41,34 +41,30 @@ size_t PaintableFragment::text_index_at(CSSPixelPoint position) const
|
|||
if (!is<TextPaintable>(paintable()))
|
||||
return 0;
|
||||
|
||||
CSSPixels relative_inline_offset = [&]() {
|
||||
auto relative_inline_offset = [&] {
|
||||
switch (orientation()) {
|
||||
case Gfx::Orientation::Horizontal:
|
||||
return position.x() - absolute_rect().x();
|
||||
case Gfx::Orientation::Vertical:
|
||||
return position.y() - absolute_rect().y();
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
case Orientation::Horizontal:
|
||||
return (position.x() - absolute_rect().x()).to_float();
|
||||
case Orientation::Vertical:
|
||||
return (position.y() - absolute_rect().y()).to_float();
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}();
|
||||
|
||||
if (relative_inline_offset < 0)
|
||||
return 0;
|
||||
|
||||
auto const& glyphs = m_glyph_run->glyphs();
|
||||
auto smallest_distance = AK::NumericLimits<float>::max();
|
||||
for (size_t i = 0; i < glyphs.size(); ++i) {
|
||||
auto glyph_position = CSSPixels::nearest_value_for(glyphs[i].position.x());
|
||||
if (i + 1 < glyphs.size()) {
|
||||
auto next_glyph_position = CSSPixels::nearest_value_for(glyphs[i + 1].position.x());
|
||||
if (relative_inline_offset >= glyph_position && relative_inline_offset < next_glyph_position)
|
||||
return m_start + i;
|
||||
} else {
|
||||
if (relative_inline_offset >= glyph_position)
|
||||
return m_start + i;
|
||||
}
|
||||
auto distance_to_position = AK::abs(glyphs[i].position.x() - relative_inline_offset);
|
||||
|
||||
// The last distance was smaller than this new distance, so we've found the closest glyph.
|
||||
if (distance_to_position > smallest_distance)
|
||||
return m_start + i - 1;
|
||||
smallest_distance = distance_to_position;
|
||||
}
|
||||
|
||||
return m_start + m_length;
|
||||
return m_start + m_length - 1;
|
||||
}
|
||||
|
||||
CSSPixelRect PaintableFragment::range_rect(size_t start_offset, size_t end_offset) const
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue