keyboard: Fix repeat deadline handling
The calloop timer is only responsible for ensuring wakeup at the right time, but we can also be woken up before time so we need to check the deadline. At the same time, We may end up being significantly delayed past the deadline if something else was slow. If we are too far behind, reset the base of the repeat timer by just offsetting from the current time.
This commit is contained in:
+18
-7
@@ -64,7 +64,7 @@ impl EventSource for KeyRepeatSource {
|
|||||||
|
|
||||||
let mut reregister = false;
|
let mut reregister = false;
|
||||||
|
|
||||||
let mut next_deadline = std::time::Instant::now();
|
let now = std::time::Instant::now();
|
||||||
|
|
||||||
// Check if the key repeat should stop
|
// Check if the key repeat should stop
|
||||||
let channel_pa = self
|
let channel_pa = self
|
||||||
@@ -78,9 +78,7 @@ impl EventSource for KeyRepeatSource {
|
|||||||
WEnum::Value(wl_keyboard::KeyState::Pressed) => {
|
WEnum::Value(wl_keyboard::KeyState::Pressed) => {
|
||||||
key.replace(event);
|
key.replace(event);
|
||||||
reregister = true;
|
reregister = true;
|
||||||
|
timer.set_deadline(now + *delay);
|
||||||
next_deadline = std::time::Instant::now() + *delay;
|
|
||||||
timer.set_deadline(next_deadline);
|
|
||||||
}
|
}
|
||||||
WEnum::Value(wl_keyboard::KeyState::Released) => match key {
|
WEnum::Value(wl_keyboard::KeyState::Released) => match key {
|
||||||
Some(k) if k.keysym == event.keysym => {
|
Some(k) if k.keysym == event.keysym => {
|
||||||
@@ -95,8 +93,7 @@ impl EventSource for KeyRepeatSource {
|
|||||||
*delay = Duration::from_millis(new_delay as u64);
|
*delay = Duration::from_millis(new_delay as u64);
|
||||||
*disabled = false;
|
*disabled = false;
|
||||||
if key.is_some() {
|
if key.is_some() {
|
||||||
next_deadline = std::time::Instant::now() + *delay;
|
timer.set_deadline(now + *delay);
|
||||||
timer.set_deadline(next_deadline);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -117,14 +114,28 @@ impl EventSource for KeyRepeatSource {
|
|||||||
return Ok(PostAction::Reregister);
|
return Ok(PostAction::Reregister);
|
||||||
}
|
}
|
||||||
|
|
||||||
let timer_pa = timer.process_events(readiness, token, |_event, _| {
|
let timer_pa = timer.process_events(readiness, token, |deadline, _| {
|
||||||
if self.disabled || key.is_none() {
|
if self.disabled || key.is_none() {
|
||||||
return TimeoutAction::Drop;
|
return TimeoutAction::Drop;
|
||||||
}
|
}
|
||||||
|
if deadline - now > std::time::Duration::from_millis(5) {
|
||||||
|
// We have not yet reached the deadline within our tolerance
|
||||||
|
return TimeoutAction::ToInstant(deadline);
|
||||||
|
}
|
||||||
|
|
||||||
// Invoke the event
|
// Invoke the event
|
||||||
callback(key.as_ref().unwrap().clone(), &mut ());
|
callback(key.as_ref().unwrap().clone(), &mut ());
|
||||||
|
|
||||||
|
let mut next_deadline = deadline;
|
||||||
|
if now - deadline > *rate * 2 {
|
||||||
|
// We're way behind, let's just set a new time
|
||||||
|
println!("KeyRepeatSource::process_events: More than two repeat cycles behind, resetting");
|
||||||
|
next_deadline = now + *rate;
|
||||||
|
} else {
|
||||||
|
while next_deadline < now {
|
||||||
next_deadline += *rate;
|
next_deadline += *rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
TimeoutAction::ToInstant(next_deadline)
|
TimeoutAction::ToInstant(next_deadline)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user