From 1b4a79f03cf26af86adb3fbd7d36aeb222227c4e Mon Sep 17 00:00:00 2001 From: Jeremy Rose <172423086+nornagon-openai@users.noreply.github.com> Date: Fri, 3 Oct 2025 15:43:41 -0700 Subject: [PATCH] requery default colors on focus (#4673) fixes an issue when terminals change their color scheme, e.g. dark/light mode, the composer wouldn't update its background color. --- codex-rs/tui/src/terminal_palette.rs | 61 ++++++++++++++++++++++++---- codex-rs/tui/src/tui.rs | 2 + 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/codex-rs/tui/src/terminal_palette.rs b/codex-rs/tui/src/terminal_palette.rs index 499fe3e0..c35b2cff 100644 --- a/codex-rs/tui/src/terminal_palette.rs +++ b/codex-rs/tui/src/terminal_palette.rs @@ -2,6 +2,10 @@ pub fn terminal_palette() -> Option<[(u8, u8, u8); 256]> { imp::terminal_palette() } +pub fn requery_default_colors() { + imp::requery_default_colors(); +} + #[derive(Clone, Copy)] pub struct DefaultColors { #[allow(dead_code)] @@ -9,7 +13,7 @@ pub struct DefaultColors { bg: (u8, u8, u8), } -pub fn default_colors() -> Option<&'static DefaultColors> { +pub fn default_colors() -> Option { imp::default_colors() } @@ -27,8 +31,44 @@ mod imp { use super::DefaultColors; use std::mem::MaybeUninit; use std::os::fd::RawFd; + use std::sync::Mutex; use std::sync::OnceLock; + struct Cache { + attempted: bool, + value: Option, + } + + impl Default for Cache { + fn default() -> Self { + Self { + attempted: false, + value: None, + } + } + } + + impl Cache { + fn get_or_init_with(&mut self, mut init: impl FnMut() -> Option) -> Option { + if !self.attempted { + self.value = init(); + self.attempted = true; + } + self.value + } + + fn refresh_with(&mut self, mut init: impl FnMut() -> Option) -> Option { + self.value = init(); + self.attempted = true; + self.value + } + } + + fn default_colors_cache() -> &'static Mutex> { + static CACHE: OnceLock>> = OnceLock::new(); + CACHE.get_or_init(|| Mutex::new(Cache::default())) + } + pub(super) fn terminal_palette() -> Option<[(u8, u8, u8); 256]> { static CACHE: OnceLock> = OnceLock::new(); *CACHE.get_or_init(|| match query_terminal_palette() { @@ -37,11 +77,16 @@ mod imp { }) } - pub(super) fn default_colors() -> Option<&'static DefaultColors> { - static CACHE: OnceLock> = OnceLock::new(); - CACHE - .get_or_init(|| query_default_colors().unwrap_or_default()) - .as_ref() + pub(super) fn default_colors() -> Option { + let cache = default_colors_cache(); + let mut cache = cache.lock().ok()?; + cache.get_or_init_with(|| query_default_colors().unwrap_or_default()) + } + + pub(super) fn requery_default_colors() { + if let Ok(mut cache) = default_colors_cache().lock() { + cache.refresh_with(|| query_default_colors().unwrap_or_default()); + } } #[allow(dead_code)] @@ -392,7 +437,9 @@ mod imp { None } - pub(super) fn default_colors() -> Option<&'static DefaultColors> { + pub(super) fn default_colors() -> Option { None } + + pub(super) fn requery_default_colors() {} } diff --git a/codex-rs/tui/src/tui.rs b/codex-rs/tui/src/tui.rs index 8db728f2..743a9fe2 100644 --- a/codex-rs/tui/src/tui.rs +++ b/codex-rs/tui/src/tui.rs @@ -362,6 +362,8 @@ impl Tui { } Event::FocusGained => { terminal_focused.store(true, Ordering::Relaxed); + crate::terminal_palette::requery_default_colors(); + yield TuiEvent::Draw; } Event::FocusLost => { terminal_focused.store(false, Ordering::Relaxed);