Moved back to the drag handler, selections work again

Mikayla Maki created

Change summary

crates/terminal/README.md             |  5 +++
crates/terminal/src/connected_el.rs   | 18 ++++++++++++++
crates/terminal/src/connected_view.rs |  6 ++--
crates/terminal/src/terminal.rs       | 34 +++++++++++++++++-----------
4 files changed, 44 insertions(+), 19 deletions(-)

Detailed changes

crates/terminal/README.md 🔗

@@ -10,7 +10,7 @@ The TerminalView struct abstracts over failed and successful terminals, passing
 
 #Input 
 
-There are currently 3 distinct paths for getting keystrokes to the terminal:
+There are currently many distinct paths for getting keystrokes to the terminal:
 
 1. Terminal specific characters and bindings. Things like ctrl-a mapping to ASCII control character 1, ANSI escape codes associated with the function keys, etc. These are caught with a raw key-down handler in the element and are processed immediately. This is done with the `try_keystroke()` method on Terminal
 
@@ -18,3 +18,6 @@ There are currently 3 distinct paths for getting keystrokes to the terminal:
 
 3. IME text. When the special character mappings fail, we pass the keystroke back to GPUI to hand it to the IME system. This comes back to us in the `View::replace_text_in_range()` method, and we then send that to the terminal directly, bypassing `try_keystroke()`.
 
+4. Pasted text has a seperate pathway. 
+
+Generally, there's a distinction between 'keystrokes that need to be mapped' and 'strings which need to be written'. I've attempted to unify these under the '.try_keystroke()' API and the `.input()` API (which try_keystroke uses) so we have consistent input handling across the terminal

crates/terminal/src/connected_el.rs 🔗

@@ -473,6 +473,22 @@ impl TerminalEl {
                         }
                     }
                 })
+                .on_drag(MouseButton::Left, move |_prev, event, cx| {
+                    if let Some(conn_handle) = connection.upgrade(cx.app) {
+                        conn_handle.update(cx.app, |terminal, cx| {
+                            let (point, side) = TerminalEl::mouse_to_cell_data(
+                                event.position,
+                                origin,
+                                cur_size,
+                                display_offset,
+                            );
+
+                            terminal.mouse_drag(point, side);
+
+                            cx.notify();
+                        })
+                    }
+                })
                 .on_down(
                     MouseButton::Left,
                     TerminalEl::generic_button_handler(
@@ -696,7 +712,7 @@ impl Element for TerminalEl {
 
                     (
                         cells,
-                        content.selection,
+                        dbg!(content.selection),
                         content.cursor,
                         content.display_offset,
                         cursor_text,

crates/terminal/src/connected_view.rs 🔗

@@ -251,7 +251,8 @@ impl ConnectedView {
     ///Attempt to paste the clipboard into the terminal
     fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
         if let Some(item) = cx.read_from_clipboard() {
-            self.terminal.read(cx).paste(item.text());
+            self.terminal
+                .update(cx, |terminal, _cx| terminal.paste(item.text()));
         }
     }
 
@@ -359,8 +360,7 @@ impl View for ConnectedView {
         cx: &mut ViewContext<Self>,
     ) {
         self.terminal.update(cx, |terminal, _| {
-            terminal.write_to_pty(text.into());
-            terminal.scroll(alacritty_terminal::grid::Scroll::Bottom);
+            terminal.input(text.into());
         });
     }
 

crates/terminal/src/terminal.rs 🔗

@@ -508,8 +508,14 @@ impl Terminal {
         }
     }
 
+    pub fn input(&mut self, input: String) {
+        self.scroll(Scroll::Bottom);
+        self.events.push(InternalEvent::SetSelection(None));
+        self.write_to_pty(input);
+    }
+
     ///Write the Input payload to the tty.
-    pub fn write_to_pty(&self, input: String) {
+    fn write_to_pty(&self, input: String) {
         self.pty_tx.notify(input.into_bytes());
     }
 
@@ -525,8 +531,7 @@ impl Terminal {
     pub fn try_keystroke(&mut self, keystroke: &Keystroke) -> bool {
         let esc = to_esc_str(keystroke, &self.last_mode);
         if let Some(esc) = esc {
-            self.write_to_pty(esc);
-            self.scroll(Scroll::Bottom);
+            self.input(esc);
             true
         } else {
             false
@@ -534,14 +539,13 @@ impl Terminal {
     }
 
     ///Paste text into the terminal
-    pub fn paste(&self, text: &str) {
-        if self.last_mode.contains(TermMode::BRACKETED_PASTE) {
-            self.write_to_pty("\x1b[200~".to_string());
-            self.write_to_pty(text.replace('\x1b', ""));
-            self.write_to_pty("\x1b[201~".to_string());
+    pub fn paste(&mut self, text: &str) {
+        let paste_text = if self.last_mode.contains(TermMode::BRACKETED_PASTE) {
+            format!("{}{}{}", "\x1b[200~", text.replace('\x1b', ""), "\x1b[201~")
         } else {
-            self.write_to_pty(text.replace("\r\n", "\r").replace('\n', "\r"));
-        }
+            text.replace("\r\n", "\r").replace('\n', "\r")
+        };
+        self.input(paste_text)
     }
 
     pub fn copy(&mut self) {
@@ -598,18 +602,20 @@ impl Terminal {
         }
     }
 
-    /// Handle a mouse move, this is mutually exclusive with drag.
+    /// Handle a mouse move
     pub fn mouse_move(&mut self, point: Point, side: Direction, e: &MouseMovedEvent) {
         if self.mouse_changed(point, side) {
             if let Some(bytes) = mouse_moved_report(point, e, self.last_mode) {
                 self.pty_tx.notify(bytes);
             }
-        } else if matches!(e.pressed_button, Some(gpui::MouseButton::Left)) {
-            self.events
-                .push(InternalEvent::UpdateSelection((point, side)));
         }
     }
 
+    pub fn mouse_drag(&mut self, point: Point, side: Direction) {
+        self.events
+            .push(InternalEvent::UpdateSelection((point, side)));
+    }
+
     pub fn mouse_down(&mut self, point: Point, side: Direction) {
         if self.last_mode.intersects(TermMode::MOUSE_REPORT_CLICK) {
             //TODE: MOUSE MODE