fix: dual-timeout held keys to fix terminal initial repeat delay
Root cause: terminals wait 300-500ms after initial Press before sending the first Repeat event. With 60ms timeout, the key was released during this gap, causing step-pause-accelerate pattern. Fix: two timeout phases: - After Press (no Repeat seen yet): 400ms timeout Covers terminal's initial repeat delay, key stays held - After first Repeat: 80ms timeout Repeats arrive every ~30ms, 80ms is safe margin Quick release detection once repeating starts Result: smooth continuous movement from first keypress, no gap
This commit is contained in:
+16
-6
@@ -44,9 +44,11 @@ pub enum HeldKey {
|
||||
|
||||
struct HeldState {
|
||||
last_seen: Instant,
|
||||
seen_repeat: bool,
|
||||
}
|
||||
|
||||
const HOLD_TIMEOUT: Duration = Duration::from_millis(60);
|
||||
const HOLD_TIMEOUT_PRESS: Duration = Duration::from_millis(400);
|
||||
const HOLD_TIMEOUT_REPEAT: Duration = Duration::from_millis(80);
|
||||
|
||||
pub struct InputHandler {
|
||||
pub paint_brush: MaterialBrush,
|
||||
@@ -102,8 +104,11 @@ impl InputHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_held(&mut self, key: HeldKey) {
|
||||
self.held.insert(key, HeldState { last_seen: Instant::now() });
|
||||
fn mark_held(&mut self, key: HeldKey, is_repeat: bool) {
|
||||
self.held.insert(key, HeldState {
|
||||
last_seen: Instant::now(),
|
||||
seen_repeat: is_repeat,
|
||||
});
|
||||
}
|
||||
|
||||
fn release(&mut self, key: HeldKey) {
|
||||
@@ -119,7 +124,10 @@ impl InputHandler {
|
||||
self.jump_pressed = false;
|
||||
let now = Instant::now();
|
||||
|
||||
self.held.retain(|_, state| now.duration_since(state.last_seen) < HOLD_TIMEOUT);
|
||||
self.held.retain(|_, state| {
|
||||
let timeout = if state.seen_repeat { HOLD_TIMEOUT_REPEAT } else { HOLD_TIMEOUT_PRESS };
|
||||
now.duration_since(state.last_seen) < timeout
|
||||
});
|
||||
|
||||
let events: Vec<Event> = match &self.receiver {
|
||||
Some(rx) => rx.try_iter().collect(),
|
||||
@@ -163,8 +171,10 @@ impl InputHandler {
|
||||
}
|
||||
|
||||
if let Some(held_key) = Self::key_to_held(code) {
|
||||
if is_press || is_repeat {
|
||||
self.mark_held(held_key);
|
||||
if is_press {
|
||||
self.mark_held(held_key, false);
|
||||
} else if is_repeat {
|
||||
self.mark_held(held_key, true);
|
||||
} else if is_release {
|
||||
self.release(held_key);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user