diff --git a/docs/next/CHANGELOG.md b/docs/next/CHANGELOG.md index 8190fbc1f3..1ded91d034 100644 --- a/docs/next/CHANGELOG.md +++ b/docs/next/CHANGELOG.md @@ -23,6 +23,7 @@ - Experimental pane graphics now support bounded named layers, acknowledged full-RGBA primary-layer direct file frames on audited local terminals, owned BGRA fallback, exact pixel mouse input, and placement-only resize replay. ### Fixed +- Herdr no longer sends the full OSC 4 palette query burst under WSL, preventing reply fragments from leaking into the shell through ConPTY. (#2440) - Qwen Code panes now use locale-independent terminal-title states and localized confirmation fallbacks, preventing active or blocked turns from appearing idle. (#2756) - Closing a terminal running `herdr --remote` no longer produces a local client core dump while the remote session stays alive. (#2424) - Active Space and Agent rows now use dedicated theme colors that remain visible when the host terminal background matches the selected Herdr theme. (#2792) diff --git a/src/app/theme_sync.rs b/src/app/theme_sync.rs index 6bf06685df..58f95bec7b 100644 --- a/src/app/theme_sync.rs +++ b/src/app/theme_sync.rs @@ -13,7 +13,9 @@ impl App { pub(super) fn query_host_terminal_theme(&self) { use std::io::Write; - let query = crate::terminal_theme::host_terminal_theme_query_sequence(); + let query = crate::terminal_theme::host_terminal_theme_query_sequence( + crate::platform::should_query_host_terminal_palette(), + ); let _ = std::io::stdout().write_all(query.as_bytes()); let _ = std::io::stdout().flush(); } diff --git a/src/client/mod.rs b/src/client/mod.rs index b70b6c9c79..c33157fb0d 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -2571,7 +2571,9 @@ fn should_query_host_terminal_theme() -> bool { } fn write_host_terminal_theme_query(mut writer: impl io::Write) -> io::Result<()> { - let query = crate::terminal_theme::host_terminal_theme_query_sequence(); + let query = crate::terminal_theme::host_terminal_theme_query_sequence( + crate::platform::should_query_host_terminal_palette(), + ); writer.write_all(query.as_bytes())?; writer.flush() } @@ -2999,7 +3001,10 @@ mod tests { write_host_terminal_theme_query(&mut output).unwrap(); assert_eq!( output, - crate::terminal_theme::host_terminal_theme_query_sequence().as_bytes() + crate::terminal_theme::host_terminal_theme_query_sequence( + crate::platform::should_query_host_terminal_palette(), + ) + .as_bytes() ); assert!(!output .windows(crate::terminal_theme::HOST_COLOR_SCHEME_QUERY_SEQUENCE.len()) diff --git a/src/platform/fallback.rs b/src/platform/fallback.rs index f0e5c2ca96..1b02fae8e2 100644 --- a/src/platform/fallback.rs +++ b/src/platform/fallback.rs @@ -89,6 +89,10 @@ pub(crate) fn should_draw_host_cursor_by_default() -> bool { false } +pub(crate) fn should_query_host_terminal_palette() -> bool { + false +} + pub(crate) fn hostname() -> Option { None } diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 89e6c96d9d..f84d9e96e8 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -41,6 +41,10 @@ pub(crate) fn should_draw_host_cursor_by_default() -> bool { running_inside_wsl() } +pub(crate) fn should_query_host_terminal_palette() -> bool { + !running_inside_wsl() +} + fn running_inside_wsl() -> bool { proc_file_indicates_wsl("/proc/sys/kernel/osrelease") || proc_file_indicates_wsl("/proc/version") diff --git a/src/platform/macos.rs b/src/platform/macos.rs index d85da44033..9c59b39cd2 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -26,6 +26,10 @@ pub(crate) fn should_draw_host_cursor_by_default() -> bool { false } +pub(crate) fn should_query_host_terminal_palette() -> bool { + true +} + fn raw_command_argv(command: &str, flag: &str) -> Vec { vec!["/bin/sh".into(), flag.into(), command.into()] } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 83f85e6a94..4e44487766 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -362,6 +362,10 @@ pub(crate) fn should_draw_host_cursor_by_default() -> bool { true } +pub(crate) fn should_query_host_terminal_palette() -> bool { + false +} + /// The machine's node name, as shown by tmux's `#h`. pub(crate) fn hostname() -> Option { std::env::var("COMPUTERNAME") diff --git a/src/terminal_theme.rs b/src/terminal_theme.rs index 3f04cc4c24..2460731e2f 100644 --- a/src/terminal_theme.rs +++ b/src/terminal_theme.rs @@ -79,12 +79,14 @@ impl TerminalTheme { } } -pub fn host_terminal_theme_query_sequence() -> String { +pub fn host_terminal_theme_query_sequence(include_palette: bool) -> String { use std::fmt::Write as _; let mut sequence = String::from(HOST_COLOR_QUERY_SEQUENCE); - for index in 0..=u8::MAX { - let _ = write!(sequence, "\x1b]4;{index};?\x1b\\"); + if include_palette { + for index in 0..=u8::MAX { + let _ = write!(sequence, "\x1b]4;{index};?\x1b\\"); + } } sequence } @@ -218,11 +220,16 @@ mod tests { )) ); - let query = host_terminal_theme_query_sequence(); + let query = host_terminal_theme_query_sequence(true); assert!(query.starts_with(HOST_COLOR_QUERY_SEQUENCE)); assert!(query.contains("\x1b]4;0;?\x1b\\")); assert!(query.ends_with("\x1b]4;255;?\x1b\\")); assert_eq!(query.matches("\x1b]4;").count(), 256); + + assert_eq!( + host_terminal_theme_query_sequence(false), + HOST_COLOR_QUERY_SEQUENCE + ); } #[test]