fix(host/windows): keep WGC through the secure desktop by default (DDA-secure opt-in)
apple / swift (push) Successful in 56s
ci / rust (push) Failing after 1m32s
ci / web (push) Successful in 29s
android / android (push) Successful in 3m15s
ci / docs-site (push) Successful in 41s
deb / build-publish (push) Successful in 2m5s
decky / build-publish (push) Successful in 11s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
ci / bench (push) Successful in 4m47s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m2s
docker / deploy-docs (push) Successful in 37s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 8m6s
apple / swift (push) Successful in 56s
ci / rust (push) Failing after 1m32s
ci / web (push) Successful in 29s
android / android (push) Successful in 3m15s
ci / docs-site (push) Successful in 41s
deb / build-publish (push) Successful in 2m5s
decky / build-publish (push) Successful in 11s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
ci / bench (push) Successful in 4m47s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m2s
docker / deploy-docs (push) Successful in 37s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 8m6s
Regression fix. The DDA-on-secure mux + force-composed overlay + rebuild-on-switch
made the stream worse than just staying on WGC: DDA can't reliably capture the
secure desktop's HDR independent-flip (storms ACCESS_LOST → instant black), and
rebuilding the output on every Default↔Winlogon flip thrashed (frequent freezes).
Meanwhile the WGC helper STAYS LIVE through a lock/UAC.
So make the DDA-on-secure path OPT-IN (PUNKTFUNK_SECURE_DDA=1, or the test
toggle). By default the mux keeps WGC the whole session — the DesktopWatcher and
the force-composed overlay aren't even started — so a lock/UAC no longer black-
screens or freezes the stream. The DDA-secure machinery stays in the tree for
future experimentation behind the flag.
(Reverts the rebuild-on-every-switch change 3f191ba via 555ec2a; this gates the
remaining switch.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2343,19 +2343,25 @@ fn virtual_stream_relay(
|
|||||||
})
|
})
|
||||||
.context("spawn send thread")?;
|
.context("spawn send thread")?;
|
||||||
|
|
||||||
// The authoritative Default↔Winlogon signal (requires SYSTEM to read the Winlogon desktop name).
|
|
||||||
let watcher = crate::capture::desktop_watch::DesktopWatcher::start();
|
|
||||||
// Keep a force-composed-flip overlay alive on the input desktop so the SECURE desktop (which
|
|
||||||
// otherwise presents via fullscreen independent-flip → DDA gets born-lost ACCESS_LOST / black) is
|
|
||||||
// forced into DWM composition and becomes capturable. Held for the stream's lifetime.
|
|
||||||
let _composed_flip = crate::capture::composed_flip::ForceComposedFlip::start();
|
|
||||||
// Test hook: PUNKTFUNK_SECURE_TEST_PERIOD_MS=N drives a square-wave secure/normal toggle every N ms
|
// Test hook: PUNKTFUNK_SECURE_TEST_PERIOD_MS=N drives a square-wave secure/normal toggle every N ms
|
||||||
// instead of the real watcher — exercises the mid-session helper↔DDA mux without a live UAC/lock
|
// instead of the real watcher — exercises the mid-session helper↔DDA mux without a live UAC/lock.
|
||||||
// (the real Winlogon DDA capture is already proven by the single-process secure path).
|
|
||||||
let secure_test_ms: Option<u128> = std::env::var("PUNKTFUNK_SECURE_TEST_PERIOD_MS")
|
let secure_test_ms: Option<u128> = std::env::var("PUNKTFUNK_SECURE_TEST_PERIOD_MS")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|s| s.parse().ok())
|
.and_then(|s| s.parse().ok())
|
||||||
.filter(|&n| n > 0);
|
.filter(|&n| n > 0);
|
||||||
|
// Switching to the host DDA on the secure (Winlogon) desktop is OPT-IN: DDA can't reliably capture
|
||||||
|
// the secure desktop's HDR independent-flip (it storms ACCESS_LOST → black), whereas the WGC helper
|
||||||
|
// STAYS LIVE through a lock/UAC. So by default the mux keeps WGC the whole time (no DesktopWatcher
|
||||||
|
// switch, no overlay). Enable the experimental DDA-on-secure path with PUNKTFUNK_SECURE_DDA=1.
|
||||||
|
let dda_secure = std::env::var("PUNKTFUNK_SECURE_DDA").is_ok() || secure_test_ms.is_some();
|
||||||
|
// The authoritative Default↔Winlogon signal (requires SYSTEM to read the Winlogon desktop name);
|
||||||
|
// only needed when the DDA-on-secure path is enabled.
|
||||||
|
let watcher = dda_secure.then(crate::capture::desktop_watch::DesktopWatcher::start);
|
||||||
|
// Force-composed-flip overlay (only with DDA-on-secure): keeps the secure desktop out of fullscreen
|
||||||
|
// independent-flip so DDA can duplicate it. Off by default to avoid touching the normal desktop.
|
||||||
|
let _composed_flip = dda_secure
|
||||||
|
.then(crate::capture::composed_flip::ForceComposedFlip::start)
|
||||||
|
.flatten();
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
||||||
let mut interval = std::time::Duration::from_secs_f64(1.0 / effective_hz.max(1) as f64);
|
let mut interval = std::time::Duration::from_secs_f64(1.0 / effective_hz.max(1) as f64);
|
||||||
@@ -2438,10 +2444,11 @@ fn virtual_stream_relay(
|
|||||||
// Source mux: capture the secure (Winlogon) desktop via the host's DDA, the normal desktop via
|
// Source mux: capture the secure (Winlogon) desktop via the host's DDA, the normal desktop via
|
||||||
// the helper relay. On a switch, latch await_idr + force the now-active source to emit an IDR
|
// the helper relay. On a switch, latch await_idr + force the now-active source to emit an IDR
|
||||||
// so the client resumes cleanly.
|
// so the client resumes cleanly.
|
||||||
let secure = match secure_test_ms {
|
let secure = dda_secure
|
||||||
Some(p) => (start.elapsed().as_millis() / p) % 2 == 1,
|
&& match secure_test_ms {
|
||||||
None => watcher.is_secure(),
|
Some(p) => (start.elapsed().as_millis() / p) % 2 == 1,
|
||||||
};
|
None => watcher.as_ref().is_some_and(|w| w.is_secure()),
|
||||||
|
};
|
||||||
if secure != on_secure {
|
if secure != on_secure {
|
||||||
on_secure = secure;
|
on_secure = secure;
|
||||||
await_idr = true;
|
await_idr = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user