Improve detect error handling

This commit is contained in:
Federico Terzi 2021-02-08 17:16:35 +01:00
parent 2f04f174b7
commit bee2001e28
6 changed files with 80 additions and 20 deletions

View File

@ -8,14 +8,14 @@ build="build.rs"
[dependencies] [dependencies]
log = "0.4.14" log = "0.4.14"
lazycell = "1.3.0" lazycell = "1.3.0"
anyhow = "1.0.38"
thiserror = "1.0.23"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
widestring = "0.4.3" widestring = "0.4.3"
[target.'cfg(target_os="linux")'.dependencies] [target.'cfg(target_os="linux")'.dependencies]
libc = "0.2.85" libc = "0.2.85"
anyhow = "1.0.38"
thiserror = "1.0.23"
scopeguard = "1.1.0" scopeguard = "1.1.0"
[build-dependencies] [build-dependencies]

View File

@ -32,6 +32,8 @@ use libc::{
__errno_location, close, epoll_ctl, epoll_event, epoll_wait, EINTR, EPOLLIN, EPOLL_CTL_ADD, __errno_location, close, epoll_ctl, epoll_event, epoll_wait, EINTR, EPOLLIN, EPOLL_CTL_ADD,
}; };
use log::{error, trace}; use log::{error, trace};
use anyhow::Result;
use thiserror::Error;
use crate::event::Status::*; use crate::event::Status::*;
use crate::event::Variant::*; 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 context = Context::new().expect("unable to obtain xkb context");
let keymap = Keymap::new(&context).expect("unable to create xkb keymap"); let keymap = Keymap::new(&context).expect("unable to create xkb keymap");
match get_devices(&keymap) { match get_devices(&keymap) {
@ -71,11 +73,14 @@ impl EVDEVSource {
error!( error!(
"You can either add the current user to the 'input' group or run espanso as root" "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) { 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<RawInputEvent> for Option<InputEvent> { impl From<RawInputEvent> for Option<InputEvent> {
fn from(raw: RawInputEvent) -> Option<InputEvent> { fn from(raw: RawInputEvent) -> Option<InputEvent> {
match raw { match raw {

View File

@ -23,6 +23,9 @@ use lazycell::LazyCell;
use log::{error, trace, warn}; use log::{error, trace, warn};
use widestring::U16CStr; use widestring::U16CStr;
use anyhow::Result;
use thiserror::Error;
use crate::event::Status::*; use crate::event::Status::*;
use crate::event::Variant::*; use crate::event::Variant::*;
use crate::event::{InputEvent, Key, KeyboardEvent, Variant}; use crate::event::{InputEvent, Key, KeyboardEvent, Variant};
@ -62,7 +65,7 @@ pub struct RawInputEvent {
#[allow(improper_ctypes)] #[allow(improper_ctypes)]
#[link(name = "espansodetect", kind = "static")] #[link(name = "espansodetect", kind = "static")]
extern "C" { 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( pub fn detect_eventloop(
window: *const c_void, window: *const c_void,
@ -87,14 +90,22 @@ impl Win32Source {
} }
} }
pub fn initialize(&mut self) { pub fn initialize(&mut self) -> Result<()> {
let handle = unsafe { detect_initialize(self as *const Win32Source) }; let mut error_code = 0;
let handle = unsafe { detect_initialize(self as *const Win32Source, &mut error_code) };
if handle.is_null() { 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; self.handle = handle;
Ok(())
} }
pub fn eventloop(&self, event_callback: Win32SourceCallback) { 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<RawInputEvent> for Option<InputEvent> { impl From<RawInputEvent> for Option<InputEvent> {
fn from(raw: RawInputEvent) -> Option<InputEvent> { fn from(raw: RawInputEvent) -> Option<InputEvent> {
let status = match raw.status { let status = match raw.status {

View File

@ -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; HWND window = NULL;
@ -308,12 +308,14 @@ void * detect_initialize(void *_self)
if (RegisterRawInputDevices(Rid, 2, sizeof(Rid[0])) == FALSE) if (RegisterRawInputDevices(Rid, 2, sizeof(Rid[0])) == FALSE)
{ // Something went wrong, error. { // Something went wrong, error.
*error_code = -2;
return nullptr; return nullptr;
} }
} }
else else
{ {
// Something went wrong, error. // Something went wrong, error.
*error_code = -1;
return nullptr; return nullptr;
} }

View File

@ -64,7 +64,7 @@ typedef void (*EventCallback)(void * rust_istance, InputEvent data);
// Initialize the Raw Input API and the Window. // 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. // Run the event loop. Blocking call.
extern "C" int32_t detect_eventloop(void * window, EventCallback callback); extern "C" int32_t detect_eventloop(void * window, EventCallback callback);

View File

@ -24,6 +24,9 @@ use std::{
use lazycell::LazyCell; use lazycell::LazyCell;
use log::{error, trace, warn}; use log::{error, trace, warn};
use anyhow::Result;
use thiserror::Error;
use crate::event::Status::*; use crate::event::Status::*;
use crate::event::Variant::*; use crate::event::Variant::*;
use crate::event::{InputEvent, Key, KeyboardEvent, Variant}; use crate::event::{InputEvent, Key, KeyboardEvent, Variant};
@ -88,23 +91,26 @@ impl X11Source {
unsafe { detect_check_x11() != 0 } unsafe { detect_check_x11() != 0 }
} }
pub fn initialize(&mut self) { pub fn initialize(&mut self) -> Result<()> {
let mut error_code = 0; let mut error_code = 0;
let handle = unsafe { detect_initialize(self as *const X11Source, &mut error_code) }; let handle = unsafe { detect_initialize(self as *const X11Source, &mut error_code) };
if handle.is_null() { if handle.is_null() {
match error_code { let error = match error_code {
-1 => panic!("Unable to initialize X11Source, cannot open displays"), -1 => X11SourceError::DisplayFailure(),
-2 => panic!("Unable to initialize X11Source, X Record Extension is not installed"), -2 => X11SourceError::XRecordMissing(),
-3 => panic!("Unable to initialize X11Source, X Keyboard Extension is not installed"), -3 => X11SourceError::XKeyboardMissing(),
-4 => panic!("Unable to initialize X11Source, cannot initialize record range"), -4 => X11SourceError::FailedRegistration("cannot initialize record range".to_owned()),
-5 => panic!("Unable to initialize X11Source, cannot initialize XRecord context"), -5 => X11SourceError::FailedRegistration("cannot initialize XRecord context".to_owned()),
-6 => panic!("Unable to initialize X11Source, cannot enable XRecord context"), -6 => X11SourceError::FailedRegistration("cannot enable XRecord context".to_owned()),
_ => panic!("Unable to initialize X11Source, unknown error"), _ => X11SourceError::Unknown(),
} };
return Err(error.into())
} }
self.handle = handle; self.handle = handle;
Ok(())
} }
pub fn eventloop(&self, event_callback: X11SourceCallback) { 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<RawInputEvent> for Option<InputEvent> { impl From<RawInputEvent> for Option<InputEvent> {
fn from(raw: RawInputEvent) -> Option<InputEvent> { fn from(raw: RawInputEvent) -> Option<InputEvent> {
let status = match raw.status { let status = match raw.status {