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"]
|
||||
mod xkbcommon;
|
||||
|
||||
#[path = "../src/libinput/consts.rs"]
|
||||
mod libinput;
|
||||
|
||||
fn get_target() -> repc::Target {
|
||||
let rustc_target = env::var("TARGET").unwrap();
|
||||
repc::TARGET_MAP
|
||||
|
|
@ -193,6 +196,67 @@ fn write_egl_procs<W: Write>(f: &mut W) -> 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")?;
|
||||
write_ty(&mut f, pixman::FORMATS, "PixmanFormat")?;
|
||||
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")]
|
||||
XrdTooLong(String),
|
||||
#[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")]
|
||||
SocketStat(#[source] std::io::Error),
|
||||
SocketStat(#[source] crate::utils::oserror::OsError),
|
||||
#[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")]
|
||||
OpenLockFile(#[source] std::io::Error),
|
||||
OpenLockFile(#[source] crate::utils::oserror::OsError),
|
||||
#[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")]
|
||||
ErrorEvent,
|
||||
#[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")]
|
||||
SpawnFailed(#[source] ClientError),
|
||||
#[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")]
|
||||
AddressesInUse,
|
||||
#[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::numcell::NumCell;
|
||||
use crate::wheel::{Wheel, WheelError};
|
||||
pub use fd::{AsyncFd, FdStatus};
|
||||
use fd::AsyncFdData;
|
||||
pub use fd::{AsyncFd, FdStatus};
|
||||
use queue::{DispatchQueue, Dispatcher};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::future::Future;
|
||||
|
|
@ -562,7 +562,10 @@ mod fd {
|
|||
let res = self.el.modify(self.id, events);
|
||||
if res.is_err() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
mod input;
|
||||
mod monitor;
|
||||
|
||||
use crate::async_engine::AsyncFd;
|
||||
use crate::dbus::DbusError;
|
||||
use crate::libinput::device::RegisteredDevice;
|
||||
use crate::libinput::{LibInput, LibInputAdapter, LibInputError};
|
||||
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 thiserror::Error;
|
||||
use uapi::OwnedFd;
|
||||
use crate::async_engine::{AsyncFd, FdStatus};
|
||||
use crate::libinput::{LibInput, LibInputError};
|
||||
use crate::udev::{UdevError, UdevMonitor};
|
||||
use uapi::{c, OwnedFd};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum MetalError {
|
||||
|
|
@ -16,12 +23,14 @@ pub enum MetalError {
|
|||
LogindSession(#[source] LogindError),
|
||||
#[error("Could not take control of the logind session")]
|
||||
TakeControl(#[source] LogindError),
|
||||
#[error("Could not enumerate devices")]
|
||||
Enumerate(#[source] Box<Self>),
|
||||
#[error(transparent)]
|
||||
Udev(#[from] UdevError),
|
||||
#[error(transparent)]
|
||||
LibInput(#[from] LibInputError),
|
||||
#[error("Dupfd failed")]
|
||||
Dup(#[source] std::io::Error),
|
||||
Dup(#[source] crate::utils::oserror::OsError),
|
||||
}
|
||||
|
||||
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> {
|
||||
let socket = match state.dbus.system() {
|
||||
Ok(s) => s,
|
||||
|
|
@ -39,90 +60,83 @@ async fn run_(state: Rc<State>) -> Result<(), MetalError> {
|
|||
Ok(s) => s,
|
||||
Err(e) => return Err(MetalError::LogindSession(e)),
|
||||
};
|
||||
// if let Err(e) = session.take_control().await {
|
||||
// return Err(MetalError::TakeControl(e));
|
||||
// }
|
||||
if let Err(e) = session.take_control().await {
|
||||
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 monitor = Rc::new(udev.create_monitor()?);
|
||||
monitor.add_match_subsystem_devtype(Some("input"), None)?;
|
||||
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) {
|
||||
Ok(m) => state.eng.fd(&Rc::new(m)).unwrap(),
|
||||
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 {
|
||||
state: state.clone(),
|
||||
udev,
|
||||
monitor,
|
||||
monitor_fd,
|
||||
libinput,
|
||||
libinput_fd,
|
||||
device_holder,
|
||||
session,
|
||||
ids: Default::default(),
|
||||
});
|
||||
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;
|
||||
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 {
|
||||
state: Rc<State>,
|
||||
udev: Rc<Udev>,
|
||||
monitor: Rc<UdevMonitor>,
|
||||
monitor_fd: AsyncFd,
|
||||
libinput: Rc<LibInput>,
|
||||
libinput_fd: AsyncFd,
|
||||
struct MetalDevice {
|
||||
slot: usize,
|
||||
device_id: u64,
|
||||
devnum: c::dev_t,
|
||||
fd: CloneCell<Option<Rc<OwnedFd>>>,
|
||||
inputdev: Cell<Option<RegisteredDevice>>,
|
||||
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 {
|
||||
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.");
|
||||
}
|
||||
|
||||
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.");
|
||||
fn id(&self) -> u64 {
|
||||
self.ids.fetch_add(1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
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) => {
|
||||
log::error!(
|
||||
"Cannot determine peer credentials of new connection: {:?}",
|
||||
std::io::Error::from(e)
|
||||
crate::utils::oserror::OsError::from(e)
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ use uapi::c::raise;
|
|||
#[derive(Debug, Error)]
|
||||
pub enum ClientMemError {
|
||||
#[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")]
|
||||
Sigbus,
|
||||
#[error("mmap failed")]
|
||||
MmapFailed(#[source] std::io::Error),
|
||||
MmapFailed(#[source] crate::utils::oserror::OsError),
|
||||
}
|
||||
|
||||
pub struct ClientMem {
|
||||
|
|
|
|||
|
|
@ -67,13 +67,13 @@ pub enum DbusError {
|
|||
#[error("Variant has an invalid type")]
|
||||
InvalidVariantType,
|
||||
#[error("Could not create a socket")]
|
||||
Socket(#[source] std::io::Error),
|
||||
Socket(#[source] crate::utils::oserror::OsError),
|
||||
#[error("Could not connect")]
|
||||
Connect(#[source] std::io::Error),
|
||||
Connect(#[source] crate::utils::oserror::OsError),
|
||||
#[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")]
|
||||
ReadError(#[source] std::io::Error),
|
||||
ReadError(#[source] crate::utils::oserror::OsError),
|
||||
#[error("timeout")]
|
||||
AsyncError(#[source] Box<AsyncError>),
|
||||
#[error("Server did not accept our authentication")]
|
||||
|
|
|
|||
|
|
@ -49,7 +49,11 @@ impl Outgoing {
|
|||
return;
|
||||
}
|
||||
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();
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,13 +12,13 @@ use uapi::{c, Errno, OwnedFd, Ustring};
|
|||
#[derive(Debug, Error)]
|
||||
pub enum DrmError {
|
||||
#[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")]
|
||||
RenderNodeName,
|
||||
#[error("Could not retrieve the device node name")]
|
||||
DeviceNodeName,
|
||||
#[error("Could not retrieve device")]
|
||||
GetDevice(#[source] std::io::Error),
|
||||
GetDevice(#[source] crate::utils::oserror::OsError),
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
|
|||
|
|
@ -9,17 +9,17 @@ use uapi::{c, Errno, OwnedFd};
|
|||
#[derive(Debug, Error)]
|
||||
pub enum EventLoopError {
|
||||
#[error("Could not create an epoll fd: {0}")]
|
||||
CreateFailed(std::io::Error),
|
||||
CreateFailed(crate::utils::oserror::OsError),
|
||||
#[error("epoll_wait failed: {0}")]
|
||||
WaitFailed(std::io::Error),
|
||||
WaitFailed(crate::utils::oserror::OsError),
|
||||
#[error("A dispatcher returned a fatal error: {0}")]
|
||||
DispatcherError(Box<dyn std::error::Error>),
|
||||
#[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}")]
|
||||
ModifyFailed(std::io::Error),
|
||||
ModifyFailed(crate::utils::oserror::OsError),
|
||||
#[error("Could not remove an fd to wait on: {0}")]
|
||||
RemoveFailed(std::io::Error),
|
||||
RemoveFailed(crate::utils::oserror::OsError),
|
||||
#[error("Entry is not registered")]
|
||||
NoEntry,
|
||||
#[error("Event loop is already destroyed")]
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ struct PidfdHandoff {
|
|||
#[derive(Debug, Error)]
|
||||
pub enum ForkerError {
|
||||
#[error("Could not create a socketpair")]
|
||||
Socketpair(#[source] std::io::Error),
|
||||
Socketpair(#[source] crate::utils::oserror::OsError),
|
||||
#[error("Could not fork")]
|
||||
Fork(#[source] std::io::Error),
|
||||
Fork(#[source] crate::utils::oserror::OsError),
|
||||
#[error("Could not read the next message")]
|
||||
ReadFailed(#[source] BufFdError),
|
||||
#[error("Could not write the next message")]
|
||||
|
|
@ -235,7 +235,10 @@ impl ForkerProxy {
|
|||
async fn check_process(self: Rc<Self>, state: Rc<State>) {
|
||||
let pidfd = state.eng.fd(&self.pidfd).unwrap();
|
||||
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 {
|
||||
let _ = uapi::waitpid(self.pid, 0);
|
||||
}
|
||||
|
|
@ -417,7 +420,10 @@ impl Forker {
|
|||
let spawn = self.ae.spawn(async move {
|
||||
let read = slf.ae.fd(&Rc::new(read)).unwrap();
|
||||
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 {
|
||||
let mut s = String::new();
|
||||
let _ = Fd::new(read.raw()).read_to_string(&mut s);
|
||||
|
|
@ -476,9 +482,9 @@ impl Forker {
|
|||
#[derive(Debug, Error)]
|
||||
enum SpawnError {
|
||||
#[error("exec failed")]
|
||||
Exec(#[source] std::io::Error),
|
||||
Exec(#[source] crate::utils::oserror::OsError),
|
||||
#[error("Could not unset cloexec flag")]
|
||||
Cloexec(#[source] std::io::Error),
|
||||
Cloexec(#[source] crate::utils::oserror::OsError),
|
||||
}
|
||||
|
||||
fn setup_fds(mut socket: OwnedFd) -> OwnedFd {
|
||||
|
|
|
|||
|
|
@ -125,9 +125,9 @@ pub enum WlKeyboardError {
|
|||
#[error("Could not process a `release` request")]
|
||||
ReleaseError(#[from] ReleaseError),
|
||||
#[error("Could not create a keymap memfd")]
|
||||
KeymapMemfd(#[source] std::io::Error),
|
||||
KeymapMemfd(#[source] crate::utils::oserror::OsError),
|
||||
#[error("Could not copy the keymap")]
|
||||
KeymapCopy(#[source] std::io::Error),
|
||||
KeymapCopy(#[source] crate::utils::oserror::OsError),
|
||||
}
|
||||
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 std::ops::DerefMut;
|
||||
use crate::utils::vasprintf::vasprintf_;
|
||||
use crate::ErrorFmt;
|
||||
use bstr::ByteSlice;
|
||||
use std::ffi::{CStr, VaList};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{c, 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),
|
||||
}
|
||||
use uapi::{c, Errno, IntoUstr, OwnedFd};
|
||||
|
||||
static INTERFACE: libinput_interface = libinput_interface {
|
||||
open_restricted,
|
||||
|
|
@ -34,23 +34,47 @@ static INTERFACE: libinput_interface = libinput_interface {
|
|||
|
||||
unsafe extern "C" fn open_restricted(
|
||||
path: *const c::c_char,
|
||||
flags: c::c_int,
|
||||
_flags: c::c_int,
|
||||
user_data: *mut c::c_void,
|
||||
) -> c::c_int {
|
||||
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) {
|
||||
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)]
|
||||
pub enum LibInputError {
|
||||
#[error("Could not create a libinput instance")]
|
||||
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 {
|
||||
|
|
@ -59,20 +83,71 @@ pub struct LibInput {
|
|||
}
|
||||
|
||||
impl LibInput {
|
||||
pub fn new() -> Result<Self, LibInputError> {
|
||||
let mut ud = Box::new(UserData {});
|
||||
pub fn new(adapter: Rc<dyn LibInputAdapter>) -> Result<Self, LibInputError> {
|
||||
let mut ud = Box::new(UserData { adapter });
|
||||
let li = unsafe {
|
||||
libinput_path_create_context(&INTERFACE, &mut *ud as *mut _ as *mut c::c_void)
|
||||
};
|
||||
if li.is_null() {
|
||||
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 })
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> c::c_int {
|
||||
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 {
|
||||
|
|
@ -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::org::freedesktop::login1::session::TakeControlReply;
|
||||
use crate::dbus::{DbusError, DbusSocket};
|
||||
use crate::org::freedesktop::login1::session::TakeDeviceReply;
|
||||
use crate::{org, FALSE};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::c;
|
||||
|
||||
const LOGIND_NAME: &str = "org.freedesktop.login1";
|
||||
const MANAGER_PATH: &str = "/org/freedesktop/login1";
|
||||
|
|
@ -72,8 +73,22 @@ impl Session {
|
|||
)
|
||||
.await;
|
||||
match res {
|
||||
Ok(r) => Ok(()),
|
||||
Ok(_) => Ok(()),
|
||||
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 {
|
||||
($t:ty, $u:ty) => {{
|
||||
struct AssertLeSize<T, U>(std::marker::PhantomData<T>, std::marker::PhantomData<U>);
|
||||
|
|
|
|||
|
|
@ -17,10 +17,11 @@
|
|||
use crate::acceptor::AcceptorError;
|
||||
use crate::async_engine::{AsyncError, Phase};
|
||||
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::clientmem::ClientMemError;
|
||||
use crate::dbus::{Dbus, FALSE, TRUE};
|
||||
use crate::dbus::{Dbus, FALSE};
|
||||
use crate::event_loop::EventLoopError;
|
||||
use crate::forker::ForkerError;
|
||||
use crate::globals::Globals;
|
||||
|
|
@ -55,7 +56,6 @@ use std::ops::Deref;
|
|||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use wheel::Wheel;
|
||||
use crate::backends::metal;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
|
|
|||
|
|
@ -10,15 +10,15 @@ use uapi::{c, Errno, OwnedFd};
|
|||
#[derive(Debug, Error)]
|
||||
pub enum ServerMemError {
|
||||
#[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")]
|
||||
SizeOverflow,
|
||||
#[error("ftruncate failed")]
|
||||
Ftruncate(#[source] std::io::Error),
|
||||
Ftruncate(#[source] crate::utils::oserror::OsError),
|
||||
#[error("mmap failed")]
|
||||
MmapFailed(#[source] std::io::Error),
|
||||
MmapFailed(#[source] crate::utils::oserror::OsError),
|
||||
#[error("sealing failed")]
|
||||
Seal(#[source] std::io::Error),
|
||||
Seal(#[source] crate::utils::oserror::OsError),
|
||||
}
|
||||
|
||||
pub struct ServerMem {
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ pub enum SighandError {
|
|||
#[error("The signal fd is in an error state")]
|
||||
ErrorEvent,
|
||||
#[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")]
|
||||
BlockFailed(#[source] std::io::Error),
|
||||
BlockFailed(#[source] crate::utils::oserror::OsError),
|
||||
#[error("Could not create a signalfd")]
|
||||
CreateFailed(#[source] std::io::Error),
|
||||
CreateFailed(#[source] crate::utils::oserror::OsError),
|
||||
#[error("The event loop caused an error")]
|
||||
EventLoopError(#[from] EventLoopError),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use uapi::c;
|
|||
#[derive(Debug, Error)]
|
||||
pub enum TimeError {
|
||||
#[error("clock_gettime failed: {0}")]
|
||||
ClockGettime(std::io::Error),
|
||||
ClockGettime(crate::utils::oserror::OsError),
|
||||
}
|
||||
|
||||
#[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::marker::PhantomData;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{c, Errno, IntoUstr, Ustr};
|
||||
use uapi::{c, Errno, IntoUstr};
|
||||
|
||||
#[link(name = "udev")]
|
||||
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_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_devnum(udev_device: *mut udev_device) -> c::dev_t;
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UdevError {
|
||||
#[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")]
|
||||
NewMonitor(#[source] std::io::Error),
|
||||
NewMonitor(#[source] crate::utils::oserror::OsError),
|
||||
#[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")]
|
||||
EnableReceiving(#[source] std::io::Error),
|
||||
EnableReceiving(#[source] crate::utils::oserror::OsError),
|
||||
#[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")]
|
||||
EnumerateAddMatch(#[source] std::io::Error),
|
||||
EnumerateAddMatch(#[source] crate::utils::oserror::OsError),
|
||||
#[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")]
|
||||
ScanDevices(#[source] std::io::Error),
|
||||
ScanDevices(#[source] crate::utils::oserror::OsError),
|
||||
#[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")]
|
||||
GetSysname(#[source] std::io::Error),
|
||||
GetSysname(#[source] crate::utils::oserror::OsError),
|
||||
#[error("Could not retrieve the devnode of a udev_device")]
|
||||
GetDevnode(#[source] std::io::Error),
|
||||
GetDevnode(#[source] crate::utils::oserror::OsError),
|
||||
}
|
||||
|
||||
pub struct Udev {
|
||||
|
|
@ -193,9 +193,7 @@ impl UdevMonitor {
|
|||
}
|
||||
|
||||
pub fn receive_device(&self) -> Option<UdevDevice> {
|
||||
let res = unsafe {
|
||||
udev_monitor_receive_device(self.monitor)
|
||||
};
|
||||
let res = unsafe { udev_monitor_receive_device(self.monitor) };
|
||||
if res.is_null() {
|
||||
None
|
||||
} 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 {
|
||||
unsafe { udev_device_get_is_initialized(self.device) != 0 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ mod parser;
|
|||
#[derive(Debug, Error)]
|
||||
pub enum BufFdError {
|
||||
#[error("An IO error occurred")]
|
||||
Io(#[source] std::io::Error),
|
||||
Io(#[source] crate::utils::oserror::OsError),
|
||||
#[error("An async error occurred")]
|
||||
Async(#[from] AsyncError),
|
||||
#[error("The peer did not send a file descriptor")]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
pub mod array;
|
||||
pub mod asyncevent;
|
||||
pub mod bitfield;
|
||||
pub mod bitflags;
|
||||
pub mod buffd;
|
||||
pub mod clonecell;
|
||||
|
|
@ -9,12 +10,13 @@ pub mod errorfmt;
|
|||
pub mod hex;
|
||||
pub mod linkedlist;
|
||||
pub mod numcell;
|
||||
pub mod oserror;
|
||||
pub mod ptr_ext;
|
||||
pub mod queue;
|
||||
pub mod run_toplevel;
|
||||
pub mod smallmap;
|
||||
pub mod stack;
|
||||
pub mod tri;
|
||||
pub mod vasprintf;
|
||||
pub mod vec_ext;
|
||||
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)]
|
||||
pub enum WheelError {
|
||||
#[error("Could not create the timerfd: {0}")]
|
||||
CreateFailed(std::io::Error),
|
||||
CreateFailed(crate::utils::oserror::OsError),
|
||||
#[error("Could not set the timerfd: {0}")]
|
||||
SetFailed(std::io::Error),
|
||||
SetFailed(crate::utils::oserror::OsError),
|
||||
#[error("The timerfd is in an error state")]
|
||||
ErrorEvent,
|
||||
#[error("An event loop error occurred: {0}")]
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ use uapi::{c, pipe2, Errno, OwnedFd};
|
|||
#[derive(Debug, Error)]
|
||||
enum XWaylandError {
|
||||
#[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")]
|
||||
MissingSocketDir,
|
||||
#[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")]
|
||||
NotASocketDir,
|
||||
#[error("/tmp/.X11-unix is writable")]
|
||||
|
|
@ -38,17 +38,17 @@ enum XWaylandError {
|
|||
#[error("The socket is already in use")]
|
||||
AlreadyInUse,
|
||||
#[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")]
|
||||
AddressesInUse,
|
||||
#[error("The async engine returned an error")]
|
||||
AsyncError(#[from] AsyncError),
|
||||
#[error("pipe(2) failed")]
|
||||
Pipe(#[source] std::io::Error),
|
||||
Pipe(#[source] crate::utils::oserror::OsError),
|
||||
#[error("dupfd(2) failed")]
|
||||
Dupfd(#[source] std::io::Error),
|
||||
Dupfd(#[source] crate::utils::oserror::OsError),
|
||||
#[error("socketpair(2) failed")]
|
||||
Socketpair(#[source] std::io::Error),
|
||||
Socketpair(#[source] crate::utils::oserror::OsError),
|
||||
#[error("Could not start Xwayland")]
|
||||
ExecFailed(#[source] ForkerError),
|
||||
#[error("Could not load the atoms")]
|
||||
|
|
@ -224,7 +224,10 @@ async fn log_xwayland(state: Rc<State>, stderr: OwnedFd) {
|
|||
let mut done = false;
|
||||
while !done {
|
||||
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;
|
||||
}
|
||||
loop {
|
||||
|
|
@ -242,7 +245,7 @@ async fn log_xwayland(state: Rc<State>, stderr: OwnedFd) {
|
|||
Err(e) => {
|
||||
log::error!(
|
||||
"Could not read from stderr fd: {}",
|
||||
ErrorFmt(std::io::Error::from(e))
|
||||
ErrorFmt(crate::utils::oserror::OsError::from(e))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue