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
|
||||
// NOTE: Hotkeys don't work under the EVDEV backend yet (Wayland)
|
||||
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
|
||||
|
@ -80,6 +86,7 @@ impl Default for SourceCreationOptions {
|
|||
use_evdev: false,
|
||||
evdev_keyboard_rmlvo: None,
|
||||
hotkeys: Vec::new(),
|
||||
win32_exclude_orphan_events: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +94,7 @@ impl Default for SourceCreationOptions {
|
|||
#[cfg(target_os = "windows")]
|
||||
pub fn get_source(options: SourceCreationOptions) -> Result<Box<dyn Source>> {
|
||||
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")]
|
||||
|
@ -115,4 +122,4 @@ pub fn get_source(options: SourceCreationOptions) -> Result<Box<dyn Source>> {
|
|||
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 variant: 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)]
|
||||
|
@ -91,15 +97,18 @@ pub struct Win32Source {
|
|||
handle: *mut c_void,
|
||||
callback: LazyCell<SourceCallback>,
|
||||
hotkeys: Vec<HotKey>,
|
||||
|
||||
exclude_orphan_events: bool,
|
||||
}
|
||||
|
||||
#[allow(clippy::new_without_default)]
|
||||
impl Win32Source {
|
||||
pub fn new(hotkeys: &[HotKey]) -> Win32Source {
|
||||
pub fn new(hotkeys: &[HotKey], exclude_orphan_events: bool) -> Win32Source {
|
||||
Self {
|
||||
handle: std::ptr::null_mut(),
|
||||
callback: LazyCell::new(),
|
||||
hotkeys: hotkeys.to_vec(),
|
||||
exclude_orphan_events,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,6 +157,16 @@ impl Source for Win32Source {
|
|||
}
|
||||
|
||||
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();
|
||||
if let Some(callback) = unsafe { (*_self).callback.borrow() } {
|
||||
if let Some(event) = event {
|
||||
|
@ -391,6 +410,7 @@ mod tests {
|
|||
key_code: 0,
|
||||
variant: INPUT_LEFT_VARIANT,
|
||||
status: INPUT_STATUS_PRESSED,
|
||||
has_known_source: 1,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,6 +479,7 @@ mod tests {
|
|||
key_code: 123,
|
||||
variant: INPUT_LEFT_VARIANT,
|
||||
status: INPUT_STATUS_PRESSED,
|
||||
has_known_source: 1,
|
||||
}
|
||||
.into();
|
||||
assert!(result.is_none());
|
||||
|
|
|
@ -121,6 +121,8 @@ LRESULT CALLBACK detect_window_procedure(HWND window, unsigned int msg, WPARAM w
|
|||
return 0;
|
||||
}
|
||||
|
||||
event.has_known_source = (raw->header.hDevice == 0) ? 0 : 1;
|
||||
|
||||
// The alt key sends a SYSKEYDOWN instead of KEYDOWN event
|
||||
int is_key_down = raw->data.keyboard.Message == WM_KEYDOWN ||
|
||||
raw->data.keyboard.Message == WM_SYSKEYDOWN;
|
||||
|
|
|
@ -60,6 +60,12 @@ typedef struct {
|
|||
|
||||
// Pressed or Released 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;
|
||||
|
||||
typedef struct {
|
||||
|
|
Loading…
Reference in New Issue
Block a user