From e049ba51fbfec214b9fd7d4a92c34f63471d1d58 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Tue, 11 May 2021 22:11:02 +0200 Subject: [PATCH] fix(core): improve handling of conflicting pressed modifiers --- espanso/src/cli/worker/engine/source/modifier.rs | 13 +++++++++---- .../engine/process/middleware/delay_modifiers.rs | 7 +++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/espanso/src/cli/worker/engine/source/modifier.rs b/espanso/src/cli/worker/engine/source/modifier.rs index 3d7f63a..bb73eae 100644 --- a/espanso/src/cli/worker/engine/source/modifier.rs +++ b/espanso/src/cli/worker/engine/source/modifier.rs @@ -32,6 +32,11 @@ use crate::engine::process::ModifierStatusProvider; /// after a while. const MAXIMUM_MODIFIERS_PRESS_TIME_RECORD: Duration = Duration::from_secs(30); +// TODO: should we add also Shift on Linux to avoid any conflict in the expansion process? Investigate +/// These are the modifiers that might conflict with the expansion process. For example, +/// if espanso injects some texts while Alt or Ctrl are pressed, strange things might happen. +const CONFLICTING_MODIFIERS: &[Modifier] = &[Modifier::Ctrl, Modifier::Alt, Modifier::Meta]; + #[derive(Debug, Hash, PartialEq, Eq)] pub enum Modifier { Ctrl, @@ -52,7 +57,7 @@ impl ModifierStateStore { } } - pub fn is_any_modifier_pressed(&self) -> bool { + pub fn is_any_conflicting_modifier_pressed(&self) -> bool { let mut state = self.state.lock().expect("unable to obtain modifier state"); let mut is_any_modifier_pressed = false; for (modifier, status) in &mut state.modifiers { @@ -64,7 +69,7 @@ impl ModifierStateStore { status.release(); } - if status.is_pressed() { + if status.is_pressed() && CONFLICTING_MODIFIERS.contains(modifier) { is_any_modifier_pressed = true; } } @@ -131,7 +136,7 @@ impl ModifierStatus { } impl ModifierStatusProvider for ModifierStateStore { - fn is_any_modifier_pressed(&self) -> bool { - self.is_any_modifier_pressed() + fn is_any_conflicting_modifier_pressed(&self) -> bool { + self.is_any_conflicting_modifier_pressed() } } diff --git a/espanso/src/engine/process/middleware/delay_modifiers.rs b/espanso/src/engine/process/middleware/delay_modifiers.rs index 22041bb..a35d681 100644 --- a/espanso/src/engine/process/middleware/delay_modifiers.rs +++ b/espanso/src/engine/process/middleware/delay_modifiers.rs @@ -31,7 +31,7 @@ use crate::engine::event::{Event, EventType}; const MODIFIER_DELAY_TIMEOUT: Duration = Duration::from_secs(3); pub trait ModifierStatusProvider { - fn is_any_modifier_pressed(&self) -> bool; + fn is_any_conflicting_modifier_pressed(&self) -> bool; } /// This middleware is used to delay the injection of text until @@ -58,11 +58,14 @@ impl <'a> Middleware for DelayForModifierReleaseMiddleware<'a> { fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event { if is_injection_event(&event.etype) { let start = Instant::now(); - while self.provider.is_any_modifier_pressed() { + while self.provider.is_any_conflicting_modifier_pressed() { if Instant::now().duration_since(start) > MODIFIER_DELAY_TIMEOUT { warn!("injection delay has timed out, please release the modifier keys (SHIFT, CTRL, ALT, CMD) to trigger an expansion"); break; } + + // TODO: here we might show a popup window to tell the users to release those keys + trace!("delaying injection event as some modifiers are pressed"); std::thread::sleep(Duration::from_millis(100)); }