pub mod keynames;
pub mod stats;
use crate::event::{self, is_key_event};
use crate::logger::EventInfo;
use input_linux_sys::{input_event, KEY_MAX};
use std::time::Duration;
pub const FILTER_MAP_SIZE: usize = KEY_MAX as usize + 1;
pub const NUM_KEY_STATES: usize = 3;
pub struct BounceFilter {
last_event_us: [[u64; NUM_KEY_STATES]; FILTER_MAP_SIZE],
recent_passed_events: Vec<Option<input_event>>,
recent_event_idx: usize,
ring_buffer_size: usize,
overall_first_event_us: Option<u64>,
overall_last_event_us: Option<u64>,
}
impl Default for BounceFilter {
fn default() -> Self {
Self::new(0)
}
}
impl BounceFilter {
#[must_use]
pub fn new(ring_buffer_size: usize) -> Self {
let recent_passed_events = if ring_buffer_size > 0 {
vec![None; ring_buffer_size]
} else {
Vec::new() };
BounceFilter {
last_event_us: [[u64::MAX; NUM_KEY_STATES]; FILTER_MAP_SIZE],
recent_passed_events,
recent_event_idx: 0,
ring_buffer_size,
overall_first_event_us: None,
overall_last_event_us: None,
}
}
pub fn check_event(
&mut self,
event: &input_event,
debounce_time: Duration,
skip_debounce: bool,
) -> EventInfo {
let event_us = event::event_microseconds(event);
if self.overall_first_event_us.is_none() {
self.overall_first_event_us = Some(event_us);
}
self.overall_last_event_us = Some(event_us);
if skip_debounce {
if self.ring_buffer_size > 0 {
self.recent_passed_events[self.recent_event_idx] = Some(*event);
self.recent_event_idx = (self.recent_event_idx + 1) % self.ring_buffer_size;
}
return EventInfo {
event: *event,
event_us,
is_bounce: false,
diff_us: None,
last_passed_us: None,
};
}
if !is_key_event(event) || event.value == 2 {
if self.ring_buffer_size > 0 {
self.recent_passed_events[self.recent_event_idx] = Some(*event);
self.recent_event_idx = (self.recent_event_idx + 1) % self.ring_buffer_size;
}
return EventInfo {
event: *event,
event_us,
is_bounce: false,
diff_us: None,
last_passed_us: None, };
}
let key_code_idx = event.code as usize;
let key_value_idx = event.value as usize;
if !(key_code_idx < FILTER_MAP_SIZE && key_value_idx < NUM_KEY_STATES) {
if self.ring_buffer_size > 0 {
self.recent_passed_events[self.recent_event_idx] = Some(*event);
self.recent_event_idx = (self.recent_event_idx + 1) % self.ring_buffer_size;
}
return EventInfo {
event: *event,
event_us,
is_bounce: false,
diff_us: None,
last_passed_us: None,
};
}
let last_passed_us = self.last_event_us[key_code_idx][key_value_idx];
if last_passed_us == u64::MAX {
self.last_event_us[key_code_idx][key_value_idx] = event_us;
if self.ring_buffer_size > 0 {
self.recent_passed_events[self.recent_event_idx] = Some(*event);
self.recent_event_idx = (self.recent_event_idx + 1) % self.ring_buffer_size;
}
return EventInfo {
event: *event, event_us,
is_bounce: false,
diff_us: None,
last_passed_us: None, };
}
let diff_us_opt = event_us.checked_sub(last_passed_us);
if let Some(diff_us) = diff_us_opt {
if debounce_time > Duration::ZERO && Duration::from_micros(diff_us) < debounce_time {
return EventInfo {
event: *event,
event_us,
is_bounce: true,
diff_us: Some(diff_us),
last_passed_us: Some(last_passed_us),
};
}
}
self.last_event_us[key_code_idx][key_value_idx] = event_us;
if self.ring_buffer_size > 0 {
self.recent_passed_events[self.recent_event_idx] = Some(*event);
self.recent_event_idx = (self.recent_event_idx + 1) % self.ring_buffer_size;
}
EventInfo {
event: *event,
event_us,
is_bounce: false,
diff_us: None, last_passed_us: Some(last_passed_us),
}
}
pub fn get_runtime_us(&self) -> Option<u64> {
self.overall_last_event_us.and_then(|last| {
self.overall_first_event_us
.map(|first| last.saturating_sub(first))
})
}
}