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 {
|
struct HeldState {
|
||||||
last_seen: Instant,
|
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 struct InputHandler {
|
||||||
pub paint_brush: MaterialBrush,
|
pub paint_brush: MaterialBrush,
|
||||||
@@ -102,8 +104,11 @@ impl InputHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_held(&mut self, key: HeldKey) {
|
fn mark_held(&mut self, key: HeldKey, is_repeat: bool) {
|
||||||
self.held.insert(key, HeldState { last_seen: Instant::now() });
|
self.held.insert(key, HeldState {
|
||||||
|
last_seen: Instant::now(),
|
||||||
|
seen_repeat: is_repeat,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release(&mut self, key: HeldKey) {
|
fn release(&mut self, key: HeldKey) {
|
||||||
@@ -119,7 +124,10 @@ impl InputHandler {
|
|||||||
self.jump_pressed = false;
|
self.jump_pressed = false;
|
||||||
let now = Instant::now();
|
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 {
|
let events: Vec<Event> = match &self.receiver {
|
||||||
Some(rx) => rx.try_iter().collect(),
|
Some(rx) => rx.try_iter().collect(),
|
||||||
@@ -163,8 +171,10 @@ impl InputHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(held_key) = Self::key_to_held(code) {
|
if let Some(held_key) = Self::key_to_held(code) {
|
||||||
if is_press || is_repeat {
|
if is_press {
|
||||||
self.mark_held(held_key);
|
self.mark_held(held_key, false);
|
||||||
|
} else if is_repeat {
|
||||||
|
self.mark_held(held_key, true);
|
||||||
} else if is_release {
|
} else if is_release {
|
||||||
self.release(held_key);
|
self.release(held_key);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user