jay-compositor 1.15.0

The Jay compositor
use crate::client::Client;
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel;
use crate::it::test_error::TestErrorError;
use crate::it::test_error::TestResult;
use crate::it::test_utils::test_window::TestWindow;
use crate::tree::ContainerNode;
use crate::tree::ContainingNode;
use crate::tree::FloatNode;
use crate::tree::ToplevelNodeBase;
use crate::utils::bhash::BHashSet;
use crate::wire::XdgToplevelId;
use crate::wire::xdg_toplevel::*;
use std::cell::Cell;
use std::cell::RefCell;
use std::future::poll_fn;
use std::rc::Rc;
use std::task::Poll;
use std::task::Waker;

pub struct TestXdgToplevelCore {
    pub id: XdgToplevelId,
    pub client: Rc<Client>,

    pub configured: Cell<bool>,
    pub configured_waiter: Cell<Option<Waker>>,

    pub width: Cell<i32>,
    pub height: Cell<i32>,
    pub states: RefCell<BHashSet<u32>>,

    pub close_requested: Cell<bool>,
}

pub struct TestXdgToplevel {
    pub core: Rc<TestXdgToplevelCore>,
    pub server: Rc<XdgToplevel>,
}

impl TestXdgToplevel {
    fn parent(&self) -> TestResult<Rc<dyn ContainingNode>> {
        match self.server.tl_data().parent.get() {
            Some(p) => Ok(p),
            _ => bail!("toplevel has no parent"),
        }
    }

    pub fn container_parent(&self) -> TestResult<Rc<ContainerNode>> {
        let parent = self.parent()?;
        match parent.node_into_container() {
            Some(p) => Ok(p),
            _ => bail!("toplevel parent is not a container"),
        }
    }

    pub fn float_parent(&self) -> TestResult<Rc<FloatNode>> {
        let parent = self.parent()?;
        match parent.node_into_float() {
            Some(p) => Ok(p),
            _ => bail!("toplevel parent is not a float"),
        }
    }
}

impl TestXdgToplevelCore {
    pub fn destroy(&self) {
        self.client.send_xdg_toplevel_destroy(self.id);
    }

    pub fn set_title(&self, title: &str) {
        self.client.send_xdg_toplevel_set_title(self.id, title);
    }

    pub fn set_parent(&self, parent: &TestWindow) {
        self.client
            .send_xdg_toplevel_set_parent(self.id, parent.tl.server.id);
    }

    pub async fn configured(&self) {
        poll_fn(|ctx| {
            if self.configured.get() {
                return Poll::Ready(());
            }
            self.configured_waiter.set(Some(ctx.waker().clone()));
            Poll::Pending
        })
        .await;
    }
}

synthetic_event_handler!(TestXdgToplevelCore);

impl XdgToplevelEventHandler for TestXdgToplevelCore {
    type Error = TestErrorError;

    fn configure(&self, ev: Configure<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        self.width.set(ev.width);
        self.height.set(ev.height);
        *self.states.borrow_mut() = ev.states.iter().copied().collect();
        self.configured.set(true);
        if let Some(waker) = self.configured_waiter.take() {
            waker.wake();
        }
        Ok(())
    }

    fn close(&self, _ev: Close, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        self.close_requested.set(true);
        Ok(())
    }

    fn configure_bounds(&self, _ev: ConfigureBounds, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        Ok(())
    }

    fn wm_capabilities(&self, _ev: WmCapabilities<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
        Ok(())
    }
}