From 8fe90a8a4b993ff480390b06dfee2161f04636c3 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 19 Jul 2026 19:18:26 +0200 Subject: [PATCH] fix(client): clipboard poll cadence was never applied (and CI clippy) POLL was dead: the local clipboard was re-read once per inbound event wait (<=120 ms) instead of on its own 400 ms cadence, so the constant documenting the interval described something the code did not do. Give it a deadline of its own -- the event wait is short because it bounds teardown latency, which is no reason to hammer the Win32 clipboard eight times a second while the user is copying in another app. Build State in one expression while here, and note for next time: CI runs clippy as --workspace --all-targets -- -D warnings, so a scoped run without -D warnings (what I did) does not reproduce it. Co-Authored-By: Claude Fable 5 --- clients/windows/src/app/hosts.rs | 3 +-- crates/pf-client-core/src/clipboard.rs | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/clients/windows/src/app/hosts.rs b/clients/windows/src/app/hosts.rs index 4e05d0c6..8b1e1038 100644 --- a/clients/windows/src/app/hosts.rs +++ b/clients/windows/src/app/hosts.rs @@ -1,5 +1,5 @@ //! The hosts page: saved (trusted/paired) hosts and live mDNS discovery as tap-to-connect -//! tiles in a responsive grid, with a per-host "…" menu (connect / speed test / rename / +//! tiles in a responsive grid, with a per-host "…" menu (connect / speed test / edit / //! forget) and a manual connect entry — the same card layout as the Linux and Apple clients. use super::connect::{initiate, initiate_waking, open_console}; @@ -14,7 +14,6 @@ use windows_reactor::*; /// Overflow-menu item labels — `on_item_clicked` reports the clicked item by its text. const MENU_CONNECT: &str = "Connect"; const MENU_LIBRARY: &str = "Browse library\u{2026}"; -const MENU_CONSOLE: &str = "Open console UI"; const MENU_SPEED: &str = "Test network speed\u{2026}"; const MENU_WAKE: &str = "Wake host"; /// One entry for every per-host property (name, address, MAC, clipboard sharing) — the diff --git a/crates/pf-client-core/src/clipboard.rs b/crates/pf-client-core/src/clipboard.rs index 5bb80645..b69e89f3 100644 --- a/crates/pf-client-core/src/clipboard.rs +++ b/crates/pf-client-core/src/clipboard.rs @@ -67,10 +67,13 @@ pub fn run(client: Arc, stop: Arc) { } tracing::info!("shared clipboard enabled"); - let mut state = State::default(); - // Adopt the CURRENT sequence number without announcing: whatever is on the clipboard from - // before the session started is the user's, not a copy they just made for this stream. - state.last_seq = os::sequence_number(); + let mut state = State { + // Adopt the CURRENT sequence number without announcing: whatever is on the clipboard + // from before the session started is the user's, not a copy they made for this stream. + last_seq: os::sequence_number(), + ..Default::default() + }; + let mut next_poll = Instant::now() + POLL; while !stop.load(Ordering::SeqCst) { // Inbound first — a pending FetchRequest is the host waiting on us. `NoFrame` is the @@ -81,7 +84,14 @@ pub fn run(client: Arc, stop: Arc) { Err(punktfunk_core::error::PunktfunkError::NoFrame) => {} Err(_) => break, } - poll_local(&client, &mut state); + // The local clipboard is polled on its OWN cadence, not once per inbound wait: the + // event wait is short (it bounds teardown latency), and hammering the Win32 clipboard + // eight times a second would contend with whatever app the user is actually copying in. + let now = Instant::now(); + if now >= next_poll { + poll_local(&client, &mut state); + next_poll = now + POLL; + } } // Best-effort: tell the host to stop announcing into a session that's ending. let _ = client.clip_control(false, 0);