diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index cf09a9d475dc37209259f7a72088c0bc4e09b32f..61caf6d725634ed6ec6d66ff1db22de57cd929db 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -3410,6 +3410,7 @@ impl EditorElement { line_layouts: &[LineWithInvisibles], line_height: Pixels, scroll_pixel_position: gpui::Point, + newest_selection_head: Option, editor_width: Pixels, style: &EditorStyle, window: &mut Window, @@ -3568,14 +3569,35 @@ impl EditorElement { edit_start.row().as_f32() * line_height - scroll_pixel_position.y, ) } else { - let target_above = - DisplayRow(edit_start.row().0.saturating_sub(line_count as u32)); - let row_target = if visible_row_range - .contains(&DisplayRow(target_above.0.saturating_sub(1))) - { - target_above + // Avoid overlapping both the edited rows and the user's cursor. + let target_above = DisplayRow( + edit_start + .row() + .0 + .min( + newest_selection_head + .map_or(u32::MAX, |cursor_row| cursor_row.row().0), + ) + .saturating_sub(line_count as u32), + ); + let mut row_target; + if visible_row_range.contains(&DisplayRow(target_above.0.saturating_sub(1))) { + row_target = target_above; } else { - DisplayRow(edit_end.row().0 + 1) + row_target = DisplayRow( + edit_end.row().0.max( + newest_selection_head.map_or(0, |cursor_row| cursor_row.row().0), + ) + 1, + ); + if !visible_row_range.contains(&row_target) { + // Not visible, so fallback on displaying immediately below the cursor. + if let Some(cursor) = newest_selection_head { + row_target = DisplayRow(cursor.row().0 + 1); + } else { + // Not visible and no cursor visible, so fallback on displaying at the top of the editor. + row_target = DisplayRow(0); + } + } }; text_bounds.origin @@ -7089,6 +7111,7 @@ impl Element for EditorElement { &line_layouts, line_height, scroll_pixel_position, + newest_selection_head, editor_width, &style, window,