1use libseat_sys as sys;
2
3use errno::{errno, Errno};
4
5use std::{
6 ffi::CString,
7 mem::MaybeUninit,
8 ops::{Deref, DerefMut},
9 os::unix::io::{AsFd, BorrowedFd, RawFd},
10 path::Path,
11 ptr::NonNull,
12};
13
14mod ffi_seat_listener;
15use ffi_seat_listener::FFI_SEAT_LISTENER;
16
17mod log;
18pub use self::log::*;
19
20#[cfg(feature = "custom_logger")]
21mod log_handler;
22
23#[derive(Debug, Clone, Copy)]
24pub enum SeatEvent {
25 Enable,
26 Disable,
27}
28
29type SeatListenerCallback = dyn FnMut(&mut SeatRef, SeatEvent);
30
31struct SeatListener {
32 callback: Box<SeatListenerCallback>,
33}
34
35impl std::fmt::Debug for SeatListener {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 f.debug_struct("UserSeatListener").finish()
38 }
39}
40
41#[derive(Debug)]
42pub struct Seat {
43 inner: SeatRef,
44 _seat_listener: Box<SeatListener>,
45}
46
47impl Seat {
48 pub fn open<C>(callback: C) -> Result<Self, Errno>
52 where
53 C: FnMut(&mut SeatRef, SeatEvent) + 'static,
54 {
55 #[cfg(feature = "custom_logger")]
56 log_handler::init();
57
58 let user_listener = SeatListener {
59 callback: Box::new(callback),
60 };
61
62 let mut user_data = Box::new(user_listener);
63
64 let seat = unsafe {
65 sys::libseat_open_seat(&FFI_SEAT_LISTENER, user_data.as_mut() as *mut _ as _)
66 };
67
68 NonNull::new(seat)
69 .map(|nn| Self {
70 inner: SeatRef(nn),
71 _seat_listener: user_data,
72 })
73 .ok_or_else(errno)
74 }
75}
76
77impl Drop for Seat {
78 fn drop(&mut self) {
79 unsafe { sys::libseat_close_seat(self.0.as_mut()) };
81 }
82}
83
84impl Deref for Seat {
85 type Target = SeatRef;
86
87 fn deref(&self) -> &Self::Target {
88 &self.inner
89 }
90}
91
92impl DerefMut for Seat {
93 fn deref_mut(&mut self) -> &mut Self::Target {
94 &mut self.inner
95 }
96}
97
98#[derive(Debug)]
99pub struct SeatRef(NonNull<sys::libseat>);
100
101impl SeatRef {
102 pub fn disable(&mut self) -> Result<(), Errno> {
106 if unsafe { sys::libseat_disable_seat(self.0.as_mut()) } == 0 {
107 Ok(())
108 } else {
109 Err(errno())
110 }
111 }
112
113 pub fn open_device<P: AsRef<Path>>(&mut self, path: &P) -> Result<Device, Errno> {
121 let path = path.as_ref();
122 let string = path.as_os_str().to_str().unwrap();
123 let cstring = CString::new(string).unwrap();
124
125 let mut fd = MaybeUninit::uninit();
126 let id =
127 unsafe { sys::libseat_open_device(self.0.as_mut(), cstring.as_ptr(), fd.as_mut_ptr()) };
128
129 if id != -1 {
130 Ok(Device {
131 id,
132 fd: unsafe { fd.assume_init() },
133 })
134 } else {
135 Err(errno())
136 }
137 }
138
139 pub fn close_device(&mut self, device: Device) -> Result<(), Errno> {
142 if unsafe { sys::libseat_close_device(self.0.as_mut(), device.id) } == 0 {
143 Ok(())
144 } else {
145 Err(errno())
146 }
147 }
148
149 pub fn name(&mut self) -> &str {
152 unsafe {
153 let cstr = sys::libseat_seat_name(self.0.as_mut());
154 let cstr = std::ffi::CStr::from_ptr(cstr as *const _);
155 cstr.to_str().unwrap()
156 }
157 }
158
159 pub fn switch_session(&mut self, session: i32) -> Result<(), Errno> {
166 if unsafe { sys::libseat_switch_session(self.0.as_mut(), session) } == 0 {
167 Ok(())
168 } else {
169 Err(errno())
170 }
171 }
172
173 pub fn get_fd(&mut self) -> Result<BorrowedFd<'_>, Errno> {
178 let fd = unsafe { sys::libseat_get_fd(self.0.as_mut()) };
179 if fd == -1 {
180 Err(errno())
181 } else {
182 Ok(unsafe { BorrowedFd::borrow_raw(fd) })
183 }
184 }
185
186 pub fn dispatch(&mut self, timeout: i32) -> Result<i32, Errno> {
196 let v = unsafe { sys::libseat_dispatch(self.0.as_mut(), timeout) };
197 if v == -1 {
198 Err(errno())
199 } else {
200 Ok(v)
201 }
202 }
203}
204
205#[derive(Debug)]
211#[must_use]
212pub struct Device {
213 id: i32,
214 fd: RawFd,
215}
216
217impl AsFd for Device {
218 fn as_fd(&self) -> BorrowedFd<'_> {
219 unsafe { BorrowedFd::borrow_raw(self.fd) }
220 }
221}