feat(host,web): experimental DDC/CI monitor power-off for Exclusive sessions
ci / web (push) Successful in 47s
ci / docs-site (push) Successful in 1m7s
decky / build-publish (push) Successful in 19s
apple / swift (push) Successful in 1m10s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 15s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 12s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 30s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 11s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 9s
apple / screenshots (push) Successful in 5m28s
ci / bench (push) Successful in 6m40s
docker / deploy-docs (push) Successful in 20s
windows-host / package (push) Successful in 8m45s
android / android (push) Successful in 12m43s
deb / build-publish (push) Successful in 13m1s
arch / build-publish (push) Successful in 14m36s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m5s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 16m20s
ci / rust (push) Successful in 22m12s

The sole-virtual-display stutter investigation's active experiment: when the
Exclusive isolate deactivates a physical monitor, the dark-but-connected head
keeps getting serviced (monitor standby auto-input-scan / DP link churn) at a
seconds-scale cadence — the leading suspect for the periodic double-jolt. A
panel commanded off over DDC/CI (the VESA monitor-control channel in the video
cable) believes it has an owner and, on cooperating firmware, stops probing.

- New `ddc_power_off` display-policy axis (default off): orthogonal to presets
  like game_session, stored in display-settings.json, surfaced in GET/PUT
  /display/settings + the enforced list, carried through the layout transform.
- windows/ddc.rs: VCP 0xD6 power-mode control via the dxva2 Physical Monitor
  API. Deliberately DPMS-off (0x04, DDC stays responsive, signal return wakes)
  and never power-button-off (0x05, bricks-until-button on many monitors).
  Probe-before-write; every failure is skip-and-log — monitors without DDC/CI,
  OSD-disabled, or behind docks/KVMs degrade to a logged no-op.
- Manager wiring: panels commanded off immediately BEFORE the Exclusive CCD
  isolate (an HMONITOR — and with it the DDC channel — only exists while the
  display is active); teardown wakes them right after the CCD restore, where
  returning signal alone already wakes most firmware.
- Web console: an Experimental-badged on/off control on the display card,
  applied immediately like the game-session axis and preserved across preset
  switches; EN/DE strings incl. the wake-failure escape hatch (press the
  monitor's power button once, turn the option off).

Diagnostic value on top of the fix: if this kills a reporter's stutter, the
churn is monitor-firmware-initiated; if only topology=primary/extend does, the
driver services dark heads regardless — the two remaining root-cause classes.

Verified: Linux 258 tests + clippy + fmt clean; Windows (RTX box) 220/220 +
clippy clean; web tsc + production build clean; openapi.json regenerated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 12:32:36 +02:00
parent f68f6bc590
commit cca5008805
9 changed files with 322 additions and 8 deletions
+38 -1
View File
@@ -165,8 +165,9 @@ const DisplayForm: FC<{
identity: effective.identity,
layout: effective.layout,
max_displays: effective.max_displays,
// Game-session is orthogonal to the preset — carry it through the Custom switch.
// Game-session + DDC are orthogonal to the preset — carry them through the Custom switch.
game_session: draft.game_session ?? "auto",
ddc_power_off: draft.ddc_power_off ?? false,
});
} else {
apply({ ...draft, preset: id as Preset });
@@ -181,6 +182,8 @@ const DisplayForm: FC<{
preset: "custom",
...p.fields,
game_session: p.game_session ?? "auto",
// The experimental DDC axis isn't part of a preset — keep the current setting.
ddc_power_off: draft.ddc_power_off ?? false,
});
// A custom card is "current" when the in-force policy is a Custom one whose fields + game-session
@@ -464,6 +467,37 @@ const DisplayForm: FC<{
/>
</div>
{/* EXPERIMENTAL: DDC/CI panel power-off — orthogonal like game-session (survives preset
switches, applies immediately). Windows-only in effect, acted on at the Exclusive isolate. */}
<div className="border-t pt-4">
<div className="space-y-3">
<div className="flex items-center gap-2">
<Label className="block">{m.display_ddc()}</Label>
<Badge variant="outline" className="text-amber-600 dark:text-amber-500">
{m.display_experimental()}
</Badge>
</div>
<div className="flex flex-wrap gap-2">
{([false, true] as const).map((on) => (
<Button
key={String(on)}
size="sm"
variant={(draft.ddc_power_off ?? false) === on ? "default" : "outline"}
disabled={busy}
onClick={() => {
const next = { ...draft, ddc_power_off: on };
setDraft(next);
apply(next);
}}
>
{on ? m.display_ddc_enabled() : m.display_ddc_disabled()}
</Button>
))}
</div>
<p className="max-w-prose text-xs text-muted-foreground">{m.display_ddc_help()}</p>
</div>
</div>
{/* What's in force right now */}
<div className="flex flex-wrap items-center gap-2 border-t pt-3">
<span className="text-sm text-muted-foreground">{m.display_effective()}:</span>
@@ -476,6 +510,9 @@ const DisplayForm: FC<{
{(draft.game_session ?? "auto") === "dedicated" && (
<Badge variant="secondary">{m.display_game_session_dedicated()}</Badge>
)}
{(draft.ddc_power_off ?? false) && (
<Badge variant="outline">{m.display_ddc_badge()}</Badge>
)}
</div>
<p className="max-w-prose text-xs text-muted-foreground">{m.display_pending_note()}</p>