use std::{cell::Cell, ptr::NonNull, rc::Rc};
use wlroots_sys::{wlr_input_device, wlr_pointer};
use {input::{self, InputState},
utils::{self, Handleable, HandleErr, HandleResult}};
pub use manager::pointer_handler::*;
pub use events::pointer_events as event;
pub type Handle = utils::Handle<NonNull<wlr_input_device>, wlr_pointer, Pointer>;
#[derive(Debug)]
pub struct Pointer {
liveliness: Rc<Cell<bool>>,
device: input::Device,
pointer: NonNull<wlr_pointer>
}
impl Pointer {
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_POINTER => {
let pointer = NonNull::new((*device).__bindgen_anon_1.pointer)
.expect("Pointer 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) });
(*pointer.as_ptr()).data = Box::into_raw(state) as *mut _;
Some(Pointer { liveliness,
device: input::Device::from_ptr(device),
pointer })
}
_ => None
}
}
pub fn input_device(&self) -> &input::Device {
&self.device
}
#[allow(dead_code)]
pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_pointer {
self.pointer.as_ptr()
}
}
impl Drop for Pointer {
fn drop(&mut self) {
if Rc::strong_count(&self.liveliness) == 1 {
wlr_log!(WLR_DEBUG, "Dropped Pointer {:p}", self.pointer);
unsafe {
let _ = Box::from_raw((*self.pointer.as_ptr()).data as *mut InputState);
}
let weak_count = Rc::weak_count(&self.liveliness);
if weak_count > 0 {
wlr_log!(WLR_DEBUG,
"Still {} weak pointers to Pointer {:p}",
weak_count,
self.pointer);
}
}
}
}
impl Handleable<NonNull<wlr_input_device>, wlr_pointer> for Pointer {
#[doc(hidden)]
unsafe fn from_ptr(pointer: *mut wlr_pointer) -> Option<Self> {
let pointer = NonNull::new(pointer)?;
let data = Box::from_raw((*pointer.as_ptr()).data as *mut InputState);
let handle = data.handle.clone();
let device = data.device.clone();
(*pointer.as_ptr()).data = Box::into_raw(data) as *mut _;
Some(Pointer { liveliness: handle.upgrade().unwrap(),
device,
pointer })
}
#[doc(hidden)]
unsafe fn as_ptr(&self) -> *mut wlr_pointer {
self.pointer.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(Pointer { liveliness,
device: input::Device { device },
pointer: handle.as_non_null()
})
}
fn weak_reference(&self) -> Handle {
Handle { ptr: self.pointer,
handle: Rc::downgrade(&self.liveliness),
data: unsafe { Some(self.device.as_non_null()) },
_marker: std::marker::PhantomData
}
}
}