Gate display frame callbacks on shared presentation visibility

This commit is contained in:
Samuel Onoja committed 2026-10-02 07:59:41 +01:00
1 parent 6b2974d0fa
commit 2f63cae54c
5 files changed
+45 -18

No files matched your search

+27
View File
@@ -44,6 +44,17 @@ impl DisplayPresentation {
self.outputs.values().any(|record| record.displayed.contains(surface))
}
// Membership describes every output; callback ownership is a separate choice.
// A stable tie-break avoids alternating owners when refresh rates match.
pub fn callback_output(&self, surface: &Id) -> Option<Output> {
self.outputs
.iter()
.filter(|(_, record)| record.displayed.contains(surface))
.map(|(output, _)| output)
.max_by_key(|output| (output.current_mode().map_or(0, |mode| mode.refresh), output.name()))
.cloned()
}
pub fn remove_surface(&mut self, surface: &Id) {
for record in self.outputs.values_mut() {
record.displayed.remove(surface);
@@ -139,4 +150,20 @@ mod tests {
states.states.get_mut(&id).unwrap().presentation_state = RenderElementPresentationState::Skipped;
assert!(visible(&states).is_empty());
}
#[test]
fn callback_ownership_is_stable_and_moves_when_an_output_disappears() {
let mut record = DisplayPresentation::default();
let a = output("a");
let b = output("b");
let id = Id::new();
for output in [&a, &b] {
record.queued(output, &scene(&id));
record.presented(output);
}
assert_eq!(record.callback_output(&id), Some(b.clone()));
record.remove_output(&b);
assert_eq!(record.callback_output(&id), Some(a.clone()));
record.remove_surface(&id);
assert_eq!(record.callback_output(&id), None);
}
}