aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-14 22:36:04 +0300
committerGitHub <noreply@github.com>2026-09-14 22:36:04 +0300
commitd8b36691d10c6055293ad45324b22af8b8f570e5 (patch)
tree42f6ff4b7ba20a59884a994b38368edd02b16ae2 /src/client
parent4c3b613c8470885df44f0844b8eaecca744c84fb (diff)
fix: avoid resending terminal cells for metadata updates (#4137)
Diffstat (limited to 'src/client')
-rw-r--r--src/client/handshake.rs1
-rw-r--r--src/client/mod.rs12
-rw-r--r--src/client/transport.rs14
3 files changed, 22 insertions, 5 deletions
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<endpoint::NativeEndpointTransport, ClientError> {
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 {