autocommit 2022-03-09 14:01:21 CET
This commit is contained in:
parent
aa0cb94143
commit
4df6b559b7
32 changed files with 1121 additions and 172 deletions
|
|
@ -15,6 +15,9 @@ mod pixman;
|
||||||
#[path = "../src/xkbcommon/consts.rs"]
|
#[path = "../src/xkbcommon/consts.rs"]
|
||||||
mod xkbcommon;
|
mod xkbcommon;
|
||||||
|
|
||||||
|
#[path = "../src/libinput/consts.rs"]
|
||||||
|
mod libinput;
|
||||||
|
|
||||||
fn get_target() -> repc::Target {
|
fn get_target() -> repc::Target {
|
||||||
let rustc_target = env::var("TARGET").unwrap();
|
let rustc_target = env::var("TARGET").unwrap();
|
||||||
repc::TARGET_MAP
|
repc::TARGET_MAP
|
||||||
|
|
@ -193,6 +196,67 @@ fn write_egl_procs<W: Write>(f: &mut W) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() -> anyhow::Result<()> {
|
pub fn main() -> anyhow::Result<()> {
|
||||||
|
let mut f = open("libinput_tys.rs")?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_LOG_PRIORITY,
|
||||||
|
"libinput_log_priority",
|
||||||
|
)?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_DEVICE_CAPABILITY,
|
||||||
|
"libinput_device_capability",
|
||||||
|
)?;
|
||||||
|
write_ty(&mut f, libinput::LIBINPUT_KEY_STATE, "libinput_key_state")?;
|
||||||
|
write_ty(&mut f, libinput::LIBINPUT_LED, "libinput_led")?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_BUTTON_STATE,
|
||||||
|
"libinput_button_state",
|
||||||
|
)?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_POINTER_AXIS,
|
||||||
|
"libinput_pointer_axis",
|
||||||
|
)?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_POINTER_AXIS_SOURCE,
|
||||||
|
"libinput_pointer_axis_source",
|
||||||
|
)?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_TABLET_PAD_RING_AXIS_SOURCE,
|
||||||
|
"libinput_tablet_pad_ring_axis_source",
|
||||||
|
)?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_TABLET_PAD_STRIP_AXIS_SOURCE,
|
||||||
|
"libinput_tablet_pad_strip_axis_source",
|
||||||
|
)?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_TABLET_TOOL_TYPE,
|
||||||
|
"libinput_tablet_tool_type",
|
||||||
|
)?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_TABLET_TOOL_PROXIMITY_STATE,
|
||||||
|
"libinput_tablet_tool_proximity_state",
|
||||||
|
)?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_TABLET_TOOL_TIP_STATE,
|
||||||
|
"libinput_tablet_tool_tip_state",
|
||||||
|
)?;
|
||||||
|
write_ty(
|
||||||
|
&mut f,
|
||||||
|
libinput::LIBINPUT_SWITCH_STATE,
|
||||||
|
"libinput_switch_state",
|
||||||
|
)?;
|
||||||
|
write_ty(&mut f, libinput::LIBINPUT_SWITCH, "libinput_switch")?;
|
||||||
|
write_ty(&mut f, libinput::LIBINPUT_EVENT_TYPE, "libinput_event_type")?;
|
||||||
|
|
||||||
let mut f = open("pixman_tys.rs")?;
|
let mut f = open("pixman_tys.rs")?;
|
||||||
write_ty(&mut f, pixman::FORMATS, "PixmanFormat")?;
|
write_ty(&mut f, pixman::FORMATS, "PixmanFormat")?;
|
||||||
write_ty(&mut f, pixman::OPS, "PixmanOp")?;
|
write_ty(&mut f, pixman::OPS, "PixmanOp")?;
|
||||||
|
|
|
||||||
|
|
@ -13,23 +13,23 @@ pub enum AcceptorError {
|
||||||
#[error("XDG_RUNTIME_DIR ({0:?}) is too long to form a unix socket address")]
|
#[error("XDG_RUNTIME_DIR ({0:?}) is too long to form a unix socket address")]
|
||||||
XrdTooLong(String),
|
XrdTooLong(String),
|
||||||
#[error("Could not create a wayland socket")]
|
#[error("Could not create a wayland socket")]
|
||||||
SocketFailed(#[source] std::io::Error),
|
SocketFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not stat the existing socket")]
|
#[error("Could not stat the existing socket")]
|
||||||
SocketStat(#[source] std::io::Error),
|
SocketStat(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not start listening for incoming connections")]
|
#[error("Could not start listening for incoming connections")]
|
||||||
ListenFailed(#[source] std::io::Error),
|
ListenFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not open the lock file")]
|
#[error("Could not open the lock file")]
|
||||||
OpenLockFile(#[source] std::io::Error),
|
OpenLockFile(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not lock the lock file")]
|
#[error("Could not lock the lock file")]
|
||||||
LockLockFile(#[source] std::io::Error),
|
LockLockFile(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("The wayland socket is in an error state")]
|
#[error("The wayland socket is in an error state")]
|
||||||
ErrorEvent,
|
ErrorEvent,
|
||||||
#[error("Could not accept new connections")]
|
#[error("Could not accept new connections")]
|
||||||
AcceptFailed(#[source] std::io::Error),
|
AcceptFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not spawn an event handler for a new connection")]
|
#[error("Could not spawn an event handler for a new connection")]
|
||||||
SpawnFailed(#[source] ClientError),
|
SpawnFailed(#[source] ClientError),
|
||||||
#[error("Could not bind the socket to an address")]
|
#[error("Could not bind the socket to an address")]
|
||||||
BindFailed(#[source] std::io::Error),
|
BindFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("All wayland addresses in the range 0..1000 are already in use")]
|
#[error("All wayland addresses in the range 0..1000 are already in use")]
|
||||||
AddressesInUse,
|
AddressesInUse,
|
||||||
#[error("The event loop caused an error")]
|
#[error("The event loop caused an error")]
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ use crate::event_loop::{EventLoop, EventLoopError};
|
||||||
use crate::utils::copyhashmap::CopyHashMap;
|
use crate::utils::copyhashmap::CopyHashMap;
|
||||||
use crate::utils::numcell::NumCell;
|
use crate::utils::numcell::NumCell;
|
||||||
use crate::wheel::{Wheel, WheelError};
|
use crate::wheel::{Wheel, WheelError};
|
||||||
pub use fd::{AsyncFd, FdStatus};
|
|
||||||
use fd::AsyncFdData;
|
use fd::AsyncFdData;
|
||||||
|
pub use fd::{AsyncFd, FdStatus};
|
||||||
use queue::{DispatchQueue, Dispatcher};
|
use queue::{DispatchQueue, Dispatcher};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
@ -562,7 +562,10 @@ mod fd {
|
||||||
let res = self.el.modify(self.id, events);
|
let res = self.el.modify(self.id, events);
|
||||||
if res.is_err() {
|
if res.is_err() {
|
||||||
if let Err(e) = self.el.remove(self.id) {
|
if let Err(e) = self.el.remove(self.id) {
|
||||||
log::error!("Fatal error: Cannot remove file descriptor from event loop: {:?}", e);
|
log::error!(
|
||||||
|
"Fatal error: Cannot remove file descriptor from event loop: {:?}",
|
||||||
|
e
|
||||||
|
);
|
||||||
self.el.stop();
|
self.el.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,19 @@
|
||||||
|
mod input;
|
||||||
|
mod monitor;
|
||||||
|
|
||||||
|
use crate::async_engine::AsyncFd;
|
||||||
use crate::dbus::DbusError;
|
use crate::dbus::DbusError;
|
||||||
|
use crate::libinput::device::RegisteredDevice;
|
||||||
|
use crate::libinput::{LibInput, LibInputAdapter, LibInputError};
|
||||||
use crate::logind::{LogindError, Session};
|
use crate::logind::{LogindError, Session};
|
||||||
use crate::{AsyncQueue, ErrorFmt, State, Udev};
|
use crate::udev::{UdevError, UdevMonitor};
|
||||||
|
use crate::utils::copyhashmap::CopyHashMap;
|
||||||
|
use crate::{AsyncQueue, CloneCell, ErrorFmt, NumCell, State, Udev};
|
||||||
|
use std::cell::{Cell, RefCell};
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use uapi::OwnedFd;
|
use uapi::{c, OwnedFd};
|
||||||
use crate::async_engine::{AsyncFd, FdStatus};
|
|
||||||
use crate::libinput::{LibInput, LibInputError};
|
|
||||||
use crate::udev::{UdevError, UdevMonitor};
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum MetalError {
|
pub enum MetalError {
|
||||||
|
|
@ -16,12 +23,14 @@ pub enum MetalError {
|
||||||
LogindSession(#[source] LogindError),
|
LogindSession(#[source] LogindError),
|
||||||
#[error("Could not take control of the logind session")]
|
#[error("Could not take control of the logind session")]
|
||||||
TakeControl(#[source] LogindError),
|
TakeControl(#[source] LogindError),
|
||||||
|
#[error("Could not enumerate devices")]
|
||||||
|
Enumerate(#[source] Box<Self>),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Udev(#[from] UdevError),
|
Udev(#[from] UdevError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
LibInput(#[from] LibInputError),
|
LibInput(#[from] LibInputError),
|
||||||
#[error("Dupfd failed")]
|
#[error("Dupfd failed")]
|
||||||
Dup(#[source] std::io::Error),
|
Dup(#[source] crate::utils::oserror::OsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(state: Rc<State>) {
|
pub async fn run(state: Rc<State>) {
|
||||||
|
|
@ -30,6 +39,18 @@ pub async fn run(state: Rc<State>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MetalBackend {
|
||||||
|
state: Rc<State>,
|
||||||
|
udev: Rc<Udev>,
|
||||||
|
monitor: Rc<UdevMonitor>,
|
||||||
|
monitor_fd: AsyncFd,
|
||||||
|
libinput: Rc<LibInput>,
|
||||||
|
libinput_fd: AsyncFd,
|
||||||
|
device_holder: Rc<DeviceHolder>,
|
||||||
|
session: Session,
|
||||||
|
ids: NumCell<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
async fn run_(state: Rc<State>) -> Result<(), MetalError> {
|
async fn run_(state: Rc<State>) -> Result<(), MetalError> {
|
||||||
let socket = match state.dbus.system() {
|
let socket = match state.dbus.system() {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
|
|
@ -39,90 +60,83 @@ async fn run_(state: Rc<State>) -> Result<(), MetalError> {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => return Err(MetalError::LogindSession(e)),
|
Err(e) => return Err(MetalError::LogindSession(e)),
|
||||||
};
|
};
|
||||||
// if let Err(e) = session.take_control().await {
|
if let Err(e) = session.take_control().await {
|
||||||
// return Err(MetalError::TakeControl(e));
|
return Err(MetalError::TakeControl(e));
|
||||||
// }
|
}
|
||||||
|
let device_holder = Rc::new(DeviceHolder {
|
||||||
|
input_devices: Default::default(),
|
||||||
|
input_devices_: Default::default(),
|
||||||
|
});
|
||||||
let udev = Rc::new(Udev::new()?);
|
let udev = Rc::new(Udev::new()?);
|
||||||
let monitor = Rc::new(udev.create_monitor()?);
|
let monitor = Rc::new(udev.create_monitor()?);
|
||||||
monitor.add_match_subsystem_devtype(Some("input"), None)?;
|
monitor.add_match_subsystem_devtype(Some("input"), None)?;
|
||||||
monitor.enable_receiving()?;
|
monitor.enable_receiving()?;
|
||||||
let libinput = Rc::new(LibInput::new()?);
|
let libinput = Rc::new(LibInput::new(device_holder.clone())?);
|
||||||
let monitor_fd = match uapi::fcntl_dupfd_cloexec(monitor.fd(), 0) {
|
let monitor_fd = match uapi::fcntl_dupfd_cloexec(monitor.fd(), 0) {
|
||||||
Ok(m) => state.eng.fd(&Rc::new(m)).unwrap(),
|
Ok(m) => state.eng.fd(&Rc::new(m)).unwrap(),
|
||||||
Err(e) => return Err(MetalError::Dup(e.into())),
|
Err(e) => return Err(MetalError::Dup(e.into())),
|
||||||
};
|
};
|
||||||
|
let libinput_fd = match uapi::fcntl_dupfd_cloexec(libinput.fd(), 0) {
|
||||||
|
Ok(m) => state.eng.fd(&Rc::new(m)).unwrap(),
|
||||||
|
Err(e) => return Err(MetalError::Dup(e.into())),
|
||||||
|
};
|
||||||
let metal = Rc::new(MetalBackend {
|
let metal = Rc::new(MetalBackend {
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
udev,
|
udev,
|
||||||
monitor,
|
monitor,
|
||||||
monitor_fd,
|
monitor_fd,
|
||||||
libinput,
|
libinput,
|
||||||
|
libinput_fd,
|
||||||
|
device_holder,
|
||||||
|
session,
|
||||||
|
ids: Default::default(),
|
||||||
});
|
});
|
||||||
let _monitor = state.eng.spawn(metal.clone().monitor_devices());
|
let _monitor = state.eng.spawn(metal.clone().monitor_devices());
|
||||||
let mut queue = AsyncQueue::<String>::new();
|
let _events = state.eng.spawn(metal.clone().handle_libinput_events());
|
||||||
|
if let Err(e) = metal.enumerate_devices() {
|
||||||
|
return Err(MetalError::Enumerate(Box::new(e)));
|
||||||
|
}
|
||||||
|
let queue = AsyncQueue::<String>::new();
|
||||||
queue.pop().await;
|
queue.pop().await;
|
||||||
Ok(())
|
Ok(())
|
||||||
// let libinput_fd = match uapi::fcntl_dupfd_cloexec(monitor.fd(), 0) {
|
|
||||||
// Ok(m) => m,
|
|
||||||
// Err(e) => Err(MetalError::Dup(e.into())),
|
|
||||||
// };
|
|
||||||
// let mut enumerate = udev.create_enumerate()?;
|
|
||||||
// enumerate.add_match_subsystem("input")?;
|
|
||||||
// enumerate.scan_devices()?;
|
|
||||||
// let mut entry_opt = enumerate.get_list_entry()?;
|
|
||||||
// while let Some(entry) = entry_opt {
|
|
||||||
// let device = udev.create_device_from_syspath(entry.name()?)?;
|
|
||||||
// if device.sysname()?.to_bytes().starts_with(b"event") {
|
|
||||||
// let devnode = device.devnode()?;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MetalBackend {
|
struct MetalDevice {
|
||||||
state: Rc<State>,
|
slot: usize,
|
||||||
udev: Rc<Udev>,
|
device_id: u64,
|
||||||
monitor: Rc<UdevMonitor>,
|
devnum: c::dev_t,
|
||||||
monitor_fd: AsyncFd,
|
fd: CloneCell<Option<Rc<OwnedFd>>>,
|
||||||
libinput: Rc<LibInput>,
|
inputdev: Cell<Option<RegisteredDevice>>,
|
||||||
libinput_fd: AsyncFd,
|
devnode: CString,
|
||||||
|
sysname: CString,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DeviceHolder {
|
||||||
|
input_devices: CopyHashMap<c::dev_t, Rc<MetalDevice>>,
|
||||||
|
input_devices_: RefCell<Vec<Option<Rc<MetalDevice>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LibInputAdapter for DeviceHolder {
|
||||||
|
fn open(&self, path: &CStr) -> Result<OwnedFd, LibInputError> {
|
||||||
|
let stat = match uapi::stat(path) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => return Err(LibInputError::Stat(e.into())),
|
||||||
|
};
|
||||||
|
match self.input_devices.get(&stat.st_rdev) {
|
||||||
|
Some(d) => match d.fd.get() {
|
||||||
|
Some(fd) => match uapi::fcntl_dupfd_cloexec(fd.raw(), 0) {
|
||||||
|
Ok(fd) => Ok(fd),
|
||||||
|
Err(e) => Err(LibInputError::DupFd(e.into())),
|
||||||
|
},
|
||||||
|
_ => Err(LibInputError::DeviceUnavailable),
|
||||||
|
},
|
||||||
|
_ => Err(LibInputError::DeviceUnavailable),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetalBackend {
|
impl MetalBackend {
|
||||||
async fn monitor_devices(self: Rc<Self>) {
|
fn id(&self) -> u64 {
|
||||||
loop {
|
self.ids.fetch_add(1)
|
||||||
match self.monitor_fd.readable().await {
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Cannot wait for udev_monitor to become readable: {}", ErrorFmt(e));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Ok(FdStatus::Err) => {
|
|
||||||
log::error!("udev_monitor fd is in an error state");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ => { },
|
|
||||||
}
|
|
||||||
while let Some(dev) = self.monitor.receive_device() {
|
|
||||||
log::info!("x {:?}", dev.devnode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log::error!("Monitor task exited. Future hotplug events will be ignored.");
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_libinput_events(self: Rc<Self>) {
|
|
||||||
loop {
|
|
||||||
match self.libinput_fd.readable().await {
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Cannot wait for udev_monitor to become readable: {}", ErrorFmt(e));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Ok(FdStatus::Err) => {
|
|
||||||
log::error!("udev_monitor fd is in an error state");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ => { },
|
|
||||||
}
|
|
||||||
self.libinput.fd()
|
|
||||||
}
|
|
||||||
log::error!("Monitor task exited. Future hotplug events will be ignored.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
55
src/backends/metal/input.rs
Normal file
55
src/backends/metal/input.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
use crate::async_engine::FdStatus;
|
||||||
|
use crate::libinput::consts::LIBINPUT_EVENT_KEYBOARD_KEY;
|
||||||
|
use crate::libinput::event::LibInputEvent;
|
||||||
|
use crate::metal::MetalBackend;
|
||||||
|
use crate::ErrorFmt;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
impl MetalBackend {
|
||||||
|
pub async fn handle_libinput_events(self: Rc<Self>) {
|
||||||
|
loop {
|
||||||
|
match self.libinput_fd.readable().await {
|
||||||
|
Err(e) => {
|
||||||
|
log::error!(
|
||||||
|
"Cannot wait for libinput fd to become readable: {}",
|
||||||
|
ErrorFmt(e)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Ok(FdStatus::Err) => {
|
||||||
|
log::error!("libinput fd fd is in an error state");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if let Err(e) = self.libinput.dispatch() {
|
||||||
|
log::error!("Could not dispatch libinput events: {}", ErrorFmt(e));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while let Some(event) = self.libinput.event() {
|
||||||
|
self.handle_event(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log::error!("Libinput task exited. Future input events will be ignored.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(self: &Rc<Self>, event: LibInputEvent) {
|
||||||
|
match event.ty() {
|
||||||
|
LIBINPUT_EVENT_KEYBOARD_KEY => self.handle_keyboard_event(event),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_keyboard_event(self: &Rc<Self>, event: LibInputEvent) {
|
||||||
|
let event = match event.keyboard_event() {
|
||||||
|
Some(event) => event,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
log::info!(
|
||||||
|
"key: {}, state: {:?}, time: {}",
|
||||||
|
event.key(),
|
||||||
|
event.key_state(),
|
||||||
|
event.time_usec()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
131
src/backends/metal/monitor.rs
Normal file
131
src/backends/metal/monitor.rs
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
use crate::async_engine::FdStatus;
|
||||||
|
use crate::dbus::TRUE;
|
||||||
|
use crate::metal::{MetalBackend, MetalDevice, MetalError};
|
||||||
|
use crate::udev::UdevDevice;
|
||||||
|
use crate::ErrorFmt;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
impl MetalBackend {
|
||||||
|
pub async fn monitor_devices(self: Rc<Self>) {
|
||||||
|
loop {
|
||||||
|
match self.monitor_fd.readable().await {
|
||||||
|
Err(e) => {
|
||||||
|
log::error!(
|
||||||
|
"Cannot wait for udev_monitor to become readable: {}",
|
||||||
|
ErrorFmt(e)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Ok(FdStatus::Err) => {
|
||||||
|
log::error!("udev_monitor fd is in an error state");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
while let Some(dev) = self.monitor.receive_device() {
|
||||||
|
log::info!("x {:?}", dev.devnode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log::error!("Monitor task exited. Future hotplug events will be ignored.");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enumerate_devices(self: &Rc<Self>) -> Result<(), MetalError> {
|
||||||
|
let mut enumerate = self.udev.create_enumerate()?;
|
||||||
|
enumerate.add_match_subsystem("input")?;
|
||||||
|
enumerate.scan_devices()?;
|
||||||
|
let mut entry_opt = enumerate.get_list_entry()?;
|
||||||
|
while let Some(entry) = entry_opt.take() {
|
||||||
|
'inner: {
|
||||||
|
let device = match self.udev.create_device_from_syspath(entry.name()) {
|
||||||
|
Ok(d) => d,
|
||||||
|
_ => break 'inner,
|
||||||
|
};
|
||||||
|
let sysname = match device.sysname() {
|
||||||
|
Ok(s) => s,
|
||||||
|
_ => break 'inner,
|
||||||
|
};
|
||||||
|
if sysname.to_bytes().starts_with(b"event") {
|
||||||
|
self.add_input_device(&device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry_opt = entry.next();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_input_device(self: &Rc<Self>, dev: &UdevDevice) {
|
||||||
|
let slf = self.clone();
|
||||||
|
let device_id = self.id();
|
||||||
|
let devnum = dev.devnum();
|
||||||
|
let devnode = match dev.devnode() {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Could not retrieve devnode of udev device: {}", ErrorFmt(e));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let sysname = match dev.sysname() {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Could not retrieve sysname of udev device: {}", ErrorFmt(e));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut slots = self.device_holder.input_devices_.borrow_mut();
|
||||||
|
let slot = 'slot: {
|
||||||
|
for (i, s) in slots.iter().enumerate() {
|
||||||
|
if s.is_none() {
|
||||||
|
break 'slot i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slots.push(None);
|
||||||
|
slots.len() - 1
|
||||||
|
};
|
||||||
|
let dev = Rc::new(MetalDevice {
|
||||||
|
slot,
|
||||||
|
device_id,
|
||||||
|
devnum,
|
||||||
|
fd: Default::default(),
|
||||||
|
inputdev: Default::default(),
|
||||||
|
devnode: devnode.to_owned(),
|
||||||
|
sysname: sysname.to_owned(),
|
||||||
|
});
|
||||||
|
slots[slot] = Some(dev.clone());
|
||||||
|
self.device_holder.input_devices.set(devnum, dev);
|
||||||
|
self.session.get_device(devnum, move |res| {
|
||||||
|
let id = &slf.device_holder.input_devices;
|
||||||
|
let mut slots = slf.device_holder.input_devices_.borrow_mut();
|
||||||
|
let dev = 'dev: {
|
||||||
|
if let Some(dev) = id.get(&devnum) {
|
||||||
|
if dev.device_id == device_id {
|
||||||
|
break 'dev dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let res = match res {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Could not take control of input device: {}", ErrorFmt(e));
|
||||||
|
slots[dev.slot] = None;
|
||||||
|
id.remove(&devnum);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if res.inactive == TRUE {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dev.fd.set(Some(res.fd.clone()));
|
||||||
|
let inputdev = match slf.libinput.open(dev.devnode.as_c_str()) {
|
||||||
|
Ok(d) => d,
|
||||||
|
Err(_) => {
|
||||||
|
slots[dev.slot] = None;
|
||||||
|
id.remove(&devnum);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
inputdev.device().set_slot(slot);
|
||||||
|
dev.inputdev.set(Some(inputdev));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -87,7 +87,7 @@ impl Clients {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Cannot determine peer credentials of new connection: {:?}",
|
"Cannot determine peer credentials of new connection: {:?}",
|
||||||
std::io::Error::from(e)
|
crate::utils::oserror::OsError::from(e)
|
||||||
);
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,11 @@ use uapi::c::raise;
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ClientMemError {
|
pub enum ClientMemError {
|
||||||
#[error("Could not install the sigbus handler")]
|
#[error("Could not install the sigbus handler")]
|
||||||
SigactionFailed(#[source] std::io::Error),
|
SigactionFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("A SIGBUS occurred while accessing mapped memory")]
|
#[error("A SIGBUS occurred while accessing mapped memory")]
|
||||||
Sigbus,
|
Sigbus,
|
||||||
#[error("mmap failed")]
|
#[error("mmap failed")]
|
||||||
MmapFailed(#[source] std::io::Error),
|
MmapFailed(#[source] crate::utils::oserror::OsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClientMem {
|
pub struct ClientMem {
|
||||||
|
|
|
||||||
|
|
@ -67,13 +67,13 @@ pub enum DbusError {
|
||||||
#[error("Variant has an invalid type")]
|
#[error("Variant has an invalid type")]
|
||||||
InvalidVariantType,
|
InvalidVariantType,
|
||||||
#[error("Could not create a socket")]
|
#[error("Could not create a socket")]
|
||||||
Socket(#[source] std::io::Error),
|
Socket(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not connect")]
|
#[error("Could not connect")]
|
||||||
Connect(#[source] std::io::Error),
|
Connect(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not write to the dbus socket")]
|
#[error("Could not write to the dbus socket")]
|
||||||
WriteError(#[source] std::io::Error),
|
WriteError(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not read from the dbus socket")]
|
#[error("Could not read from the dbus socket")]
|
||||||
ReadError(#[source] std::io::Error),
|
ReadError(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("timeout")]
|
#[error("timeout")]
|
||||||
AsyncError(#[source] Box<AsyncError>),
|
AsyncError(#[source] Box<AsyncError>),
|
||||||
#[error("Server did not accept our authentication")]
|
#[error("Server did not accept our authentication")]
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,11 @@ impl Outgoing {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Err(e) = self.socket.fd.writable().await {
|
if let Err(e) = self.socket.fd.writable().await {
|
||||||
log::error!("{}: Cannot wait for fd to become readable: {}", self.socket.bus_name, ErrorFmt(e));
|
log::error!(
|
||||||
|
"{}: Cannot wait for fd to become readable: {}",
|
||||||
|
self.socket.bus_name,
|
||||||
|
ErrorFmt(e)
|
||||||
|
);
|
||||||
self.socket.kill();
|
self.socket.kill();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@ use uapi::{c, Errno, OwnedFd, Ustring};
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum DrmError {
|
pub enum DrmError {
|
||||||
#[error("Could not reopen a node")]
|
#[error("Could not reopen a node")]
|
||||||
ReopenNode(#[source] std::io::Error),
|
ReopenNode(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not retrieve the render node name")]
|
#[error("Could not retrieve the render node name")]
|
||||||
RenderNodeName,
|
RenderNodeName,
|
||||||
#[error("Could not retrieve the device node name")]
|
#[error("Could not retrieve the device node name")]
|
||||||
DeviceNodeName,
|
DeviceNodeName,
|
||||||
#[error("Could not retrieve device")]
|
#[error("Could not retrieve device")]
|
||||||
GetDevice(#[source] std::io::Error),
|
GetDevice(#[source] crate::utils::oserror::OsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,17 @@ use uapi::{c, Errno, OwnedFd};
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum EventLoopError {
|
pub enum EventLoopError {
|
||||||
#[error("Could not create an epoll fd: {0}")]
|
#[error("Could not create an epoll fd: {0}")]
|
||||||
CreateFailed(std::io::Error),
|
CreateFailed(crate::utils::oserror::OsError),
|
||||||
#[error("epoll_wait failed: {0}")]
|
#[error("epoll_wait failed: {0}")]
|
||||||
WaitFailed(std::io::Error),
|
WaitFailed(crate::utils::oserror::OsError),
|
||||||
#[error("A dispatcher returned a fatal error: {0}")]
|
#[error("A dispatcher returned a fatal error: {0}")]
|
||||||
DispatcherError(Box<dyn std::error::Error>),
|
DispatcherError(Box<dyn std::error::Error>),
|
||||||
#[error("Could not insert an fd to wait on: {0}")]
|
#[error("Could not insert an fd to wait on: {0}")]
|
||||||
InsertFailed(std::io::Error),
|
InsertFailed(crate::utils::oserror::OsError),
|
||||||
#[error("Could not modify an fd to wait on: {0}")]
|
#[error("Could not modify an fd to wait on: {0}")]
|
||||||
ModifyFailed(std::io::Error),
|
ModifyFailed(crate::utils::oserror::OsError),
|
||||||
#[error("Could not remove an fd to wait on: {0}")]
|
#[error("Could not remove an fd to wait on: {0}")]
|
||||||
RemoveFailed(std::io::Error),
|
RemoveFailed(crate::utils::oserror::OsError),
|
||||||
#[error("Entry is not registered")]
|
#[error("Entry is not registered")]
|
||||||
NoEntry,
|
NoEntry,
|
||||||
#[error("Event loop is already destroyed")]
|
#[error("Event loop is already destroyed")]
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,9 @@ struct PidfdHandoff {
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ForkerError {
|
pub enum ForkerError {
|
||||||
#[error("Could not create a socketpair")]
|
#[error("Could not create a socketpair")]
|
||||||
Socketpair(#[source] std::io::Error),
|
Socketpair(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not fork")]
|
#[error("Could not fork")]
|
||||||
Fork(#[source] std::io::Error),
|
Fork(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not read the next message")]
|
#[error("Could not read the next message")]
|
||||||
ReadFailed(#[source] BufFdError),
|
ReadFailed(#[source] BufFdError),
|
||||||
#[error("Could not write the next message")]
|
#[error("Could not write the next message")]
|
||||||
|
|
@ -235,7 +235,10 @@ impl ForkerProxy {
|
||||||
async fn check_process(self: Rc<Self>, state: Rc<State>) {
|
async fn check_process(self: Rc<Self>, state: Rc<State>) {
|
||||||
let pidfd = state.eng.fd(&self.pidfd).unwrap();
|
let pidfd = state.eng.fd(&self.pidfd).unwrap();
|
||||||
if let Err(e) = pidfd.readable().await {
|
if let Err(e) = pidfd.readable().await {
|
||||||
log::error!("Cannot wait for the forker pidfd to become readable: {}", ErrorFmt(e));
|
log::error!(
|
||||||
|
"Cannot wait for the forker pidfd to become readable: {}",
|
||||||
|
ErrorFmt(e)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
let _ = uapi::waitpid(self.pid, 0);
|
let _ = uapi::waitpid(self.pid, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -417,7 +420,10 @@ impl Forker {
|
||||||
let spawn = self.ae.spawn(async move {
|
let spawn = self.ae.spawn(async move {
|
||||||
let read = slf.ae.fd(&Rc::new(read)).unwrap();
|
let read = slf.ae.fd(&Rc::new(read)).unwrap();
|
||||||
if let Err(e) = read.readable().await {
|
if let Err(e) = read.readable().await {
|
||||||
log::error!("Cannot wait for the child fd to become readable: {}", ErrorFmt(e));
|
log::error!(
|
||||||
|
"Cannot wait for the child fd to become readable: {}",
|
||||||
|
ErrorFmt(e)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
let _ = Fd::new(read.raw()).read_to_string(&mut s);
|
let _ = Fd::new(read.raw()).read_to_string(&mut s);
|
||||||
|
|
@ -476,9 +482,9 @@ impl Forker {
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
enum SpawnError {
|
enum SpawnError {
|
||||||
#[error("exec failed")]
|
#[error("exec failed")]
|
||||||
Exec(#[source] std::io::Error),
|
Exec(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not unset cloexec flag")]
|
#[error("Could not unset cloexec flag")]
|
||||||
Cloexec(#[source] std::io::Error),
|
Cloexec(#[source] crate::utils::oserror::OsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_fds(mut socket: OwnedFd) -> OwnedFd {
|
fn setup_fds(mut socket: OwnedFd) -> OwnedFd {
|
||||||
|
|
|
||||||
|
|
@ -125,9 +125,9 @@ pub enum WlKeyboardError {
|
||||||
#[error("Could not process a `release` request")]
|
#[error("Could not process a `release` request")]
|
||||||
ReleaseError(#[from] ReleaseError),
|
ReleaseError(#[from] ReleaseError),
|
||||||
#[error("Could not create a keymap memfd")]
|
#[error("Could not create a keymap memfd")]
|
||||||
KeymapMemfd(#[source] std::io::Error),
|
KeymapMemfd(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not copy the keymap")]
|
#[error("Could not copy the keymap")]
|
||||||
KeymapCopy(#[source] std::io::Error),
|
KeymapCopy(#[source] crate::utils::oserror::OsError),
|
||||||
}
|
}
|
||||||
efrom!(WlKeyboardError, ClientError, ClientError);
|
efrom!(WlKeyboardError, ClientError, ClientError);
|
||||||
|
|
||||||
|
|
|
||||||
157
src/libinput.rs
157
src/libinput.rs
|
|
@ -1,31 +1,31 @@
|
||||||
use crate::udev::Udev;
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
pub mod consts;
|
||||||
|
pub mod device;
|
||||||
|
pub mod event;
|
||||||
|
mod sys;
|
||||||
|
|
||||||
|
use crate::libinput::consts::{
|
||||||
|
LogPriority, LIBINPUT_LOG_PRIORITY_DEBUG, LIBINPUT_LOG_PRIORITY_ERROR,
|
||||||
|
LIBINPUT_LOG_PRIORITY_INFO,
|
||||||
|
};
|
||||||
|
use crate::libinput::device::RegisteredDevice;
|
||||||
|
use crate::libinput::event::LibInputEvent;
|
||||||
|
use crate::libinput::sys::{
|
||||||
|
libinput, libinput_device_ref, libinput_dispatch, libinput_get_event, libinput_get_fd,
|
||||||
|
libinput_interface, libinput_log_priority, libinput_log_set_handler, libinput_log_set_priority,
|
||||||
|
libinput_path_add_device, libinput_path_create_context, libinput_unref,
|
||||||
|
};
|
||||||
|
use crate::udev::UdevError;
|
||||||
|
use crate::utils::oserror::OsError;
|
||||||
use crate::utils::ptr_ext::PtrExt;
|
use crate::utils::ptr_ext::PtrExt;
|
||||||
use std::ops::DerefMut;
|
use crate::utils::vasprintf::vasprintf_;
|
||||||
|
use crate::ErrorFmt;
|
||||||
|
use bstr::ByteSlice;
|
||||||
|
use std::ffi::{CStr, VaList};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use uapi::{c, OwnedFd};
|
use uapi::{c, Errno, IntoUstr, OwnedFd};
|
||||||
|
|
||||||
#[link(name = "input")]
|
|
||||||
extern "C" {
|
|
||||||
type libinput;
|
|
||||||
|
|
||||||
fn libinput_path_create_context(
|
|
||||||
interface: *const libinput_interface,
|
|
||||||
user_data: *mut c::c_void,
|
|
||||||
) -> *mut libinput;
|
|
||||||
fn libinput_unref(libinput: *mut libinput) -> *mut libinput;
|
|
||||||
fn libinput_get_fd(libinput: *mut libinput) -> c::c_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
struct libinput_interface {
|
|
||||||
open_restricted: unsafe extern "C" fn(
|
|
||||||
path: *const c::c_char,
|
|
||||||
flags: c::c_int,
|
|
||||||
user_data: *mut c::c_void,
|
|
||||||
) -> c::c_int,
|
|
||||||
close_restricted: unsafe extern "C" fn(fd: c::c_int, user_data: *mut c::c_void),
|
|
||||||
}
|
|
||||||
|
|
||||||
static INTERFACE: libinput_interface = libinput_interface {
|
static INTERFACE: libinput_interface = libinput_interface {
|
||||||
open_restricted,
|
open_restricted,
|
||||||
|
|
@ -34,23 +34,47 @@ static INTERFACE: libinput_interface = libinput_interface {
|
||||||
|
|
||||||
unsafe extern "C" fn open_restricted(
|
unsafe extern "C" fn open_restricted(
|
||||||
path: *const c::c_char,
|
path: *const c::c_char,
|
||||||
flags: c::c_int,
|
_flags: c::c_int,
|
||||||
user_data: *mut c::c_void,
|
user_data: *mut c::c_void,
|
||||||
) -> c::c_int {
|
) -> c::c_int {
|
||||||
let ud = (user_data as *const UserData).deref();
|
let ud = (user_data as *const UserData).deref();
|
||||||
-1
|
match ud.adapter.open(CStr::from_ptr(path)) {
|
||||||
|
Ok(f) => f.unwrap(),
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Could not open device for libinput: {}", ErrorFmt(e));
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn close_restricted(fd: c::c_int, _user_data: *mut c::c_void) {
|
unsafe extern "C" fn close_restricted(fd: c::c_int, _user_data: *mut c::c_void) {
|
||||||
drop(OwnedFd::new(fd));
|
drop(OwnedFd::new(fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UserData {}
|
struct UserData {
|
||||||
|
adapter: Rc<dyn LibInputAdapter>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LibInputAdapter {
|
||||||
|
fn open(&self, path: &CStr) -> Result<OwnedFd, LibInputError>;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum LibInputError {
|
pub enum LibInputError {
|
||||||
#[error("Could not create a libinput instance")]
|
#[error("Could not create a libinput instance")]
|
||||||
New,
|
New,
|
||||||
|
#[error("Could not open a libinput device")]
|
||||||
|
Open,
|
||||||
|
#[error("Could not dispatch libinput events")]
|
||||||
|
Dispatch(#[source] OsError),
|
||||||
|
#[error("The requested device is not available")]
|
||||||
|
DeviceUnavailable,
|
||||||
|
#[error("Dupfd failed")]
|
||||||
|
DupFd(#[source] OsError),
|
||||||
|
#[error("The udev subsystem produced an error")]
|
||||||
|
Udev(#[from] UdevError),
|
||||||
|
#[error("Stat failed")]
|
||||||
|
Stat(#[source] OsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LibInput {
|
pub struct LibInput {
|
||||||
|
|
@ -59,20 +83,71 @@ pub struct LibInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LibInput {
|
impl LibInput {
|
||||||
pub fn new() -> Result<Self, LibInputError> {
|
pub fn new(adapter: Rc<dyn LibInputAdapter>) -> Result<Self, LibInputError> {
|
||||||
let mut ud = Box::new(UserData {});
|
let mut ud = Box::new(UserData { adapter });
|
||||||
let li = unsafe {
|
let li = unsafe {
|
||||||
libinput_path_create_context(&INTERFACE, &mut *ud as *mut _ as *mut c::c_void)
|
libinput_path_create_context(&INTERFACE, &mut *ud as *mut _ as *mut c::c_void)
|
||||||
};
|
};
|
||||||
if li.is_null() {
|
if li.is_null() {
|
||||||
return Err(LibInputError::New);
|
return Err(LibInputError::New);
|
||||||
}
|
}
|
||||||
|
unsafe {
|
||||||
|
libinput_log_set_handler(li, log_handler);
|
||||||
|
let priority = if log::log_enabled!(log::Level::Debug) {
|
||||||
|
LIBINPUT_LOG_PRIORITY_DEBUG
|
||||||
|
} else if log::log_enabled!(log::Level::Info) {
|
||||||
|
LIBINPUT_LOG_PRIORITY_INFO
|
||||||
|
} else {
|
||||||
|
LIBINPUT_LOG_PRIORITY_ERROR
|
||||||
|
};
|
||||||
|
libinput_log_set_priority(li, priority.raw() as _);
|
||||||
|
}
|
||||||
Ok(Self { data: ud, li })
|
Ok(Self { data: ud, li })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fd(&self) -> c::c_int {
|
pub fn fd(&self) -> c::c_int {
|
||||||
unsafe { libinput_get_fd(self.li) }
|
unsafe { libinput_get_fd(self.li) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn open<'a>(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
path: impl IntoUstr<'a>,
|
||||||
|
) -> Result<RegisteredDevice, LibInputError> {
|
||||||
|
let path = path.into_ustr();
|
||||||
|
let res = unsafe { libinput_path_add_device(self.li, path.as_ptr()) };
|
||||||
|
if res.is_null() {
|
||||||
|
Err(LibInputError::Open)
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
libinput_device_ref(res);
|
||||||
|
}
|
||||||
|
Ok(RegisteredDevice {
|
||||||
|
li: self.clone(),
|
||||||
|
dev: res,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispatch(&self) -> Result<(), LibInputError> {
|
||||||
|
let res = unsafe { libinput_dispatch(self.li) };
|
||||||
|
if res < 0 {
|
||||||
|
Err(LibInputError::Dispatch(Errno(-res).into()))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn event(&self) -> Option<LibInputEvent> {
|
||||||
|
let res = unsafe { libinput_get_event(self.li) };
|
||||||
|
if res.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(LibInputEvent {
|
||||||
|
event: res,
|
||||||
|
_phantom: Default::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for LibInput {
|
impl Drop for LibInput {
|
||||||
|
|
@ -82,3 +157,25 @@ impl Drop for LibInput {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn log_handler(
|
||||||
|
_libinput: *mut libinput,
|
||||||
|
priority: libinput_log_priority,
|
||||||
|
format: *const c::c_char,
|
||||||
|
args: VaList,
|
||||||
|
) {
|
||||||
|
let str = match vasprintf_(format, args) {
|
||||||
|
Some(s) => s,
|
||||||
|
_ => {
|
||||||
|
log::error!("Could not format log message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let priority = match LogPriority(priority as _) {
|
||||||
|
LIBINPUT_LOG_PRIORITY_DEBUG => log::Level::Debug,
|
||||||
|
LIBINPUT_LOG_PRIORITY_INFO => log::Level::Info,
|
||||||
|
LIBINPUT_LOG_PRIORITY_ERROR => log::Level::Error,
|
||||||
|
_ => log::Level::Error,
|
||||||
|
};
|
||||||
|
log::log!(priority, "libinput: {}", str.to_bytes().trim().as_bstr());
|
||||||
|
}
|
||||||
|
|
|
||||||
152
src/libinput/consts.rs
Normal file
152
src/libinput/consts.rs
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
LogPriority, LIBINPUT_LOG_PRIORITY;
|
||||||
|
|
||||||
|
LIBINPUT_LOG_PRIORITY_DEBUG = 10,
|
||||||
|
LIBINPUT_LOG_PRIORITY_INFO = 20,
|
||||||
|
LIBINPUT_LOG_PRIORITY_ERROR = 30,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
DeviceCapability, LIBINPUT_DEVICE_CAPABILITY;
|
||||||
|
|
||||||
|
LIBINPUT_DEVICE_CAP_KEYBOARD = 0,
|
||||||
|
LIBINPUT_DEVICE_CAP_POINTER = 1,
|
||||||
|
LIBINPUT_DEVICE_CAP_TOUCH = 2,
|
||||||
|
LIBINPUT_DEVICE_CAP_TABLET_TOOL = 3,
|
||||||
|
LIBINPUT_DEVICE_CAP_TABLET_PAD = 4,
|
||||||
|
LIBINPUT_DEVICE_CAP_GESTURE = 5,
|
||||||
|
LIBINPUT_DEVICE_CAP_SWITCH = 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
KeyState, LIBINPUT_KEY_STATE;
|
||||||
|
|
||||||
|
LIBINPUT_KEY_STATE_RELEASED = 0,
|
||||||
|
LIBINPUT_KEY_STATE_PRESSED = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
Led, LIBINPUT_LED;
|
||||||
|
|
||||||
|
LIBINPUT_LED_NUM_LOCK = 1 << 0,
|
||||||
|
LIBINPUT_LED_CAPS_LOCK = 1 << 1,
|
||||||
|
LIBINPUT_LED_SCROLL_LOCK = 1 << 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
ButtonState, LIBINPUT_BUTTON_STATE;
|
||||||
|
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED = 0,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
PointerAxis, LIBINPUT_POINTER_AXIS;
|
||||||
|
|
||||||
|
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL = 0,
|
||||||
|
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
PointerAxisSource, LIBINPUT_POINTER_AXIS_SOURCE;
|
||||||
|
|
||||||
|
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL = 1,
|
||||||
|
LIBINPUT_POINTER_AXIS_SOURCE_FINGER = 2,
|
||||||
|
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS = 3,
|
||||||
|
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
TabletPadRingAxisSource, LIBINPUT_TABLET_PAD_RING_AXIS_SOURCE;
|
||||||
|
|
||||||
|
LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN = 1,
|
||||||
|
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
TabletPadStripAxisSource, LIBINPUT_TABLET_PAD_STRIP_AXIS_SOURCE;
|
||||||
|
|
||||||
|
LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN = 1,
|
||||||
|
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
TabletToolType, LIBINPUT_TABLET_TOOL_TYPE;
|
||||||
|
|
||||||
|
LIBINPUT_TABLET_TOOL_TYPE_PEN = 1,
|
||||||
|
LIBINPUT_TABLET_TOOL_TYPE_ERASER = 2,
|
||||||
|
LIBINPUT_TABLET_TOOL_TYPE_BRUSH = 3,
|
||||||
|
LIBINPUT_TABLET_TOOL_TYPE_PENCIL = 4,
|
||||||
|
LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH = 5,
|
||||||
|
LIBINPUT_TABLET_TOOL_TYPE_MOUSE = 6,
|
||||||
|
LIBINPUT_TABLET_TOOL_TYPE_LENS = 7,
|
||||||
|
LIBINPUT_TABLET_TOOL_TYPE_TOTEM = 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
TabletToolProximityState, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE;
|
||||||
|
|
||||||
|
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT = 0,
|
||||||
|
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
TabletToolTipState, LIBINPUT_TABLET_TOOL_TIP_STATE;
|
||||||
|
|
||||||
|
LIBINPUT_TABLET_TOOL_TIP_UP = 0,
|
||||||
|
LIBINPUT_TABLET_TOOL_TIP_DOWN = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
SwitchState, LIBINPUT_SWITCH_STATE;
|
||||||
|
|
||||||
|
LIBINPUT_SWITCH_STATE_OFF = 0,
|
||||||
|
LIBINPUT_SWITCH_STATE_ON = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
Switch, LIBINPUT_SWITCH;
|
||||||
|
|
||||||
|
LIBINPUT_SWITCH_LID = 1,
|
||||||
|
LIBINPUT_SWITCH_TABLET_MODE = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
cenum! {
|
||||||
|
EventType, LIBINPUT_EVENT_TYPE;
|
||||||
|
|
||||||
|
LIBINPUT_EVENT_NONE = 0,
|
||||||
|
LIBINPUT_EVENT_DEVICE_ADDED = 1,
|
||||||
|
LIBINPUT_EVENT_DEVICE_REMOVED = 2,
|
||||||
|
LIBINPUT_EVENT_KEYBOARD_KEY = 300,
|
||||||
|
LIBINPUT_EVENT_POINTER_MOTION = 400,
|
||||||
|
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE = 401,
|
||||||
|
LIBINPUT_EVENT_POINTER_BUTTON = 402,
|
||||||
|
LIBINPUT_EVENT_POINTER_AXIS = 403,
|
||||||
|
LIBINPUT_EVENT_POINTER_SCROLL_WHEEL = 404,
|
||||||
|
LIBINPUT_EVENT_POINTER_SCROLL_FINGER = 405,
|
||||||
|
LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS = 406,
|
||||||
|
LIBINPUT_EVENT_TOUCH_DOWN = 500,
|
||||||
|
LIBINPUT_EVENT_TOUCH_UP = 501,
|
||||||
|
LIBINPUT_EVENT_TOUCH_MOTION = 502,
|
||||||
|
LIBINPUT_EVENT_TOUCH_CANCEL = 503,
|
||||||
|
LIBINPUT_EVENT_TOUCH_FRAME = 504,
|
||||||
|
LIBINPUT_EVENT_TABLET_TOOL_AXIS = 600,
|
||||||
|
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY = 601,
|
||||||
|
LIBINPUT_EVENT_TABLET_TOOL_TIP = 602,
|
||||||
|
LIBINPUT_EVENT_TABLET_TOOL_BUTTON = 603,
|
||||||
|
LIBINPUT_EVENT_TABLET_PAD_BUTTON = 700,
|
||||||
|
LIBINPUT_EVENT_TABLET_PAD_RING = 701,
|
||||||
|
LIBINPUT_EVENT_TABLET_PAD_STRIP = 702,
|
||||||
|
LIBINPUT_EVENT_TABLET_PAD_KEY = 703,
|
||||||
|
LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN = 800,
|
||||||
|
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE = 801,
|
||||||
|
LIBINPUT_EVENT_GESTURE_SWIPE_END = 802,
|
||||||
|
LIBINPUT_EVENT_GESTURE_PINCH_BEGIN = 803,
|
||||||
|
LIBINPUT_EVENT_GESTURE_PINCH_UPDATE = 804,
|
||||||
|
LIBINPUT_EVENT_GESTURE_PINCH_END = 805,
|
||||||
|
LIBINPUT_EVENT_GESTURE_HOLD_BEGIN = 806,
|
||||||
|
LIBINPUT_EVENT_GESTURE_HOLD_END = 807,
|
||||||
|
LIBINPUT_EVENT_SWITCH_TOGGLE = 900,
|
||||||
|
}
|
||||||
51
src/libinput/device.rs
Normal file
51
src/libinput/device.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
use crate::libinput::sys::{
|
||||||
|
libinput_device, libinput_device_set_user_data, libinput_device_unref,
|
||||||
|
libinput_path_remove_device,
|
||||||
|
};
|
||||||
|
use crate::libinput::LibInput;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct LibInputDevice<'a> {
|
||||||
|
pub(super) dev: *mut libinput_device,
|
||||||
|
pub(super) _phantom: PhantomData<&'a ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RegisteredDevice {
|
||||||
|
pub(super) li: Rc<LibInput>,
|
||||||
|
pub(super) dev: *mut libinput_device,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LibInputDevice<'a> {
|
||||||
|
pub fn set_slot(&self, slot: usize) {
|
||||||
|
self.set_slot_(slot + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unset_slot(&self) {
|
||||||
|
self.set_slot_(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_slot_(&self, slot: usize) {
|
||||||
|
unsafe {
|
||||||
|
libinput_device_set_user_data(self.dev, slot as _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisteredDevice {
|
||||||
|
pub fn device(&self) -> LibInputDevice {
|
||||||
|
LibInputDevice {
|
||||||
|
dev: self.dev,
|
||||||
|
_phantom: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for RegisteredDevice {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
libinput_path_remove_device(self.dev);
|
||||||
|
libinput_device_unref(self.dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
66
src/libinput/event.rs
Normal file
66
src/libinput/event.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
use crate::libinput::consts::{EventType, KeyState};
|
||||||
|
use crate::libinput::device::LibInputDevice;
|
||||||
|
use crate::libinput::sys::{
|
||||||
|
libinput_event, libinput_event_destroy, libinput_event_get_device,
|
||||||
|
libinput_event_get_keyboard_event, libinput_event_get_type, libinput_event_keyboard,
|
||||||
|
libinput_event_keyboard_get_key, libinput_event_keyboard_get_key_state,
|
||||||
|
libinput_event_keyboard_get_time_usec,
|
||||||
|
};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
pub struct LibInputEvent<'a> {
|
||||||
|
pub(super) event: *mut libinput_event,
|
||||||
|
pub(super) _phantom: PhantomData<&'a ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LibInputEventKeyboard<'a> {
|
||||||
|
pub(super) event: *mut libinput_event_keyboard,
|
||||||
|
pub(super) _phantom: PhantomData<&'a ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Drop for LibInputEvent<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
libinput_event_destroy(self.event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LibInputEvent<'a> {
|
||||||
|
pub fn ty(&self) -> EventType {
|
||||||
|
unsafe { EventType(libinput_event_get_type(self.event)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn device(&self) -> LibInputDevice {
|
||||||
|
LibInputDevice {
|
||||||
|
dev: unsafe { libinput_event_get_device(self.event) },
|
||||||
|
_phantom: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn keyboard_event(&self) -> Option<LibInputEventKeyboard> {
|
||||||
|
let res = unsafe { libinput_event_get_keyboard_event(self.event) };
|
||||||
|
if res.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(LibInputEventKeyboard {
|
||||||
|
event: res,
|
||||||
|
_phantom: Default::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LibInputEventKeyboard<'a> {
|
||||||
|
pub fn key(&self) -> u32 {
|
||||||
|
unsafe { libinput_event_keyboard_get_key(self.event) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn key_state(&self) -> KeyState {
|
||||||
|
unsafe { KeyState(libinput_event_keyboard_get_key_state(self.event)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn time_usec(&self) -> u64 {
|
||||||
|
unsafe { libinput_event_keyboard_get_time_usec(self.event) }
|
||||||
|
}
|
||||||
|
}
|
||||||
64
src/libinput/sys.rs
Normal file
64
src/libinput/sys.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
use std::ffi::VaList;
|
||||||
|
use uapi::c;
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/libinput_tys.rs"));
|
||||||
|
|
||||||
|
pub type libinput_log_handler = unsafe extern "C" fn(
|
||||||
|
libinput: *mut libinput,
|
||||||
|
priority: libinput_log_priority,
|
||||||
|
format: *const c::c_char,
|
||||||
|
args: VaList,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[link(name = "input")]
|
||||||
|
extern "C" {
|
||||||
|
pub type libinput;
|
||||||
|
pub type libinput_device;
|
||||||
|
pub type libinput_event;
|
||||||
|
pub type libinput_event_keyboard;
|
||||||
|
|
||||||
|
pub fn libinput_log_set_handler(libinput: *mut libinput, log_handler: libinput_log_handler);
|
||||||
|
pub fn libinput_log_set_priority(libinput: *mut libinput, priority: libinput_log_priority);
|
||||||
|
pub fn libinput_path_create_context(
|
||||||
|
interface: *const libinput_interface,
|
||||||
|
user_data: *mut c::c_void,
|
||||||
|
) -> *mut libinput;
|
||||||
|
pub fn libinput_device_set_user_data(device: *mut libinput_device, user_data: *mut c::c_void);
|
||||||
|
pub fn libinput_device_get_user_data(device: *mut libinput_device) -> *mut c::c_void;
|
||||||
|
pub fn libinput_device_ref(device: *mut libinput_device) -> *mut libinput_device;
|
||||||
|
pub fn libinput_device_unref(device: *mut libinput_device) -> *mut libinput_device;
|
||||||
|
pub fn libinput_path_add_device(
|
||||||
|
libinput: *mut libinput,
|
||||||
|
path: *const c::c_char,
|
||||||
|
) -> *mut libinput_device;
|
||||||
|
pub fn libinput_path_remove_device(device: *mut libinput_device);
|
||||||
|
pub fn libinput_unref(libinput: *mut libinput) -> *mut libinput;
|
||||||
|
pub fn libinput_get_fd(libinput: *mut libinput) -> c::c_int;
|
||||||
|
|
||||||
|
pub fn libinput_dispatch(libinput: *mut libinput) -> c::c_int;
|
||||||
|
|
||||||
|
pub fn libinput_get_event(libinput: *mut libinput) -> *mut libinput_event;
|
||||||
|
|
||||||
|
pub fn libinput_event_destroy(event: *mut libinput_event);
|
||||||
|
pub fn libinput_event_get_type(event: *mut libinput_event) -> libinput_event_type;
|
||||||
|
pub fn libinput_event_get_device(event: *mut libinput_event) -> *mut libinput_device;
|
||||||
|
pub fn libinput_event_get_keyboard_event(
|
||||||
|
event: *mut libinput_event,
|
||||||
|
) -> *mut libinput_event_keyboard;
|
||||||
|
|
||||||
|
pub fn libinput_event_keyboard_get_key(event: *mut libinput_event_keyboard) -> u32;
|
||||||
|
pub fn libinput_event_keyboard_get_key_state(
|
||||||
|
event: *mut libinput_event_keyboard,
|
||||||
|
) -> libinput_key_state;
|
||||||
|
pub fn libinput_event_keyboard_get_time_usec(event: *mut libinput_event_keyboard) -> u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct libinput_interface {
|
||||||
|
pub open_restricted: unsafe extern "C" fn(
|
||||||
|
path: *const c::c_char,
|
||||||
|
flags: c::c_int,
|
||||||
|
user_data: *mut c::c_void,
|
||||||
|
) -> c::c_int,
|
||||||
|
pub close_restricted: unsafe extern "C" fn(fd: c::c_int, user_data: *mut c::c_void),
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::dbus::{DbusError, DbusSocket, Reply};
|
use crate::dbus::{DbusError, DbusSocket};
|
||||||
use crate::org::freedesktop::login1::session::TakeControlReply;
|
use crate::org::freedesktop::login1::session::TakeDeviceReply;
|
||||||
use crate::{org, FALSE};
|
use crate::{org, FALSE};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use uapi::c;
|
||||||
|
|
||||||
const LOGIND_NAME: &str = "org.freedesktop.login1";
|
const LOGIND_NAME: &str = "org.freedesktop.login1";
|
||||||
const MANAGER_PATH: &str = "/org/freedesktop/login1";
|
const MANAGER_PATH: &str = "/org/freedesktop/login1";
|
||||||
|
|
@ -72,8 +73,22 @@ impl Session {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
match res {
|
match res {
|
||||||
Ok(r) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(e) => Err(LogindError::TakeControl(e)),
|
Err(e) => Err(LogindError::TakeControl(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_device<F>(&self, dev: c::dev_t, f: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(Result<&TakeDeviceReply, DbusError>) + 'static,
|
||||||
|
{
|
||||||
|
let major = uapi::major(dev) as _;
|
||||||
|
let minor = uapi::minor(dev) as _;
|
||||||
|
self.socket.call(
|
||||||
|
LOGIND_NAME,
|
||||||
|
&self.session_path,
|
||||||
|
org::freedesktop::login1::session::TakeDevice { major, minor },
|
||||||
|
move |r| f(r),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -330,6 +330,7 @@ macro_rules! assert_size_eq {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_macros)]
|
||||||
macro_rules! assert_size_le {
|
macro_rules! assert_size_le {
|
||||||
($t:ty, $u:ty) => {{
|
($t:ty, $u:ty) => {{
|
||||||
struct AssertLeSize<T, U>(std::marker::PhantomData<T>, std::marker::PhantomData<U>);
|
struct AssertLeSize<T, U>(std::marker::PhantomData<T>, std::marker::PhantomData<U>);
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,11 @@
|
||||||
use crate::acceptor::AcceptorError;
|
use crate::acceptor::AcceptorError;
|
||||||
use crate::async_engine::{AsyncError, Phase};
|
use crate::async_engine::{AsyncError, Phase};
|
||||||
use crate::backends::dummy::DummyBackend;
|
use crate::backends::dummy::DummyBackend;
|
||||||
use crate::backends::xorg::{XorgBackend, XorgBackendError};
|
use crate::backends::metal;
|
||||||
|
use crate::backends::xorg::XorgBackendError;
|
||||||
use crate::client::Clients;
|
use crate::client::Clients;
|
||||||
use crate::clientmem::ClientMemError;
|
use crate::clientmem::ClientMemError;
|
||||||
use crate::dbus::{Dbus, FALSE, TRUE};
|
use crate::dbus::{Dbus, FALSE};
|
||||||
use crate::event_loop::EventLoopError;
|
use crate::event_loop::EventLoopError;
|
||||||
use crate::forker::ForkerError;
|
use crate::forker::ForkerError;
|
||||||
use crate::globals::Globals;
|
use crate::globals::Globals;
|
||||||
|
|
@ -55,7 +56,6 @@ use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use wheel::Wheel;
|
use wheel::Wheel;
|
||||||
use crate::backends::metal;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,15 @@ use uapi::{c, Errno, OwnedFd};
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ServerMemError {
|
pub enum ServerMemError {
|
||||||
#[error("memfd_create failed")]
|
#[error("memfd_create failed")]
|
||||||
MemfdCreate(#[source] std::io::Error),
|
MemfdCreate(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("The provided size does not fit into off_t")]
|
#[error("The provided size does not fit into off_t")]
|
||||||
SizeOverflow,
|
SizeOverflow,
|
||||||
#[error("ftruncate failed")]
|
#[error("ftruncate failed")]
|
||||||
Ftruncate(#[source] std::io::Error),
|
Ftruncate(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("mmap failed")]
|
#[error("mmap failed")]
|
||||||
MmapFailed(#[source] std::io::Error),
|
MmapFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("sealing failed")]
|
#[error("sealing failed")]
|
||||||
Seal(#[source] std::io::Error),
|
Seal(#[source] crate::utils::oserror::OsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ServerMem {
|
pub struct ServerMem {
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,11 @@ pub enum SighandError {
|
||||||
#[error("The signal fd is in an error state")]
|
#[error("The signal fd is in an error state")]
|
||||||
ErrorEvent,
|
ErrorEvent,
|
||||||
#[error("Could not read from the signal fd")]
|
#[error("Could not read from the signal fd")]
|
||||||
ReadFailed(#[source] std::io::Error),
|
ReadFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not block the signalfd signals")]
|
#[error("Could not block the signalfd signals")]
|
||||||
BlockFailed(#[source] std::io::Error),
|
BlockFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not create a signalfd")]
|
#[error("Could not create a signalfd")]
|
||||||
CreateFailed(#[source] std::io::Error),
|
CreateFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("The event loop caused an error")]
|
#[error("The event loop caused an error")]
|
||||||
EventLoopError(#[from] EventLoopError),
|
EventLoopError(#[from] EventLoopError),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use uapi::c;
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum TimeError {
|
pub enum TimeError {
|
||||||
#[error("clock_gettime failed: {0}")]
|
#[error("clock_gettime failed: {0}")]
|
||||||
ClockGettime(std::io::Error),
|
ClockGettime(crate::utils::oserror::OsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
|
|
||||||
34
src/udev.rs
34
src/udev.rs
|
|
@ -1,10 +1,9 @@
|
||||||
use crate::dbus::DbusError;
|
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use uapi::{c, Errno, IntoUstr, Ustr};
|
use uapi::{c, Errno, IntoUstr};
|
||||||
|
|
||||||
#[link(name = "udev")]
|
#[link(name = "udev")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -47,32 +46,33 @@ extern "C" {
|
||||||
fn udev_device_get_sysname(udev_device: *mut udev_device) -> *const c::c_char;
|
fn udev_device_get_sysname(udev_device: *mut udev_device) -> *const c::c_char;
|
||||||
fn udev_device_get_is_initialized(udev_device: *mut udev_device) -> c::c_int;
|
fn udev_device_get_is_initialized(udev_device: *mut udev_device) -> c::c_int;
|
||||||
fn udev_device_get_devnode(udev_device: *mut udev_device) -> *const c::c_char;
|
fn udev_device_get_devnode(udev_device: *mut udev_device) -> *const c::c_char;
|
||||||
|
fn udev_device_get_devnum(udev_device: *mut udev_device) -> c::dev_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum UdevError {
|
pub enum UdevError {
|
||||||
#[error("Could not create a new udev instance")]
|
#[error("Could not create a new udev instance")]
|
||||||
New(#[source] std::io::Error),
|
New(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not create a new udev_monitor instance")]
|
#[error("Could not create a new udev_monitor instance")]
|
||||||
NewMonitor(#[source] std::io::Error),
|
NewMonitor(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not create a new udev_enumerate instance")]
|
#[error("Could not create a new udev_enumerate instance")]
|
||||||
NewEnumerate(#[source] std::io::Error),
|
NewEnumerate(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not enable receiving on a udev_monitor")]
|
#[error("Could not enable receiving on a udev_monitor")]
|
||||||
EnableReceiving(#[source] std::io::Error),
|
EnableReceiving(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not add a match rule to a udev_monitor")]
|
#[error("Could not add a match rule to a udev_monitor")]
|
||||||
MonitorAddMatch(#[source] std::io::Error),
|
MonitorAddMatch(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not add a match rule to a udev_enumerate")]
|
#[error("Could not add a match rule to a udev_enumerate")]
|
||||||
EnumerateAddMatch(#[source] std::io::Error),
|
EnumerateAddMatch(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not list devices of a udev_enumerate")]
|
#[error("Could not list devices of a udev_enumerate")]
|
||||||
EnumerateGetListEntry(#[source] std::io::Error),
|
EnumerateGetListEntry(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not scan devices of a udev_enumerate")]
|
#[error("Could not scan devices of a udev_enumerate")]
|
||||||
ScanDevices(#[source] std::io::Error),
|
ScanDevices(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not create a udev_device from a syspath")]
|
#[error("Could not create a udev_device from a syspath")]
|
||||||
DeviceFromSyspath(#[source] std::io::Error),
|
DeviceFromSyspath(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not retrieve the sysname of a udev_device")]
|
#[error("Could not retrieve the sysname of a udev_device")]
|
||||||
GetSysname(#[source] std::io::Error),
|
GetSysname(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not retrieve the devnode of a udev_device")]
|
#[error("Could not retrieve the devnode of a udev_device")]
|
||||||
GetDevnode(#[source] std::io::Error),
|
GetDevnode(#[source] crate::utils::oserror::OsError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Udev {
|
pub struct Udev {
|
||||||
|
|
@ -193,9 +193,7 @@ impl UdevMonitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn receive_device(&self) -> Option<UdevDevice> {
|
pub fn receive_device(&self) -> Option<UdevDevice> {
|
||||||
let res = unsafe {
|
let res = unsafe { udev_monitor_receive_device(self.monitor) };
|
||||||
udev_monitor_receive_device(self.monitor)
|
|
||||||
};
|
|
||||||
if res.is_null() {
|
if res.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -303,6 +301,10 @@ impl UdevDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn devnum(&self) -> c::dev_t {
|
||||||
|
unsafe { udev_device_get_devnum(self.device) }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_initialized(&self) -> bool {
|
pub fn is_initialized(&self) -> bool {
|
||||||
unsafe { udev_device_get_is_initialized(self.device) != 0 }
|
unsafe { udev_device_get_is_initialized(self.device) != 0 }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ mod parser;
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum BufFdError {
|
pub enum BufFdError {
|
||||||
#[error("An IO error occurred")]
|
#[error("An IO error occurred")]
|
||||||
Io(#[source] std::io::Error),
|
Io(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("An async error occurred")]
|
#[error("An async error occurred")]
|
||||||
Async(#[from] AsyncError),
|
Async(#[from] AsyncError),
|
||||||
#[error("The peer did not send a file descriptor")]
|
#[error("The peer did not send a file descriptor")]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod array;
|
pub mod array;
|
||||||
pub mod asyncevent;
|
pub mod asyncevent;
|
||||||
|
pub mod bitfield;
|
||||||
pub mod bitflags;
|
pub mod bitflags;
|
||||||
pub mod buffd;
|
pub mod buffd;
|
||||||
pub mod clonecell;
|
pub mod clonecell;
|
||||||
|
|
@ -9,12 +10,13 @@ pub mod errorfmt;
|
||||||
pub mod hex;
|
pub mod hex;
|
||||||
pub mod linkedlist;
|
pub mod linkedlist;
|
||||||
pub mod numcell;
|
pub mod numcell;
|
||||||
|
pub mod oserror;
|
||||||
pub mod ptr_ext;
|
pub mod ptr_ext;
|
||||||
pub mod queue;
|
pub mod queue;
|
||||||
pub mod run_toplevel;
|
pub mod run_toplevel;
|
||||||
pub mod smallmap;
|
pub mod smallmap;
|
||||||
pub mod stack;
|
pub mod stack;
|
||||||
pub mod tri;
|
pub mod tri;
|
||||||
|
pub mod vasprintf;
|
||||||
pub mod vec_ext;
|
pub mod vec_ext;
|
||||||
pub mod vecstorage;
|
pub mod vecstorage;
|
||||||
pub mod bitfield;
|
|
||||||
|
|
|
||||||
181
src/utils/oserror.rs
Normal file
181
src/utils/oserror.rs
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use uapi::{c, Errno};
|
||||||
|
|
||||||
|
static ERRORS: Lazy<&'static [Option<&'static str>]> = Lazy::new(|| {
|
||||||
|
static MSGS: &'static [(c::c_int, &'static str)] = &[
|
||||||
|
(c::EWOULDBLOCK, "Operation would block"),
|
||||||
|
(c::ENOTSUP, "Not supported"),
|
||||||
|
(c::EHWPOISON, "Memory page has hardware error"),
|
||||||
|
(c::ERFKILL, "Operation not possible due to RF-kill"),
|
||||||
|
(c::EKEYREJECTED, "Key was rejected by service"),
|
||||||
|
(c::EKEYREVOKED, "Key has been revoked"),
|
||||||
|
(c::EKEYEXPIRED, "Key has expired"),
|
||||||
|
(c::ENOKEY, "Required key not available"),
|
||||||
|
(c::EMEDIUMTYPE, "Wrong medium type"),
|
||||||
|
(c::ENOMEDIUM, "No medium found"),
|
||||||
|
(c::EREMOTEIO, "Remote I/O error"),
|
||||||
|
(c::EISNAM, "Is a named type file"),
|
||||||
|
(c::ENAVAIL, "No XENIX semaphores available"),
|
||||||
|
(c::ENOTNAM, "Not a XENIX named type file"),
|
||||||
|
(c::EUCLEAN, "Structure needs cleaning"),
|
||||||
|
(c::ESTRPIPE, "Streams pipe error"),
|
||||||
|
(c::ELIBEXEC, "Cannot exec a shared library directly"),
|
||||||
|
(
|
||||||
|
c::ELIBMAX,
|
||||||
|
"Attempting to link in too many shared libraries",
|
||||||
|
),
|
||||||
|
(c::ELIBSCN, ".lib section in a.out corrupted"),
|
||||||
|
(c::ELIBBAD, "Accessing a corrupted shared library"),
|
||||||
|
(c::ELIBACC, "Can not access a needed shared library"),
|
||||||
|
(c::EREMCHG, "Remote address changed"),
|
||||||
|
(c::EBADFD, "File descriptor in bad state"),
|
||||||
|
(c::ENOTUNIQ, "Name not unique on network"),
|
||||||
|
(c::EDOTDOT, "RFS specific error"),
|
||||||
|
(c::ECOMM, "Communication error on send"),
|
||||||
|
(c::ESRMNT, "Srmount error"),
|
||||||
|
(c::EADV, "Advertise error"),
|
||||||
|
(c::ENOPKG, "Package not installed"),
|
||||||
|
(c::ENONET, "Machine is not on the network"),
|
||||||
|
(c::EBFONT, "Bad font file format"),
|
||||||
|
(c::EBADSLT, "Invalid slot"),
|
||||||
|
(c::EBADRQC, "Invalid request code"),
|
||||||
|
(c::ENOANO, "No anode"),
|
||||||
|
(c::EXFULL, "Exchange full"),
|
||||||
|
(c::EBADR, "Invalid request descriptor"),
|
||||||
|
(c::EBADE, "Invalid exchange"),
|
||||||
|
(c::EL2HLT, "Level 2 halted"),
|
||||||
|
(c::ENOCSI, "No CSI structure available"),
|
||||||
|
(c::EUNATCH, "Protocol driver not attached"),
|
||||||
|
(c::ELNRNG, "Link number out of range"),
|
||||||
|
(c::EL3RST, "Level 3 reset"),
|
||||||
|
(c::EL3HLT, "Level 3 halted"),
|
||||||
|
(c::EL2NSYNC, "Level 2 not synchronized"),
|
||||||
|
(c::ECHRNG, "Channel number out of range"),
|
||||||
|
(c::ERESTART, "Interrupted system call should be restarted"),
|
||||||
|
(c::ENOTRECOVERABLE, "State not recoverable"),
|
||||||
|
(c::EOWNERDEAD, "Owner died"),
|
||||||
|
(c::ECANCELED, "Operation canceled"),
|
||||||
|
(c::ETIME, "Timer expired"),
|
||||||
|
(c::EPROTO, "Protocol error"),
|
||||||
|
(c::EOVERFLOW, "Value too large for defined data type"),
|
||||||
|
(c::ENOSTR, "Device not a stream"),
|
||||||
|
(c::ENOSR, "Out of streams resources"),
|
||||||
|
(c::ENOMSG, "No message of desired type"),
|
||||||
|
(c::ENOLINK, "Link has been severed"),
|
||||||
|
(c::ENODATA, "No data available"),
|
||||||
|
(c::EMULTIHOP, "Multihop attempted"),
|
||||||
|
(c::EIDRM, "Identifier removed"),
|
||||||
|
(c::EBADMSG, "Bad message"),
|
||||||
|
(
|
||||||
|
c::EILSEQ,
|
||||||
|
"Invalid or incomplete multibyte or wide character",
|
||||||
|
),
|
||||||
|
(c::ENOSYS, "Function not implemented"),
|
||||||
|
(c::ENOLCK, "No locks available"),
|
||||||
|
(c::EREMOTE, "Object is remote"),
|
||||||
|
(c::ESTALE, "Stale file handle"),
|
||||||
|
(c::EDQUOT, "Disk quota exceeded"),
|
||||||
|
(c::EUSERS, "Too many users"),
|
||||||
|
(c::ENOTEMPTY, "Directory not empty"),
|
||||||
|
(c::EHOSTUNREACH, "No route to host"),
|
||||||
|
(c::EHOSTDOWN, "Host is down"),
|
||||||
|
(c::ENAMETOOLONG, "File name too long"),
|
||||||
|
(c::ELOOP, "Too many levels of symbolic links"),
|
||||||
|
(c::ECONNREFUSED, "Connection refused"),
|
||||||
|
(c::ETIMEDOUT, "Connection timed out"),
|
||||||
|
(c::ETOOMANYREFS, "Too many references: cannot splice"),
|
||||||
|
(
|
||||||
|
c::ESHUTDOWN,
|
||||||
|
"Cannot send after transport endpoint shutdown",
|
||||||
|
),
|
||||||
|
(c::EDESTADDRREQ, "Destination address required"),
|
||||||
|
(c::ENOTCONN, "Transport endpoint is not connected"),
|
||||||
|
(c::EISCONN, "Transport endpoint is already connected"),
|
||||||
|
(c::ENOBUFS, "No buffer space available"),
|
||||||
|
(c::ECONNRESET, "Connection reset by peer"),
|
||||||
|
(c::ECONNABORTED, "Software caused connection abort"),
|
||||||
|
(c::ENETRESET, "Network dropped connection on reset"),
|
||||||
|
(c::ENETUNREACH, "Network is unreachable"),
|
||||||
|
(c::ENETDOWN, "Network is down"),
|
||||||
|
(c::EADDRNOTAVAIL, "Cannot assign requested address"),
|
||||||
|
(c::EADDRINUSE, "Address already in use"),
|
||||||
|
(c::EAFNOSUPPORT, "Address family not supported by protocol"),
|
||||||
|
(c::EPFNOSUPPORT, "Protocol family not supported"),
|
||||||
|
(c::EOPNOTSUPP, "Operation not supported"),
|
||||||
|
(c::ESOCKTNOSUPPORT, "Socket type not supported"),
|
||||||
|
(c::EPROTONOSUPPORT, "Protocol not supported"),
|
||||||
|
(c::ENOPROTOOPT, "Protocol not available"),
|
||||||
|
(c::EPROTOTYPE, "Protocol wrong type for socket"),
|
||||||
|
(c::EMSGSIZE, "Message too long"),
|
||||||
|
(c::ENOTSOCK, "Socket operation on non-socket"),
|
||||||
|
(c::EALREADY, "Operation already in progress"),
|
||||||
|
(c::EINPROGRESS, "Operation now in progress"),
|
||||||
|
(c::EAGAIN, "Resource temporarily unavailable"),
|
||||||
|
(c::ERANGE, "Numerical result out of range"),
|
||||||
|
(c::EDOM, "Numerical argument out of domain"),
|
||||||
|
(c::EPIPE, "Broken pipe"),
|
||||||
|
(c::EMLINK, "Too many links"),
|
||||||
|
(c::EROFS, "Read-only file system"),
|
||||||
|
(c::ESPIPE, "Illegal seek"),
|
||||||
|
(c::ENOSPC, "No space left on device"),
|
||||||
|
(c::EFBIG, "File too large"),
|
||||||
|
(c::ETXTBSY, "Text file busy"),
|
||||||
|
(c::ENOTTY, "Inappropriate ioctl for device"),
|
||||||
|
(c::ENFILE, "Too many open files in system"),
|
||||||
|
(c::EMFILE, "Too many open files"),
|
||||||
|
(c::EINVAL, "Invalid argument"),
|
||||||
|
(c::EISDIR, "Is a directory"),
|
||||||
|
(c::ENOTDIR, "Not a directory"),
|
||||||
|
(c::ENODEV, "No such device"),
|
||||||
|
(c::EXDEV, "Invalid cross-device link"),
|
||||||
|
(c::EEXIST, "File exists"),
|
||||||
|
(c::EBUSY, "Device or resource busy"),
|
||||||
|
(c::ENOTBLK, "Block device required"),
|
||||||
|
(c::EFAULT, "Bad address"),
|
||||||
|
(c::EACCES, "Permission denied"),
|
||||||
|
(c::ENOMEM, "Cannot allocate memory"),
|
||||||
|
(c::EDEADLK, "Resource deadlock avoided"),
|
||||||
|
(c::ECHILD, "No child processes"),
|
||||||
|
(c::EBADF, "Bad file descriptor"),
|
||||||
|
(c::ENOEXEC, "Exec format error"),
|
||||||
|
(c::E2BIG, "Argument list too long"),
|
||||||
|
(c::ENXIO, "No such device or address"),
|
||||||
|
(c::EIO, "Input/output error"),
|
||||||
|
(c::EINTR, "Interrupted system call"),
|
||||||
|
(c::ESRCH, "No such process"),
|
||||||
|
(c::ENOENT, "No such file or directory"),
|
||||||
|
(c::EPERM, "Operation not permitted"),
|
||||||
|
];
|
||||||
|
let mut res = vec![];
|
||||||
|
for &(idx, msg) in MSGS {
|
||||||
|
let idx = idx as usize;
|
||||||
|
while res.len() <= idx {
|
||||||
|
res.push(None);
|
||||||
|
}
|
||||||
|
res[idx] = Some(msg);
|
||||||
|
}
|
||||||
|
res.leak()
|
||||||
|
});
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct OsError(pub c::c_int);
|
||||||
|
|
||||||
|
impl From<Errno> for OsError {
|
||||||
|
fn from(e: Errno) -> Self {
|
||||||
|
Self(e.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for OsError {}
|
||||||
|
|
||||||
|
impl Display for OsError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let msg = ERRORS
|
||||||
|
.get(self.0 as usize)
|
||||||
|
.and_then(|v| *v)
|
||||||
|
.unwrap_or("unknown error");
|
||||||
|
write!(f, "{} (os error {})", msg, self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/utils/vasprintf.rs
Normal file
38
src/utils/vasprintf.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
use std::ffi::{CStr, VaList};
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::ptr;
|
||||||
|
use uapi::c;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn vasprintf(strp: *mut *mut c::c_char, fmt: *const c::c_char, ap: VaList) -> c::c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OwnedCStr {
|
||||||
|
val: &'static CStr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for OwnedCStr {
|
||||||
|
type Target = CStr;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for OwnedCStr {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
c::free(self.val.as_ptr() as _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn vasprintf_(fmt: *const c::c_char, ap: VaList) -> Option<OwnedCStr> {
|
||||||
|
let mut res = ptr::null_mut();
|
||||||
|
if vasprintf(&mut res, fmt, ap) == -1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(OwnedCStr {
|
||||||
|
val: CStr::from_ptr(res),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -14,9 +14,9 @@ use uapi::{c, OwnedFd};
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum WheelError {
|
pub enum WheelError {
|
||||||
#[error("Could not create the timerfd: {0}")]
|
#[error("Could not create the timerfd: {0}")]
|
||||||
CreateFailed(std::io::Error),
|
CreateFailed(crate::utils::oserror::OsError),
|
||||||
#[error("Could not set the timerfd: {0}")]
|
#[error("Could not set the timerfd: {0}")]
|
||||||
SetFailed(std::io::Error),
|
SetFailed(crate::utils::oserror::OsError),
|
||||||
#[error("The timerfd is in an error state")]
|
#[error("The timerfd is in an error state")]
|
||||||
ErrorEvent,
|
ErrorEvent,
|
||||||
#[error("An event loop error occurred: {0}")]
|
#[error("An event loop error occurred: {0}")]
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,11 @@ use uapi::{c, pipe2, Errno, OwnedFd};
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
enum XWaylandError {
|
enum XWaylandError {
|
||||||
#[error("Could not create a wayland socket")]
|
#[error("Could not create a wayland socket")]
|
||||||
SocketFailed(#[source] std::io::Error),
|
SocketFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("/tmp/.X11-unix does not exist")]
|
#[error("/tmp/.X11-unix does not exist")]
|
||||||
MissingSocketDir,
|
MissingSocketDir,
|
||||||
#[error("Could not stat /tmp/.X11-unix")]
|
#[error("Could not stat /tmp/.X11-unix")]
|
||||||
StatSocketDir(#[source] std::io::Error),
|
StatSocketDir(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("/tmp/.X11-unix is not a directory")]
|
#[error("/tmp/.X11-unix is not a directory")]
|
||||||
NotASocketDir,
|
NotASocketDir,
|
||||||
#[error("/tmp/.X11-unix is writable")]
|
#[error("/tmp/.X11-unix is writable")]
|
||||||
|
|
@ -38,17 +38,17 @@ enum XWaylandError {
|
||||||
#[error("The socket is already in use")]
|
#[error("The socket is already in use")]
|
||||||
AlreadyInUse,
|
AlreadyInUse,
|
||||||
#[error("Could not bind the socket to an address")]
|
#[error("Could not bind the socket to an address")]
|
||||||
BindFailed(#[source] std::io::Error),
|
BindFailed(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("All X displays in the range 0..1000 are already in use")]
|
#[error("All X displays in the range 0..1000 are already in use")]
|
||||||
AddressesInUse,
|
AddressesInUse,
|
||||||
#[error("The async engine returned an error")]
|
#[error("The async engine returned an error")]
|
||||||
AsyncError(#[from] AsyncError),
|
AsyncError(#[from] AsyncError),
|
||||||
#[error("pipe(2) failed")]
|
#[error("pipe(2) failed")]
|
||||||
Pipe(#[source] std::io::Error),
|
Pipe(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("dupfd(2) failed")]
|
#[error("dupfd(2) failed")]
|
||||||
Dupfd(#[source] std::io::Error),
|
Dupfd(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("socketpair(2) failed")]
|
#[error("socketpair(2) failed")]
|
||||||
Socketpair(#[source] std::io::Error),
|
Socketpair(#[source] crate::utils::oserror::OsError),
|
||||||
#[error("Could not start Xwayland")]
|
#[error("Could not start Xwayland")]
|
||||||
ExecFailed(#[source] ForkerError),
|
ExecFailed(#[source] ForkerError),
|
||||||
#[error("Could not load the atoms")]
|
#[error("Could not load the atoms")]
|
||||||
|
|
@ -224,7 +224,10 @@ async fn log_xwayland(state: Rc<State>, stderr: OwnedFd) {
|
||||||
let mut done = false;
|
let mut done = false;
|
||||||
while !done {
|
while !done {
|
||||||
if let Err(e) = afd.readable().await {
|
if let Err(e) = afd.readable().await {
|
||||||
log::error!("Cannot wait for the xwayland stderr to become readable: {}", ErrorFmt(e));
|
log::error!(
|
||||||
|
"Cannot wait for the xwayland stderr to become readable: {}",
|
||||||
|
ErrorFmt(e)
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -242,7 +245,7 @@ async fn log_xwayland(state: Rc<State>, stderr: OwnedFd) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Could not read from stderr fd: {}",
|
"Could not read from stderr fd: {}",
|
||||||
ErrorFmt(std::io::Error::from(e))
|
ErrorFmt(crate::utils::oserror::OsError::from(e))
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue