fix(client): clipboard poll cadence was never applied (and CI clippy)
ci / web (push) Successful in 1m8s
apple / swift (push) Successful in 1m17s
ci / docs-site (push) Successful in 1m9s
apple / screenshots (push) Successful in 6m17s
ci / bench (push) Successful in 6m51s
decky / build-publish (push) Successful in 21s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
deb / build-publish (push) Successful in 9m11s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 10s
android / android (push) Successful in 13m32s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 8m1s
arch / build-publish (push) Successful in 17m21s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Failing after 5m6s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7m43s
deb / build-publish-host (push) Successful in 11m42s
flatpak / build-publish (push) Failing after 8m23s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Failing after 6m14s
ci / rust (push) Successful in 25m38s
windows / build (aarch64-pc-windows-msvc) (push) Failing after 5m45s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 15m54s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m32s
docker / deploy-docs (push) Successful in 27s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 9m8s

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 <noreply@anthropic.com>
This commit is contained in:
2026-07-19 19:18:26 +02:00
parent cac23b7a05
commit 8fe90a8a4b
2 changed files with 16 additions and 7 deletions
+1 -2
View File
@@ -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
+15 -5
View File
@@ -67,10 +67,13 @@ pub fn run(client: Arc<NativeClient>, stop: Arc<AtomicBool>) {
}
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<NativeClient>, stop: Arc<AtomicBool>) {
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);