aboutsummaryrefslogtreecommitdiff
path: root/src/pty/actor.rs
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-08-03 02:05:27 +0300
committerGitHub <noreply@github.com>2026-08-03 02:05:27 +0300
commit10eb0bc744165ae91dfce9fd731fe170410b34ec (patch)
tree8622d429d9453c2e8d06630322804a702973d94a /src/pty/actor.rs
parentcbc31d34a1fb3da64415737de57ad10fe6af5ba5 (diff)
fix: propagate host color scheme to pane apps (#2214)
refs #714
Diffstat (limited to 'src/pty/actor.rs')
-rw-r--r--src/pty/actor.rs73
1 files changed, 47 insertions, 26 deletions
diff --git a/src/pty/actor.rs b/src/pty/actor.rs
index 8c3a6b52..6fde5051 100644
--- a/src/pty/actor.rs
+++ b/src/pty/actor.rs
@@ -52,6 +52,8 @@ mod windows {
pub(crate) struct PtyIoActorHandle {
data_tx: mpsc::Sender<Bytes>,
control_tx: std_mpsc::Sender<PtyIoControlCommand>,
+ write_tx: std_mpsc::Sender<Bytes>,
+ response_order: Arc<Mutex<()>>,
accepting: Arc<Mutex<bool>>,
}
@@ -84,6 +86,16 @@ mod windows {
self.data_tx.try_send(bytes)
}
+ pub(crate) fn write_terminal_response(&self, response: impl FnOnce() -> Option<Bytes>) {
+ let _order = self
+ .response_order
+ .lock()
+ .unwrap_or_else(|poisoned| poisoned.into_inner());
+ if let Some(bytes) = response().filter(|bytes| !bytes.is_empty()) {
+ let _ = self.write_tx.send(bytes);
+ }
+ }
+
pub(crate) fn resize(
&self,
rows: u16,
@@ -128,39 +140,55 @@ mod windows {
let mut reader = master
.try_clone_reader()
.map_err(|err| std::io::Error::other(err.to_string()))?;
- let writer = master
+ let mut writer = master
.take_writer()
.map_err(|err| std::io::Error::other(err.to_string()))?;
- let writer = Arc::new(Mutex::new(writer));
let (data_tx, mut data_rx) = mpsc::channel::<Bytes>(1024);
let (control_tx, control_rx) = std_mpsc::channel::<PtyIoControlCommand>();
+ let (write_tx, write_rx) = std_mpsc::channel::<Bytes>();
+ let response_order = Arc::new(Mutex::new(()));
let accepting = Arc::new(Mutex::new(!initially_quiesced));
+ std::thread::spawn(move || {
+ for bytes in write_rx {
+ if writer.write_all(&bytes).is_err() || writer.flush().is_err() {
+ break;
+ }
+ }
+ debug!(pane_id, "windows pty writer thread exiting");
+ });
+
{
- let writer = Arc::clone(&writer);
+ let write_tx = write_tx.clone();
std::thread::spawn(move || {
while let Some(bytes) = data_rx.blocking_recv() {
- if write_all_locked(&writer, &bytes).is_err() {
+ if write_tx.send(bytes).is_err() {
break;
}
}
- debug!(pane_id, "windows pty writer thread exiting");
+ debug!(pane_id, "windows pty input thread exiting");
});
}
{
- let writer = Arc::clone(&writer);
+ let write_tx = write_tx.clone();
+ let response_order = Arc::clone(&response_order);
std::thread::spawn(move || {
let mut buf = [0u8; 8192];
loop {
match reader.read(&mut buf) {
Ok(0) => break,
Ok(n) => {
+ let _order = response_order
+ .lock()
+ .unwrap_or_else(|poisoned| poisoned.into_inner());
let result = on_read(&buf[..n]);
- for response in result.terminal_responses {
- if write_all_locked(&writer, &response).is_err() {
- break;
- }
+ if result
+ .terminal_responses
+ .into_iter()
+ .any(|response| write_tx.send(response).is_err())
+ {
+ break;
}
}
Err(err) => {
@@ -177,7 +205,7 @@ mod windows {
}
{
- let writer = Arc::clone(&writer);
+ let write_tx = write_tx.clone();
std::thread::spawn(move || {
for command in control_rx {
match command {
@@ -191,10 +219,12 @@ mod windows {
}) {
warn!(pane_id, err = %err, "windows pty resize failed");
}
- for response in request.terminal_responses {
- if write_all_locked(&writer, &response).is_err() {
- break;
- }
+ if request
+ .terminal_responses
+ .into_iter()
+ .any(|response| write_tx.send(response).is_err())
+ {
+ break;
}
}
PtyIoControlCommand::Shutdown => break,
@@ -207,22 +237,13 @@ mod windows {
Ok(PtyIoActorHandle {
data_tx,
control_tx,
+ write_tx,
+ response_order,
accepting,
})
}
}
- fn write_all_locked(
- writer: &Arc<Mutex<Box<dyn Write + Send>>>,
- bytes: &[u8],
- ) -> std::io::Result<()> {
- let mut writer = writer
- .lock()
- .unwrap_or_else(|poisoned| poisoned.into_inner());
- writer.write_all(bytes)?;
- writer.flush()
- }
-
#[allow(dead_code)]
fn _assert_duration_send(_: Duration) {}
}