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