Hide cursor both locally and remotely when following

Antonio Scandurra created

Change summary

crates/editor/src/editor.rs       |  8 ++++++--
crates/editor/src/items.rs        | 18 ++++++++++++++++++
crates/workspace/src/workspace.rs |  7 +++++++
3 files changed, 31 insertions(+), 2 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -464,6 +464,7 @@ pub struct Editor {
     pending_rename: Option<RenameState>,
     searchable: bool,
     cursor_shape: CursorShape,
+    following: bool,
 }
 
 pub struct EditorSnapshot {
@@ -937,6 +938,7 @@ impl Editor {
             searchable: true,
             override_text_style: None,
             cursor_shape: Default::default(),
+            following: false,
         };
         this.end_selection(cx);
         this
@@ -5036,7 +5038,7 @@ impl Editor {
 
         self.selections = selections;
         self.pending_selection = pending_selection;
-        if self.focused {
+        if self.focused && !self.following {
             self.buffer.update(cx, |buffer, cx| {
                 buffer.set_active_selections(&self.selections, cx)
             });
@@ -5671,7 +5673,9 @@ impl View for Editor {
             self.blink_cursors(self.blink_epoch, cx);
             self.buffer.update(cx, |buffer, cx| {
                 buffer.finalize_last_transaction(cx);
-                buffer.set_active_selections(&self.selections, cx)
+                if !self.following {
+                    buffer.set_active_selections(&self.selections, cx);
+                }
             });
         }
     }

crates/editor/src/items.rs 🔗

@@ -50,6 +50,24 @@ impl FollowableItem for Editor {
         }))
     }
 
+    fn set_following(&mut self, following: bool, cx: &mut ViewContext<Self>) {
+        self.following = following;
+        if self.following {
+            self.show_local_selections = false;
+            self.buffer.update(cx, |buffer, cx| {
+                buffer.remove_active_selections(cx);
+            });
+        } else {
+            self.show_local_selections = true;
+            if self.focused {
+                self.buffer.update(cx, |buffer, cx| {
+                    buffer.set_active_selections(&self.selections, cx);
+                });
+            }
+        }
+        cx.notify();
+    }
+
     fn to_state_message(&self, cx: &AppContext) -> Option<proto::view::Variant> {
         let buffer_id = self.buffer.read(cx).as_singleton()?.read(cx).remote_id();
         Some(proto::view::Variant::Editor(proto::view::Editor {

crates/workspace/src/workspace.rs 🔗

@@ -250,6 +250,7 @@ pub trait FollowableItem: Item {
         state: &mut Option<proto::view::Variant>,
         cx: &mut MutableAppContext,
     ) -> Option<Task<Result<ViewHandle<Self>>>>;
+    fn set_following(&mut self, following: bool, cx: &mut ViewContext<Self>);
     fn to_state_message(&self, cx: &AppContext) -> Option<proto::view::Variant>;
     fn to_update_message(
         &self,
@@ -264,6 +265,7 @@ pub trait FollowableItem: Item {
 }
 
 pub trait FollowableItemHandle: ItemHandle {
+    fn set_following(&self, following: bool, cx: &mut MutableAppContext);
     fn to_state_message(&self, cx: &AppContext) -> Option<proto::view::Variant>;
     fn to_update_message(
         &self,
@@ -278,6 +280,10 @@ pub trait FollowableItemHandle: ItemHandle {
 }
 
 impl<T: FollowableItem> FollowableItemHandle for ViewHandle<T> {
+    fn set_following(&self, following: bool, cx: &mut MutableAppContext) {
+        self.update(cx, |this, cx| this.set_following(following, cx))
+    }
+
     fn to_state_message(&self, cx: &AppContext) -> Option<proto::view::Variant> {
         self.read(cx).to_state_message(cx)
     }
@@ -1267,6 +1273,7 @@ impl Workspace {
             let state = this.follower_states_by_leader.entry(leader_id).or_default();
             state.panes.insert(pane);
             for (id, item) in leader_view_ids.into_iter().zip(items) {
+                item.set_following(true, cx);
                 match state.items_by_leader_view_id.entry(id) {
                     hash_map::Entry::Occupied(e) => {
                         let e = e.into_mut();