Skip to main content

Mountain/IPC/WindServiceHandlers/Terminal/
LocalPTYResize.rs

1//! Wire method: `localPty:resize`.
2//! Forwards a resize event to the PTY master (SIGWINCH) via
3//! `TerminalProvider::ResizeTerminal`. Accepts either positional
4//! `[id, cols, rows]` or object `{ id, cols, rows }` from the workbench.
5//!
6//! Clamps cols/rows to ≥ 1 - portable-pty crashes the IO thread with
7//! "size out of range" on 0×0, which the workbench can emit during
8//! pane drag-storms before the requestAnimationFrame settle.
9
10use std::sync::Arc;
11
12use CommonLibrary::{Environment::Requires::Requires, Terminal::TerminalProvider::TerminalProvider};
13use serde_json::Value;
14
15use crate::{
16	IPC::WindServiceHandlers::Utilities::JsonValueHelpers::{arg_u64, arg_u64_or},
17	RunTime::ApplicationRunTime::ApplicationRunTime,
18};
19
20pub async fn Fn(RunTime:Arc<ApplicationRunTime>, Arguments:Vec<Value>) -> Result<Value, String> {
21	let (TerminalId, Columns, Rows) = {
22		let First = Arguments.first().cloned().unwrap_or(Value::Null);
23
24		if First.is_object() {
25			let Id = First.get("id").and_then(|V| V.as_u64()).unwrap_or(0);
26
27			let C = First.get("cols").and_then(|V| V.as_u64()).unwrap_or(80) as u16;
28
29			let R = First.get("rows").and_then(|V| V.as_u64()).unwrap_or(24) as u16;
30
31			(Id, C, R)
32		} else {
33			let Id = arg_u64(&Arguments, 0);
34
35			let C = arg_u64_or(&Arguments, 1, 80) as u16;
36
37			let R = arg_u64_or(&Arguments, 2, 24) as u16;
38
39			(Id, C, R)
40		}
41	};
42
43	if TerminalId == 0 {
44		return Ok(Value::Null);
45	}
46
47	let Columns = if Columns == 0 { 1 } else { Columns };
48
49	let Rows = if Rows == 0 { 1 } else { Rows };
50
51	let Provider:Arc<dyn TerminalProvider> = RunTime.Environment.Require();
52
53	match Provider.ResizeTerminal(TerminalId, Columns, Rows).await {
54		Ok(_) => Ok(Value::Null),
55
56		Err(Error) => {
57			// Resize on a disposed terminal is a common race during shutdown -
58			// the workbench layout pass fires after `exit`, the PTY closes, and
59			// the resize call lands on a dropped master. Log at warn, return
60			// Null so the workbench's resize loop continues instead of stalling.
61			crate::dev_log!(
62				"terminal",
63				"warn: localPty:resize id={} cols={} rows={} failed: {}",
64				TerminalId,
65				Columns,
66				Rows,
67				Error
68			);
69
70			Ok(Value::Null)
71		},
72	}
73}