feat: phase 4 — Hextile decoder and recording example
All checks were successful
CI / fmt (push) Successful in 28s
CI / check (push) Successful in 1m12s
CI / clippy (push) Successful in 1m12s

codec/hextile.rs:
- Full Hextile (encoding 5) decoder per ByteColorRFBRenderer.int()
- Handles: Raw tiles, BackgroundSpecified, ForegroundSpecified,
  AnySubrects, SubrectsColoured flags
- Background/foreground colors persist across tiles
- 4 unit tests covering all subencoding paths

framebuffer.rs:
- Added fill_rect() for Hextile background/subrect fills

session.rs:
- Wired Hextile encoding 5 into the rect dispatch

examples/record.rs:
- 30-second (configurable) recording session
- Saves 1 PNG per second to out/ directory
- Requests encodings [5, 1, 0] (Hextile, CopyRect, Raw)
- Tested against real OmniView: 10 frames in 10s, no errors

27 tests passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-06 14:35:20 +03:00
parent 1164ffdd98
commit 21ed797302
6 changed files with 279 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
use std::io::{BufReader, BufWriter};
use std::net::TcpStream;
use crate::codec::hextile;
use crate::framebuffer::Framebuffer;
use crate::handshake::{self, Config, ServerInit};
use crate::msg::{self, ServerMsg};
@@ -196,6 +197,17 @@ impl ActiveSession {
self.framebuffer
.copy_rect(src_x, src_y, hdr.x, hdr.y, hdr.w, hdr.h);
}
5 => {
// Hextile
hextile::decode_hextile(
&mut self.reader,
&mut self.framebuffer,
hdr.x,
hdr.y,
hdr.w,
hdr.h,
)?;
}
other => {
return Err(SessionError::UnsupportedEncoding(other));
}