fix(core): improve handling of conflicting pressed modifiers

This commit is contained in:
Federico Terzi 2021-05-11 22:11:02 +02:00
parent 2eef404d6c
commit e049ba51fb
2 changed files with 14 additions and 6 deletions

View File

@ -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()
}
}

View File

@ -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));
}