refactor(state): make output probe readiness transform-only
CI / Build + Clippy + Test (pull_request) Failing after 11s
CI / Security audit (RUSTSEC) (pull_request) Failing after 31s
CI / Build + Clippy + Test (pull_request) Failing after 11s
CI / Security audit (RUSTSEC) (pull_request) Failing after 31s
Drops PartialOutputInfo.physical_size and .logical_position. After the
warning cleanup in 6332472 these fields were probe-time-only gates with
no downstream consumer (encoder reads geometry from the dmabuf frame
itself, not from wl_output description).
Readiness simplification (try_finalize_output):
- xdg-output path (Sway/Hyprland): done_count >= 2 + name + transform
- wlr-output-management path (niri): done_count >= 1 + wlr_manager_done + transform
Safe because Wayland protocol guarantees Geometry/Mode/Position events
fire before Done, so done_count >= N implies the prior events arrived.
done_count is the real signal; the per-field .is_none() checks were
redundant belt-and-suspenders.
Cascading cleanup of writers that only fed the deleted fields:
- WlOutput::Geometry handler — drop physical_size write, keep transform
- XdgOutputEvent::LogicalPosition arm — deleted
- WlrHeadEvent::Position arm — deleted (was the only reader of
wlr_head_proxy_to_name; both maps now write-only markers)
- WlrHeadInfo.position field — deleted; struct becomes empty marker
Behavior change risk: probe may finalize slightly earlier in cases where
a compositor fires Done before physical_size/logical_position events
(protocol violation, but possible). Verified with cargo test --release
(79 unit + 3 integration, 1 ignored). Hardware/Wayland-session test
deferred to user.
Net: -48 lines.
This commit is contained in:
+9
-56
@@ -85,20 +85,17 @@ pub struct PartialOutputInfo {
|
||||
/// Name from wl_output::Name (v4) — used to match wlr-output-management heads
|
||||
pub wl_name: Option<String>,
|
||||
pub transform: Option<Transform>,
|
||||
pub physical_size: Option<(i32, i32)>,
|
||||
pub logical_position: Option<(i32, i32)>,
|
||||
// Pixel dimensions from Mode event — preparatory for Phase 2 resolution logic
|
||||
pub mode_size: Option<(i32, i32)>,
|
||||
pub done_count: u32,
|
||||
}
|
||||
|
||||
|
||||
/// Stores head info from wlr-output-management for name-based matching with wl_output.
|
||||
/// Marker for wlr-output-management heads seen during probing; tracked by name
|
||||
/// in `EncConstructionStage::ProbingOutputs.wlr_heads`.
|
||||
// `pub(crate)` (not module-private): exposed via `EncConstructionStage::ProbingOutputs.wlr_heads`
|
||||
// which is reached from main.rs during the wlr-screencopy probing loop.
|
||||
pub(crate) struct WlrHeadInfo {
|
||||
position: Option<(i32, i32)>,
|
||||
}
|
||||
pub(crate) struct WlrHeadInfo {}
|
||||
|
||||
/// User data for XdgOutput dispatch to identify which WlOutput it belongs to.
|
||||
pub struct OutputId(pub u32);
|
||||
@@ -832,22 +829,6 @@ impl<S: CaptureSource> State<S> {
|
||||
}
|
||||
|
||||
fn try_finalize_output(&mut self, _idx: usize) -> bool {
|
||||
// Merge wlr head position info into outputs (needed for niri path)
|
||||
if let EncConstructionStage::ProbingOutputs {
|
||||
outputs, wlr_heads, ..
|
||||
} = &mut self.stage
|
||||
{
|
||||
for info in outputs.iter_mut() {
|
||||
if info.logical_position.is_none() {
|
||||
if let Some(ref wl_name) = info.wl_name {
|
||||
if let Some(head_info) = wlr_heads.get(wl_name) {
|
||||
info.logical_position = head_info.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (target_idx, output_count) = match &self.stage {
|
||||
EncConstructionStage::ProbingOutputs {
|
||||
outputs,
|
||||
@@ -890,24 +871,19 @@ impl<S: CaptureSource> State<S> {
|
||||
Some(i) => {
|
||||
let info = &outputs[i];
|
||||
if has_xdg {
|
||||
// xdg-output path (Sway/Hyprland) — strict checks
|
||||
// done_count >= 2 implies physical_size and logical_position
|
||||
// already arrived (Wayland: Geometry/Mode/Position fire before Done).
|
||||
if info.done_count < 2
|
||||
|| info.name.is_none()
|
||||
|| info.transform.is_none()
|
||||
|| info.physical_size.is_none()
|
||||
|| info.logical_position.is_none()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// wlr-output-management path (niri) — relaxed checks
|
||||
if info.done_count < 1 || !wlr_manager_done {
|
||||
// done_count >= 1 implies transform arrived (Geometry precedes Done).
|
||||
if info.done_count < 1 || !wlr_manager_done || info.transform.is_none() {
|
||||
return false;
|
||||
}
|
||||
if info.transform.is_none() || info.physical_size.is_none() {
|
||||
return false;
|
||||
}
|
||||
// name and logical_position can use defaults
|
||||
}
|
||||
(i, output_count)
|
||||
}
|
||||
@@ -1180,8 +1156,6 @@ impl<S: CaptureSource> Dispatch<WlOutput, OutputId> for State<S> {
|
||||
match event {
|
||||
OutputEvent::Geometry {
|
||||
transform,
|
||||
physical_width,
|
||||
physical_height,
|
||||
..
|
||||
} => {
|
||||
let t = match transform {
|
||||
@@ -1198,7 +1172,6 @@ impl<S: CaptureSource> Dispatch<WlOutput, OutputId> for State<S> {
|
||||
if let EncConstructionStage::ProbingOutputs { outputs, .. } = &mut state.stage {
|
||||
if let Some(info) = outputs.get_mut(idx) {
|
||||
info.transform = Some(t);
|
||||
info.physical_size = Some((physical_width, physical_height));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1272,13 +1245,6 @@ impl<S: CaptureSource> Dispatch<ZxdgOutputV1, OutputId> for State<S> {
|
||||
}
|
||||
}
|
||||
}
|
||||
XdgOutputEvent::LogicalPosition { x, y } => {
|
||||
if let EncConstructionStage::ProbingOutputs { outputs, .. } = &mut state.stage {
|
||||
if let Some(info) = outputs.get_mut(idx) {
|
||||
info.logical_position = Some((x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
XdgOutputEvent::LogicalSize { .. } => {}
|
||||
XdgOutputEvent::Done => {
|
||||
if let EncConstructionStage::ProbingOutputs { outputs, .. } = &mut state.stage {
|
||||
@@ -1563,24 +1529,11 @@ impl<S: CaptureSource> Dispatch<ZwlrOutputHeadV1, ()> for State<S> {
|
||||
{
|
||||
wlr_heads
|
||||
.entry(name.clone())
|
||||
.or_insert(WlrHeadInfo { position: None });
|
||||
.or_insert(WlrHeadInfo {});
|
||||
wlr_head_proxy_to_name.insert(proxy.id(), name);
|
||||
}
|
||||
}
|
||||
WlrHeadEvent::Position { x, y } => {
|
||||
if let EncConstructionStage::ProbingOutputs {
|
||||
wlr_heads,
|
||||
wlr_head_proxy_to_name,
|
||||
..
|
||||
} = &mut state.stage
|
||||
{
|
||||
if let Some(name) = wlr_head_proxy_to_name.get(&proxy.id()) {
|
||||
if let Some(head) = wlr_heads.get_mut(name) {
|
||||
head.position = Some((x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
WlrHeadEvent::Position { .. } => {}
|
||||
WlrHeadEvent::Finished => {
|
||||
tracing::debug!("zwlr_output_head_v1::Finished received");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user