feat(vdisplay): enumerate the host's physical monitors
P0 of per-monitor capture (design/per-monitor-portal-capture.md): nothing in the tree could answer "what heads does this host have?", which both a monitor pin and a console picker need first. One read per compositor, each beside the code that already speaks that dialect: KWin's kde_output_device_v2 (the topology session now also records geometry + scale), Mutter's DisplayConfig.GetCurrentState, swaymsg get_outputs, hyprctl monitors. Logical geometry throughout, because x/y is what identifies a head — two monitors can share a size but never an origin. PUNKTFUNK_CAPTURE_MONITOR parses here and is reported at startup, loudly including that it is not yet enforced: a knob that is read but inert has to say so, or "it didn't work" reads as a bug. GET /display/monitors always answers 200 with an explained empty list, so a compositor-less host renders as "nothing to pick", not as a broken console. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -231,6 +231,37 @@ fn real_main() -> Result<()> {
|
||||
);
|
||||
}
|
||||
|
||||
// Report a `PUNKTFUNK_CAPTURE_MONITOR` pin at startup — the operator sets it in a host.env and
|
||||
// then has no session to watch, so this is the only place a typo can surface. It is deliberately
|
||||
// loud about not being enforced yet: a knob that is parsed but inert must SAY so, or a silent
|
||||
// "it didn't work" reads as a bug.
|
||||
#[cfg(target_os = "linux")]
|
||||
if !management_cli {
|
||||
if let Some(want) = pf_host_config::config().capture_monitor.as_deref() {
|
||||
match pf_vdisplay::detect().and_then(pf_vdisplay::monitors::list) {
|
||||
Ok(ms) => match pf_vdisplay::monitors::resolve(&ms, want) {
|
||||
Ok(m) => tracing::info!(
|
||||
connector = %m.connector,
|
||||
description = %m.description,
|
||||
mode = %m.mode_label(),
|
||||
at = %format!("+{}+{}", m.x, m.y),
|
||||
"PUNKTFUNK_CAPTURE_MONITOR names this monitor — NOTE: per-monitor capture \
|
||||
is not implemented yet, so sessions still use the normal display path"
|
||||
),
|
||||
Err(e) => tracing::warn!(
|
||||
error = %e,
|
||||
"PUNKTFUNK_CAPTURE_MONITOR names no monitor on this host"
|
||||
),
|
||||
},
|
||||
Err(e) => tracing::warn!(
|
||||
error = %format!("{e:#}"),
|
||||
monitor = %want,
|
||||
"PUNKTFUNK_CAPTURE_MONITOR is set but the monitors could not be enumerated"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wire pf-vdisplay's display-lifecycle events into the SSE event bus (the subsystem crate emits a
|
||||
// neutral DisplayEvent; the orchestrator owns the bus type — plan §W6). Set once, ignore re-set.
|
||||
let _ = pf_vdisplay::DISPLAY_EVENT_SINK.set(Box::new(|ev| match ev {
|
||||
|
||||
Reference in New Issue
Block a user