Use `Project`'s EntityId as the "window id" for Alacritty PTYs (#35876)

Antonio Scandurra and Ben Brandt created

It's unfortunate to need to have access to a GPUI window in order to
create a terminal, because it forces to take a `Window` parameter in
entities that otherwise would have been pure models.

This pull request changes it so that we pass the `Project`'s entity id,
which is equally stable as the window id.

Release Notes:

- N/A

Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>

Change summary

crates/assistant_tools/src/terminal_tool.rs |  1 -
crates/debugger_ui/src/session/running.rs   |  7 ++-----
crates/project/src/terminals.rs             |  8 +++-----
crates/terminal/src/terminal.rs             | 14 +++++---------
crates/terminal_view/src/persistence.rs     |  5 ++---
crates/terminal_view/src/terminal_panel.rs  | 16 ++++------------
crates/terminal_view/src/terminal_view.rs   |  5 +----
7 files changed, 17 insertions(+), 39 deletions(-)

Detailed changes

crates/debugger_ui/src/session/running.rs 🔗

@@ -1014,10 +1014,9 @@ impl RunningState {
                     ..task.resolved.clone()
                 };
                 let terminal = project
-                    .update_in(cx, |project, window, cx| {
+                    .update(cx, |project, cx| {
                         project.create_terminal(
                             TerminalKind::Task(task_with_shell.clone()),
-                            window.window_handle(),
                             cx,
                         )
                     })?
@@ -1189,9 +1188,7 @@ impl RunningState {
         let workspace = self.workspace.clone();
         let weak_project = project.downgrade();
 
-        let terminal_task = project.update(cx, |project, cx| {
-            project.create_terminal(kind, window.window_handle(), cx)
-        });
+        let terminal_task = project.update(cx, |project, cx| project.create_terminal(kind, cx));
         let terminal_task = cx.spawn_in(window, async move |_, cx| {
             let terminal = terminal_task.await?;
 

crates/project/src/terminals.rs 🔗

@@ -1,7 +1,7 @@
 use crate::{Project, ProjectPath};
 use anyhow::{Context as _, Result};
 use collections::HashMap;
-use gpui::{AnyWindowHandle, App, AppContext as _, Context, Entity, Task, WeakEntity};
+use gpui::{App, AppContext as _, Context, Entity, Task, WeakEntity};
 use itertools::Itertools;
 use language::LanguageName;
 use remote::ssh_session::SshArgs;
@@ -98,7 +98,6 @@ impl Project {
     pub fn create_terminal(
         &mut self,
         kind: TerminalKind,
-        window: AnyWindowHandle,
         cx: &mut Context<Self>,
     ) -> Task<Result<Entity<Terminal>>> {
         let path: Option<Arc<Path>> = match &kind {
@@ -134,7 +133,7 @@ impl Project {
                 None
             };
             project.update(cx, |project, cx| {
-                project.create_terminal_with_venv(kind, python_venv_directory, window, cx)
+                project.create_terminal_with_venv(kind, python_venv_directory, cx)
             })?
         })
     }
@@ -209,7 +208,6 @@ impl Project {
         &mut self,
         kind: TerminalKind,
         python_venv_directory: Option<PathBuf>,
-        window: AnyWindowHandle,
         cx: &mut Context<Self>,
     ) -> Result<Entity<Terminal>> {
         let this = &mut *self;
@@ -396,7 +394,7 @@ impl Project {
             settings.alternate_scroll,
             settings.max_scroll_history_lines,
             is_ssh_terminal,
-            window,
+            cx.entity_id().as_u64(),
             completion_tx,
             cx,
         )

crates/terminal/src/terminal.rs 🔗

@@ -63,9 +63,9 @@ use std::{
 use thiserror::Error;
 
 use gpui::{
-    AnyWindowHandle, App, AppContext as _, Bounds, ClipboardItem, Context, EventEmitter, Hsla,
-    Keystroke, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point,
-    Rgba, ScrollWheelEvent, SharedString, Size, Task, TouchPhase, Window, actions, black, px,
+    App, AppContext as _, Bounds, ClipboardItem, Context, EventEmitter, Hsla, Keystroke, Modifiers,
+    MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point, Rgba,
+    ScrollWheelEvent, SharedString, Size, Task, TouchPhase, Window, actions, black, px,
 };
 
 use crate::mappings::{colors::to_alac_rgb, keys::to_esc_str};
@@ -351,7 +351,7 @@ impl TerminalBuilder {
         alternate_scroll: AlternateScroll,
         max_scroll_history_lines: Option<usize>,
         is_ssh_terminal: bool,
-        window: AnyWindowHandle,
+        window_id: u64,
         completion_tx: Sender<Option<ExitStatus>>,
         cx: &App,
     ) -> Result<TerminalBuilder> {
@@ -463,11 +463,7 @@ impl TerminalBuilder {
         let term = Arc::new(FairMutex::new(term));
 
         //Setup the pty...
-        let pty = match tty::new(
-            &pty_options,
-            TerminalBounds::default().into(),
-            window.window_id().as_u64(),
-        ) {
+        let pty = match tty::new(&pty_options, TerminalBounds::default().into(), window_id) {
             Ok(pty) => pty,
             Err(error) => {
                 bail!(TerminalError {

crates/terminal_view/src/persistence.rs 🔗

@@ -245,9 +245,8 @@ async fn deserialize_pane_group(
                         let kind = TerminalKind::Shell(
                             working_directory.as_deref().map(Path::to_path_buf),
                         );
-                        let window = window.window_handle();
-                        let terminal = project
-                            .update(cx, |project, cx| project.create_terminal(kind, window, cx));
+                        let terminal =
+                            project.update(cx, |project, cx| project.create_terminal(kind, cx));
                         Some(Some(terminal))
                     } else {
                         Some(None)

crates/terminal_view/src/terminal_panel.rs 🔗

@@ -432,10 +432,9 @@ impl TerminalPanel {
             })
             .unwrap_or((None, None));
         let kind = TerminalKind::Shell(working_directory);
-        let window_handle = window.window_handle();
         let terminal = project
             .update(cx, |project, cx| {
-                project.create_terminal_with_venv(kind, python_venv_directory, window_handle, cx)
+                project.create_terminal_with_venv(kind, python_venv_directory, cx)
             })
             .ok()?;
 
@@ -666,13 +665,10 @@ impl TerminalPanel {
                 "terminal not yet supported for remote projects"
             )));
         }
-        let window_handle = window.window_handle();
         let project = workspace.project().downgrade();
         cx.spawn_in(window, async move |workspace, cx| {
             let terminal = project
-                .update(cx, |project, cx| {
-                    project.create_terminal(kind, window_handle, cx)
-                })?
+                .update(cx, |project, cx| project.create_terminal(kind, cx))?
                 .await?;
 
             workspace.update_in(cx, |workspace, window, cx| {
@@ -709,11 +705,8 @@ impl TerminalPanel {
                 terminal_panel.active_pane.clone()
             })?;
             let project = workspace.read_with(cx, |workspace, _| workspace.project().clone())?;
-            let window_handle = cx.window_handle();
             let terminal = project
-                .update(cx, |project, cx| {
-                    project.create_terminal(kind, window_handle, cx)
-                })?
+                .update(cx, |project, cx| project.create_terminal(kind, cx))?
                 .await?;
             let result = workspace.update_in(cx, |workspace, window, cx| {
                 let terminal_view = Box::new(cx.new(|cx| {
@@ -814,7 +807,6 @@ impl TerminalPanel {
     ) -> Task<Result<WeakEntity<Terminal>>> {
         let reveal = spawn_task.reveal;
         let reveal_target = spawn_task.reveal_target;
-        let window_handle = window.window_handle();
         let task_workspace = self.workspace.clone();
         cx.spawn_in(window, async move |terminal_panel, cx| {
             let project = terminal_panel.update(cx, |this, cx| {
@@ -823,7 +815,7 @@ impl TerminalPanel {
             })??;
             let new_terminal = project
                 .update(cx, |project, cx| {
-                    project.create_terminal(TerminalKind::Task(spawn_task), window_handle, cx)
+                    project.create_terminal(TerminalKind::Task(spawn_task), cx)
                 })?
                 .await?;
             terminal_to_replace.update_in(cx, |terminal_to_replace, window, cx| {

crates/terminal_view/src/terminal_view.rs 🔗

@@ -1654,7 +1654,6 @@ impl Item for TerminalView {
         window: &mut Window,
         cx: &mut Context<Self>,
     ) -> Option<Entity<Self>> {
-        let window_handle = window.window_handle();
         let terminal = self
             .project
             .update(cx, |project, cx| {
@@ -1666,7 +1665,6 @@ impl Item for TerminalView {
                 project.create_terminal_with_venv(
                     TerminalKind::Shell(working_directory),
                     python_venv_directory,
-                    window_handle,
                     cx,
                 )
             })
@@ -1802,7 +1800,6 @@ impl SerializableItem for TerminalView {
         window: &mut Window,
         cx: &mut App,
     ) -> Task<anyhow::Result<Entity<Self>>> {
-        let window_handle = window.window_handle();
         window.spawn(cx, async move |cx| {
             let cwd = cx
                 .update(|_window, cx| {
@@ -1826,7 +1823,7 @@ impl SerializableItem for TerminalView {
 
             let terminal = project
                 .update(cx, |project, cx| {
-                    project.create_terminal(TerminalKind::Shell(cwd), window_handle, cx)
+                    project.create_terminal(TerminalKind::Shell(cwd), cx)
                 })?
                 .await?;
             cx.update(|window, cx| {