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,
|
||||
}
|
||||
|
||||
#[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)]
|
||||
pub struct SecureInputEnabledEvent {
|
||||
pub app_name: String,
|
||||
|
|
|
@ -71,6 +71,7 @@ pub enum EventType {
|
|||
ImageResolved(internal::ImageResolvedEvent),
|
||||
MatchInjected,
|
||||
DiscardPrevious(internal::DiscardPreviousEvent),
|
||||
DiscardBetween(internal::DiscardBetweenEvent),
|
||||
Undo(internal::UndoEvent),
|
||||
|
||||
Disabled,
|
||||
|
|
|
@ -25,11 +25,11 @@ use super::{
|
|||
cause::CauseCompensateMiddleware,
|
||||
cursor_hint::CursorHintMiddleware,
|
||||
delay_modifiers::{DelayForModifierReleaseMiddleware, ModifierStatusProvider},
|
||||
discard::EventsDiscardMiddleware,
|
||||
markdown::MarkdownMiddleware,
|
||||
match_select::MatchSelectMiddleware,
|
||||
matcher::MatcherMiddleware,
|
||||
multiplex::MultiplexMiddleware,
|
||||
past_discard::PastEventsDiscardMiddleware,
|
||||
render::RenderMiddleware,
|
||||
},
|
||||
DisableOptions, EnabledStatusProvider, MatchFilter, MatchInfoProvider, MatchProvider,
|
||||
|
@ -73,14 +73,18 @@ impl<'a> DefaultProcessor<'a> {
|
|||
Self {
|
||||
event_queue: VecDeque::new(),
|
||||
middleware: vec![
|
||||
Box::new(PastEventsDiscardMiddleware::new()),
|
||||
Box::new(EventsDiscardMiddleware::new()),
|
||||
Box::new(DisableMiddleware::new(disable_options)),
|
||||
Box::new(IconStatusMiddleware::new()),
|
||||
Box::new(MatcherMiddleware::new(matchers, matcher_options_provider)),
|
||||
Box::new(SuppressMiddleware::new(enabled_status_provider)),
|
||||
Box::new(ContextMenuMiddleware::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(MultiplexMiddleware::new(multiplexer)),
|
||||
Box::new(RenderMiddleware::new(renderer)),
|
||||
|
|
|
@ -24,42 +24,54 @@ use log::trace;
|
|||
use super::super::Middleware;
|
||||
use crate::event::{Event, EventType, SourceId};
|
||||
|
||||
/// This middleware discards all events that have a source_id smaller than its
|
||||
/// configured threshold. This useful to discard past events that might have
|
||||
/// been stuck in the event queue for too long.
|
||||
pub struct PastEventsDiscardMiddleware {
|
||||
source_id_threshold: RefCell<SourceId>,
|
||||
/// This middleware discards all events that have a source_id between
|
||||
/// the given maximum and minimum.
|
||||
/// This useful to discard past events that might have been stuck in the
|
||||
/// event queue for too long, or events generated while the search bar was open.
|
||||
pub struct EventsDiscardMiddleware {
|
||||
min_id_threshold: RefCell<SourceId>,
|
||||
max_id_threshold: RefCell<SourceId>,
|
||||
}
|
||||
|
||||
impl PastEventsDiscardMiddleware {
|
||||
impl EventsDiscardMiddleware {
|
||||
pub fn new() -> 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 {
|
||||
"past_discard"
|
||||
"discard"
|
||||
}
|
||||
|
||||
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
|
||||
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);
|
||||
return Event::caused_by(event.source_id, EventType::NOOP);
|
||||
}
|
||||
|
||||
// Update the minimum threshold
|
||||
// Update the thresholds
|
||||
if let EventType::DiscardPrevious(m_event) = &event.etype {
|
||||
trace!(
|
||||
"updating minimum source id threshold for events to: {}",
|
||||
"updating discard max_id_threshold threshold for events to: {}",
|
||||
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
|
|
@ -20,7 +20,13 @@
|
|||
use log::{debug, error};
|
||||
|
||||
use super::super::Middleware;
|
||||
use crate::event::{internal::MatchSelectedEvent, Event, EventType};
|
||||
use crate::{
|
||||
event::{
|
||||
internal::{DiscardBetweenEvent, MatchSelectedEvent},
|
||||
Event, EventType,
|
||||
},
|
||||
process::EventSequenceProvider,
|
||||
};
|
||||
|
||||
pub trait MatchFilter {
|
||||
fn filter_active(&self, matches_ids: &[i32]) -> Vec<i32>;
|
||||
|
@ -33,13 +39,19 @@ pub trait MatchSelector {
|
|||
pub struct MatchSelectMiddleware<'a> {
|
||||
match_filter: &'a dyn MatchFilter,
|
||||
match_selector: &'a dyn MatchSelector,
|
||||
event_sequence_provider: &'a dyn EventSequenceProvider,
|
||||
}
|
||||
|
||||
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 {
|
||||
match_filter,
|
||||
match_selector,
|
||||
event_sequence_provider,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +61,7 @@ impl<'a> Middleware for MatchSelectMiddleware<'a> {
|
|||
"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 {
|
||||
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
|
||||
if let Some(selected_id) = self.match_selector.select(&valid_ids, m_event.is_search) {
|
||||
let m = m_event.matches.into_iter().find(|m| m.id == selected_id);
|
||||
if let Some(m) = m {
|
||||
Event::caused_by(
|
||||
event.source_id,
|
||||
EventType::MatchSelected(MatchSelectedEvent { chosen: m }),
|
||||
)
|
||||
let next_event =
|
||||
if let Some(selected_id) = self.match_selector.select(&valid_ids, m_event.is_search) {
|
||||
let m = m_event.matches.into_iter().find(|m| m.id == selected_id);
|
||||
if let Some(m) = m {
|
||||
Event::caused_by(
|
||||
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 {
|
||||
error!("MatchSelectMiddleware could not find the correspondent match");
|
||||
debug!("MatchSelectMiddleware did not receive any match selection");
|
||||
Event::caused_by(event.source_id, EventType::NOOP)
|
||||
}
|
||||
} else {
|
||||
debug!("MatchSelectMiddleware did not receive any match selection");
|
||||
Event::caused_by(event.source_id, EventType::NOOP)
|
||||
}
|
||||
};
|
||||
|
||||
let end_event_id = self.event_sequence_provider.get_next_id();
|
||||
|
||||
// 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 delay_modifiers;
|
||||
pub mod disable;
|
||||
pub mod discard;
|
||||
pub mod exit;
|
||||
pub mod hotkey;
|
||||
pub mod icon_status;
|
||||
|
@ -31,7 +32,6 @@ pub mod markdown;
|
|||
pub mod match_select;
|
||||
pub mod matcher;
|
||||
pub mod multiplex;
|
||||
pub mod past_discard;
|
||||
pub mod render;
|
||||
pub mod search;
|
||||
pub mod suppress;
|
||||
|
|
Loading…
Reference in New Issue
Block a user