feat(clients/windows): screen-module restructure + parity features (speed test, native mode, capture UX)
Structure: split the 1400-line app.rs into per-screen app/ modules (mod=root/ router, hosts, connect, pair, speed, settings, licenses, stream, style) with shared card/header/busy-page builders and setting_combo/toggle helpers; the re-render rule (thread-driven state lives in root use_async_state, flows down as props) is now documented at the module root. Parity features the other clients already had: - "Native display" resolves the real monitor mode at connect (MonitorFromWindow -> EnumDisplaySettingsW; was a hardcoded 1080p60) - per-host network speed test: saved-host card button + a results screen (probe burst -> goodput/loss -> ~70% recommended bitrate applied in one tap; stale runs invalidated by generation) and `--headless --speed-test`; the bitrate setting becomes a free-form NumberBox so the recommendation round-trips - forget host (ContentDialog confirm -> KnownHosts::remove_by_fp) - settings: forwarded-controller picker (pads/pinned/set_pinned now wired), gamepad type, host compositor, capture-system-shortcuts; the previously dead Settings.compositor / inhibit_shortcuts are honored (shortcuts off = Alt+Tab/Alt+Esc/Ctrl+Esc/Win act locally) - click-to-recapture after a Ctrl+Alt+Shift+Q release; the HUD hint tracks the live capture state Perf: the input hook caches lock geometry (clip rect + contain-fit scale) at engage instead of GetClientRect per WM_MOUSEMOVE; the audio jitter ring trims via drain() and reuses the render scratch buffer. Validated on the bare-metal box: --discover, synthetic-host loopback E2E (TOFU -> clock skew -> HEVC negotiate -> D3D11VA init -> session end), speed-test E2E, and the WinUI shell rendering in the console session via PsExec (SSH/session-0 cannot create windows, pre-existing 0x80070005). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -80,6 +80,55 @@ pub struct SessionHandle {
|
||||
pub stop: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
/// Blocking speed-test probe (the GUI's per-host "Test" and the `--headless --speed-test` CLI):
|
||||
/// a minimal identified connect (720p60 — the host builds a virtual output, but nothing is
|
||||
/// decoded), then `request_probe` (a 2 s burst up to the host's 3 Gbps ceiling) polled to
|
||||
/// completion. Run on a worker thread.
|
||||
pub fn run_speed_probe(
|
||||
addr: &str,
|
||||
port: u16,
|
||||
fp_hex: Option<&str>,
|
||||
identity: (String, String),
|
||||
) -> Result<punktfunk_core::client::ProbeOutcome, String> {
|
||||
// Pin the saved/advertised fingerprint when we have one; a manual host measures over TOFU.
|
||||
let pin = fp_hex.and_then(crate::trust::parse_hex32);
|
||||
let c = NativeClient::connect(
|
||||
addr,
|
||||
port,
|
||||
Mode {
|
||||
width: 1280,
|
||||
height: 720,
|
||||
refresh_hz: 60,
|
||||
},
|
||||
CompositorPref::Auto,
|
||||
GamepadPref::Auto,
|
||||
0, // bitrate_kbps: host default
|
||||
0, // video_caps: probe connect, nothing is decoded
|
||||
2, // audio_channels: stereo baseline
|
||||
crate::video::decodable_codecs(),
|
||||
0, // preferred_codec: no preference
|
||||
None, // launch: no game
|
||||
pin,
|
||||
Some(identity),
|
||||
Duration::from_secs(15),
|
||||
)
|
||||
.map_err(|e| format!("connect: {e:?}"))?;
|
||||
c.request_probe(3_000_000, 2_000)
|
||||
.map_err(|e| format!("probe: {e:?}"))?;
|
||||
let deadline = Instant::now() + Duration::from_secs(10);
|
||||
loop {
|
||||
std::thread::sleep(Duration::from_millis(250));
|
||||
if c.probe_result().done {
|
||||
// Let the last UDP shards land before tearing down.
|
||||
std::thread::sleep(Duration::from_millis(400));
|
||||
return Ok(c.probe_result());
|
||||
}
|
||||
if Instant::now() > deadline {
|
||||
return Err("probe timed out".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(params: SessionParams) -> SessionHandle {
|
||||
let (ev_tx, ev_rx) = async_channel::unbounded();
|
||||
// Tiny frame queue, newest wins: force_send displaces the oldest when the UI lags.
|
||||
|
||||
Reference in New Issue
Block a user