jay-compositor 1.15.0

The Jay compositor
use crate::format::formats;
use crate::object::Version;
use crate::utils::clonecell::CloneCell;
use crate::video::dmabuf::DmaBuf;
use crate::video::dmabuf::DmaBufPlane;
use crate::video::dmabuf::PlaneVec;
use crate::wire::JayScreencastId;
use crate::wire::jay_screencast::*;
use crate::wl_usr::UsrCon;
use crate::wl_usr::usr_ifs::usr_jay_output::UsrJayOutput;
use crate::wl_usr::usr_ifs::usr_jay_toplevel::UsrJayToplevel;
use crate::wl_usr::usr_ifs::usr_jay_workspace::UsrJayWorkspace;
use crate::wl_usr::usr_ifs::usr_wl_buffer::UsrWlBuffer;
use crate::wl_usr::usr_object::UsrObject;
use std::cell::RefCell;
use std::mem;
use std::ops::DerefMut;
use std::rc::Rc;
use thiserror::Error;

pub struct UsrJayScreencast {
    pub id: JayScreencastId,
    pub con: Rc<UsrCon>,
    pub owner: CloneCell<Option<Rc<dyn UsrJayScreencastOwner>>>,
    pub version: Version,

    pub pending_buffers: RefCell<Vec<Rc<DmaBuf>>>,
    pub pending_planes: RefCell<PlaneVec<DmaBufPlane>>,

    pub pending_config: RefCell<UsrJayScreencastServerConfig>,
}

#[derive(Default)]
pub struct UsrJayScreencastServerConfig {
    output: Option<u32>,
    show_all: bool,
    running: bool,
    use_linear_buffers: bool,
    allowed_workspaces: Vec<u32>,
    pub width: i32,
    pub height: i32,
}

pub trait UsrJayScreencastOwner {
    fn buffers(&self, buffers: Vec<Rc<DmaBuf>>) {
        let _ = buffers;
    }

    fn ready(&self, ev: &Ready) {
        let _ = ev;
    }

    fn destroyed(&self) {}

    fn missed_frame(&self) {}

    fn config(&self, config: UsrJayScreencastServerConfig) {
        let _ = config;
    }
}

impl UsrJayScreencast {
    pub fn set_output(&self, output: &UsrJayOutput) {
        self.con.request(SetOutput {
            self_id: self.id,
            output: output.id,
        });
    }

    pub fn set_toplevel(&self, tl: &UsrJayToplevel) {
        self.con.request(SetToplevel {
            self_id: self.id,
            id: tl.id,
        });
    }

    pub fn set_allow_all_workspaces(&self, allow_all: bool) {
        self.con.request(SetAllowAllWorkspaces {
            self_id: self.id,
            allow_all,
        });
    }

    pub fn allow_workspace(&self, ws: &UsrJayWorkspace) {
        self.con.request(AllowWorkspace {
            self_id: self.id,
            workspace: ws.id,
        });
    }

    #[expect(unused)]
    pub fn touch_allowed_workspaces(&self) {
        self.con
            .request(TouchAllowedWorkspaces { self_id: self.id });
    }

    pub fn set_use_linear_buffers(&self, use_linear: bool) {
        self.con.request(SetUseLinearBuffers {
            self_id: self.id,
            use_linear,
        });
    }

    pub fn set_running(&self, running: bool) {
        self.con.request(SetRunning {
            self_id: self.id,
            running,
        });
    }

    pub fn configure(&self) {
        self.con.request(Configure { self_id: self.id });
    }

    pub fn release_buffer(&self, idx: usize) {
        self.con.request(ReleaseBuffer {
            self_id: self.id,
            idx: idx as _,
        });
    }

    pub fn clear_buffers(&self) {
        self.con.request(ClearBuffers { self_id: self.id });
    }

    pub fn add_buffer(&self, buffer: &UsrWlBuffer) {
        self.con.request(AddBuffer {
            self_id: self.id,
            buffer: buffer.id,
        });
    }
}

impl JayScreencastEventHandler for UsrJayScreencast {
    type Error = UsrJayScreencastError;

    fn plane(&self, ev: Plane, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        self.pending_planes.borrow_mut().push(DmaBufPlane {
            offset: ev.offset,
            stride: ev.stride,
            fd: ev.fd,
        });
        Ok(())
    }

    fn buffer(&self, ev: Buffer, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        let Some(format) = formats().get(&ev.format) else {
            return Err(UsrJayScreencastError::UnknownFormat(ev.format));
        };
        self.pending_buffers.borrow_mut().push(DmaBuf::new(
            &self.con.dma_buf_ids,
            ev.width,
            ev.height,
            format,
            ev.modifier,
            mem::take(self.pending_planes.borrow_mut().deref_mut()),
        ));
        Ok(())
    }

    fn buffers_done(&self, ev: BuffersDone, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        if let Some(owner) = self.owner.get() {
            owner.buffers(mem::take(self.pending_buffers.borrow_mut().deref_mut()));
        }
        self.con.request(AckBuffers {
            self_id: self.id,
            serial: ev.serial,
        });
        Ok(())
    }

    fn ready(&self, ev: Ready, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        if let Some(owner) = self.owner.get() {
            owner.ready(&ev);
        }
        Ok(())
    }

    fn destroyed(&self, _ev: Destroyed, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        if let Some(owner) = self.owner.get() {
            owner.destroyed();
        }
        Ok(())
    }

    fn missed_frame(&self, _ev: MissedFrame, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        if let Some(owner) = self.owner.get() {
            owner.missed_frame();
        }
        Ok(())
    }

    fn config_output(&self, ev: ConfigOutput, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        self.pending_config.borrow_mut().output = Some(ev.linear_id);
        Ok(())
    }

    fn config_allow_all_workspaces(
        &self,
        ev: ConfigAllowAllWorkspaces,
        _slf: &Rc<Self>,
    ) -> Result<(), Self::Error> {
        self.pending_config.borrow_mut().show_all = ev.allow_all;
        Ok(())
    }

    fn config_allow_workspace(
        &self,
        ev: ConfigAllowWorkspace,
        _slf: &Rc<Self>,
    ) -> Result<(), Self::Error> {
        self.pending_config
            .borrow_mut()
            .allowed_workspaces
            .push(ev.linear_id);
        Ok(())
    }

    fn config_use_linear_buffers(
        &self,
        ev: ConfigUseLinearBuffers,
        _slf: &Rc<Self>,
    ) -> Result<(), Self::Error> {
        self.pending_config.borrow_mut().use_linear_buffers = ev.use_linear;
        Ok(())
    }

    fn config_running(&self, ev: ConfigRunning, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        self.pending_config.borrow_mut().running = ev.running;
        Ok(())
    }

    fn config_done(&self, ev: ConfigDone, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        if let Some(owner) = self.owner.get() {
            owner.config(mem::take(self.pending_config.borrow_mut().deref_mut()));
        }
        self.con.request(AckConfig {
            self_id: self.id,
            serial: ev.serial,
        });
        Ok(())
    }

    fn config_size(&self, ev: ConfigSize, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        self.pending_config.borrow_mut().width = ev.width;
        self.pending_config.borrow_mut().height = ev.height;
        Ok(())
    }
}

usr_object_base! {
    self = UsrJayScreencast = JayScreencast;
    version = self.version;
}

impl UsrObject for UsrJayScreencast {
    fn destroy(&self) {
        self.con.request(Destroy { self_id: self.id });
    }

    fn break_loops(&self) {
        self.owner.take();
    }
}

#[derive(Debug, Error)]
pub enum UsrJayScreencastError {
    #[error("The server sent an unknown format {0}")]
    UnknownFormat(u32),
}