aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-04 16:28:46 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-04 16:28:46 +0300
commitf5f753c7286ff4cc30cfe3a9d48c053bfe2881c7 (patch)
tree71002ec66ef3fe1d047ae8def74296402b781da1 /src/server
parent7081954d1081842dc089f5a7ef9ae3f1a5643288 (diff)
fix: avoid stale clipboard feedback
refs #443
Diffstat (limited to 'src/server')
-rw-r--r--src/server/headless.rs58
1 files changed, 54 insertions, 4 deletions
diff --git a/src/server/headless.rs b/src/server/headless.rs
index 30ee2439..596c55df 100644
--- a/src/server/headless.rs
+++ b/src/server/headless.rs
@@ -1305,11 +1305,10 @@ impl HeadlessServer {
AppEvent::ClipboardWrite { content } => {
// Clipboard writes are client-local side effects. Forward them only to
// the foreground client instead of broadcasting to every attached client.
- if let Some(client_id) = self.foreground_client_id {
- let data = base64::engine::general_purpose::STANDARD.encode(content.as_slice());
- self.send_to_client(client_id, ServerMessage::Clipboard { data });
+ let data = base64::engine::general_purpose::STANDARD.encode(content.as_slice());
+ if self.send_to_foreground_client(ServerMessage::Clipboard { data }) {
+ self.app.show_clipboard_feedback();
}
- self.app.show_clipboard_feedback();
true
}
AppEvent::StateChanged { pane_id, agent, .. } => {
@@ -5996,6 +5995,57 @@ next_tab = ""
}
#[test]
+ fn clipboard_write_without_foreground_client_does_not_show_feedback() {
+ let mut server = test_headless_server();
+ server.foreground_client_id = None;
+
+ let changed = server.handle_internal_event_with_forwarding(AppEvent::ClipboardWrite {
+ content: b"test".to_vec(),
+ });
+
+ assert!(changed);
+ assert!(
+ server.app.state.copy_feedback.is_none(),
+ "clipboard feedback should only show when a foreground client can receive the write"
+ );
+ }
+
+ #[test]
+ fn clipboard_write_failed_foreground_send_does_not_show_feedback() {
+ let mut server = test_headless_server();
+ let (foreground_tx, foreground_control_rx, _foreground_rx) = test_client_writer();
+ drop(foreground_control_rx);
+
+ server.clients.insert(
+ 1,
+ ClientConnection::new(
+ (80, 24),
+ crate::kitty_graphics::HostCellSize::default(),
+ crate::terminal_theme::TerminalTheme::default(),
+ None,
+ 1,
+ RenderEncoding::SemanticFrame,
+ Some(foreground_tx),
+ ),
+ );
+ server.foreground_client_id = Some(1);
+
+ let changed = server.handle_internal_event_with_forwarding(AppEvent::ClipboardWrite {
+ content: b"test".to_vec(),
+ });
+
+ assert!(changed);
+ assert!(
+ server.app.state.copy_feedback.is_none(),
+ "clipboard feedback should only show after the foreground client receives the write"
+ );
+ assert!(
+ !server.clients.contains_key(&1),
+ "failed targeted send should remove the broken foreground client"
+ );
+ }
+
+ #[test]
fn client_local_notifications_target_foreground_client_only() {
let mut server = test_headless_server();
let (background_tx, background_control_rx, _background_rx) = test_client_writer();