1
0
Fork 0
forked from wry/wry

Merge pull request #783 from mahkoh/jorth/sync-file-surface

wl_surface: add jay_sync_file_surface extension
This commit is contained in:
mahkoh 2026-03-09 19:28:50 +01:00 committed by GitHub
commit fe8b51ffb6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 424 additions and 24 deletions

View file

@ -24,6 +24,7 @@ use {
jay_tree_query::JayTreeQuery, jay_tree_query::JayTreeQuery,
jay_workspace_watcher::JayWorkspaceWatcher, jay_workspace_watcher::JayWorkspaceWatcher,
jay_xwayland::JayXwayland, jay_xwayland::JayXwayland,
wl_surface::jay_sync_file_surface::JaySyncFileSurface,
}, },
leaks::Tracker, leaks::Tracker,
object::{Object, Version}, object::{Object, Version},
@ -76,7 +77,7 @@ global_base!(JayCompositorGlobal, JayCompositor, JayCompositorError);
impl Global for JayCompositorGlobal { impl Global for JayCompositorGlobal {
fn version(&self) -> u32 { fn version(&self) -> u32 {
25 26
} }
fn required_caps(&self) -> ClientCaps { fn required_caps(&self) -> ClientCaps {
@ -520,6 +521,18 @@ impl JayCompositorRequestHandler for JayCompositor {
} }
Ok(()) Ok(())
} }
fn get_sync_file_surface(
&self,
req: GetSyncFileSurface,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
let surface = self.client.lookup(req.surface)?;
let obj = Rc::new(JaySyncFileSurface::new(req.id, self.version, &surface));
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
Ok(())
}
} }
object_base! { object_base! {

View file

@ -2,6 +2,8 @@ pub mod commit_timeline;
pub mod cursor; pub mod cursor;
pub mod dnd_icon; pub mod dnd_icon;
pub mod ext_session_lock_surface_v1; pub mod ext_session_lock_surface_v1;
pub mod jay_sync_file_release;
pub mod jay_sync_file_surface;
pub mod tray; pub mod tray;
pub mod wl_subsurface; pub mod wl_subsurface;
pub mod wp_alpha_modifier_surface_v1; pub mod wp_alpha_modifier_surface_v1;
@ -31,7 +33,7 @@ use {
fixed::Fixed, fixed::Fixed,
gfx_api::{ gfx_api::{
AlphaMode, AsyncShmGfxTexture, BufferResv, BufferResvUser, FdSync, GfxError, AlphaMode, AsyncShmGfxTexture, BufferResv, BufferResvUser, FdSync, GfxError,
GfxStagingBuffer, ReleaseSync, SampleRect, GfxStagingBuffer, ReleaseSync, SampleRect, SyncFile,
}, },
ifs::{ ifs::{
color_management::wp_color_management_surface_feedback_v1::WpColorManagementSurfaceFeedbackV1, color_management::wp_color_management_surface_feedback_v1::WpColorManagementSurfaceFeedbackV1,
@ -52,6 +54,7 @@ use {
commit_timeline::{ClearReason, CommitTimeline, CommitTimelineError}, commit_timeline::{ClearReason, CommitTimeline, CommitTimelineError},
cursor::CursorSurface, cursor::CursorSurface,
dnd_icon::DndIcon, dnd_icon::DndIcon,
jay_sync_file_release::SyncFileRelease,
tray::TrayItemId, tray::TrayItemId,
wl_subsurface::{PendingSubsurfaceData, SubsurfaceId, WlSubsurface}, wl_subsurface::{PendingSubsurfaceData, SubsurfaceId, WlSubsurface},
wp_alpha_modifier_surface_v1::WpAlphaModifierSurfaceV1, wp_alpha_modifier_surface_v1::WpAlphaModifierSurfaceV1,
@ -90,7 +93,7 @@ use {
}, },
video::{ video::{
dmabuf::DMA_BUF_SYNC_READ, dmabuf::DMA_BUF_SYNC_READ,
drm::syncobj::{Syncobj, SyncobjPoint}, drm::syncobj::{Syncobj, SyncobjPoint, merge_sync_files},
}, },
wire::{ wire::{
WlOutputId, WlSurfaceId, WpColorManagementSurfaceFeedbackV1Id, ZwpIdleInhibitorV1Id, WlOutputId, WlSurfaceId, WpColorManagementSurfaceFeedbackV1Id, ZwpIdleInhibitorV1Id,
@ -219,11 +222,20 @@ pub struct SurfaceBuffer {
pub release_sync: ReleaseSync, pub release_sync: ReleaseSync,
release: Option<SyncobjRelease>, release: Option<SyncobjRelease>,
_surface_release: SmallVec<[SurfaceRelease; 1]>, _surface_release: SmallVec<[SurfaceRelease; 1]>,
sync_file_release: Option<SyncFileRelease>,
} }
impl Drop for SurfaceBuffer { impl Drop for SurfaceBuffer {
fn drop(&mut self) { fn drop(&mut self) {
let syncs = self.syncs.take(); let syncs = self.syncs.take();
if let Some(release) = &mut self.sync_file_release {
let sync_file = merge_sync_files(syncs.iter().flat_map(|f| f.1.get_sync_file()))
.unwrap_or_else(|e| {
log::error!("Could not merge sync files: {}", ErrorFmt(e));
None
});
release.done(sync_file.as_ref());
}
if let Some(release) = &mut self.release { if let Some(release) = &mut self.release {
release.signal(Some(&syncs)); release.signal(Some(&syncs));
return; return;
@ -456,8 +468,10 @@ struct PendingState {
subsurfaces: AHashMap<SubsurfaceId, AttachedSubsurfaceState>, subsurfaces: AHashMap<SubsurfaceId, AttachedSubsurfaceState>,
acquire_point: Option<(Rc<Syncobj>, SyncobjPoint)>, acquire_point: Option<(Rc<Syncobj>, SyncobjPoint)>,
release_point: Option<SyncobjRelease>, release_point: Option<SyncobjRelease>,
sync_file_acquire: Option<Option<SyncFile>>,
sync_file_release: Option<SyncFileRelease>,
alpha_multiplier: Option<Option<f32>>, alpha_multiplier: Option<Option<f32>>,
explicit_sync: bool, syncobj_sync: bool,
fifo_barrier_set: bool, fifo_barrier_set: bool,
fifo_barrier_wait: bool, fifo_barrier_wait: bool,
commit_time: Option<u64>, commit_time: Option<u64>,
@ -485,8 +499,9 @@ impl PendingState {
self.buffer = Some(buffer); self.buffer = Some(buffer);
self.acquire_point = next.acquire_point.take(); self.acquire_point = next.acquire_point.take();
self.release_point = next.release_point.take(); self.release_point = next.release_point.take();
self.explicit_sync = mem::take(&mut next.explicit_sync); self.syncobj_sync = mem::take(&mut next.syncobj_sync);
self.surface_release = mem::take(&mut next.surface_release); self.surface_release = mem::take(&mut next.surface_release);
self.sync_file_release = next.sync_file_release.take();
} }
macro_rules! opt { macro_rules! opt {
($name:ident) => { ($name:ident) => {
@ -510,6 +525,7 @@ impl PendingState {
opt!(color_description); opt!(color_description);
opt!(serial); opt!(serial);
opt!(alpha_mode); opt!(alpha_mode);
opt!(sync_file_acquire);
{ {
let (dx1, dy1) = self.offset; let (dx1, dy1) = self.offset;
let (dx2, dy2) = mem::take(&mut next.offset); let (dx2, dy2) = mem::take(&mut next.offset);
@ -1094,16 +1110,20 @@ impl WlSurfaceRequestHandler for WlSurface {
let pending = &mut *self.pending.borrow_mut(); let pending = &mut *self.pending.borrow_mut();
if let Some(Some(buffer)) = &mut pending.buffer if let Some(Some(buffer)) = &mut pending.buffer
&& pending.release_point.is_none() && pending.release_point.is_none()
&& pending.sync_file_release.is_none()
{ {
buffer.send_release = true; buffer.send_release = true;
} }
if let Some(release) = &mut pending.release_point { if let Some(release) = &mut pending.release_point {
release.committed = true; release.committed = true;
} }
self.verify_explicit_sync(pending)?; self.verify_syncobj_sync(pending)?;
if pending.surface_release.is_not_empty() && not_matches!(pending.buffer, Some(Some(_))) { if pending.surface_release.is_not_empty() && not_matches!(pending.buffer, Some(Some(_))) {
return Err(WlSurfaceError::SurfaceReleaseWithoutAttach); return Err(WlSurfaceError::SurfaceReleaseWithoutAttach);
} }
if pending.sync_file_release.is_some() && not_matches!(pending.buffer, Some(Some(_))) {
return Err(WlSurfaceError::SyncFileReleaseWithoutAttach);
}
if ext.commit_requested(pending) == CommitAction::ContinueCommit { if ext.commit_requested(pending) == CommitAction::ContinueCommit {
self.commit_timeline.commit(slf, pending)?; self.commit_timeline.commit(slf, pending)?;
} }
@ -1227,16 +1247,17 @@ impl WlSurface {
self.reset_shm_textures(); self.reset_shm_textures();
} }
buffer.buf.update_texture_or_log(self, false); buffer.buf.update_texture_or_log(self, false);
let release_sync = match pending.explicit_sync { let mut release_sync = ReleaseSync::Implicit;
false => ReleaseSync::Implicit, if pending.syncobj_sync || pending.sync_file_release.is_some() {
true => ReleaseSync::Explicit, release_sync = ReleaseSync::Explicit;
}; }
let surface_buffer = SurfaceBuffer { let surface_buffer = SurfaceBuffer {
buffer, buffer,
syncs: Default::default(), syncs: Default::default(),
release_sync, release_sync,
release: pending.release_point.take(), release: pending.release_point.take(),
_surface_release: mem::take(&mut pending.surface_release), _surface_release: mem::take(&mut pending.surface_release),
sync_file_release: pending.sync_file_release.take(),
}; };
self.buffer.set(Some(Rc::new(surface_buffer))); self.buffer.set(Some(Rc::new(surface_buffer)));
} else { } else {
@ -1542,9 +1563,9 @@ impl WlSurface {
} }
} }
fn verify_explicit_sync(&self, pending: &mut PendingState) -> Result<(), WlSurfaceError> { fn verify_syncobj_sync(&self, pending: &mut PendingState) -> Result<(), WlSurfaceError> {
pending.explicit_sync = self.syncobj_surface.is_some(); pending.syncobj_sync = self.syncobj_surface.is_some();
if !pending.explicit_sync { if !pending.syncobj_sync {
return Ok(()); return Ok(());
} }
let have_new_buffer = match &pending.buffer { let have_new_buffer = match &pending.buffer {
@ -2171,6 +2192,8 @@ pub enum WlSurfaceError {
RegisterCommitTimeout(#[source] IoUringError), RegisterCommitTimeout(#[source] IoUringError),
#[error("Content update contains release callbacks but no non-null buffer")] #[error("Content update contains release callbacks but no non-null buffer")]
SurfaceReleaseWithoutAttach, SurfaceReleaseWithoutAttach,
#[error("Content update contains sync file release but no non-null buffer")]
SyncFileReleaseWithoutAttach,
} }
efrom!(WlSurfaceError, ClientError); efrom!(WlSurfaceError, ClientError);
efrom!(WlSurfaceError, XdgSurfaceError); efrom!(WlSurfaceError, XdgSurfaceError);

View file

@ -203,18 +203,18 @@ impl CommitTimeline {
let mut collector = CommitDataCollector { let mut collector = CommitDataCollector {
acquire_points: Default::default(), acquire_points: Default::default(),
shm_uploads: 0, shm_uploads: 0,
implicit_dmabufs: Default::default(), acquire_files: Default::default(),
commit_time: Default::default(), commit_time: Default::default(),
}; };
collector.collect(pending); collector.collect(pending);
let points = collector.acquire_points; let points = collector.acquire_points;
let pending_uploads = collector.shm_uploads; let pending_uploads = collector.shm_uploads;
let implicit_dmabufs = collector.implicit_dmabufs; let acquire_files = collector.acquire_files;
let commit_time = collector.commit_time; let commit_time = collector.commit_time;
let has_commit_time = commit_time > 0; let has_commit_time = commit_time > 0;
let has_dependencies = points.is_not_empty() let has_dependencies = points.is_not_empty()
|| pending_uploads > 0 || pending_uploads > 0
|| implicit_dmabufs.is_not_empty() || acquire_files.is_not_empty()
|| has_commit_time; || has_commit_time;
let must_be_queued = has_dependencies let must_be_queued = has_dependencies
|| self.own_timeline.entries.is_not_empty() || self.own_timeline.entries.is_not_empty()
@ -242,7 +242,7 @@ impl CommitTimeline {
wait_handles: Cell::new(Default::default()), wait_handles: Cell::new(Default::default()),
pending_uploads: NumCell::new(pending_uploads), pending_uploads: NumCell::new(pending_uploads),
shm_upload: RefCell::new(ShmUploadState::None), shm_upload: RefCell::new(ShmUploadState::None),
num_pending_polls: NumCell::new(implicit_dmabufs.len()), num_pending_polls: NumCell::new(acquire_files.len()),
pending_polls: Cell::new(Default::default()), pending_polls: Cell::new(Default::default()),
fifo_state: Cell::new(commit_fifo_state), fifo_state: Cell::new(commit_fifo_state),
commit_times: RefCell::new(CommitTimesState::Ready), commit_times: RefCell::new(CommitTimesState::Ready),
@ -270,9 +270,9 @@ impl CommitTimeline {
*commit.shm_upload.borrow_mut() = ShmUploadState::Todo(noderef.clone()); *commit.shm_upload.borrow_mut() = ShmUploadState::Todo(noderef.clone());
needs_flush = true; needs_flush = true;
} }
if implicit_dmabufs.is_not_empty() { if acquire_files.is_not_empty() {
let mut pending_polls = SmallVec::new(); let mut pending_polls = SmallVec::new();
for fd in implicit_dmabufs { for fd in acquire_files {
let handle = self let handle = self
.shared .shared
.ring .ring
@ -692,7 +692,7 @@ type Point = (Rc<Syncobj>, SyncobjPoint);
struct CommitDataCollector { struct CommitDataCollector {
acquire_points: SmallVec<[Point; 1]>, acquire_points: SmallVec<[Point; 1]>,
shm_uploads: usize, shm_uploads: usize,
implicit_dmabufs: SmallVec<[Rc<OwnedFd>; 1]>, acquire_files: SmallVec<[Rc<OwnedFd>; 1]>,
commit_time: u64, commit_time: u64,
} }
@ -703,14 +703,18 @@ impl CommitDataCollector {
if buffer.is_shm() { if buffer.is_shm() {
self.shm_uploads += 1; self.shm_uploads += 1;
} }
if !pending.explicit_sync if !pending.syncobj_sync
&& pending.sync_file_acquire.is_none()
&& let Some(dmabuf) = &buffer.client_dmabuf && let Some(dmabuf) = &buffer.client_dmabuf
{ {
for plane in &dmabuf.planes { for plane in &dmabuf.planes {
self.implicit_dmabufs.push(plane.fd.clone()); self.acquire_files.push(plane.fd.clone());
} }
} }
} }
if let Some(Some(sf)) = pending.sync_file_acquire.take() {
self.acquire_files.push(sf.0);
}
if let Some(point) = pending.acquire_point.take() { if let Some(point) = pending.acquire_point.take() {
self.acquire_points.push(point); self.acquire_points.push(point);
} }

View file

@ -0,0 +1,92 @@
use {
crate::{
client::{Client, ClientError},
gfx_api::SyncFile,
leaks::Tracker,
object::{Object, Version},
wire::{JaySyncFileReleaseId, jay_sync_file_release::*},
},
std::{cell::Cell, rc::Rc},
thiserror::Error,
};
pub struct SyncFileRelease {
pub release: Option<Rc<JaySyncFileRelease>>,
}
impl SyncFileRelease {
pub fn done(&mut self, sync_file: Option<&SyncFile>) {
if let Some(release) = self.release.take() {
release.done(sync_file);
}
}
}
impl Drop for SyncFileRelease {
fn drop(&mut self) {
self.done(None);
}
}
pub struct JaySyncFileRelease {
pub id: JaySyncFileReleaseId,
pub client: Rc<Client>,
pub tracker: Tracker<Self>,
pub version: Version,
pub destroyed: Cell<bool>,
}
impl JaySyncFileRelease {
pub fn new(client: &Rc<Client>, id: JaySyncFileReleaseId, version: Version) -> Self {
Self {
id,
client: client.clone(),
tracker: Default::default(),
version,
destroyed: Cell::new(false),
}
}
pub fn done(&self, sync_file: Option<&SyncFile>) {
if self.destroyed.get() {
return;
}
match sync_file {
None => {
self.client.event(ReleaseImmediate { self_id: self.id });
}
Some(fd) => {
self.client.event(ReleaseAsync {
self_id: self.id,
sync_file: fd.0.clone(),
});
}
}
}
}
impl JaySyncFileReleaseRequestHandler for JaySyncFileRelease {
type Error = JaySyncFileReleaseError;
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.destroyed.set(true);
self.client.remove_obj(self)?;
Ok(())
}
}
object_base! {
self = JaySyncFileRelease;
version = self.version;
}
impl Object for JaySyncFileRelease {}
simple_add_obj!(JaySyncFileRelease);
#[derive(Debug, Error)]
pub enum JaySyncFileReleaseError {
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(JaySyncFileReleaseError, ClientError);

View file

@ -0,0 +1,92 @@
use {
crate::{
client::{Client, ClientError},
gfx_api::SyncFile,
ifs::wl_surface::{
WlSurface,
jay_sync_file_release::{JaySyncFileRelease, SyncFileRelease},
},
leaks::Tracker,
object::{Object, Version},
wire::{JaySyncFileSurfaceId, jay_sync_file_surface::*},
},
std::rc::Rc,
thiserror::Error,
};
pub struct JaySyncFileSurface {
pub id: JaySyncFileSurfaceId,
pub client: Rc<Client>,
pub surface: Rc<WlSurface>,
pub tracker: Tracker<Self>,
pub version: Version,
}
impl JaySyncFileSurface {
pub fn new(id: JaySyncFileSurfaceId, version: Version, surface: &Rc<WlSurface>) -> Self {
Self {
id,
client: surface.client.clone(),
surface: surface.clone(),
tracker: Default::default(),
version,
}
}
}
impl JaySyncFileSurfaceRequestHandler for JaySyncFileSurface {
type Error = JaySyncFileSurfaceError;
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.client.remove_obj(self)?;
Ok(())
}
fn set_acquire_immediate(
&self,
_req: SetAcquireImmediate,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
self.surface.pending.borrow_mut().sync_file_acquire = Some(None);
Ok(())
}
fn set_acquire_async(&self, req: SetAcquireAsync, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.surface.pending.borrow_mut().sync_file_acquire = Some(Some(SyncFile(req.sync_file)));
Ok(())
}
fn get_release(&self, req: GetRelease, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let obj = Rc::new(JaySyncFileRelease::new(
&self.client,
req.release,
self.version,
));
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
let pending = &mut *self.surface.pending.borrow_mut();
if pending.sync_file_release.is_some() {
return Err(JaySyncFileSurfaceError::HasRelease);
}
pending.sync_file_release = Some(SyncFileRelease { release: Some(obj) });
Ok(())
}
}
object_base! {
self = JaySyncFileSurface;
version = self.version;
}
impl Object for JaySyncFileSurface {}
simple_add_obj!(JaySyncFileSurface);
#[derive(Debug, Error)]
pub enum JaySyncFileSurfaceError {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("The content update already has a release object")]
HasRelease,
}
efrom!(JaySyncFileSurfaceError, ClientError);

View file

@ -352,7 +352,7 @@ fn destroy(drm: &OwnedFd, handle: SyncobjHandle) {
} }
} }
fn merge_sync_files<'a, I>(sync_files: I) -> Result<Option<SyncFile>, DrmError> pub fn merge_sync_files<'a, I>(sync_files: I) -> Result<Option<SyncFile>, DrmError>
where where
I: IntoIterator<Item = &'a SyncFile>, I: IntoIterator<Item = &'a SyncFile>,
{ {

View file

@ -7,6 +7,8 @@ pub mod usr_jay_render_ctx;
pub mod usr_jay_screencast; pub mod usr_jay_screencast;
pub mod usr_jay_select_toplevel; pub mod usr_jay_select_toplevel;
pub mod usr_jay_select_workspace; pub mod usr_jay_select_workspace;
pub mod usr_jay_sync_file_release;
pub mod usr_jay_sync_file_surface;
pub mod usr_jay_toplevel; pub mod usr_jay_toplevel;
pub mod usr_jay_workspace; pub mod usr_jay_workspace;
pub mod usr_jay_workspace_watcher; pub mod usr_jay_workspace_watcher;

View file

@ -12,8 +12,9 @@ use {
usr_jay_screencast::UsrJayScreencast, usr_jay_screencast::UsrJayScreencast,
usr_jay_select_toplevel::UsrJaySelectToplevel, usr_jay_select_toplevel::UsrJaySelectToplevel,
usr_jay_select_workspace::UsrJaySelectWorkspace, usr_jay_select_workspace::UsrJaySelectWorkspace,
usr_jay_sync_file_surface::UsrJaySyncFileSurface,
usr_jay_workspace_watcher::UsrJayWorkspaceWatcher, usr_wl_output::UsrWlOutput, usr_jay_workspace_watcher::UsrJayWorkspaceWatcher, usr_wl_output::UsrWlOutput,
usr_wl_seat::UsrWlSeat, usr_wl_seat::UsrWlSeat, usr_wl_surface::UsrWlSurface,
}, },
usr_object::UsrObject, usr_object::UsrObject,
}, },
@ -187,6 +188,22 @@ impl UsrJayCompositor {
self.con.add_object(obj.clone()); self.con.add_object(obj.clone());
obj obj
} }
#[expect(dead_code)]
pub fn get_sync_file_surface(&self, surface: &UsrWlSurface) -> Rc<UsrJaySyncFileSurface> {
let obj = Rc::new(UsrJaySyncFileSurface {
id: self.con.id(),
con: self.con.clone(),
version: self.version,
});
self.con.request(GetSyncFileSurface {
self_id: self.id,
id: obj.id,
surface: surface.id,
});
self.con.add_object(obj.clone());
obj
}
} }
impl JayCompositorEventHandler for UsrJayCompositor { impl JayCompositorEventHandler for UsrJayCompositor {

View file

@ -0,0 +1,60 @@
use {
crate::{
gfx_api::SyncFile,
object::Version,
utils::clonecell::CloneCell,
wire::{JaySyncFileReleaseId, jay_sync_file_release::*},
wl_usr::{UsrCon, usr_object::UsrObject},
},
std::{convert::Infallible, rc::Rc},
uapi::OwnedFd,
};
pub struct UsrJaySyncFileRelease {
pub id: JaySyncFileReleaseId,
pub con: Rc<UsrCon>,
pub owner: CloneCell<Option<Rc<dyn UsrJaySyncFileReleaseOwner>>>,
pub version: Version,
}
pub trait UsrJaySyncFileReleaseOwner {
fn release(&self, sync_file: Option<SyncFile>);
}
impl UsrJaySyncFileRelease {
fn release(&self, sf: Option<Rc<OwnedFd>>) {
if let Some(owner) = self.owner.get() {
owner.release(sf.map(SyncFile));
}
self.con.remove_obj(self);
}
}
impl JaySyncFileReleaseEventHandler for UsrJaySyncFileRelease {
type Error = Infallible;
fn release_immediate(&self, _ev: ReleaseImmediate, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.release(None);
Ok(())
}
fn release_async(&self, ev: ReleaseAsync, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.release(Some(ev.sync_file));
Ok(())
}
}
usr_object_base! {
self = UsrJaySyncFileRelease = JaySyncFileRelease;
version = self.version;
}
impl UsrObject for UsrJaySyncFileRelease {
fn destroy(&self) {
self.con.request(Destroy { self_id: self.id });
}
fn break_loops(&self) {
self.owner.take();
}
}

View file

@ -0,0 +1,66 @@
use {
crate::{
gfx_api::SyncFile,
object::Version,
wire::{JaySyncFileSurfaceId, jay_sync_file_surface::*},
wl_usr::{
UsrCon, usr_ifs::usr_jay_sync_file_release::UsrJaySyncFileRelease,
usr_object::UsrObject,
},
},
std::{convert::Infallible, rc::Rc},
};
pub struct UsrJaySyncFileSurface {
pub id: JaySyncFileSurfaceId,
pub con: Rc<UsrCon>,
pub version: Version,
}
impl UsrJaySyncFileSurface {
#[expect(dead_code)]
pub fn set_acquire(&self, sf: Option<&SyncFile>) {
match sf {
None => {
self.con.request(SetAcquireImmediate { self_id: self.id });
}
Some(sf) => {
self.con.request(SetAcquireAsync {
self_id: self.id,
sync_file: sf.0.clone(),
});
}
}
}
#[expect(dead_code)]
pub fn get_release(&self) -> Rc<UsrJaySyncFileRelease> {
let obj = Rc::new(UsrJaySyncFileRelease {
id: self.con.id(),
con: self.con.clone(),
owner: Default::default(),
version: self.version,
});
self.con.request(GetRelease {
self_id: self.id,
release: obj.id,
});
self.con.add_object(obj.clone());
obj
}
}
impl JaySyncFileSurfaceEventHandler for UsrJaySyncFileSurface {
type Error = Infallible;
}
usr_object_base! {
self = UsrJaySyncFileSurface = JaySyncFileSurface;
version = self.version;
}
impl UsrObject for UsrJaySyncFileSurface {
fn destroy(&self) {
self.con.request(Destroy { self_id: self.id });
}
}

View file

@ -126,6 +126,11 @@ request get_tagged_acceptor (since = 25) {
tag: str, tag: str,
} }
request get_sync_file_surface (since = 26) {
id: id(jay_sync_file_surface),
surface: id(wl_surface),
}
# events # events
event client_id { event client_id {

View file

@ -0,0 +1,11 @@
request destroy {
}
event release_immediate {
}
event release_async {
sync_file: fd,
}

View file

@ -0,0 +1,15 @@
request destroy {
}
request set_acquire_immediate {
}
request set_acquire_async {
sync_file: fd,
}
request get_release {
release: id(jay_sync_file_release) (new),
}