use libseat_sys as sys;
use errno::{errno, Errno};
use std::{
ffi::CString,
mem::MaybeUninit,
ops::{Deref, DerefMut},
os::unix::io::{AsFd, BorrowedFd, RawFd},
path::Path,
ptr::NonNull,
};
mod ffi_seat_listener;
use ffi_seat_listener::FFI_SEAT_LISTENER;
mod log;
pub use self::log::*;
#[cfg(feature = "custom_logger")]
mod log_handler;
#[derive(Debug, Clone, Copy)]
pub enum SeatEvent {
Enable,
Disable,
}
type SeatListenerCallback = dyn FnMut(&mut SeatRef, SeatEvent);
struct SeatListener {
callback: Box<SeatListenerCallback>,
}
impl std::fmt::Debug for SeatListener {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("UserSeatListener").finish()
}
}
#[derive(Debug)]
pub struct Seat {
inner: SeatRef,
_seat_listener: Box<SeatListener>,
}
impl Seat {
pub fn open<C>(callback: C) -> Result<Self, Errno>
where
C: FnMut(&mut SeatRef, SeatEvent) + 'static,
{
#[cfg(feature = "custom_logger")]
log_handler::init();
let user_listener = SeatListener {
callback: Box::new(callback),
};
let mut user_data = Box::new(user_listener);
let seat = unsafe {
sys::libseat_open_seat(&FFI_SEAT_LISTENER, user_data.as_mut() as *mut _ as _)
};
NonNull::new(seat)
.map(|nn| Self {
inner: SeatRef(nn),
_seat_listener: user_data,
})
.ok_or_else(errno)
}
}
impl Drop for Seat {
fn drop(&mut self) {
unsafe { sys::libseat_close_seat(self.0.as_mut()) };
}
}
impl Deref for Seat {
type Target = SeatRef;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for Seat {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
#[derive(Debug)]
pub struct SeatRef(NonNull<sys::libseat>);
impl SeatRef {
pub fn disable(&mut self) -> Result<(), Errno> {
if unsafe { sys::libseat_disable_seat(self.0.as_mut()) } == 0 {
Ok(())
} else {
Err(errno())
}
}
pub fn open_device<P: AsRef<Path>>(&mut self, path: &P) -> Result<Device, Errno> {
let path = path.as_ref();
let string = path.as_os_str().to_str().unwrap();
let cstring = CString::new(string).unwrap();
let mut fd = MaybeUninit::uninit();
let id =
unsafe { sys::libseat_open_device(self.0.as_mut(), cstring.as_ptr(), fd.as_mut_ptr()) };
if id != -1 {
Ok(Device {
id,
fd: unsafe { fd.assume_init() },
})
} else {
Err(errno())
}
}
pub fn close_device(&mut self, device: Device) -> Result<(), Errno> {
if unsafe { sys::libseat_close_device(self.0.as_mut(), device.id) } == 0 {
Ok(())
} else {
Err(errno())
}
}
pub fn name(&mut self) -> &str {
unsafe {
let cstr = sys::libseat_seat_name(self.0.as_mut());
let cstr = std::ffi::CStr::from_ptr(cstr as *const _);
cstr.to_str().unwrap()
}
}
pub fn switch_session(&mut self, session: i32) -> Result<(), Errno> {
if unsafe { sys::libseat_switch_session(self.0.as_mut(), session) } == 0 {
Ok(())
} else {
Err(errno())
}
}
pub fn get_fd(&mut self) -> Result<BorrowedFd<'_>, Errno> {
let fd = unsafe { sys::libseat_get_fd(self.0.as_mut()) };
if fd == -1 {
Err(errno())
} else {
Ok(unsafe { BorrowedFd::borrow_raw(fd) })
}
}
pub fn dispatch(&mut self, timeout: i32) -> Result<i32, Errno> {
let v = unsafe { sys::libseat_dispatch(self.0.as_mut(), timeout) };
if v == -1 {
Err(errno())
} else {
Ok(v)
}
}
}
#[derive(Debug)]
#[must_use]
pub struct Device {
id: i32,
fd: RawFd,
}
impl AsFd for Device {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe { BorrowedFd::borrow_raw(self.fd) }
}
}