aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-10 14:27:39 +0300
committerGitHub <noreply@github.com>2026-09-10 14:27:39 +0300
commit3813af0ffee325bf6bf6ee78ee952240524d0ee1 (patch)
treee406f4028674661197df9b7098f9081f036899a3 /src/client
parent7265a2b101c9541a4ee5c800485b074774be26a7 (diff)
fix: use host background for pane selection highlights (#3894)
refs #3798
Diffstat (limited to 'src/client')
-rw-r--r--src/client/shell/composition.rs5
-rw-r--r--src/client/shell/input.rs22
-rw-r--r--src/client/shell/state.rs2
-rw-r--r--src/client/shell/tests/copy.rs78
4 files changed, 98 insertions, 9 deletions
diff --git a/src/client/shell/composition.rs b/src/client/shell/composition.rs
index 92cf3c46..1d5e583d 100644
--- a/src/client/shell/composition.rs
+++ b/src/client/shell/composition.rs
@@ -351,7 +351,10 @@ impl ClientShellState {
hit.inner_rect,
hit.scroll,
&self.config.palette,
- crate::terminal_theme::TerminalTheme::default(),
+ crate::terminal_theme::TerminalTheme {
+ background: self.host_background,
+ ..Default::default()
+ },
);
}
if copy_surface_coherent {
diff --git a/src/client/shell/input.rs b/src/client/shell/input.rs
index dd7bf87d..41a9f64c 100644
--- a/src/client/shell/input.rs
+++ b/src/client/shell/input.rs
@@ -267,16 +267,22 @@ impl ClientShellState {
RawInputEvent::HostDefaultColor {
kind: crate::terminal_theme::DefaultColorKind::Background,
color,
- } if !self.host_appearance_explicit => {
- let appearance = color.inferred_appearance();
- self.host_appearance = Some(appearance);
- if self.config.theme_runtime.auto_switch {
- self.config.palette = crate::app::client_palette_for_appearance(
- &self.config.theme_runtime,
- appearance,
- );
+ } => {
+ if self.host_background != Some(color) {
+ self.host_background = Some(color);
outcome.repaint = true;
}
+ if !self.host_appearance_explicit {
+ let appearance = color.inferred_appearance();
+ self.host_appearance = Some(appearance);
+ if self.config.theme_runtime.auto_switch {
+ self.config.palette = crate::app::client_palette_for_appearance(
+ &self.config.theme_runtime,
+ appearance,
+ );
+ outcome.repaint = true;
+ }
+ }
}
RawInputEvent::HostDefaultColor { .. }
| RawInputEvent::HostPaletteColors { .. }
diff --git a/src/client/shell/state.rs b/src/client/shell/state.rs
index 4ac49680..add297e2 100644
--- a/src/client/shell/state.rs
+++ b/src/client/shell/state.rs
@@ -969,6 +969,7 @@ pub(crate) struct ClientShellState {
pub(super) pending_input_source_changes: Vec<bool>,
pub(super) host_appearance: Option<crate::terminal_theme::HostAppearance>,
pub(super) host_appearance_explicit: bool,
+ pub(super) host_background: Option<crate::terminal_theme::RgbColor>,
pub(super) local_config_diagnostic: Option<String>,
pub(super) config_diagnostic: Option<String>,
pub(super) endpoint_error: Option<String>,
@@ -1124,6 +1125,7 @@ impl ClientShellState {
pending_input_source_changes: Vec::new(),
host_appearance: None,
host_appearance_explicit: false,
+ host_background: None,
config_diagnostic: local_config_diagnostic.clone(),
local_config_diagnostic,
endpoint_error: None,
diff --git a/src/client/shell/tests/copy.rs b/src/client/shell/tests/copy.rs
index fa0635af..2e0ca28d 100644
--- a/src/client/shell/tests/copy.rs
+++ b/src/client/shell/tests/copy.rs
@@ -52,6 +52,84 @@ fn pasted_help_and_copy_queries_strip_control_characters() {
}
#[test]
+fn client_selection_uses_host_background_and_repaints_when_it_changes() {
+ use crate::terminal_theme::{DefaultColorKind, HostAppearance, RgbColor};
+ use ratatui::style::Color;
+
+ for explicit_appearance in [false, true] {
+ let mut config = ClientShellConfig::from_config(&Config::default());
+ config.palette = Palette::terminal();
+ config.theme_runtime.auto_switch = false;
+ let mut state = ClientShellState::new(config);
+ state.set_snapshot(Box::new(snapshot()));
+ state.set_pane_surface(surface());
+ state.compose(106, 20).expect("composed frame");
+ let pane = state.hits.panes[0].clone();
+ for (kind, column) in [
+ (MouseEventKind::Down(MouseButton::Left), pane.inner_rect.x),
+ (
+ MouseEventKind::Drag(MouseButton::Left),
+ pane.inner_rect.x + 2,
+ ),
+ ] {
+ state.handle_raw_events(vec![RawInputEvent::Mouse(crossterm::event::MouseEvent {
+ kind,
+ column,
+ row: pane.inner_rect.y,
+ modifiers: KeyModifiers::empty(),
+ })]);
+ }
+ let cell_index = usize::from(pane.inner_rect.y) * 106 + usize::from(pane.inner_rect.x);
+ let fallback = state.compose(106, 20).expect("fallback frame");
+ assert_eq!(
+ fallback.cells[cell_index].bg,
+ crate::protocol::color_to_u32(Color::DarkGray)
+ );
+ if explicit_appearance {
+ state.handle_raw_events(vec![RawInputEvent::HostColorSchemeChanged(
+ HostAppearance::Light,
+ )]);
+ }
+ for (background, selected_bg, selected_fg) in [
+ ((237, 237, 234), (171, 171, 168), (0, 0, 0)),
+ ((26, 27, 38), (90, 91, 99), (255, 255, 255)),
+ ] {
+ let (r, g, b) = background;
+ let outcome = state.handle_raw_events(vec![RawInputEvent::HostDefaultColor {
+ kind: DefaultColorKind::Background,
+ color: RgbColor { r, g, b },
+ }]);
+ assert!(outcome
+ .requests
+ .iter()
+ .any(|request| matches!(request, ClientMessage::ClientShellHostTheme { .. })));
+ let frame = state.compose(106, 20).expect("host-colored selection");
+ let cell = &frame.cells[cell_index];
+ assert_eq!(
+ cell.bg,
+ crate::protocol::color_to_u32(Color::Rgb(
+ selected_bg.0,
+ selected_bg.1,
+ selected_bg.2
+ ))
+ );
+ assert_eq!(
+ cell.fg,
+ crate::protocol::color_to_u32(Color::Rgb(
+ selected_fg.0,
+ selected_fg.1,
+ selected_fg.2
+ ))
+ );
+ assert!(
+ outcome.repaint,
+ "host background changes must repaint selection"
+ );
+ }
+ }
+}
+
+#[test]
fn client_mouse_selection_highlights_and_copies_through_endpoint_extraction() {
let mut state = ClientShellState::new(ClientShellConfig::from_config(&Config::default()));
state.set_snapshot(Box::new(snapshot()));