fix(theme): refresh host appearance on focus

refs #2416
This commit is contained in:
akbash-bot
2026-08-06 12:09:45 +00:00
parent 5dd20c0a9d
commit 16c8ea388d
5 changed files with 59 additions and 0 deletions
+2
View File
@@ -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();
+9
View File
@@ -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;
+25
View File
@@ -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]
+21
View File
@@ -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 [
+2
View File
@@ -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";