diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index fbc67207..e7c8a08c 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -67,7 +67,7 @@ use { zwlr_layer_surface_v1::{PendingLayerSurfaceData, ZwlrLayerSurfaceV1Error}, }, wp_content_type_v1::ContentType, - wp_presentation_feedback::{VRR_REFRESH_SINCE, WpPresentationFeedback}, + wp_presentation_feedback::PresentationFeedback, zwp_linux_dmabuf_feedback_v1::ZwpLinuxDmabufFeedbackV1, }, io_uring::IoUringError, @@ -311,8 +311,8 @@ pub struct WlSurface { pub children: RefCell>>, ext: CloneCell>, frame_requests: RefCell>, - presentation_feedback: RefCell>>, - latched_presentation_feedback: RefCell>>, + presentation_feedback: RefCell>, + latched_presentation_feedback: RefCell>, seat_state: NodeSeatState, toplevel: CloneCell>>, cursors: SmallMap, 1>, @@ -469,7 +469,7 @@ struct PendingState { damage_full: bool, buffer_damage: Vec, surface_damage: Vec, - presentation_feedback: Vec>, + presentation_feedback: Vec, src_rect: Option>, dst_size: Option>, scale: Option, @@ -511,10 +511,7 @@ impl PendingState { } } } - for fb in self.presentation_feedback.drain(..) { - fb.send_discarded(); - let _ = client.remove_obj(&*fb); - } + self.presentation_feedback.clear(); // overwrite state @@ -799,11 +796,8 @@ impl WlSurface { } } - pub fn add_presentation_feedback(&self, fb: &Rc) { - self.pending - .borrow_mut() - .presentation_feedback - .push(fb.clone()); + pub fn add_presentation_feedback(&self, fb: PresentationFeedback) { + self.pending.borrow_mut().presentation_feedback.push(fb); } pub fn is_cursor(&self) -> bool { @@ -1382,10 +1376,7 @@ impl WlSurface { } let has_presentation_feedback = { let mut fbs = self.presentation_feedback.borrow_mut(); - for fb in fbs.drain(..) { - fb.send_discarded(); - let _ = self.client.remove_obj(&*fb); - } + fbs.clear(); mem::swap(fbs.deref_mut(), &mut pending.presentation_feedback); fbs.is_not_empty() }; @@ -2224,10 +2215,7 @@ impl LatchListener for WlSurface { if self.visible.get() { if self.latched_commit_version.get() < self.commit_version.get() { let latched = &mut *self.latched_presentation_feedback.borrow_mut(); - for pf in latched.drain(..) { - pf.send_discarded(); - let _ = pf.client.remove_obj(&*pf); - } + latched.clear(); latched.append(&mut self.presentation_feedback.borrow_mut()); if latched.is_not_empty() { self.presentation_listener @@ -2262,17 +2250,7 @@ impl PresentationListener for WlSurface { let bindings = output.global.bindings.borrow(); let bindings = bindings.get(&self.client.id); for pf in self.latched_presentation_feedback.borrow_mut().drain(..) { - if let Some(bindings) = bindings { - for binding in bindings.values() { - pf.send_sync_output(binding); - } - } - let mut refresh = refresh; - if vrr && pf.version < VRR_REFRESH_SINCE { - refresh = 0; - } - pf.send_presented(tv_sec, tv_nsec, refresh, seq, flags); - let _ = pf.client.remove_obj(&*pf); + pf.presented(bindings, tv_sec, tv_nsec, refresh, seq, flags, vrr); } self.presentation_listener.detach(); } diff --git a/src/ifs/wl_surface/cursor.rs b/src/ifs/wl_surface/cursor.rs index 68f41796..fabcea95 100644 --- a/src/ifs/wl_surface/cursor.rs +++ b/src/ifs/wl_surface/cursor.rs @@ -10,7 +10,7 @@ use { scale::Scale, tree::{Node, NodeLocation, NodeVisitorBase, OutputNode}, }, - std::{cell::Cell, ops::Deref, rc::Rc}, + std::{cell::Cell, rc::Rc}, }; pub struct CursorSurface { @@ -103,14 +103,8 @@ impl Cursor for CursorSurface { fr.now = self.0; drop(fr); } - for fr in node.presentation_feedback.borrow_mut().drain(..) { - fr.send_discarded(); - let _ = fr.client.remove_obj(fr.deref()); - } - for fr in node.latched_presentation_feedback.borrow_mut().drain(..) { - fr.send_discarded(); - let _ = fr.client.remove_obj(fr.deref()); - } + node.presentation_feedback.borrow_mut().clear(); + node.latched_presentation_feedback.borrow_mut().clear(); node.node_visit_children(self); } } diff --git a/src/ifs/wp_presentation.rs b/src/ifs/wp_presentation.rs index 347cf39b..1314d0d4 100644 --- a/src/ifs/wp_presentation.rs +++ b/src/ifs/wp_presentation.rs @@ -3,7 +3,7 @@ use { crate::{ client::{Client, ClientError}, globals::{Global, GlobalName}, - ifs::wp_presentation_feedback::WpPresentationFeedback, + ifs::wp_presentation_feedback::{PresentationFeedback, WpPresentationFeedback}, leaks::Tracker, object::{Object, Version}, state::State, @@ -94,7 +94,7 @@ impl WpPresentationRequestHandler for WpPresentation { }); track!(self.client, fb); self.client.add_client_obj(&fb)?; - surface.add_presentation_feedback(&fb); + surface.add_presentation_feedback(PresentationFeedback::new(fb)); Ok(()) } } diff --git a/src/ifs/wp_presentation_feedback.rs b/src/ifs/wp_presentation_feedback.rs index 57cdbd15..5a481120 100644 --- a/src/ifs/wp_presentation_feedback.rs +++ b/src/ifs/wp_presentation_feedback.rs @@ -4,11 +4,55 @@ use { ifs::{wl_output::WlOutput, wl_surface::WlSurface}, leaks::Tracker, object::{Object, Version}, - wire::{WpPresentationFeedbackId, wp_presentation_feedback::*}, + wire::{WlOutputId, WpPresentationFeedbackId, wp_presentation_feedback::*}, }, + ahash::AHashMap, std::{convert::Infallible, rc::Rc}, }; +pub struct PresentationFeedback { + fb: Option>, +} + +impl PresentationFeedback { + pub fn new(fb: Rc) -> Self { + Self { fb: Some(fb) } + } + + pub fn presented( + mut self, + outputs: Option<&AHashMap>>, + tv_sec: u64, + tv_nsec: u32, + mut refresh: u32, + seq: u64, + flags: u32, + vrr: bool, + ) { + if let Some(fb) = self.fb.take() { + if let Some(outputs) = outputs { + for output in outputs.values() { + fb.send_sync_output(output); + } + } + if vrr && fb.version < VRR_REFRESH_SINCE { + refresh = 0; + } + fb.send_presented(tv_sec, tv_nsec, refresh, seq, flags); + let _ = fb.client.remove_obj(&*fb); + } + } +} + +impl Drop for PresentationFeedback { + fn drop(&mut self) { + if let Some(fb) = self.fb.take() { + fb.send_discarded(); + let _ = fb.client.remove_obj(&*fb); + } + } +} + pub struct WpPresentationFeedback { pub id: WpPresentationFeedbackId, pub client: Rc, @@ -33,7 +77,7 @@ impl WpPresentationFeedback { }); } - pub fn send_presented(&self, tv_sec: u64, tv_nsec: u32, refresh: u32, seq: u64, flags: u32) { + fn send_presented(&self, tv_sec: u64, tv_nsec: u32, refresh: u32, seq: u64, flags: u32) { self.client.event(Presented { self_id: self.id, tv_sec, @@ -44,7 +88,7 @@ impl WpPresentationFeedback { }); } - pub fn send_discarded(&self) { + fn send_discarded(&self) { self.client.event(Discarded { self_id: self.id }); } }