aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-03 19:18:53 +0300
committerGitHub <noreply@github.com>2026-09-03 19:18:53 +0300
commit27b05c1082790e33e072e94822522eaea1753903 (patch)
treeb7b5421622fef5092d52b57c0e138845386b78f5 /src/client
parent0496636dc75db14a99aa71a7cadb006dc027d5c6 (diff)
fix(client): batch host palette updates (#3580)
Diffstat (limited to 'src/client')
-rw-r--r--src/client/shell/input.rs22
-rw-r--r--src/client/shell/tests/input.rs28
2 files changed, 47 insertions, 3 deletions
diff --git a/src/client/shell/input.rs b/src/client/shell/input.rs
index d3af1480..d2ca3a82 100644
--- a/src/client/shell/input.rs
+++ b/src/client/shell/input.rs
@@ -58,6 +58,24 @@ fn host_theme_update(event: &RawInputEvent) -> Option<crate::protocol::ClientHos
}
}
+fn push_host_theme_update(
+ requests: &mut Vec<ClientMessage>,
+ update: crate::protocol::ClientHostThemeUpdate,
+) {
+ if let crate::protocol::ClientHostThemeUpdate::PaletteColors(colors) = &update {
+ if let Some(ClientMessage::ClientShellHostTheme {
+ update: crate::protocol::ClientHostThemeUpdate::PaletteColors(pending),
+ }) = requests.last_mut()
+ {
+ if pending.len() + colors.len() <= 256 {
+ pending.extend_from_slice(colors);
+ return;
+ }
+ }
+ }
+ requests.push(ClientMessage::ClientShellHostTheme { update });
+}
+
impl ClientShellState {
pub(crate) fn host_keyboard_report_all_requested(&self) -> bool {
matches!(
@@ -142,9 +160,7 @@ impl ClientShellState {
}
for event in events {
if let Some(update) = host_theme_update(&event) {
- outcome
- .requests
- .push(ClientMessage::ClientShellHostTheme { update });
+ push_host_theme_update(&mut outcome.requests, update);
}
match event {
RawInputEvent::Key(key) => self.handle_key(key, &mut outcome),
diff --git a/src/client/shell/tests/input.rs b/src/client/shell/tests/input.rs
index bc72b01a..3f831fa4 100644
--- a/src/client/shell/tests/input.rs
+++ b/src/client/shell/tests/input.rs
@@ -77,6 +77,34 @@ fn host_appearance_prefers_explicit_reports_over_background_inference() {
}
#[test]
+fn full_host_palette_response_is_sent_as_one_theme_update() {
+ use std::fmt::Write as _;
+
+ let mut state = ClientShellState::new(ClientShellConfig::from_config(&Config::default()));
+ let mut responses = String::new();
+ for index in 0..=u8::MAX {
+ let _ = write!(responses, "\x1b]4;{index};rgb:1111/2222/3333\x1b\\");
+ }
+
+ let outcome = state.handle_input_bytes(responses.as_bytes());
+
+ let [ClientMessage::ClientShellHostTheme {
+ update: crate::protocol::ClientHostThemeUpdate::PaletteColors(colors),
+ }] = outcome.requests.as_slice()
+ else {
+ panic!(
+ "expected one batched palette update, got {} requests",
+ outcome.requests.len()
+ );
+ };
+ assert_eq!(colors.len(), 256);
+ assert_eq!(
+ colors.iter().map(|(index, _)| *index).collect::<Vec<_>>(),
+ (0..=u8::MAX).collect::<Vec<_>>()
+ );
+}
+
+#[test]
fn modal_paste_shortcut_modifiers_are_platform_specific() {
let key = |code, modifiers| crate::input::TerminalKey::new(code, modifiers);