use { crate::{ client::{Client, ClientError}, ifs::{ jay_toplevel::{CLIENT_ID_SINCE, ID_SINCE, JayToplevel}, wl_seat::ToplevelSelector, }, leaks::Tracker, object::{Object, Version}, tree::ToplevelNode, utils::clonecell::CloneCell, wire::{JaySelectToplevelId, JayToplevelId, jay_select_toplevel::*}, }, std::{cell::Cell, rc::Rc}, thiserror::Error, }; pub struct JaySelectToplevel { pub id: JaySelectToplevelId, pub client: Rc, pub tracker: Tracker, pub destroyed: Cell, pub version: Version, } pub struct JayToplevelSelector { pub tl: CloneCell>>, pub jst: Rc, } impl ToplevelSelector for JayToplevelSelector { fn set(&self, toplevel: Rc) { self.tl.set(Some(toplevel)); } } impl Drop for JayToplevelSelector { fn drop(&mut self) { if self.jst.destroyed.get() { return; } self.jst.done(self.tl.take()); } } impl JaySelectToplevel { pub fn done(&self, tl: Option>) { let jtl = match tl { None => None, Some(toplevel) => { let id = match self.client.new_id() { Ok(id) => id, Err(e) => { self.client.error(e); return; } }; let jtl = Rc::new(JayToplevel { id, client: self.client.clone(), tracker: Default::default(), toplevel, destroyed: Cell::new(false), version: self.version, }); track!(self.client, jtl); self.client.add_server_obj(&jtl); jtl.toplevel .tl_data() .jay_toplevels .set((jtl.client.id, jtl.id), jtl.clone()); Some(jtl) } }; match jtl { None => self.send_done(JayToplevelId::NONE), Some(jtl) => { self.send_done(jtl.id); if jtl.version >= ID_SINCE { jtl.send_id(); if jtl.version >= CLIENT_ID_SINCE { jtl.send_client_id(); } jtl.send_done(); } } } let _ = self.client.remove_obj(self); } pub fn new(client: &Rc, id: JaySelectToplevelId, version: Version) -> Rc { Rc::new(JaySelectToplevel { id, client: client.clone(), tracker: Default::default(), destroyed: Cell::new(false), version, }) } fn send_done(&self, id: JayToplevelId) { self.client.event(Done { self_id: self.id, id, }); } } impl JaySelectToplevelRequestHandler for JaySelectToplevel { type Error = JaySelectToplevelError; } object_base! { self = JaySelectToplevel; version = Version(1); } impl Object for JaySelectToplevel { fn break_loops(&self) { self.destroyed.set(true); } } simple_add_obj!(JaySelectToplevel); #[derive(Debug, Error)] pub enum JaySelectToplevelError { #[error(transparent)] ClientError(Box), } efrom!(JaySelectToplevelError, ClientError);