editor: Represent scroll offset with more precision (#39367)
Closes #5355 Release Notes: - Fixed rendering glitches with files with more than 16 million lines (that occured due to floating number rounding errors). --------- Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
This commit is contained in:
co-authored by
Smit Barmase
parent
4c35274b6e
commit
d359a814f8
+54
-39
@@ -210,6 +210,7 @@ use crate::{
|
||||
code_context_menus::CompletionsMenuSource,
|
||||
editor_settings::MultiCursorModifier,
|
||||
hover_links::{find_url, find_url_from_range},
|
||||
scroll::{ScrollOffset, ScrollPixelOffset},
|
||||
signature_help::{SignatureHelpHiddenBy, SignatureHelpState},
|
||||
};
|
||||
|
||||
@@ -8621,8 +8622,8 @@ impl Editor {
|
||||
self.context_menu_options = Some(options);
|
||||
}
|
||||
|
||||
const EDIT_PREDICTION_POPOVER_PADDING_X: Pixels = Pixels(24.);
|
||||
const EDIT_PREDICTION_POPOVER_PADDING_Y: Pixels = Pixels(2.);
|
||||
const EDIT_PREDICTION_POPOVER_PADDING_X: Pixels = px(24.);
|
||||
const EDIT_PREDICTION_POPOVER_PADDING_Y: Pixels = px(2.);
|
||||
|
||||
fn render_edit_prediction_popover(
|
||||
&mut self,
|
||||
@@ -8631,11 +8632,12 @@ impl Editor {
|
||||
right_margin: Pixels,
|
||||
editor_snapshot: &EditorSnapshot,
|
||||
visible_row_range: Range<DisplayRow>,
|
||||
scroll_top: f32,
|
||||
scroll_bottom: f32,
|
||||
scroll_top: ScrollOffset,
|
||||
scroll_bottom: ScrollOffset,
|
||||
line_layouts: &[LineWithInvisibles],
|
||||
line_height: Pixels,
|
||||
scroll_pixel_position: gpui::Point<Pixels>,
|
||||
scroll_position: gpui::Point<ScrollOffset>,
|
||||
scroll_pixel_position: gpui::Point<ScrollPixelOffset>,
|
||||
newest_selection_head: Option<DisplayPoint>,
|
||||
editor_width: Pixels,
|
||||
style: &EditorStyle,
|
||||
@@ -8727,6 +8729,7 @@ impl Editor {
|
||||
visible_row_range,
|
||||
line_layouts,
|
||||
line_height,
|
||||
scroll_position,
|
||||
scroll_pixel_position,
|
||||
newest_selection_head,
|
||||
editor_width,
|
||||
@@ -8769,14 +8772,14 @@ impl Editor {
|
||||
visible_row_range: Range<DisplayRow>,
|
||||
line_layouts: &[LineWithInvisibles],
|
||||
line_height: Pixels,
|
||||
scroll_pixel_position: gpui::Point<Pixels>,
|
||||
scroll_pixel_position: gpui::Point<ScrollPixelOffset>,
|
||||
newest_selection_head: Option<DisplayPoint>,
|
||||
target_display_point: DisplayPoint,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Option<(AnyElement, gpui::Point<Pixels>)> {
|
||||
let scrolled_content_origin =
|
||||
content_origin - gpui::Point::new(scroll_pixel_position.x, Pixels(0.0));
|
||||
content_origin - gpui::Point::new(scroll_pixel_position.x.into(), Pixels::ZERO);
|
||||
|
||||
const SCROLL_PADDING_Y: Pixels = px(12.);
|
||||
|
||||
@@ -8811,8 +8814,8 @@ impl Editor {
|
||||
let target_column = target_display_point.column() as usize;
|
||||
|
||||
let target_x = line_layout.x_for_index(target_column);
|
||||
let target_y =
|
||||
(target_display_point.row().as_f32() * line_height) - scroll_pixel_position.y;
|
||||
let target_y = (target_display_point.row().as_f64() * f64::from(line_height))
|
||||
- scroll_pixel_position.y;
|
||||
|
||||
let flag_on_right = target_x < text_bounds.size.width / 2.;
|
||||
|
||||
@@ -8840,7 +8843,7 @@ impl Editor {
|
||||
|
||||
let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
|
||||
|
||||
let mut origin = scrolled_content_origin + point(target_x, target_y)
|
||||
let mut origin = scrolled_content_origin + point(target_x, target_y.into())
|
||||
- point(
|
||||
if flag_on_right {
|
||||
POLE_WIDTH
|
||||
@@ -8893,16 +8896,16 @@ impl Editor {
|
||||
content_origin: gpui::Point<Pixels>,
|
||||
editor_snapshot: &EditorSnapshot,
|
||||
visible_row_range: Range<DisplayRow>,
|
||||
scroll_top: f32,
|
||||
scroll_bottom: f32,
|
||||
scroll_top: ScrollOffset,
|
||||
scroll_bottom: ScrollOffset,
|
||||
line_height: Pixels,
|
||||
scroll_pixel_position: gpui::Point<Pixels>,
|
||||
scroll_pixel_position: gpui::Point<ScrollPixelOffset>,
|
||||
target_display_point: DisplayPoint,
|
||||
editor_width: Pixels,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Option<(AnyElement, gpui::Point<Pixels>)> {
|
||||
if target_display_point.row().as_f32() < scroll_top {
|
||||
if target_display_point.row().as_f64() < scroll_top {
|
||||
let mut element = self
|
||||
.render_edit_prediction_line_popover(
|
||||
"Jump to Edit",
|
||||
@@ -8921,7 +8924,7 @@ impl Editor {
|
||||
let origin = text_bounds.origin + offset;
|
||||
element.prepaint_at(origin, window, cx);
|
||||
Some((element, origin))
|
||||
} else if (target_display_point.row().as_f32() + 1.) > scroll_bottom {
|
||||
} else if (target_display_point.row().as_f64() + 1.) > scroll_bottom {
|
||||
let mut element = self
|
||||
.render_edit_prediction_line_popover(
|
||||
"Jump to Edit",
|
||||
@@ -8963,7 +8966,7 @@ impl Editor {
|
||||
visible_row_range: Range<DisplayRow>,
|
||||
target_display_point: DisplayPoint,
|
||||
line_height: Pixels,
|
||||
scroll_pixel_position: gpui::Point<Pixels>,
|
||||
scroll_pixel_position: gpui::Point<ScrollPixelOffset>,
|
||||
content_origin: gpui::Point<Pixels>,
|
||||
editor_width: Pixels,
|
||||
window: &mut Window,
|
||||
@@ -8982,7 +8985,7 @@ impl Editor {
|
||||
|
||||
let line_origin = self.display_to_pixel_point(target_line_end, editor_snapshot, window)?;
|
||||
|
||||
let start_point = content_origin - point(scroll_pixel_position.x, Pixels::ZERO);
|
||||
let start_point = content_origin - point(scroll_pixel_position.x.into(), Pixels::ZERO);
|
||||
let mut origin = start_point
|
||||
+ line_origin
|
||||
+ point(Self::EDIT_PREDICTION_POPOVER_PADDING_X, Pixels::ZERO);
|
||||
@@ -9023,7 +9026,8 @@ impl Editor {
|
||||
visible_row_range: Range<DisplayRow>,
|
||||
line_layouts: &[LineWithInvisibles],
|
||||
line_height: Pixels,
|
||||
scroll_pixel_position: gpui::Point<Pixels>,
|
||||
scroll_position: gpui::Point<ScrollOffset>,
|
||||
scroll_pixel_position: gpui::Point<ScrollPixelOffset>,
|
||||
newest_selection_head: Option<DisplayPoint>,
|
||||
editor_width: Pixels,
|
||||
style: &EditorStyle,
|
||||
@@ -9136,9 +9140,11 @@ impl Editor {
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let x_after_longest =
|
||||
text_bounds.origin.x + longest_line_width + Self::EDIT_PREDICTION_POPOVER_PADDING_X
|
||||
- scroll_pixel_position.x;
|
||||
let x_after_longest = Pixels::from(
|
||||
ScrollPixelOffset::from(
|
||||
text_bounds.origin.x + longest_line_width + Self::EDIT_PREDICTION_POPOVER_PADDING_X,
|
||||
) - scroll_pixel_position.x,
|
||||
);
|
||||
|
||||
let element_bounds = element.layout_as_root(AvailableSpace::min_size(), window, cx);
|
||||
|
||||
@@ -9150,8 +9156,11 @@ impl Editor {
|
||||
let mut origin = if can_position_to_the_right {
|
||||
point(
|
||||
x_after_longest,
|
||||
text_bounds.origin.y + edit_start.row().as_f32() * line_height
|
||||
- scroll_pixel_position.y,
|
||||
text_bounds.origin.y
|
||||
+ Pixels::from(
|
||||
edit_start.row().as_f64() * ScrollPixelOffset::from(line_height)
|
||||
- scroll_pixel_position.y,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
let cursor_row = newest_selection_head.map(|head| head.row());
|
||||
@@ -9181,8 +9190,10 @@ impl Editor {
|
||||
|
||||
content_origin
|
||||
+ point(
|
||||
-scroll_pixel_position.x,
|
||||
row_target.as_f32() * line_height - scroll_pixel_position.y,
|
||||
Pixels::from(-scroll_pixel_position.x),
|
||||
Pixels::from(
|
||||
(row_target.as_f64() - scroll_position.y) * f64::from(line_height),
|
||||
),
|
||||
)
|
||||
};
|
||||
|
||||
@@ -14250,7 +14261,7 @@ impl Editor {
|
||||
let mut row = range.start.row();
|
||||
let positions =
|
||||
if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
|
||||
px(start)..px(end)
|
||||
Pixels::from(start)..Pixels::from(end)
|
||||
} else {
|
||||
let start_x =
|
||||
display_map.x_for_display_point(range.start, &text_layout_details);
|
||||
@@ -15884,7 +15895,7 @@ impl Editor {
|
||||
|
||||
if should_scroll_up {
|
||||
let new_scroll_position =
|
||||
current_scroll_position + gpui::Point::new(0.0, lines_to_expand as f32);
|
||||
current_scroll_position + gpui::Point::new(0.0, lines_to_expand as ScrollOffset);
|
||||
self.set_scroll_position(new_scroll_position, window, cx);
|
||||
}
|
||||
}
|
||||
@@ -21737,11 +21748,11 @@ impl Editor {
|
||||
.scroll_position(editor_snapshot)
|
||||
.y;
|
||||
|
||||
if source.row().as_f32() < scroll_top.floor() {
|
||||
if source.row().as_f64() < scroll_top.floor() {
|
||||
return None;
|
||||
}
|
||||
let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
|
||||
let source_y = line_height * (source.row().as_f32() - scroll_top);
|
||||
let source_y = line_height * (source.row().as_f64() - scroll_top) as f32;
|
||||
Some(gpui::Point::new(source_x, source_y))
|
||||
}
|
||||
|
||||
@@ -23323,7 +23334,7 @@ impl EditorSnapshot {
|
||||
.map(|display_map| display_map.text())
|
||||
}
|
||||
|
||||
pub fn scroll_position(&self) -> gpui::Point<f32> {
|
||||
pub fn scroll_position(&self) -> gpui::Point<ScrollOffset> {
|
||||
self.scroll_anchor.scroll_position(&self.display_snapshot)
|
||||
}
|
||||
|
||||
@@ -23889,12 +23900,16 @@ impl EntityInputHandler for Editor {
|
||||
|
||||
let snapshot = self.snapshot(window, cx);
|
||||
let scroll_position = snapshot.scroll_position();
|
||||
let scroll_left = scroll_position.x * em_advance;
|
||||
let scroll_left = scroll_position.x * ScrollOffset::from(em_advance);
|
||||
|
||||
let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
|
||||
let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
|
||||
+ self.gutter_dimensions.full_width();
|
||||
let y = line_height * (start.row().as_f32() - scroll_position.y);
|
||||
let x = Pixels::from(
|
||||
ScrollOffset::from(
|
||||
snapshot.x_for_display_point(start, &text_layout_details)
|
||||
+ self.gutter_dimensions.full_width(),
|
||||
) - scroll_left,
|
||||
);
|
||||
let y = line_height * (start.row().as_f64() - scroll_position.y) as f32;
|
||||
|
||||
Some(Bounds {
|
||||
origin: element_bounds.origin + point(x, y),
|
||||
@@ -24161,7 +24176,7 @@ impl<T: ToOffset> RangeToAnchorExt for Range<T> {
|
||||
}
|
||||
|
||||
pub trait RowExt {
|
||||
fn as_f32(&self) -> f32;
|
||||
fn as_f64(&self) -> f64;
|
||||
|
||||
fn next_row(&self) -> Self;
|
||||
|
||||
@@ -24171,8 +24186,8 @@ pub trait RowExt {
|
||||
}
|
||||
|
||||
impl RowExt for DisplayRow {
|
||||
fn as_f32(&self) -> f32 {
|
||||
self.0 as f32
|
||||
fn as_f64(&self) -> f64 {
|
||||
self.0 as _
|
||||
}
|
||||
|
||||
fn next_row(&self) -> Self {
|
||||
@@ -24189,8 +24204,8 @@ impl RowExt for DisplayRow {
|
||||
}
|
||||
|
||||
impl RowExt for MultiBufferRow {
|
||||
fn as_f32(&self) -> f32 {
|
||||
self.0 as f32
|
||||
fn as_f64(&self) -> f64 {
|
||||
self.0 as _
|
||||
}
|
||||
|
||||
fn next_row(&self) -> Self {
|
||||
|
||||
Reference in New Issue
Block a user