Linux key press debounce setting#1605
Conversation
jtroo
left a comment
There was a problem hiding this comment.
Thanks! The high level approach seems reasonable.
|
|
||
| let (preprocess_tx, preprocess_rx) = std::sync::mpsc::sync_channel(100); | ||
| let k = kanata.lock(); | ||
| let debounce_duration = Duration::from_millis(k.linux_debounce_duration); |
There was a problem hiding this comment.
Reading and passing this here means live reloads will not update correctly. This should be read within the preprocessor loop.
Likely would be good to have the datatype within the Kanata struct be an Arc<Mutex<_>> for fine-grained locking of this value.
|
@jtroo Thanks for the feedback. I am looking into it. I am a bit stuck on the implementation of a good debouncing algorithm. Before you look though (you don't even have to), a summary of what I have been trying:
The "eager" algorithms are not that difficult to implement, just keep track of when certain keys are pressed in a For the "defer" algorithms: I need to have a cancellable timer of some sort in order to delay the sending of events. |
|
The existing processing loop follows a pattern that could be useful here: You can process while doing a non-blocking check on the receive channel every 1ms if there is any pending action and tick down any deadlines. If no deadlines need to be processed, block on the receive channel to save on processing cost. |
|
@jtroo Thanks again for the feedback. I did my best to follow your recommendations.
These can also be selected via the config file. Some other remarks:
Any other feedback is welcome of course. |
I haven't yet gotten a chance to review in more depth, but you should change these to |
jtroo
left a comment
There was a problem hiding this comment.
Thanks for the work so far! In addition to the comments, please also add tests for the debounce algorithms. PR is heading in the right direction :)
| algorithm.process_event(key_a_press, &tx); | ||
| assert!(rx.try_recv().is_err(), "Expected no key A press event immediately"); | ||
|
|
||
| std::thread::sleep(std::time::Duration::from_millis(1)); // Simulate a short delay |
There was a problem hiding this comment.
In this test I noticed that the sym_defer_pk algorithm, as implemented right now, can change the order of the pressed keys if they are pressed at exactly the same time.
This can be verified by removing the Simulate a short delay line.
I am not sure if this is an issue. But feel free to comment @jtroo since you have much more experience in these matters.
There was a problem hiding this comment.
Would this be because the iteration order of HashMap is not guaranteed?
for (&oscode, &(ref event, deadline)) in &self.pending_events {
if now >= deadline {
log::debug!("Emitting deferred event for {:?}", oscode);
try_send_panic(process_tx, event.clone());
to_remove.push(oscode);
}
}
|
I tried to take your remaining feedback into account. I also added some tests, feel free to comment on those as well. This could definitely still use some extra documentation and more debouncing algorithms, but let's leave those for separate PRs. |
|
I already noticed that some of the tests I wrote are flaky. Edit: or the tick algorithm should be rewritten -- as you recommended in one of your comments -- in order to ensure the same order of emitted events as the actual hardware events. |
|
I've done the splitting out of the tick counting in this commit: |
I guess rather than a hashmap we need a map that maintains insertion order for iteration order. BTreeMap may do the trick |
Actually no this isn't correct; |
…methods to Debounce trait
|
The debounce preprocessor loop has been updated to use your extracted The debounce algorithms now use Vec instead of Hashmap (where required), to ensure the correct order of emitted events. |
|
Alright, |
|
@jtroo Let me know if anything else is blocking this. |
|
Ah thanks for the reminder. The PR checks are failing, so would need to resolve those. |
4a2cbcd to
789b815
Compare
Describe your changes. Use imperative present tense.
Faulty or dirty keyboard hardware often results in 'chatter' or 'double taps'. Where a single physical press on the key results in multiple key press events in rapid succession.
This PR adds support for configuring a debounce duration on Linux to mitigate keyboard chatter or double taps.
Only key press events are debounced, other events are passed through.
Based on @jtroo 's comment from a while back, advising to create an event loop like in the Windows specific code:
#408
Checklist
This is my first work in rust ever, so please bear with me. Any feedback is welcome.