jay-compositor 1.15.0

The Jay compositor
use crate::client::Client;
use crate::ifs::jay_wl_surface_factory_v1::WlSurfaceFactoryState::Abandoned;
use crate::ifs::jay_wl_surface_factory_v1::WlSurfaceFactoryState::Assigned;
use crate::ifs::jay_wl_surface_factory_v1::WlSurfaceFactoryState::Initial;
use crate::ifs::wl_surface::WlSurface;
use crate::leaks::Tracker;
use crate::object::Version;
use crate::wire::JayWlSurfaceFactoryV1Id;
use crate::wire::jay_wl_surface_factory_v1::*;
use jay_proc::Object;
use std::cell::Cell;
use std::rc::Rc;
use thiserror::Error;

#[derive(Object)]
pub struct JayWlSurfaceFactoryV1 {
    id: JayWlSurfaceFactoryV1Id,
    client: Rc<Client>,
    tracker: Tracker<Self>,
    version: Version,
    fs: Cell<WlSurfaceFactoryState>,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
enum WlSurfaceFactoryState {
    #[default]
    Initial,
    Assigned,
    Abandoned,
}

impl JayWlSurfaceFactoryV1 {
    pub fn new(id: JayWlSurfaceFactoryV1Id, version: Version, client: &Rc<Client>) -> Rc<Self> {
        let obj = Rc::new(Self {
            id,
            client: client.clone(),
            tracker: Default::default(),
            version,
            fs: Default::default(),
        });
        track!(client, obj);
        obj
    }

    pub fn assign(&self) -> Result<(), JayWlSurfaceFactoryV1Error> {
        match self.fs.get() {
            Initial => self.fs.set(Assigned),
            Assigned => return Err(JayWlSurfaceFactoryV1Error::AlreadyAssigned),
            Abandoned => return Err(JayWlSurfaceFactoryV1Error::AlreadyAbandoned),
        }
        Ok(())
    }

    pub fn abandon(&self) {
        if self.fs.get() != Assigned {
            log::warn!("Factory is not assigned");
        }
        self.fs.set(Abandoned);
    }

    pub fn send_surface(&self) -> Rc<WlSurface> {
        if self.fs.get() != Assigned {
            log::warn!("Factory is not assigned");
        }
        let surface = Rc::new_cyclic(|slf| {
            WlSurface::new(self.client.new_id(self), &self.client, self.version, slf)
        });
        track!(self.client, surface);
        self.client.add_server_obj(&surface);
        self.client.event(Surface {
            self_id: self.id,
            id: surface.id,
        });
        surface
    }
}

impl JayWlSurfaceFactoryV1RequestHandler for JayWlSurfaceFactoryV1 {
    type Error = JayWlSurfaceFactoryV1Error;

    fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        if self.fs.get() == Assigned {
            return Err(JayWlSurfaceFactoryV1Error::StillAssigned);
        }
        self.client.remove_obj(self);
        Ok(())
    }
}

#[derive(Debug, Error)]
pub enum JayWlSurfaceFactoryV1Error {
    #[error("The wl_surface factory is already assigned to a producer")]
    AlreadyAssigned,
    #[error("The wl_surface factory is already abandoned")]
    AlreadyAbandoned,
    #[error("The wl_surface factory is still assigned to a producer")]
    StillAssigned,
}