Refactor linux methods

This commit is contained in:
Federico Terzi 2021-02-18 19:51:45 +01:00
parent 75ca7ec071
commit 79a1b85769
4 changed files with 42 additions and 16 deletions
espanso-detect/src
evdev
x11
espanso-ui/src

View File

@ -100,9 +100,10 @@ impl Source for EVDEVSource {
Ok(())
}
fn eventloop(&self, event_callback: SourceCallback) {
fn eventloop(&self, event_callback: SourceCallback) -> Result<()> {
if self.devices.is_empty() {
panic!("can't start eventloop without evdev devices");
error!("can't start eventloop without evdev devices");
return Err(EVDEVSourceError::NoDevices().into());
}
let raw_epfd = unsafe { libc::epoll_create1(0) };
@ -111,7 +112,8 @@ impl Source for EVDEVSource {
});
if *epfd < 0 {
panic!("could not create epoll instance");
error!("could not create epoll instance");
return Err(EVDEVSourceError::Internal().into());
}
// Setup epoll for all input devices
@ -121,11 +123,12 @@ impl Source for EVDEVSource {
ev.events = EPOLLIN as u32;
ev.u64 = i as u64;
if unsafe { epoll_ctl(*epfd, EPOLL_CTL_ADD, device.get_raw_fd(), &mut ev) } != 0 {
panic!(format!(
error!(
"Could not add {} to epoll, errno {}",
device.get_path(),
unsafe { *errno_ptr }
));
);
return Err(EVDEVSourceError::Internal().into());
}
}
@ -137,9 +140,10 @@ impl Source for EVDEVSource {
if unsafe { *errno_ptr } == EINTR {
continue;
} else {
panic!(format!("Could not poll for events, {}", unsafe {
error!("Could not poll for events, {}", unsafe {
*errno_ptr
}))
});
return Err(EVDEVSourceError::Internal().into());
}
}
@ -172,6 +176,12 @@ pub enum EVDEVSourceError {
#[error("permission denied")]
PermissionDenied(),
#[error("no devices")]
NoDevices(),
#[error("internal error")]
Internal(),
}
impl From<RawInputEvent> for Option<InputEvent> {

View File

@ -114,13 +114,15 @@ impl Source for X11Source {
Ok(())
}
fn eventloop(&self, event_callback: SourceCallback) {
fn eventloop(&self, event_callback: SourceCallback) -> Result<()> {
if self.handle.is_null() {
panic!("Attempt to start X11Source eventloop without initialization");
error!("Attempt to start X11Source eventloop without initialization");
return Err(X11SourceError::Internal().into());
}
if self.callback.fill(event_callback).is_err() {
panic!("Unable to set X11Source event callback");
error!("Unable to set X11Source event callback");
return Err(X11SourceError::Internal().into());
}
extern "C" fn callback(_self: *mut X11Source, event: RawInputEvent) {
@ -137,8 +139,11 @@ impl Source for X11Source {
let error_code = unsafe { detect_eventloop(self.handle, callback) };
if error_code <= 0 {
panic!("X11Source eventloop returned a negative error code");
error!("X11Source eventloop returned a negative error code");
return Err(X11SourceError::Internal().into());
}
Ok(())
}
}
@ -173,6 +178,9 @@ pub enum X11SourceError {
#[error("unknown error")]
Unknown(),
#[error("internal error")]
Internal(),
}
impl From<RawInputEvent> for Option<InputEvent> {

View File

@ -54,7 +54,8 @@ pub fn create_ui(options: UIOptions) -> Result<(Box<dyn UIRemote>, Box<dyn UIEve
}
#[cfg(target_os = "macos")]
pub fn create_ui(options: UIOptions) -> Result<(Box<dyn UIRemote>, Box<dyn UIEventLoop>)> {
pub fn create_ui(options: UIOptions) -> Result<(Box<dyn UIRemote>, Box<dyn
UIEventLoop>)> {
let (remote, eventloop) = mac::create(mac::MacUIOptions {
show_icon: options.show_icon,
icon_paths: &options.icon_paths,
@ -65,7 +66,7 @@ pub fn create_ui(options: UIOptions) -> Result<(Box<dyn UIRemote>, Box<dyn UIEve
#[cfg(target_os = "linux")]
pub fn create_ui(options: UIOptions) -> Result<(Box<dyn UIRemote>, Box<dyn UIEventLoop>)> {
let (remote, eventloop) = linux::create(linux::LinuxUIOptions {
notification_icon_path: options.notification_icon_path.ok_or(UIError::MissingOption("notification icon".to_string()))?,
notification_icon_path: options.notification_icon_path.ok_or_else(|| UIError::MissingOption("notification icon".to_string()))?,
});
Ok((Box::new(remote), Box::new(eventloop)))
}

View File

@ -1,4 +1,5 @@
use log::error;
use anyhow::Result;
use notify_rust::Notification;
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
@ -66,13 +67,19 @@ impl LinuxEventLoop {
}
impl UIEventLoop for LinuxEventLoop {
fn initialize(&mut self) {
fn initialize(&mut self) -> Result<()> {
// NOOP on linux
Ok(())
}
fn run(&self, _: crate::UIEventCallback) {
fn run(&self, _: crate::UIEventCallback) -> Result<()> {
// We don't run an event loop on Linux as there is no tray icon or application window needed.
// Thad said, we still need a way to block this method, and thus we use a channel
self.rx.recv().expect("Unable to block the LinuxEventLoop");
if let Err(error) = self.rx.recv() {
error!("Unable to block the LinuxEventLoop: {}", error);
return Err(error.into());
}
Ok(())
}
}