1
0
Fork 0
forked from wry/wry
wry/src/ifs/jay_select_toplevel.rs
2025-05-07 22:41:43 +02:00

131 lines
3.4 KiB
Rust

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<Client>,
pub tracker: Tracker<Self>,
pub destroyed: Cell<bool>,
pub version: Version,
}
pub struct JayToplevelSelector {
pub tl: CloneCell<Option<Rc<dyn ToplevelNode>>>,
pub jst: Rc<JaySelectToplevel>,
}
impl ToplevelSelector for JayToplevelSelector {
fn set(&self, toplevel: Rc<dyn ToplevelNode>) {
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<Rc<dyn ToplevelNode>>) {
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<Client>, id: JaySelectToplevelId, version: Version) -> Rc<Self> {
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<ClientError>),
}
efrom!(JaySelectToplevelError, ClientError);