From d8b36691d10c6055293ad45324b22af8b8f570e5 Mon Sep 17 00:00:00 2001 From: Can Celik Date: Mon, 14 Sep 2026 22:36:04 +0300 Subject: fix: avoid resending terminal cells for metadata updates (#4137) --- src/client/handshake.rs | 1 + src/client/mod.rs | 12 ++++++++---- src/client/transport.rs | 14 +++++++++++++- 3 files changed, 22 insertions(+), 5 deletions(-) (limited to 'src/client') diff --git a/src/client/handshake.rs b/src/client/handshake.rs index 937f92ac..ef55fe22 100644 --- a/src/client/handshake.rs +++ b/src/client/handshake.rs @@ -182,6 +182,7 @@ pub(super) fn do_handshake( endpoint_keybindings, mouse_capture, surface_active, + surface_reuse: true, snapshot_codecs: vec![SNAPSHOT_CODEC_V1.into()], surface_codecs: vec![SURFACE_CODEC_V1.into()], input_codecs: vec![INPUT_CODEC_V1.into()], diff --git a/src/client/mod.rs b/src/client/mod.rs index f78150ac..13125c2d 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -535,6 +535,10 @@ async fn run_client_loop( } else { crate::protocol::MAX_FRAME_SIZE }; + let negotiation = endpoint::EndpointNegotiation::new( + handshake.endpoint_methods.unwrap_or_default(), + handshake.endpoint_capabilities.unwrap_or_default(), + ); let transport = start_endpoint_transport( stream, (), @@ -542,11 +546,8 @@ async fn run_client_loop( endpoint::ClientEndpointId::Local, 1, max_frame_size, + negotiation.supports_capability(protocol::surface_reuse::CAPABILITY), )?; - let negotiation = endpoint::EndpointNegotiation::new( - handshake.endpoint_methods.unwrap_or_default(), - handshake.endpoint_capabilities.unwrap_or_default(), - ); let mut registry = endpoint::EndpointRegistry::new(transport, 1, negotiation); if state.shell.is_some() { registry.send(&ClientMessage::ClientShellFocus { focused: true }); @@ -1195,6 +1196,8 @@ async fn run_client_loop( ) { continue; } + let surface_reuse = + negotiation.supports_capability(protocol::surface_reuse::CAPABILITY); let agent_view_projection_supported = negotiation.supports_capability( crate::protocol::endpoint::AGENT_VIEW_PROJECTION_CAPABILITY, ); @@ -1226,6 +1229,7 @@ async fn run_client_loop( MAX_GRAPHICS_FRAME_SIZE, endpoint_id, generation, + surface_reuse, ); }); } diff --git a/src/client/transport.rs b/src/client/transport.rs index 2320598b..4396690a 100644 --- a/src/client/transport.rs +++ b/src/client/transport.rs @@ -7,6 +7,7 @@ pub(super) fn start_endpoint_transport( endpoint_id: endpoint::ClientEndpointId, generation: u64, max_frame_size: usize, + surface_reuse: bool, ) -> Result { let reader = stream.try_clone().map_err(ClientError::ConnectionFailed)?; let transport = endpoint::NativeEndpointTransport::with_lifetime(stream, lifetime) @@ -23,6 +24,7 @@ pub(super) fn start_endpoint_transport( max_frame_size, endpoint_id, generation, + surface_reuse, ); }) .map_err(ClientError::ConnectionFailed)?; @@ -37,6 +39,7 @@ pub(super) fn server_reader_thread( max_frame_size: usize, endpoint_id: endpoint::ClientEndpointId, generation: u64, + surface_reuse: bool, ) { if stream.set_nonblocking(true).is_err() { let _ = event_tx.blocking_send(ClientLoopEvent::ServerDisconnected { @@ -50,12 +53,21 @@ pub(super) fn server_reader_thread( stream: &mut stream, stopped: should_quit, }; + let mut surface_decoder = surface_reuse.then(protocol::surface_reuse::Decoder::default); loop { if should_quit.load(Ordering::Acquire) { break; } - match protocol::read_message(&mut stream, max_frame_size) { + let message = protocol::read_message(&mut stream, max_frame_size).and_then(|message| { + match &mut surface_decoder { + Some(decoder) => decoder.decode(message).map_err(|error| { + protocol::FramingError::Io(io::Error::new(io::ErrorKind::InvalidData, error)) + }), + None => Ok(message), + } + }); + match message { Ok(msg) => { if event_tx .blocking_send(ClientLoopEvent::ServerMessage { -- cgit v1.2.3