use std::{cell::Cell, ptr::NonNull, rc::Rc};
use wlroots_sys::{wlr_input_device, wlr_touch};
use {input::{self, InputState},
utils::{self, Handleable, HandleErr, HandleResult}};
pub use manager::touch_handler::*;
pub use events::touch_events as event;
pub type Handle = utils::Handle<NonNull<wlr_input_device>, wlr_touch, Touch>;
#[derive(Debug)]
pub struct Touch {
liveliness: Rc<Cell<bool>>,
device: input::Device,
touch: NonNull<wlr_touch>
}
impl Touch {
pub(crate) unsafe fn new_from_input_device(device: *mut wlr_input_device) -> Option<Self> {
use wlroots_sys::wlr_input_device_type::*;
match (*device).type_ {
WLR_INPUT_DEVICE_TOUCH => {
let touch = NonNull::new((*device).__bindgen_anon_1.touch)
.expect("Touch pointer was null");
let liveliness = Rc::new(Cell::new(false));
let handle = Rc::downgrade(&liveliness);
let state = Box::new(InputState { handle,
device: input::Device::from_ptr(device) });
(*touch.as_ptr()).data = Box::into_raw(state) as *mut _;
Some(Touch { liveliness,
device: input::Device::from_ptr(device),
touch })
}
_ => None
}
}
pub fn input_device(&self) -> &input::Device {
&self.device
}
}
impl Drop for Touch {
fn drop(&mut self) {
if Rc::strong_count(&self.liveliness) == 1 {
wlr_log!(WLR_DEBUG, "Dropped Touch {:p}", self.touch.as_ptr());
unsafe {
let _ = Box::from_raw((*self.touch.as_ptr()).data as *mut input::Device);
}
let weak_count = Rc::weak_count(&self.liveliness);
if weak_count > 0 {
wlr_log!(WLR_DEBUG,
"Still {} weak pointers to Touch {:p}",
weak_count,
self.touch.as_ptr());
}
}
}
}
impl Handleable<NonNull<wlr_input_device>, wlr_touch> for Touch {
#[doc(hidden)]
unsafe fn from_ptr(touch: *mut wlr_touch) -> Option<Self> {
let touch = NonNull::new(touch)?;
let data = Box::from_raw((*touch.as_ptr()).data as *mut InputState);
let handle = data.handle.clone();
let device = data.device.clone();
(*touch.as_ptr()).data = Box::into_raw(data) as *mut _;
Some(Touch { liveliness: handle.upgrade().unwrap(),
device,
touch })
}
#[doc(hidden)]
unsafe fn as_ptr(&self) -> *mut wlr_touch {
self.touch.as_ptr()
}
#[doc(hidden)]
unsafe fn from_handle(handle: &Handle) -> HandleResult<Self> {
let liveliness = handle.handle
.upgrade()
.ok_or(HandleErr::AlreadyDropped)?;
let device = handle.data.ok_or(HandleErr::AlreadyDropped)?;
Ok(Touch { liveliness,
device: input::Device { device },
touch: handle.as_non_null()
})
}
fn weak_reference(&self) -> Handle {
Handle { ptr: self.touch,
handle: Rc::downgrade(&self.liveliness),
data: unsafe { Some(self.device.as_non_null()) },
_marker: std::marker::PhantomData
}
}
}