use std::{
any::Any,
fmt,
os::unix::{
io::{BorrowedFd, OwnedFd, RawFd},
net::UnixStream,
},
sync::Arc,
};
#[cfg(doc)]
use std::io::ErrorKind::WouldBlock;
use crate::protocol::{Interface, Message, ObjectInfo};
use super::client_impl;
pub use crate::types::client::{InvalidId, NoWaylandLib, WaylandError};
pub trait ObjectData: downcast_rs::DowncastSync {
fn event(
self: Arc<Self>,
backend: &Backend,
msg: Message<ObjectId, OwnedFd>,
) -> Option<Arc<dyn ObjectData>>;
fn destroyed(&self, object_id: ObjectId);
#[cfg_attr(coverage, coverage(off))]
fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ObjectData").finish_non_exhaustive()
}
fn data_as_any(&self) -> &dyn Any {
self.as_any()
}
}
impl std::fmt::Debug for dyn ObjectData {
#[cfg_attr(coverage, coverage(off))]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.debug(f)
}
}
downcast_rs::impl_downcast!(sync ObjectData);
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct ObjectId {
pub(crate) id: client_impl::InnerObjectId,
}
impl fmt::Display for ObjectId {
#[cfg_attr(coverage, coverage(off))]
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.id.fmt(f)
}
}
impl fmt::Debug for ObjectId {
#[cfg_attr(coverage, coverage(off))]
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.id.fmt(f)
}
}
impl ObjectId {
#[inline]
pub fn is_null(&self) -> bool {
self.id.is_null()
}
#[inline]
pub fn null() -> ObjectId {
client_impl::InnerBackend::null_id()
}
#[inline]
pub fn interface(&self) -> &'static Interface {
self.id.interface()
}
#[inline]
pub fn protocol_id(&self) -> u32 {
self.id.protocol_id()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Backend {
pub(crate) backend: client_impl::InnerBackend,
}
#[derive(Clone, Debug)]
pub struct WeakBackend {
inner: client_impl::WeakInnerBackend,
}
impl WeakBackend {
pub fn upgrade(&self) -> Option<Backend> {
self.inner.upgrade().map(|backend| Backend { backend })
}
}
impl Backend {
pub fn connect(stream: UnixStream) -> Result<Self, NoWaylandLib> {
client_impl::InnerBackend::connect(stream).map(|backend| Self { backend })
}
pub fn downgrade(&self) -> WeakBackend {
WeakBackend { inner: self.backend.downgrade() }
}
pub fn flush(&self) -> Result<(), WaylandError> {
self.backend.flush()
}
#[inline]
pub fn poll_fd(&self) -> BorrowedFd {
self.backend.poll_fd()
}
#[inline]
pub fn display_id(&self) -> ObjectId {
self.backend.display_id()
}
#[inline]
pub fn last_error(&self) -> Option<WaylandError> {
self.backend.last_error()
}
#[inline]
pub fn info(&self, id: ObjectId) -> Result<ObjectInfo, InvalidId> {
self.backend.info(id)
}
pub fn send_request(
&self,
msg: Message<ObjectId, RawFd>,
data: Option<Arc<dyn ObjectData>>,
child_spec: Option<(&'static Interface, u32)>,
) -> Result<ObjectId, InvalidId> {
self.backend.send_request(msg, data, child_spec)
}
pub fn get_data(&self, id: ObjectId) -> Result<Arc<dyn ObjectData>, InvalidId> {
self.backend.get_data(id)
}
pub fn set_data(&self, id: ObjectId, data: Arc<dyn ObjectData>) -> Result<(), InvalidId> {
self.backend.set_data(id, data)
}
#[inline]
#[must_use]
pub fn prepare_read(&self) -> Option<ReadEventsGuard> {
client_impl::InnerReadEventsGuard::try_new(self.backend.clone())
.map(|guard| ReadEventsGuard { guard })
}
#[inline]
pub fn dispatch_inner_queue(&self) -> Result<usize, WaylandError> {
self.backend.dispatch_inner_queue()
}
}
#[derive(Debug)]
pub struct ReadEventsGuard {
pub(crate) guard: client_impl::InnerReadEventsGuard,
}
impl ReadEventsGuard {
#[inline]
pub fn connection_fd(&self) -> BorrowedFd {
self.guard.connection_fd()
}
#[inline]
pub fn read(self) -> Result<usize, WaylandError> {
self.guard.read()
}
}
pub(crate) struct DumbObjectData;
impl ObjectData for DumbObjectData {
#[cfg_attr(coverage, coverage(off))]
fn event(
self: Arc<Self>,
_handle: &Backend,
_msg: Message<ObjectId, OwnedFd>,
) -> Option<Arc<dyn ObjectData>> {
unreachable!()
}
#[cfg_attr(coverage, coverage(off))]
fn destroyed(&self, _object_id: ObjectId) {
unreachable!()
}
}
pub(crate) struct UninitObjectData;
impl ObjectData for UninitObjectData {
#[cfg_attr(coverage, coverage(off))]
fn event(
self: Arc<Self>,
_handle: &Backend,
msg: Message<ObjectId, OwnedFd>,
) -> Option<Arc<dyn ObjectData>> {
panic!("Received a message on an uninitialized object: {:?}", msg);
}
#[cfg_attr(coverage, coverage(off))]
fn destroyed(&self, _object_id: ObjectId) {}
#[cfg_attr(coverage, coverage(off))]
fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("UninitObjectData").finish()
}
}