use std::time::Duration;
use crate::event::KeyEvent;
const MAX_BURST: u64 = 8;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(
clippy::exhaustive_structs,
reason = "built by callers with `..Default::default()`, which a new field does not break"
)]
pub struct RepeatConfig {
pub delay: Duration,
pub interval: Duration,
}
impl Default for RepeatConfig {
fn default() -> Self {
Self {
delay: Duration::from_millis(600),
interval: Duration::from_millis(40),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum Timer {
Arm,
Disarm,
Unchanged,
}
#[derive(Debug, Clone)]
pub struct Repeat {
config: RepeatConfig,
held: Option<u32>,
}
impl Repeat {
#[must_use]
pub const fn new(config: RepeatConfig) -> Self {
Self { config, held: None }
}
#[must_use]
pub const fn config(&self) -> RepeatConfig {
self.config
}
#[must_use]
pub const fn held_key(&self) -> Option<u32> {
self.held
}
pub fn on_key(&mut self, event: &KeyEvent, repeats: bool) -> Timer {
if event.repeat {
return Timer::Unchanged;
}
if event.pressed {
if !repeats {
return Timer::Unchanged;
}
self.held = Some(event.key);
return Timer::Arm;
}
if self.held == Some(event.key) {
self.held = None;
Timer::Disarm
} else {
Timer::Unchanged
}
}
pub fn cancel(&mut self) -> Timer {
self.held = None;
Timer::Disarm
}
pub fn synthesize(&self, expirations: u64, time_ms: u32, out: &mut Vec<KeyEvent>) -> u64 {
let Some(key) = self.held else {
return 0;
};
let emit = expirations.min(MAX_BURST);
out.reserve(usize::try_from(emit).unwrap_or(usize::MAX));
for _ in 0..emit {
out.push(KeyEvent {
time_ms,
key,
pressed: true,
repeat: true,
sym: 0,
utf8: String::new(),
});
}
expirations - emit
}
}