gpui: Unify the index_for_x methods (#42162)

Supersedes https://github.com/zed-industries/zed/pull/39910

At some point, these two (`index_for_x` and `closest_index_for_x`)
methods where separated out and some code paths used one, while other
code paths took the other. That said, their behavior is almost
identical:

- `index_for_x` computes the index behind the pixel offset, and returns
`None` if there's an overshoot
- `closest_index_for_x` computes the nearest index to the pixel offset,
taking into account whether the offset is over halfway through or not.
If there's an overshoot, it returns the length of the line.

Given these two behaviors, `closest_index_for_x` seems to be a more
useful API than `index_for_x`, and indeed the display map and other core
editor features use it extensively. So this PR is an experiment in
simply replacing one behavior with the other.

Release Notes:

- Improved the accuracy of mouse selections in Markdown
This commit is contained in:
Mikayla Maki
2025-11-07 14:23:43 +02:00
committed by GitHub
parent 483e31e42a
commit 082b80ec89
6 changed files with 13 additions and 62 deletions
+1 -1
View File
@@ -1097,7 +1097,7 @@ impl DisplaySnapshot {
details: &TextLayoutDetails,
) -> u32 {
let layout_line = self.layout_row(display_row, details);
layout_line.closest_index_for_x(x) as u32
layout_line.index_for_x(x) as u32
}
pub fn grapheme_at(&self, mut point: DisplayPoint) -> Option<SharedString> {
+1 -1
View File
@@ -8334,7 +8334,7 @@ impl LineWithInvisibles {
let fragment_end_x = fragment_start_x + shaped_line.width;
if x < fragment_end_x {
return Some(
fragment_start_index + shaped_line.index_for_x(x - fragment_start_x)?,
fragment_start_index + shaped_line.index_for_x(x - fragment_start_x),
);
}
fragment_start_x = fragment_end_x;
+2 -2
View File
@@ -372,7 +372,7 @@ impl SelectionsCollection {
let is_empty = positions.start == positions.end;
let line_len = display_map.line_len(row);
let line = display_map.layout_row(row, text_layout_details);
let start_col = line.closest_index_for_x(positions.start) as u32;
let start_col = line.index_for_x(positions.start) as u32;
let (start, end) = if is_empty {
let point = DisplayPoint::new(row, std::cmp::min(start_col, line_len));
@@ -382,7 +382,7 @@ impl SelectionsCollection {
return None;
}
let start = DisplayPoint::new(row, start_col);
let end_col = line.closest_index_for_x(positions.end) as u32;
let end_col = line.index_for_x(positions.end) as u32;
let end = DisplayPoint::new(row, end_col);
(start, end)
};