aboutsummaryrefslogtreecommitdiff
path: root/src/protocol/surface_reuse.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/protocol/surface_reuse.rs')
-rw-r--r--src/protocol/surface_reuse.rs43
1 files changed, 37 insertions, 6 deletions
diff --git a/src/protocol/surface_reuse.rs b/src/protocol/surface_reuse.rs
index aa2187d4..ec430492 100644
--- a/src/protocol/surface_reuse.rs
+++ b/src/protocol/surface_reuse.rs
@@ -53,6 +53,16 @@ struct CellBaseline {
popup: Option<PopupBaseline>,
}
+impl CellBaseline {
+ /// Whether a patch applies to exactly this baseline as its next revision.
+ fn matches_patch(&self, patch: &super::PaneSurfacePatch) -> bool {
+ patch.boot_id == self.boot_id
+ && patch.projection_revision == self.projection_revision
+ && patch.base_surface_revision == self.surface_revision
+ && patch.surface_revision == self.surface_revision.saturating_add(1)
+ }
+}
+
struct PopupBaseline {
terminal_id: String,
width: u16,
@@ -75,13 +85,15 @@ fn popup_baseline(surface: &PaneSurfaceFrame) -> Option<PopupBaseline> {
pub(crate) struct Decoder {
baseline: Option<CellBaseline>,
surface_delta: bool,
+ surface_scroll: bool,
}
impl Decoder {
- pub(crate) fn new(surface_delta: bool) -> Self {
+ pub(crate) fn new(surface_delta: bool, surface_scroll: bool) -> Self {
Self {
baseline: None,
surface_delta,
+ surface_scroll,
}
}
@@ -95,6 +107,16 @@ impl Decoder {
}
return self.decode_delta(&data).map(ServerMessage::PaneSurface);
}
+ ServerMessage::EndpointControl { kind, data }
+ if kind == super::surface_scroll::MESSAGE_KIND =>
+ {
+ if !self.surface_scroll {
+ return Err("surface scroll was not negotiated".into());
+ }
+ return self
+ .decode_scroll(&data)
+ .map(ServerMessage::PaneSurfacePatch);
+ }
ServerMessage::EndpointControl { kind, data } if kind == MESSAGE_KIND => {
let reuse: SurfaceReuse<PaneSurfaceFrame> = serde_json::from_str(&data)
.map_err(|error| format!("invalid surface reuse: {error}"))?;
@@ -136,11 +158,7 @@ impl Decoder {
}
ServerMessage::PaneSurfacePatch(patch) => {
if let Some(base) = &mut self.baseline {
- if patch.boot_id != base.boot_id
- || patch.projection_revision != base.projection_revision
- || patch.base_surface_revision != base.surface_revision
- || patch.surface_revision != base.surface_revision.saturating_add(1)
- {
+ if !base.matches_patch(patch) {
self.baseline = None;
} else {
for row in &patch.rows {
@@ -164,6 +182,19 @@ impl Decoder {
Ok(message)
}
+ fn decode_scroll(&mut self, data: &str) -> Result<super::PaneSurfacePatch, String> {
+ let Some(base) = &mut self.baseline else {
+ return Err("surface scroll without a baseline".into());
+ };
+ let scroll = super::surface_scroll::decode(data)?;
+ if !base.matches_patch(&scroll.patch) {
+ return Err("surface scroll does not match its baseline".into());
+ }
+ let patch = super::surface_scroll::apply(&mut base.cells, base.width, base.height, scroll)?;
+ base.surface_revision = patch.surface_revision;
+ Ok(patch)
+ }
+
fn decode_delta(&mut self, data: &str) -> Result<PaneSurfaceFrame, String> {
use super::surface_delta::{self, GridUpdate};
let Some(base) = &mut self.baseline else {