editor: Fix Follow Agent unexpectedly stopping during edits (#35845)

smit created

Closes #34881

For horizontal scroll, we weren't keeping track of the `local` bool, so
whenever the agent tries to autoscroll horizontally, it would be seen as
a user scroll event resulting in unfollow.

Release Notes:

- Fixed an issue where the Follow Agent could unexpectedly stop
following during edits.

Change summary

crates/editor/src/element.rs           | 19 ++++++++++++++++---
crates/editor/src/scroll.rs            |  4 ++--
crates/editor/src/scroll/autoscroll.rs | 14 +++++++-------
3 files changed, 25 insertions(+), 12 deletions(-)

Detailed changes

crates/editor/src/element.rs 🔗

@@ -8030,12 +8030,20 @@ impl Element for EditorElement {
                         autoscroll_containing_element,
                         needs_horizontal_autoscroll,
                     ) = self.editor.update(cx, |editor, cx| {
-                        let autoscroll_request = editor.autoscroll_request();
+                        let autoscroll_request = editor.scroll_manager.take_autoscroll_request();
+
                         let autoscroll_containing_element =
                             autoscroll_request.is_some() || editor.has_pending_selection();
 
                         let (needs_horizontal_autoscroll, was_scrolled) = editor
-                            .autoscroll_vertically(bounds, line_height, max_scroll_top, window, cx);
+                            .autoscroll_vertically(
+                                bounds,
+                                line_height,
+                                max_scroll_top,
+                                autoscroll_request,
+                                window,
+                                cx,
+                            );
                         if was_scrolled.0 {
                             snapshot = editor.snapshot(window, cx);
                         }
@@ -8425,7 +8433,11 @@ impl Element for EditorElement {
                         Ok(blocks) => blocks,
                         Err(resized_blocks) => {
                             self.editor.update(cx, |editor, cx| {
-                                editor.resize_blocks(resized_blocks, autoscroll_request, cx)
+                                editor.resize_blocks(
+                                    resized_blocks,
+                                    autoscroll_request.map(|(autoscroll, _)| autoscroll),
+                                    cx,
+                                )
                             });
                             return self.prepaint(None, _inspector_id, bounds, &mut (), window, cx);
                         }
@@ -8470,6 +8482,7 @@ impl Element for EditorElement {
                                 scroll_width,
                                 em_advance,
                                 &line_layouts,
+                                autoscroll_request,
                                 window,
                                 cx,
                             )

crates/editor/src/scroll.rs 🔗

@@ -348,8 +348,8 @@ impl ScrollManager {
         self.show_scrollbars
     }
 
-    pub fn autoscroll_request(&self) -> Option<Autoscroll> {
-        self.autoscroll_request.map(|(autoscroll, _)| autoscroll)
+    pub fn take_autoscroll_request(&mut self) -> Option<(Autoscroll, bool)> {
+        self.autoscroll_request.take()
     }
 
     pub fn active_scrollbar_state(&self) -> Option<&ActiveScrollbarState> {

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

@@ -102,15 +102,12 @@ impl AutoscrollStrategy {
 pub(crate) struct NeedsHorizontalAutoscroll(pub(crate) bool);
 
 impl Editor {
-    pub fn autoscroll_request(&self) -> Option<Autoscroll> {
-        self.scroll_manager.autoscroll_request()
-    }
-
     pub(crate) fn autoscroll_vertically(
         &mut self,
         bounds: Bounds<Pixels>,
         line_height: Pixels,
         max_scroll_top: f32,
+        autoscroll_request: Option<(Autoscroll, bool)>,
         window: &mut Window,
         cx: &mut Context<Editor>,
     ) -> (NeedsHorizontalAutoscroll, WasScrolled) {
@@ -137,7 +134,7 @@ impl Editor {
             WasScrolled(false)
         };
 
-        let Some((autoscroll, local)) = self.scroll_manager.autoscroll_request.take() else {
+        let Some((autoscroll, local)) = autoscroll_request else {
             return (NeedsHorizontalAutoscroll(false), editor_was_scrolled);
         };
 
@@ -284,9 +281,12 @@ impl Editor {
         scroll_width: Pixels,
         em_advance: Pixels,
         layouts: &[LineWithInvisibles],
+        autoscroll_request: Option<(Autoscroll, bool)>,
         window: &mut Window,
         cx: &mut Context<Self>,
     ) -> Option<gpui::Point<f32>> {
+        let (_, local) = autoscroll_request?;
+
         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
         let selections = self.selections.all::<Point>(cx);
         let mut scroll_position = self.scroll_manager.scroll_position(&display_map);
@@ -335,10 +335,10 @@ impl Editor {
 
         let was_scrolled = if target_left < scroll_left {
             scroll_position.x = target_left / em_advance;
-            self.set_scroll_position_internal(scroll_position, true, true, window, cx)
+            self.set_scroll_position_internal(scroll_position, local, true, window, cx)
         } else if target_right > scroll_right {
             scroll_position.x = (target_right - viewport_width) / em_advance;
-            self.set_scroll_position_internal(scroll_position, true, true, window, cx)
+            self.set_scroll_position_internal(scroll_position, local, true, window, cx)
         } else {
             WasScrolled(false)
         };