From bd69871d51d683e27c2e7db905704a5964fd94eb Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 26 Sep 2026 19:17:55 +0200 Subject: fix: refresh host palette on terminal redraw (#4349) * fix: refresh host palette on terminal redraw * fix: count overlapping host palette queries --------- Co-authored-by: Ogulcan Celik --- src/client/input.rs | 11 ++++++++++- src/client/mod.rs | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'src/client') diff --git a/src/client/input.rs b/src/client/input.rs index 23067576..1e308d54 100644 --- a/src/client/input.rs +++ b/src/client/input.rs @@ -10,7 +10,7 @@ //! - We avoid duplicating parsing logic in the client //! - Host terminal control replies can be buffered or discarded before they leak -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; use std::sync::Arc; #[cfg(unix)] @@ -39,6 +39,7 @@ pub fn stdin_reader_loop( event_tx: mpsc::Sender, should_quit: &Arc, host_color_query_sent: bool, + host_theme_query_pending: Arc, host_cell_size_query_sent: bool, host_mouse_capture_active: Arc, host_sgr_pixels_active: Arc, @@ -51,6 +52,7 @@ pub fn stdin_reader_loop( { let _ = ( host_color_query_sent, + host_theme_query_pending, host_cell_size_query_sent, host_mouse_capture_active, host_sgr_pixels_active, @@ -64,6 +66,7 @@ pub fn stdin_reader_loop( event_tx, should_quit, host_color_query_sent, + host_theme_query_pending, host_cell_size_query_sent, host_mouse_capture_active, host_sgr_pixels_active, @@ -79,6 +82,7 @@ fn unix_stdin_reader_loop( event_tx: mpsc::Sender, should_quit: &Arc, host_color_query_sent: bool, + host_theme_query_pending: Arc, host_cell_size_query_sent: bool, host_mouse_capture_active: Arc, host_sgr_pixels_active: Arc, @@ -178,6 +182,11 @@ fn unix_stdin_reader_loop( match reader.read(&mut scratch) { Ok(0) => break, Ok(n) => { + // A redraw can issue queries while this thread is blocked in read(). + // Arm the split-reply guard before framing the returned bytes. + for _ in 0..host_theme_query_pending.swap(0, Ordering::AcqRel) { + framer.host_color_query_sent(); + } let sgr_pixels = *pending_mode .get_or_insert_with(|| host_sgr_pixels_active.load(Ordering::Acquire)); if sgr_pixels { diff --git a/src/client/mod.rs b/src/client/mod.rs index 1a0f8dd5..2cec6d2d 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -128,7 +128,7 @@ use terminal_sessions::terminal_control_command_from_json; #[cfg(unix)] use std::collections::HashMap; use std::io::{self, Write as _}; -use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering}; use std::sync::Arc; #[cfg(unix)] use std::sync::Mutex; @@ -509,6 +509,8 @@ async fn run_client_loop( // Spawn the stdin reader thread. let will_query_host_terminal_theme = state.attach_escape.is_none() && should_query_host_terminal_theme(); + let host_theme_query_pending = Arc::new(AtomicU32::new(0)); + let stdin_host_theme_query_pending = host_theme_query_pending.clone(); // Terminals behind ConPTY report no pixel size through the ioctl, so ask the // host terminal directly instead of falling back to an assumed cell size. let will_query_host_cell_size = state.attach_escape.is_none() @@ -530,6 +532,7 @@ async fn run_client_loop( stdin_tx, &stdin_quit, will_query_host_terminal_theme, + stdin_host_theme_query_pending, will_query_host_cell_size, stdin_mouse_capture_active, stdin_sgr_pixels_active, @@ -1181,6 +1184,13 @@ async fn run_client_loop( cell_height_px, pixel_geometry_exact, ) => { + // Palette updates through OSC do not necessarily produce a color-scheme + // notification. Re-query on redraw, including SIGWINCH without a resize, + // so desktop theme switchers can refresh the existing panes in place. + if will_query_host_terminal_theme { + host_theme_query_pending.fetch_add(1, Ordering::AcqRel); + query_host_terminal_theme(); + } if !pixel_geometry_exact && host_sgr_pixels_active.load(Ordering::Acquire) { set_mouse_capture(state.mouse_capture_active, false) .map_err(ClientError::ConnectionFailed)?; -- cgit v1.2.3