diff --git a/espanso-detect/src/evdev/mod.rs b/espanso-detect/src/evdev/mod.rs index 9faf115..e87c87f 100644 --- a/espanso-detect/src/evdev/mod.rs +++ b/espanso-detect/src/evdev/mod.rs @@ -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 for Option { diff --git a/espanso-detect/src/x11/mod.rs b/espanso-detect/src/x11/mod.rs index 36326ee..b753b31 100644 --- a/espanso-detect/src/x11/mod.rs +++ b/espanso-detect/src/x11/mod.rs @@ -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 for Option { diff --git a/espanso-ui/src/lib.rs b/espanso-ui/src/lib.rs index f1d6032..197d9eb 100644 --- a/espanso-ui/src/lib.rs +++ b/espanso-ui/src/lib.rs @@ -54,7 +54,8 @@ pub fn create_ui(options: UIOptions) -> Result<(Box, Box Result<(Box, Box)> { +pub fn create_ui(options: UIOptions) -> Result<(Box, Box)> { 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, Box Result<(Box, Box)> { 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))) } diff --git a/espanso-ui/src/linux/mod.rs b/espanso-ui/src/linux/mod.rs index 66a28e4..2ed70c2 100644 --- a/espanso-ui/src/linux/mod.rs +++ b/espanso-ui/src/linux/mod.rs @@ -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(()) } }