fix(detect): exclude software-generated events by default on Windows to avoid reading back espanso's events
This commit is contained in:
parent
2129494ae3
commit
53eef3ce7b
|
@ -60,6 +60,12 @@ pub struct SourceCreationOptions {
|
||||||
// List of global hotkeys the detection module has to register
|
// List of global hotkeys the detection module has to register
|
||||||
// NOTE: Hotkeys don't work under the EVDEV backend yet (Wayland)
|
// NOTE: Hotkeys don't work under the EVDEV backend yet (Wayland)
|
||||||
pub hotkeys: Vec<HotKey>,
|
pub hotkeys: Vec<HotKey>,
|
||||||
|
|
||||||
|
// If true, filter out keyboard events without an explicit HID device source on Windows.
|
||||||
|
// This is needed to filter out the software-generated events, including
|
||||||
|
// those from espanso, but might need to be disabled when using some software-level keyboards.
|
||||||
|
// Disabling this option might conflict with the undo feature.
|
||||||
|
pub win32_exclude_orphan_events: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This struct identifies the keyboard layout that
|
// This struct identifies the keyboard layout that
|
||||||
|
@ -80,6 +86,7 @@ impl Default for SourceCreationOptions {
|
||||||
use_evdev: false,
|
use_evdev: false,
|
||||||
evdev_keyboard_rmlvo: None,
|
evdev_keyboard_rmlvo: None,
|
||||||
hotkeys: Vec::new(),
|
hotkeys: Vec::new(),
|
||||||
|
win32_exclude_orphan_events: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +94,7 @@ impl Default for SourceCreationOptions {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub fn get_source(options: SourceCreationOptions) -> Result<Box<dyn Source>> {
|
pub fn get_source(options: SourceCreationOptions) -> Result<Box<dyn Source>> {
|
||||||
info!("using Win32Source");
|
info!("using Win32Source");
|
||||||
Ok(Box::new(win32::Win32Source::new(&options.hotkeys)))
|
Ok(Box::new(win32::Win32Source::new(&options.hotkeys, options.win32_exclude_orphan_events)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
@ -115,4 +122,4 @@ pub fn get_source(options: SourceCreationOptions) -> Result<Box<dyn Source>> {
|
||||||
Ok(Box::new(evdev::EVDEVSource::new(options)))
|
Ok(Box::new(evdev::EVDEVSource::new(options)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use layout::get_active_layout;
|
pub use layout::get_active_layout;
|
||||||
|
|
|
@ -64,6 +64,12 @@ pub struct RawInputEvent {
|
||||||
pub key_code: i32,
|
pub key_code: i32,
|
||||||
pub variant: i32,
|
pub variant: i32,
|
||||||
pub status: i32,
|
pub status: i32,
|
||||||
|
|
||||||
|
// Only relevant for keyboard events, this is set to 1
|
||||||
|
// if a keyboard event has an explicit source, 0 otherwise.
|
||||||
|
// This is needed to filter out software generated events,
|
||||||
|
// including those from espanso.
|
||||||
|
pub has_known_source: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -91,15 +97,18 @@ pub struct Win32Source {
|
||||||
handle: *mut c_void,
|
handle: *mut c_void,
|
||||||
callback: LazyCell<SourceCallback>,
|
callback: LazyCell<SourceCallback>,
|
||||||
hotkeys: Vec<HotKey>,
|
hotkeys: Vec<HotKey>,
|
||||||
|
|
||||||
|
exclude_orphan_events: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::new_without_default)]
|
#[allow(clippy::new_without_default)]
|
||||||
impl Win32Source {
|
impl Win32Source {
|
||||||
pub fn new(hotkeys: &[HotKey]) -> Win32Source {
|
pub fn new(hotkeys: &[HotKey], exclude_orphan_events: bool) -> Win32Source {
|
||||||
Self {
|
Self {
|
||||||
handle: std::ptr::null_mut(),
|
handle: std::ptr::null_mut(),
|
||||||
callback: LazyCell::new(),
|
callback: LazyCell::new(),
|
||||||
hotkeys: hotkeys.to_vec(),
|
hotkeys: hotkeys.to_vec(),
|
||||||
|
exclude_orphan_events,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,6 +157,16 @@ impl Source for Win32Source {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn callback(_self: *mut Win32Source, event: RawInputEvent) {
|
extern "C" fn callback(_self: *mut Win32Source, event: RawInputEvent) {
|
||||||
|
// Filter out keyboard events without an explicit HID device source.
|
||||||
|
// This is needed to filter out the software-generated events, including
|
||||||
|
// those from espanso.
|
||||||
|
if event.event_type == INPUT_EVENT_TYPE_KEYBOARD && event.has_known_source == 0 {
|
||||||
|
if unsafe { (*_self).exclude_orphan_events } {
|
||||||
|
trace!("skipping keyboard event with unknown HID source (probably software generated).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let event: Option<InputEvent> = event.into();
|
let event: Option<InputEvent> = event.into();
|
||||||
if let Some(callback) = unsafe { (*_self).callback.borrow() } {
|
if let Some(callback) = unsafe { (*_self).callback.borrow() } {
|
||||||
if let Some(event) = event {
|
if let Some(event) = event {
|
||||||
|
@ -391,6 +410,7 @@ mod tests {
|
||||||
key_code: 0,
|
key_code: 0,
|
||||||
variant: INPUT_LEFT_VARIANT,
|
variant: INPUT_LEFT_VARIANT,
|
||||||
status: INPUT_STATUS_PRESSED,
|
status: INPUT_STATUS_PRESSED,
|
||||||
|
has_known_source: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,6 +479,7 @@ mod tests {
|
||||||
key_code: 123,
|
key_code: 123,
|
||||||
variant: INPUT_LEFT_VARIANT,
|
variant: INPUT_LEFT_VARIANT,
|
||||||
status: INPUT_STATUS_PRESSED,
|
status: INPUT_STATUS_PRESSED,
|
||||||
|
has_known_source: 1,
|
||||||
}
|
}
|
||||||
.into();
|
.into();
|
||||||
assert!(result.is_none());
|
assert!(result.is_none());
|
||||||
|
|
|
@ -121,6 +121,8 @@ LRESULT CALLBACK detect_window_procedure(HWND window, unsigned int msg, WPARAM w
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event.has_known_source = (raw->header.hDevice == 0) ? 0 : 1;
|
||||||
|
|
||||||
// The alt key sends a SYSKEYDOWN instead of KEYDOWN event
|
// The alt key sends a SYSKEYDOWN instead of KEYDOWN event
|
||||||
int is_key_down = raw->data.keyboard.Message == WM_KEYDOWN ||
|
int is_key_down = raw->data.keyboard.Message == WM_KEYDOWN ||
|
||||||
raw->data.keyboard.Message == WM_SYSKEYDOWN;
|
raw->data.keyboard.Message == WM_SYSKEYDOWN;
|
||||||
|
|
|
@ -60,6 +60,12 @@ typedef struct {
|
||||||
|
|
||||||
// Pressed or Released status
|
// Pressed or Released status
|
||||||
int32_t status;
|
int32_t status;
|
||||||
|
|
||||||
|
// Only relevant for keyboard events, this is set to 1
|
||||||
|
// if a keyboard event has an explicit source, 0 otherwise.
|
||||||
|
// This is needed to filter out software generated events,
|
||||||
|
// including those from espanso.
|
||||||
|
int32_t has_known_source;
|
||||||
} InputEvent;
|
} InputEvent;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user