gardesk/garterm / 9ae74bd

Browse files

fix: wait for DA1 response before sending startup commands

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
9ae74bd57aeca36bb2436f33bd24b5c0f5d13a41
Parents
6571830
Tree
5a94128

2 changed files

StatusFile+-
M garterm/src/terminal/mod.rs 12 0
M garterm/src/ui/pane.rs 16 2
garterm/src/terminal/mod.rsmodified
@@ -78,6 +78,9 @@ pub struct Terminal {
7878
     clipboard_events: VecDeque<ClipboardEvent>,
7979
     /// Prompt ready flag (from OSC 133;A - shell integration)
8080
     prompt_ready: bool,
81
+    /// DA1 (Primary Device Attributes) has been responded to
82
+    /// Used to know when shell initialization queries are complete
83
+    da1_responded: bool,
8184
 }
8285
 
8386
 impl Terminal {
@@ -112,6 +115,7 @@ impl Terminal {
112115
             current_hyperlink_id: 0,
113116
             clipboard_events: VecDeque::new(),
114117
             prompt_ready: false,
118
+            da1_responded: false,
115119
         }
116120
     }
117121
 
@@ -179,6 +183,12 @@ impl Terminal {
179183
         std::mem::replace(&mut self.prompt_ready, false)
180184
     }
181185
 
186
+    /// Check if DA1 (Primary Device Attributes) has been responded to
187
+    /// Used to know when shell initialization is far enough along
188
+    pub fn da1_responded(&self) -> bool {
189
+        self.da1_responded
190
+    }
191
+
182192
     /// Get current working directory (from OSC 7)
183193
     pub fn cwd(&self) -> Option<&str> {
184194
         self.cwd.as_deref()
@@ -1079,6 +1089,8 @@ impl vte::Perform for Performer<'_> {
10791089
                 // 9 = national replacement charsets, 15 = technical charsets,
10801090
                 // 18 = user windows, 21 = horizontal scrolling, 22 = ANSI color
10811091
                 self.term.queue_response(b"\x1b[?64;1;2;6;9;15;18;21;22c".to_vec());
1092
+                self.term.da1_responded = true;
1093
+                debug!("DA1: responded with VT420 capabilities");
10821094
             }
10831095
 
10841096
             // Secondary Device Attributes (DA2)
garterm/src/ui/pane.rsmodified
@@ -98,7 +98,8 @@ impl Pane {
9898
         if let Some(cmd) = startup_cmd {
9999
             pane.startup_cmd_state = StartupCmdState::WaitingForPrompt {
100100
                 cmd: cmd.to_string(),
101
-                deadline: Instant::now() + Duration::from_millis(500),
101
+                // Deadline is checked only AFTER DA1 response, so this is additional wait time
102
+                deadline: Instant::now() + Duration::from_millis(1000),
102103
             };
103104
         }
104105
 
@@ -167,24 +168,37 @@ impl Pane {
167168
     /// Called when terminal receives OSC 133;A prompt marker
168169
     pub fn on_prompt_ready(&mut self) {
169170
         if let StartupCmdState::WaitingForPrompt { ref cmd, .. } = self.startup_cmd_state {
171
+            // Also require DA1 to be responded to (shell has completed basic init)
172
+            if !self.terminal.da1_responded() {
173
+                return;
174
+            }
170175
             let cmd_with_newline = format!("{}\n", cmd);
171176
             if let Err(e) = self.write_pty(cmd_with_newline.as_bytes()) {
172177
                 tracing::error!("Failed to send startup command: {}", e);
173178
             }
174179
             self.startup_cmd_state = StartupCmdState::Sent;
180
+            tracing::debug!("Sent startup command on prompt ready");
175181
         }
176182
     }
177183
 
178184
     /// Check startup deadline and send command if timed out
185
+    /// Only sends after DA1 has been responded to (shell has started initialization)
179186
     pub fn check_startup_deadline(&mut self) {
180187
         if let StartupCmdState::WaitingForPrompt { ref cmd, deadline } = self.startup_cmd_state {
188
+            // Wait for DA1 response before considering the deadline
189
+            // This ensures the shell has at least started initialization
190
+            if !self.terminal.da1_responded() {
191
+                return;
192
+            }
193
+
181194
             if Instant::now() >= deadline {
182
-                // Fallback: send anyway after timeout
195
+                // Fallback: send anyway after timeout (DA1 responded + deadline passed)
183196
                 let cmd_with_newline = format!("{}\n", cmd);
184197
                 if let Err(e) = self.write_pty(cmd_with_newline.as_bytes()) {
185198
                     tracing::error!("Failed to send startup command (deadline): {}", e);
186199
                 }
187200
                 self.startup_cmd_state = StartupCmdState::Sent;
201
+                tracing::debug!("Sent startup command after DA1 + deadline");
188202
             }
189203
         }
190204
     }