From bee2001e28ac89bd65f718314fc040fef6794dbd Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Mon, 8 Feb 2021 17:16:35 +0100 Subject: [PATCH] Improve detect error handling --- espanso-detect/Cargo.toml | 4 +-- espanso-detect/src/evdev/mod.rs | 15 ++++++++-- espanso-detect/src/win32/mod.rs | 31 +++++++++++++++++--- espanso-detect/src/win32/native.cpp | 4 ++- espanso-detect/src/win32/native.h | 2 +- espanso-detect/src/x11/mod.rs | 44 ++++++++++++++++++++++------- 6 files changed, 80 insertions(+), 20 deletions(-) diff --git a/espanso-detect/Cargo.toml b/espanso-detect/Cargo.toml index c314944..ab5bc5e 100644 --- a/espanso-detect/Cargo.toml +++ b/espanso-detect/Cargo.toml @@ -8,14 +8,14 @@ build="build.rs" [dependencies] log = "0.4.14" lazycell = "1.3.0" +anyhow = "1.0.38" +thiserror = "1.0.23" [target.'cfg(windows)'.dependencies] widestring = "0.4.3" [target.'cfg(target_os="linux")'.dependencies] libc = "0.2.85" -anyhow = "1.0.38" -thiserror = "1.0.23" scopeguard = "1.1.0" [build-dependencies] diff --git a/espanso-detect/src/evdev/mod.rs b/espanso-detect/src/evdev/mod.rs index 7ab06d7..37f3cde 100644 --- a/espanso-detect/src/evdev/mod.rs +++ b/espanso-detect/src/evdev/mod.rs @@ -32,6 +32,8 @@ use libc::{ __errno_location, close, epoll_ctl, epoll_event, epoll_wait, EINTR, EPOLLIN, EPOLL_CTL_ADD, }; use log::{error, trace}; +use anyhow::Result; +use thiserror::Error; use crate::event::Status::*; use crate::event::Variant::*; @@ -59,7 +61,7 @@ impl EVDEVSource { } } - pub fn initialize(&mut self) { + pub fn initialize(&mut self) -> Result<()> { let context = Context::new().expect("unable to obtain xkb context"); let keymap = Keymap::new(&context).expect("unable to create xkb keymap"); match get_devices(&keymap) { @@ -71,11 +73,14 @@ impl EVDEVSource { error!( "You can either add the current user to the 'input' group or run espanso as root" ); + return Err(EVDEVSourceError::PermissionDenied().into()) } } - panic!("error when initilizing EVDEV source {}", error); + return Err(error) } } + + Ok(()) } pub fn eventloop(&self, event_callback: EVDEVSourceCallback) { @@ -143,6 +148,12 @@ impl EVDEVSource { } } +#[derive(Error, Debug)] +pub enum EVDEVSourceError { + #[error("permission denied")] + PermissionDenied(), +} + impl From for Option { fn from(raw: RawInputEvent) -> Option { match raw { diff --git a/espanso-detect/src/win32/mod.rs b/espanso-detect/src/win32/mod.rs index 6d1ee33..87475a7 100644 --- a/espanso-detect/src/win32/mod.rs +++ b/espanso-detect/src/win32/mod.rs @@ -23,6 +23,9 @@ use lazycell::LazyCell; use log::{error, trace, warn}; use widestring::U16CStr; +use anyhow::Result; +use thiserror::Error; + use crate::event::Status::*; use crate::event::Variant::*; use crate::event::{InputEvent, Key, KeyboardEvent, Variant}; @@ -62,7 +65,7 @@ pub struct RawInputEvent { #[allow(improper_ctypes)] #[link(name = "espansodetect", kind = "static")] extern "C" { - pub fn detect_initialize(_self: *const Win32Source) -> *mut c_void; + pub fn detect_initialize(_self: *const Win32Source, error_code: *mut i32) -> *mut c_void; pub fn detect_eventloop( window: *const c_void, @@ -87,14 +90,22 @@ impl Win32Source { } } - pub fn initialize(&mut self) { - let handle = unsafe { detect_initialize(self as *const Win32Source) }; + pub fn initialize(&mut self) -> Result<()> { + let mut error_code = 0; + let handle = unsafe { detect_initialize(self as *const Win32Source, &mut error_code) }; if handle.is_null() { - panic!("Unable to initialize Win32Source"); + let error = match error_code { + -1 => Win32SourceError::WindowFailed(), + -2 => Win32SourceError::RawInputFailed(), + _ => Win32SourceError::Unknown(), + }; + return Err(error.into()) } self.handle = handle; + + Ok(()) } pub fn eventloop(&self, event_callback: Win32SourceCallback) { @@ -140,6 +151,18 @@ impl Drop for Win32Source { } } +#[derive(Error, Debug)] +pub enum Win32SourceError { + #[error("window registration failed")] + WindowFailed(), + + #[error("raw input API failed")] + RawInputFailed(), + + #[error("unknown error")] + Unknown(), +} + impl From for Option { fn from(raw: RawInputEvent) -> Option { let status = match raw.status { diff --git a/espanso-detect/src/win32/native.cpp b/espanso-detect/src/win32/native.cpp index 9e7db4f..51065ec 100644 --- a/espanso-detect/src/win32/native.cpp +++ b/espanso-detect/src/win32/native.cpp @@ -246,7 +246,7 @@ LRESULT CALLBACK detect_window_procedure(HWND window, unsigned int msg, WPARAM w } } -void * detect_initialize(void *_self) +void * detect_initialize(void *_self, int32_t *error_code) { HWND window = NULL; @@ -308,12 +308,14 @@ void * detect_initialize(void *_self) if (RegisterRawInputDevices(Rid, 2, sizeof(Rid[0])) == FALSE) { // Something went wrong, error. + *error_code = -2; return nullptr; } } else { // Something went wrong, error. + *error_code = -1; return nullptr; } diff --git a/espanso-detect/src/win32/native.h b/espanso-detect/src/win32/native.h index eeb6d7a..7ba3f09 100644 --- a/espanso-detect/src/win32/native.h +++ b/espanso-detect/src/win32/native.h @@ -64,7 +64,7 @@ typedef void (*EventCallback)(void * rust_istance, InputEvent data); // Initialize the Raw Input API and the Window. -extern "C" void * detect_initialize(void * rust_istance); +extern "C" void * detect_initialize(void * rust_istance, int32_t *error_code); // Run the event loop. Blocking call. extern "C" int32_t detect_eventloop(void * window, EventCallback callback); diff --git a/espanso-detect/src/x11/mod.rs b/espanso-detect/src/x11/mod.rs index 9971ded..a3d15be 100644 --- a/espanso-detect/src/x11/mod.rs +++ b/espanso-detect/src/x11/mod.rs @@ -24,6 +24,9 @@ use std::{ use lazycell::LazyCell; use log::{error, trace, warn}; +use anyhow::Result; +use thiserror::Error; + use crate::event::Status::*; use crate::event::Variant::*; use crate::event::{InputEvent, Key, KeyboardEvent, Variant}; @@ -88,23 +91,26 @@ impl X11Source { unsafe { detect_check_x11() != 0 } } - pub fn initialize(&mut self) { + pub fn initialize(&mut self) -> Result<()> { let mut error_code = 0; let handle = unsafe { detect_initialize(self as *const X11Source, &mut error_code) }; if handle.is_null() { - match error_code { - -1 => panic!("Unable to initialize X11Source, cannot open displays"), - -2 => panic!("Unable to initialize X11Source, X Record Extension is not installed"), - -3 => panic!("Unable to initialize X11Source, X Keyboard Extension is not installed"), - -4 => panic!("Unable to initialize X11Source, cannot initialize record range"), - -5 => panic!("Unable to initialize X11Source, cannot initialize XRecord context"), - -6 => panic!("Unable to initialize X11Source, cannot enable XRecord context"), - _ => panic!("Unable to initialize X11Source, unknown error"), - } + let error = match error_code { + -1 => X11SourceError::DisplayFailure(), + -2 => X11SourceError::XRecordMissing(), + -3 => X11SourceError::XKeyboardMissing(), + -4 => X11SourceError::FailedRegistration("cannot initialize record range".to_owned()), + -5 => X11SourceError::FailedRegistration("cannot initialize XRecord context".to_owned()), + -6 => X11SourceError::FailedRegistration("cannot enable XRecord context".to_owned()), + _ => X11SourceError::Unknown(), + }; + return Err(error.into()) } self.handle = handle; + + Ok(()) } pub fn eventloop(&self, event_callback: X11SourceCallback) { @@ -150,6 +156,24 @@ impl Drop for X11Source { } } +#[derive(Error, Debug)] +pub enum X11SourceError { + #[error("cannot open displays")] + DisplayFailure(), + + #[error("X Record Extension is not installed")] + XRecordMissing(), + + #[error("X Keyboard Extension is not installed")] + XKeyboardMissing(), + + #[error("failed registration: ${0}")] + FailedRegistration(String), + + #[error("unknown error")] + Unknown(), +} + impl From for Option { fn from(raw: RawInputEvent) -> Option { let status = match raw.status {