Prevent espanso crash when an X11 exception occurs. Fix #312

This commit is contained in:
Federico Terzi 2020-06-22 19:09:51 +02:00
parent 34c0a52455
commit 6766d91af3
4 changed files with 39 additions and 2 deletions

View File

@ -77,14 +77,20 @@ xdo_t * xdo_context;
// Callback invoked when a new key event occur. // Callback invoked when a new key event occur.
void event_callback (XPointer, XRecordInterceptData*); void event_callback (XPointer, XRecordInterceptData*);
int error_callback(Display *display, XErrorEvent *error);
KeypressCallback keypress_callback; KeypressCallback keypress_callback;
X11ErrorCallback x11_error_callback;
void * context_instance; void * context_instance;
void register_keypress_callback(KeypressCallback callback) { void register_keypress_callback(KeypressCallback callback) {
keypress_callback = callback; keypress_callback = callback;
} }
void register_error_callback(X11ErrorCallback callback) {
x11_error_callback = callback;
}
int32_t check_x11() { int32_t check_x11() {
Display *check_disp = XOpenDisplay(NULL); Display *check_disp = XOpenDisplay(NULL);
@ -156,6 +162,9 @@ int32_t initialize(void * _context_instance) {
xdo_context = xdo_new(NULL); xdo_context = xdo_new(NULL);
// Setup a custom error handler
XSetErrorHandler(&error_callback);
/** /**
* Note: We might never get a MappingNotify event if the * Note: We might never get a MappingNotify event if the
* modifier and keymap information was never cached in Xlib. * modifier and keymap information was never cached in Xlib.
@ -272,6 +281,11 @@ void event_callback(XPointer p, XRecordInterceptData *hook)
XRecordFreeData(hook); XRecordFreeData(hook);
} }
int error_callback(Display *display, XErrorEvent *error) {
x11_error_callback(context_instance, error->error_code, error->request_code, error->minor_code);
return 0;
}
void release_all_keys() { void release_all_keys() {
char keys[32]; char keys[32];
XQueryKeymap(xdo_context->xdpy, keys); // Get the current status of the keyboard XQueryKeymap(xdo_context->xdpy, keys); // Get the current status of the keyboard

View File

@ -49,7 +49,6 @@ extern "C" void cleanup();
* while the second is the size of the array. * while the second is the size of the array.
*/ */
typedef void (*KeypressCallback)(void * self, const char *buffer, int32_t len, int32_t event_type, int32_t key_code); typedef void (*KeypressCallback)(void * self, const char *buffer, int32_t len, int32_t event_type, int32_t key_code);
extern KeypressCallback keypress_callback; extern KeypressCallback keypress_callback;
/* /*
@ -57,6 +56,17 @@ extern KeypressCallback keypress_callback;
*/ */
extern "C" void register_keypress_callback(KeypressCallback callback); extern "C" void register_keypress_callback(KeypressCallback callback);
/*
* Called when a X11 error occurs
*/
typedef void (*X11ErrorCallback)(void * self, char error_code, char request_code, char minor_code);
extern X11ErrorCallback x11_error_callback;
/*
* Register the callback that will be called when an X11 error occurs
*/
extern "C" void register_error_callback(X11ErrorCallback callback);
/* /*
* Type the given string by simulating Key Presses * Type the given string by simulating Key Presses
*/ */

View File

@ -32,6 +32,9 @@ extern "C" {
pub fn get_active_window_class(buffer: *mut c_char, size: i32) -> i32; pub fn get_active_window_class(buffer: *mut c_char, size: i32) -> i32;
pub fn get_active_window_executable(buffer: *mut c_char, size: i32) -> i32; pub fn get_active_window_executable(buffer: *mut c_char, size: i32) -> i32;
pub fn is_current_window_special() -> i32; pub fn is_current_window_special() -> i32;
pub fn register_error_callback(
cb: extern "C" fn(_self: *mut c_void, error_code: c_char, request_code: c_char, minor_code: c_char),
);
// Keyboard // Keyboard
pub fn register_keypress_callback( pub fn register_keypress_callback(

View File

@ -21,7 +21,7 @@ use crate::bridge::linux::*;
use crate::config::Configs; use crate::config::Configs;
use crate::event::KeyModifier::*; use crate::event::KeyModifier::*;
use crate::event::*; use crate::event::*;
use log::{debug, error}; use log::{debug, error, warn};
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw::{c_char, c_void}; use std::os::raw::{c_char, c_void};
use std::process::exit; use std::process::exit;
@ -59,6 +59,7 @@ impl LinuxContext {
let context_ptr = &*context as *const LinuxContext as *const c_void; let context_ptr = &*context as *const LinuxContext as *const c_void;
register_keypress_callback(keypress_callback); register_keypress_callback(keypress_callback);
register_error_callback(error_callback);
let res = initialize(context_ptr); let res = initialize(context_ptr);
if res <= 0 { if res <= 0 {
@ -155,3 +156,12 @@ extern "C" fn keypress_callback(
} }
} }
} }
extern "C" fn error_callback(
_self: *mut c_void,
error_code: c_char,
request_code: c_char,
minor_code: c_char,
) {
warn!("X11 reported an error code: {}, request_code: {} and minor_code: {}", error_code, request_code, minor_code);
}