Save cursor scroll position when the editor is auto-scrolled

Antonio Scandurra created

Change summary

crates/ai/src/assistant.rs             |  9 ++++++---
crates/editor/src/editor.rs            |  1 +
crates/editor/src/items.rs             |  2 +-
crates/editor/src/scroll.rs            | 23 ++++++++++++++++-------
crates/editor/src/scroll/autoscroll.rs | 10 +++++-----
5 files changed, 29 insertions(+), 16 deletions(-)

Detailed changes

crates/ai/src/assistant.rs 🔗

@@ -693,6 +693,7 @@ impl Assistant {
                     error: None,
                 },
             );
+            cx.emit(AssistantEvent::MessagesEdited);
             Some(message)
         } else {
             None
@@ -874,7 +875,6 @@ impl AssistantEditor {
                     |selections| selections.select_ranges([cursor..cursor]),
                 );
             });
-            self.scroll_position = self.cursor_scroll_position(cx);
         }
     }
 
@@ -922,8 +922,11 @@ impl AssistantEditor {
         cx: &mut ViewContext<Self>,
     ) {
         match event {
-            editor::Event::ScrollPositionChanged { .. } => {
-                if self.cursor_scroll_position(cx) != self.scroll_position {
+            editor::Event::ScrollPositionChanged { autoscroll, .. } => {
+                let cursor_scroll_position = self.cursor_scroll_position(cx);
+                if *autoscroll {
+                    self.scroll_position = cursor_scroll_position;
+                } else if self.scroll_position != cursor_scroll_position {
                     self.scroll_position = None;
                 }
             }

crates/editor/src/items.rs 🔗

@@ -294,7 +294,7 @@ impl FollowableItem for Editor {
         match event {
             Event::Edited => true,
             Event::SelectionsChanged { local } => *local,
-            Event::ScrollPositionChanged { local } => *local,
+            Event::ScrollPositionChanged { local, .. } => *local,
             _ => false,
         }
     }

crates/editor/src/scroll.rs 🔗

@@ -173,6 +173,7 @@ impl ScrollManager {
         scroll_position: Vector2F,
         map: &DisplaySnapshot,
         local: bool,
+        autoscroll: bool,
         workspace_id: Option<i64>,
         cx: &mut ViewContext<Editor>,
     ) {
@@ -203,7 +204,7 @@ impl ScrollManager {
             )
         };
 
-        self.set_anchor(new_anchor, top_row, local, workspace_id, cx);
+        self.set_anchor(new_anchor, top_row, local, autoscroll, workspace_id, cx);
     }
 
     fn set_anchor(
@@ -211,11 +212,12 @@ impl ScrollManager {
         anchor: ScrollAnchor,
         top_row: u32,
         local: bool,
+        autoscroll: bool,
         workspace_id: Option<i64>,
         cx: &mut ViewContext<Editor>,
     ) {
         self.anchor = anchor;
-        cx.emit(Event::ScrollPositionChanged { local });
+        cx.emit(Event::ScrollPositionChanged { local, autoscroll });
         self.show_scrollbar(cx);
         self.autoscroll_request.take();
         if let Some(workspace_id) = workspace_id {
@@ -296,21 +298,28 @@ impl Editor {
     }
 
     pub fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
-        self.set_scroll_position_internal(scroll_position, true, cx);
+        self.set_scroll_position_internal(scroll_position, true, false, cx);
     }
 
     pub(crate) fn set_scroll_position_internal(
         &mut self,
         scroll_position: Vector2F,
         local: bool,
+        autoscroll: bool,
         cx: &mut ViewContext<Self>,
     ) {
         let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 
         hide_hover(self, cx);
         let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
-        self.scroll_manager
-            .set_scroll_position(scroll_position, &map, local, workspace_id, cx);
+        self.scroll_manager.set_scroll_position(
+            scroll_position,
+            &map,
+            local,
+            autoscroll,
+            workspace_id,
+            cx,
+        );
     }
 
     pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F {
@@ -326,7 +335,7 @@ impl Editor {
             .to_point(&self.buffer().read(cx).snapshot(cx))
             .row;
         self.scroll_manager
-            .set_anchor(scroll_anchor, top_row, true, workspace_id, cx);
+            .set_anchor(scroll_anchor, top_row, true, false, workspace_id, cx);
     }
 
     pub(crate) fn set_scroll_anchor_remote(
@@ -341,7 +350,7 @@ impl Editor {
             .to_point(&self.buffer().read(cx).snapshot(cx))
             .row;
         self.scroll_manager
-            .set_anchor(scroll_anchor, top_row, false, workspace_id, cx);
+            .set_anchor(scroll_anchor, top_row, false, false, workspace_id, cx);
     }
 
     pub fn scroll_screen(&mut self, amount: &ScrollAmount, cx: &mut ViewContext<Self>) {

crates/editor/src/scroll/autoscroll.rs 🔗

@@ -136,23 +136,23 @@ impl Editor {
 
                 if target_top < start_row {
                     scroll_position.set_y(target_top);
-                    self.set_scroll_position_internal(scroll_position, local, cx);
+                    self.set_scroll_position_internal(scroll_position, local, true, cx);
                 } else if target_bottom >= end_row {
                     scroll_position.set_y(target_bottom - visible_lines);
-                    self.set_scroll_position_internal(scroll_position, local, cx);
+                    self.set_scroll_position_internal(scroll_position, local, true, cx);
                 }
             }
             AutoscrollStrategy::Center => {
                 scroll_position.set_y((first_cursor_top - margin).max(0.0));
-                self.set_scroll_position_internal(scroll_position, local, cx);
+                self.set_scroll_position_internal(scroll_position, local, true, cx);
             }
             AutoscrollStrategy::Top => {
                 scroll_position.set_y((first_cursor_top).max(0.0));
-                self.set_scroll_position_internal(scroll_position, local, cx);
+                self.set_scroll_position_internal(scroll_position, local, true, cx);
             }
             AutoscrollStrategy::Bottom => {
                 scroll_position.set_y((last_cursor_bottom - visible_lines).max(0.0));
-                self.set_scroll_position_internal(scroll_position, local, cx);
+                self.set_scroll_position_internal(scroll_position, local, true, cx);
             }
         }