fix(engine): prevent events from stacking up when the search bar is open. Fix #781
This commit is contained in:
parent
a257cf96e5
commit
70bff10fd5
|
@ -85,6 +85,14 @@ pub struct DiscardPreviousEvent {
|
||||||
pub minimum_source_id: u32,
|
pub minimum_source_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct DiscardBetweenEvent {
|
||||||
|
// All Events with a source_id between start_id (included) and end_id (excluded)
|
||||||
|
// will be discarded
|
||||||
|
pub start_id: u32,
|
||||||
|
pub end_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct SecureInputEnabledEvent {
|
pub struct SecureInputEnabledEvent {
|
||||||
pub app_name: String,
|
pub app_name: String,
|
||||||
|
|
|
@ -71,6 +71,7 @@ pub enum EventType {
|
||||||
ImageResolved(internal::ImageResolvedEvent),
|
ImageResolved(internal::ImageResolvedEvent),
|
||||||
MatchInjected,
|
MatchInjected,
|
||||||
DiscardPrevious(internal::DiscardPreviousEvent),
|
DiscardPrevious(internal::DiscardPreviousEvent),
|
||||||
|
DiscardBetween(internal::DiscardBetweenEvent),
|
||||||
Undo(internal::UndoEvent),
|
Undo(internal::UndoEvent),
|
||||||
|
|
||||||
Disabled,
|
Disabled,
|
||||||
|
|
|
@ -25,11 +25,11 @@ use super::{
|
||||||
cause::CauseCompensateMiddleware,
|
cause::CauseCompensateMiddleware,
|
||||||
cursor_hint::CursorHintMiddleware,
|
cursor_hint::CursorHintMiddleware,
|
||||||
delay_modifiers::{DelayForModifierReleaseMiddleware, ModifierStatusProvider},
|
delay_modifiers::{DelayForModifierReleaseMiddleware, ModifierStatusProvider},
|
||||||
|
discard::EventsDiscardMiddleware,
|
||||||
markdown::MarkdownMiddleware,
|
markdown::MarkdownMiddleware,
|
||||||
match_select::MatchSelectMiddleware,
|
match_select::MatchSelectMiddleware,
|
||||||
matcher::MatcherMiddleware,
|
matcher::MatcherMiddleware,
|
||||||
multiplex::MultiplexMiddleware,
|
multiplex::MultiplexMiddleware,
|
||||||
past_discard::PastEventsDiscardMiddleware,
|
|
||||||
render::RenderMiddleware,
|
render::RenderMiddleware,
|
||||||
},
|
},
|
||||||
DisableOptions, EnabledStatusProvider, MatchFilter, MatchInfoProvider, MatchProvider,
|
DisableOptions, EnabledStatusProvider, MatchFilter, MatchInfoProvider, MatchProvider,
|
||||||
|
@ -73,14 +73,18 @@ impl<'a> DefaultProcessor<'a> {
|
||||||
Self {
|
Self {
|
||||||
event_queue: VecDeque::new(),
|
event_queue: VecDeque::new(),
|
||||||
middleware: vec![
|
middleware: vec![
|
||||||
Box::new(PastEventsDiscardMiddleware::new()),
|
Box::new(EventsDiscardMiddleware::new()),
|
||||||
Box::new(DisableMiddleware::new(disable_options)),
|
Box::new(DisableMiddleware::new(disable_options)),
|
||||||
Box::new(IconStatusMiddleware::new()),
|
Box::new(IconStatusMiddleware::new()),
|
||||||
Box::new(MatcherMiddleware::new(matchers, matcher_options_provider)),
|
Box::new(MatcherMiddleware::new(matchers, matcher_options_provider)),
|
||||||
Box::new(SuppressMiddleware::new(enabled_status_provider)),
|
Box::new(SuppressMiddleware::new(enabled_status_provider)),
|
||||||
Box::new(ContextMenuMiddleware::new()),
|
Box::new(ContextMenuMiddleware::new()),
|
||||||
Box::new(HotKeyMiddleware::new()),
|
Box::new(HotKeyMiddleware::new()),
|
||||||
Box::new(MatchSelectMiddleware::new(match_filter, match_selector)),
|
Box::new(MatchSelectMiddleware::new(
|
||||||
|
match_filter,
|
||||||
|
match_selector,
|
||||||
|
event_sequence_provider,
|
||||||
|
)),
|
||||||
Box::new(CauseCompensateMiddleware::new()),
|
Box::new(CauseCompensateMiddleware::new()),
|
||||||
Box::new(MultiplexMiddleware::new(multiplexer)),
|
Box::new(MultiplexMiddleware::new(multiplexer)),
|
||||||
Box::new(RenderMiddleware::new(renderer)),
|
Box::new(RenderMiddleware::new(renderer)),
|
||||||
|
|
|
@ -24,42 +24,54 @@ use log::trace;
|
||||||
use super::super::Middleware;
|
use super::super::Middleware;
|
||||||
use crate::event::{Event, EventType, SourceId};
|
use crate::event::{Event, EventType, SourceId};
|
||||||
|
|
||||||
/// This middleware discards all events that have a source_id smaller than its
|
/// This middleware discards all events that have a source_id between
|
||||||
/// configured threshold. This useful to discard past events that might have
|
/// the given maximum and minimum.
|
||||||
/// been stuck in the event queue for too long.
|
/// This useful to discard past events that might have been stuck in the
|
||||||
pub struct PastEventsDiscardMiddleware {
|
/// event queue for too long, or events generated while the search bar was open.
|
||||||
source_id_threshold: RefCell<SourceId>,
|
pub struct EventsDiscardMiddleware {
|
||||||
|
min_id_threshold: RefCell<SourceId>,
|
||||||
|
max_id_threshold: RefCell<SourceId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PastEventsDiscardMiddleware {
|
impl EventsDiscardMiddleware {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
source_id_threshold: RefCell::new(0),
|
min_id_threshold: RefCell::new(0),
|
||||||
|
max_id_threshold: RefCell::new(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Middleware for PastEventsDiscardMiddleware {
|
impl Middleware for EventsDiscardMiddleware {
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"past_discard"
|
"discard"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
|
fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
|
||||||
let mut source_id_threshold = self.source_id_threshold.borrow_mut();
|
let mut min_id_threshold = self.min_id_threshold.borrow_mut();
|
||||||
|
let mut max_id_threshold = self.max_id_threshold.borrow_mut();
|
||||||
|
|
||||||
// Filter out previous events
|
// Filter out previous events
|
||||||
if event.source_id < *source_id_threshold {
|
if event.source_id < *max_id_threshold && event.source_id >= *min_id_threshold {
|
||||||
trace!("discarding previous event: {:?}", event);
|
trace!("discarding previous event: {:?}", event);
|
||||||
return Event::caused_by(event.source_id, EventType::NOOP);
|
return Event::caused_by(event.source_id, EventType::NOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the minimum threshold
|
// Update the thresholds
|
||||||
if let EventType::DiscardPrevious(m_event) = &event.etype {
|
if let EventType::DiscardPrevious(m_event) = &event.etype {
|
||||||
trace!(
|
trace!(
|
||||||
"updating minimum source id threshold for events to: {}",
|
"updating discard max_id_threshold threshold for events to: {}",
|
||||||
m_event.minimum_source_id
|
m_event.minimum_source_id
|
||||||
);
|
);
|
||||||
*source_id_threshold = m_event.minimum_source_id;
|
*max_id_threshold = m_event.minimum_source_id;
|
||||||
|
} else if let EventType::DiscardBetween(m_event) = &event.etype {
|
||||||
|
trace!(
|
||||||
|
"updating discard thresholds for events to: max={} min={}",
|
||||||
|
m_event.end_id,
|
||||||
|
m_event.start_id
|
||||||
|
);
|
||||||
|
*max_id_threshold = m_event.end_id;
|
||||||
|
*min_id_threshold = m_event.start_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
event
|
event
|
|
@ -20,7 +20,13 @@
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
|
|
||||||
use super::super::Middleware;
|
use super::super::Middleware;
|
||||||
use crate::event::{internal::MatchSelectedEvent, Event, EventType};
|
use crate::{
|
||||||
|
event::{
|
||||||
|
internal::{DiscardBetweenEvent, MatchSelectedEvent},
|
||||||
|
Event, EventType,
|
||||||
|
},
|
||||||
|
process::EventSequenceProvider,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait MatchFilter {
|
pub trait MatchFilter {
|
||||||
fn filter_active(&self, matches_ids: &[i32]) -> Vec<i32>;
|
fn filter_active(&self, matches_ids: &[i32]) -> Vec<i32>;
|
||||||
|
@ -33,13 +39,19 @@ pub trait MatchSelector {
|
||||||
pub struct MatchSelectMiddleware<'a> {
|
pub struct MatchSelectMiddleware<'a> {
|
||||||
match_filter: &'a dyn MatchFilter,
|
match_filter: &'a dyn MatchFilter,
|
||||||
match_selector: &'a dyn MatchSelector,
|
match_selector: &'a dyn MatchSelector,
|
||||||
|
event_sequence_provider: &'a dyn EventSequenceProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MatchSelectMiddleware<'a> {
|
impl<'a> MatchSelectMiddleware<'a> {
|
||||||
pub fn new(match_filter: &'a dyn MatchFilter, match_selector: &'a dyn MatchSelector) -> Self {
|
pub fn new(
|
||||||
|
match_filter: &'a dyn MatchFilter,
|
||||||
|
match_selector: &'a dyn MatchSelector,
|
||||||
|
event_sequence_provider: &'a dyn EventSequenceProvider,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
match_filter,
|
match_filter,
|
||||||
match_selector,
|
match_selector,
|
||||||
|
event_sequence_provider,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +61,7 @@ impl<'a> Middleware for MatchSelectMiddleware<'a> {
|
||||||
"match_select"
|
"match_select"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
|
fn next(&self, event: Event, dispatch: &mut dyn FnMut(Event)) -> Event {
|
||||||
if let EventType::MatchesDetected(m_event) = event.etype {
|
if let EventType::MatchesDetected(m_event) = event.etype {
|
||||||
let matches_ids: Vec<i32> = m_event.matches.iter().map(|m| m.id).collect();
|
let matches_ids: Vec<i32> = m_event.matches.iter().map(|m| m.id).collect();
|
||||||
|
|
||||||
|
@ -75,22 +87,40 @@ impl<'a> Middleware for MatchSelectMiddleware<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
let start_event_id = self.event_sequence_provider.get_next_id();
|
||||||
|
|
||||||
// Multiple matches, we need to ask the user which one to use
|
// Multiple matches, we need to ask the user which one to use
|
||||||
if let Some(selected_id) = self.match_selector.select(&valid_ids, m_event.is_search) {
|
let next_event =
|
||||||
let m = m_event.matches.into_iter().find(|m| m.id == selected_id);
|
if let Some(selected_id) = self.match_selector.select(&valid_ids, m_event.is_search) {
|
||||||
if let Some(m) = m {
|
let m = m_event.matches.into_iter().find(|m| m.id == selected_id);
|
||||||
Event::caused_by(
|
if let Some(m) = m {
|
||||||
event.source_id,
|
Event::caused_by(
|
||||||
EventType::MatchSelected(MatchSelectedEvent { chosen: m }),
|
event.source_id,
|
||||||
)
|
EventType::MatchSelected(MatchSelectedEvent { chosen: m }),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
error!("MatchSelectMiddleware could not find the correspondent match");
|
||||||
|
Event::caused_by(event.source_id, EventType::NOOP)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error!("MatchSelectMiddleware could not find the correspondent match");
|
debug!("MatchSelectMiddleware did not receive any match selection");
|
||||||
Event::caused_by(event.source_id, EventType::NOOP)
|
Event::caused_by(event.source_id, EventType::NOOP)
|
||||||
}
|
};
|
||||||
} else {
|
|
||||||
debug!("MatchSelectMiddleware did not receive any match selection");
|
let end_event_id = self.event_sequence_provider.get_next_id();
|
||||||
Event::caused_by(event.source_id, EventType::NOOP)
|
|
||||||
}
|
// We want to prevent espanso from "stacking up" events while the search bar is open,
|
||||||
|
// therefore we filter out all events that were generated while the search bar was open.
|
||||||
|
// See also: https://github.com/federico-terzi/espanso/issues/781
|
||||||
|
dispatch(Event::caused_by(
|
||||||
|
event.source_id,
|
||||||
|
EventType::DiscardBetween(DiscardBetweenEvent {
|
||||||
|
start_id: start_event_id,
|
||||||
|
end_id: end_event_id,
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
|
||||||
|
next_event
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ pub mod context_menu;
|
||||||
pub mod cursor_hint;
|
pub mod cursor_hint;
|
||||||
pub mod delay_modifiers;
|
pub mod delay_modifiers;
|
||||||
pub mod disable;
|
pub mod disable;
|
||||||
|
pub mod discard;
|
||||||
pub mod exit;
|
pub mod exit;
|
||||||
pub mod hotkey;
|
pub mod hotkey;
|
||||||
pub mod icon_status;
|
pub mod icon_status;
|
||||||
|
@ -31,7 +32,6 @@ pub mod markdown;
|
||||||
pub mod match_select;
|
pub mod match_select;
|
||||||
pub mod matcher;
|
pub mod matcher;
|
||||||
pub mod multiplex;
|
pub mod multiplex;
|
||||||
pub mod past_discard;
|
|
||||||
pub mod render;
|
pub mod render;
|
||||||
pub mod search;
|
pub mod search;
|
||||||
pub mod suppress;
|
pub mod suppress;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user