diff --git a/espanso/src/cli/worker/engine/funnel/detect.rs b/espanso/src/cli/worker/engine/funnel/detect.rs index f0a074f..c587f30 100644 --- a/espanso/src/cli/worker/engine/funnel/detect.rs +++ b/espanso/src/cli/worker/engine/funnel/detect.rs @@ -37,12 +37,12 @@ impl<'a> funnel::Source<'a> for DetectSource { select.recv(&self.receiver) } - fn receive(&self, op: SelectedOperation) -> Event { + fn receive(&self, op: SelectedOperation) -> Option { let (input_event, source_id) = op .recv(&self.receiver) .expect("unable to select data from DetectSource receiver"); match input_event { - InputEvent::Keyboard(keyboard_event) => Event { + InputEvent::Keyboard(keyboard_event) => Some(Event { source_id, etype: EventType::Keyboard(KeyboardEvent { key: convert_to_engine_key(keyboard_event.key), @@ -50,20 +50,21 @@ impl<'a> funnel::Source<'a> for DetectSource { status: convert_to_engine_status(keyboard_event.status), variant: keyboard_event.variant.map(convert_to_engine_variant), }), - }, - InputEvent::Mouse(mouse_event) => Event { + }), + InputEvent::Mouse(mouse_event) => Some(Event { source_id, etype: EventType::Mouse(MouseEvent { status: convert_to_engine_status(mouse_event.status), button: convert_to_engine_mouse_button(mouse_event.button), }), - }, - InputEvent::HotKey(hotkey_event) => Event { + }), + InputEvent::HotKey(hotkey_event) => Some(Event { source_id, etype: EventType::HotKey(HotKeyEvent { hotkey_id: hotkey_event.hotkey_id, }), - }, + }), + InputEvent::AllModifiersReleased => None, } } } diff --git a/espanso/src/cli/worker/engine/funnel/exit.rs b/espanso/src/cli/worker/engine/funnel/exit.rs index ad1f540..f119e73 100644 --- a/espanso/src/cli/worker/engine/funnel/exit.rs +++ b/espanso/src/cli/worker/engine/funnel/exit.rs @@ -45,13 +45,13 @@ impl<'a> funnel::Source<'a> for ExitSource<'a> { select.recv(&self.exit_signal) } - fn receive(&self, op: SelectedOperation) -> Event { + fn receive(&self, op: SelectedOperation) -> Option { let mode = op .recv(&self.exit_signal) .expect("unable to select data from ExitSource receiver"); - Event { + Some(Event { source_id: self.sequencer.next_id(), etype: EventType::ExitRequested(mode), - } + }) } } diff --git a/espanso/src/cli/worker/engine/funnel/mod.rs b/espanso/src/cli/worker/engine/funnel/mod.rs index 78bd38b..f1d699b 100644 --- a/espanso/src/cli/worker/engine/funnel/mod.rs +++ b/espanso/src/cli/worker/engine/funnel/mod.rs @@ -81,6 +81,8 @@ pub fn init_and_spawn( // Update the modifiers state if let Some((modifier, is_pressed)) = get_modifier_status(&event) { modifier_state_store_clone.update_state(modifier, is_pressed); + } else if let InputEvent::AllModifiersReleased = &event { + modifier_state_store_clone.clear_state(); } // Update the key state (if needed) diff --git a/espanso/src/cli/worker/engine/funnel/modifier.rs b/espanso/src/cli/worker/engine/funnel/modifier.rs index ba3229f..6545e73 100644 --- a/espanso/src/cli/worker/engine/funnel/modifier.rs +++ b/espanso/src/cli/worker/engine/funnel/modifier.rs @@ -91,6 +91,13 @@ impl ModifierStateStore { } } } + + pub fn clear_state(&self) { + let mut state = self.state.lock().expect("unable to obtain modifier state"); + for (_, status) in &mut state.modifiers { + status.release(); + } + } } struct ModifiersState { diff --git a/espanso/src/cli/worker/engine/funnel/secure_input.rs b/espanso/src/cli/worker/engine/funnel/secure_input.rs index 527c80b..3e4da03 100644 --- a/espanso/src/cli/worker/engine/funnel/secure_input.rs +++ b/espanso/src/cli/worker/engine/funnel/secure_input.rs @@ -50,13 +50,13 @@ impl<'a> funnel::Source<'a> for SecureInputSource<'a> { } } - fn receive(&self, op: SelectedOperation) -> Event { + fn receive(&self, op: SelectedOperation) -> Option { if cfg!(target_os = "macos") { let si_event = op .recv(&self.receiver) .expect("unable to select data from SecureInputSource receiver"); - Event { + Some(Event { source_id: self.sequencer.next_id(), etype: match si_event { SecureInputEvent::Disabled => EventType::SecureInputDisabled, @@ -64,13 +64,12 @@ impl<'a> funnel::Source<'a> for SecureInputSource<'a> { EventType::SecureInputEnabled(SecureInputEnabledEvent { app_name, app_path }) } }, - } + }) } else { - println!("noop"); - Event { + Some(Event { source_id: self.sequencer.next_id(), etype: EventType::NOOP, - } + }) } } } diff --git a/espanso/src/cli/worker/engine/funnel/ui.rs b/espanso/src/cli/worker/engine/funnel/ui.rs index ded79c5..e70cb97 100644 --- a/espanso/src/cli/worker/engine/funnel/ui.rs +++ b/espanso/src/cli/worker/engine/funnel/ui.rs @@ -46,12 +46,12 @@ impl<'a> funnel::Source<'a> for UISource<'a> { select.recv(&self.ui_receiver) } - fn receive(&self, op: SelectedOperation) -> Event { + fn receive(&self, op: SelectedOperation) -> Option { let ui_event = op .recv(&self.ui_receiver) .expect("unable to select data from UISource receiver"); - Event { + Some(Event { source_id: self.sequencer.next_id(), etype: match ui_event { UIEvent::TrayIconClick => EventType::TrayIconClicked, @@ -60,6 +60,6 @@ impl<'a> funnel::Source<'a> for UISource<'a> { } UIEvent::Heartbeat => EventType::Heartbeat, }, - } + }) } }