use std::{cell::Cell, ptr::NonNull, rc::Rc};
use libc;
use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wlroots_sys::wlr_subsurface;
use {compositor,
surface,
utils::{self, HandleErr, HandleResult, Handleable}};
pub type Handle = utils::Handle<(), wlr_subsurface, Subsurface>;
#[allow(unused_variables)]
pub trait Handler {
fn on_destroy(&mut self,
compositor_handle: compositor::Handle,
subsurface_handle: Handle,
surface_handle: surface::Handle) {}
}
wayland_listener!(pub(crate) InternalSubsurface, (Subsurface, Box<Handler>), [
on_destroy_listener => on_destroy_notify: |this: &mut InternalSubsurface,
data: *mut libc::c_void,|
unsafe {
let (ref mut subsurface, ref mut manager) = this.data;
let subsurface_ptr = data as *mut wlr_subsurface;
let surface = surface::Handle::from_ptr((*subsurface_ptr).surface);
let compositor = match compositor::handle() {
Some(handle) => handle,
None => return
};
manager.on_destroy(compositor, subsurface.weak_reference(), surface);
Box::from_raw((*subsurface_ptr).data as *mut InternalSubsurface);
};
]);
#[derive(Debug)]
pub struct Subsurface {
liveliness: Rc<Cell<bool>>,
subsurface: NonNull<wlr_subsurface>
}
impl Subsurface {
pub(crate) unsafe fn new(subsurface: *mut wlr_subsurface) -> Self {
let subsurface = NonNull::new(subsurface)
.expect("Subsurface pointer was null");
let liveliness = Rc::new(Cell::new(false));
Subsurface { subsurface,
liveliness }
}
pub fn surface(&self) -> surface::Handle {
unsafe { surface::Handle::from_ptr((*self.subsurface.as_ptr()).surface) }
}
pub fn parent_surface(&self) -> surface::Handle {
unsafe { surface::Handle::from_ptr((*self.subsurface.as_ptr()).parent) }
}
pub fn cached_state<'surface>(&'surface self) -> Option<surface::State<'surface>> {
unsafe {
if (*self.subsurface.as_ptr()).has_cache {
None
} else {
Some(surface::State::new((*self.subsurface.as_ptr()).cached))
}
}
}
pub fn has_cache(&self) -> bool {
unsafe { (*self.subsurface.as_ptr()).has_cache }
}
pub fn synchronized(&self) -> bool {
unsafe { (*self.subsurface.as_ptr()).synchronized }
}
pub fn reordered(&self) -> bool {
unsafe { (*self.subsurface.as_ptr()).reordered }
}
}
impl Handleable<(), wlr_subsurface> for Subsurface {
#[doc(hidden)]
unsafe fn from_ptr(subsurface: *mut wlr_subsurface) -> Option<Self> {
let subsurface = NonNull::new(subsurface)?;
let data = (*subsurface.as_ptr()).data as *mut InternalSubsurface;
Some(Subsurface {liveliness: (*data).data.0.liveliness.clone(),
subsurface
})
}
#[doc(hidden)]
unsafe fn as_ptr(&self) -> *mut wlr_subsurface {
self.subsurface.as_ptr()
}
#[doc(hidden)]
unsafe fn from_handle(handle: &Handle) -> HandleResult<Self> {
let liveliness = handle.handle
.upgrade()
.ok_or_else(|| HandleErr::AlreadyDropped)?;
Ok(Subsurface { liveliness,
subsurface: handle.ptr })
}
fn weak_reference(&self) -> Handle {
Handle { ptr: self.subsurface,
handle: Rc::downgrade(&self.liveliness),
data: Some(()),
_marker: std::marker::PhantomData
}
}
}
impl Drop for InternalSubsurface {
fn drop(&mut self) {
unsafe {
ffi_dispatch!(WAYLAND_SERVER_HANDLE,
wl_list_remove,
&mut (*self.on_destroy_listener()).link as *mut _ as _);
}
}
}