diff --git a/src/app/runtime.rs b/src/app/runtime.rs index e05b9599..49420381 100644 --- a/src/app/runtime.rs +++ b/src/app/runtime.rs @@ -233,6 +233,8 @@ impl App { changes_view } crate::raw_input::RawInputEvent::OuterFocusGained => { + #[cfg(not(windows))] + self.query_host_terminal_appearance(); self.send_outer_focus_event(crate::ghostty::FocusEvent::Gained); if self.state.redraw_on_focus_gained { self.request_repaint(); diff --git a/src/app/theme_sync.rs b/src/app/theme_sync.rs index 32716ced..6bf06685 100644 --- a/src/app/theme_sync.rs +++ b/src/app/theme_sync.rs @@ -1,6 +1,15 @@ use super::App; impl App { + #[cfg(not(windows))] + pub(super) fn query_host_terminal_appearance(&self) { + use std::io::Write; + + let _ = std::io::stdout() + .write_all(crate::terminal_theme::HOST_COLOR_SCHEME_QUERY_SEQUENCE.as_bytes()); + let _ = std::io::stdout().flush(); + } + pub(super) fn query_host_terminal_theme(&self) { use std::io::Write; diff --git a/src/client/mod.rs b/src/client/mod.rs index fd92d188..b153dd93 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1442,6 +1442,9 @@ async fn run_client_loop( ) { state.request_repaint(); } + if crate::raw_input::events_require_host_terminal_appearance_query(&events) { + query_host_terminal_appearance(); + } if crate::raw_input::events_require_host_terminal_theme_query(&events) { query_host_terminal_theme(); } @@ -2281,6 +2284,17 @@ fn resize_poll_loop( // Logging // --------------------------------------------------------------------------- +#[cfg(any(not(windows), test))] +fn query_host_terminal_appearance() { + let _ = write_host_terminal_appearance_query(io::stdout()); +} + +#[cfg(any(not(windows), test))] +fn write_host_terminal_appearance_query(mut writer: impl io::Write) -> io::Result<()> { + writer.write_all(crate::terminal_theme::HOST_COLOR_SCHEME_QUERY_SEQUENCE.as_bytes())?; + writer.flush() +} + /// Initialize logging for the client process. fn query_host_terminal_theme() { let _ = write_host_terminal_theme_query(io::stdout()); @@ -2672,6 +2686,13 @@ mod tests { assert!(!text.contains("d=A")); } + #[test] + fn write_host_terminal_appearance_query_emits_mode_2031_query() { + let mut output = Vec::new(); + write_host_terminal_appearance_query(&mut output).unwrap(); + assert_eq!(output, b"\x1b[?996n"); + } + #[test] fn write_host_terminal_theme_query_emits_osc_queries() { let mut output = Vec::new(); @@ -2680,6 +2701,10 @@ mod tests { output, crate::terminal_theme::host_terminal_theme_query_sequence().as_bytes() ); + assert!(!output + .windows(crate::terminal_theme::HOST_COLOR_SCHEME_QUERY_SEQUENCE.len()) + .any(|window| window + == crate::terminal_theme::HOST_COLOR_SCHEME_QUERY_SEQUENCE.as_bytes())); } #[test] diff --git a/src/raw_input.rs b/src/raw_input.rs index 12bcba4d..40ff7b4b 100644 --- a/src/raw_input.rs +++ b/src/raw_input.rs @@ -579,6 +579,13 @@ pub(crate) fn events_require_host_surface_redraw( .any(|event| matches!(event, RawInputEvent::OuterFocusGained)) } +#[cfg(any(not(windows), test))] +pub(crate) fn events_require_host_terminal_appearance_query(events: &[RawInputEvent]) -> bool { + events + .iter() + .any(|event| matches!(event, RawInputEvent::OuterFocusGained)) +} + #[cfg(any(not(windows), test))] pub(crate) fn events_require_host_terminal_theme_query(events: &[RawInputEvent]) -> bool { events @@ -1544,6 +1551,20 @@ mod tests { assert!(!events_require_host_surface_redraw(&events, true)); } + #[test] + fn outer_focus_gained_requests_host_appearance_query() { + let gained = parse_raw_input_bytes_sync(b"\x1b[I"); + let lost = parse_raw_input_bytes_sync(b"\x1b[O"); + let scheme_report = parse_raw_input_bytes_sync(b"\x1b[?997;1n"); + + assert!(events_require_host_terminal_appearance_query(&gained)); + assert!(!events_require_host_terminal_appearance_query(&lost)); + assert!(!events_require_host_terminal_appearance_query( + &scheme_report + )); + assert!(events_require_host_terminal_theme_query(&scheme_report)); + } + #[test] fn parses_ghostty_color_scheme_reports() { for bytes in [ diff --git a/src/terminal_theme.rs b/src/terminal_theme.rs index ffe78a95..3f04cc4c 100644 --- a/src/terminal_theme.rs +++ b/src/terminal_theme.rs @@ -55,6 +55,8 @@ pub enum DefaultColorKind { } pub const HOST_COLOR_QUERY_SEQUENCE: &str = "\x1b]10;?\x1b\\\x1b]11;?\x1b\\"; +#[cfg(any(not(windows), test))] +pub const HOST_COLOR_SCHEME_QUERY_SEQUENCE: &str = "\x1b[?996n"; pub const HOST_COLOR_SCHEME_REPORT_ENABLE_SEQUENCE: &str = "\x1b[?2031h"; pub const HOST_COLOR_SCHEME_REPORT_DISABLE_SEQUENCE: &str = "\x1b[?2031l";