I'm trying to detect key releasing instead of pressing using crossterm. I'm using the basic example named event-stream-tokio. I need tokio runtime for the project.
Link to the example code: https://github.com/crossterm-rs/crossterm/blob/master/examples/event-stream-tokio.rs
Anyway, when I'm trying to amend the example to catch key release and not press - I'm not able to do so. Only the press kind is detected.
Does anybody know how to make it work?
Here is my changed function in that example:
async fn print_events() {
let mut reader = EventStream::new();
loop {
let mut delay = Delay::new(Duration::from_millis(1_000)).fuse();
let mut event = reader.next().fuse();
select! {
_ = delay => { println!(".\r"); },
maybe_event = event => {
match maybe_event {
Some(Ok(event)) => {
println!("Event::{:?}\r", event);
if event == Event::Key(
// Here I changed the example
KeyEvent::new_with_kind(
KeyCode::Char('c'),
KeyModifiers::NONE,
KeyEventKind::Release
)) {
println!("c key was released!. position is: {:?}\r", position());
}
if event == Event::Key(KeyCode::Esc.into()) {
break;
}
}
Some(Err(e)) => println!("Error: {:?}\r", e),
None => break,
}
}
};
}
}
Printing the position of the cursor is not important. It's only part of their example.
Thanks!
The default behavior of terminals is that what you get is not a stream of key state events but a stream of text — of characters typed. There is no concept of key-up.
However, the kitty keyboard protocol is a set of extensions which some terminals support to allow reporting key-up events, and that is what crossterm
's KeyEventKind
is about. You have to enable the features by using PushKeyboardEnhancementFlags
, and you have to be using a terminal that implements that extension. Otherwise you will never see a release event.
While you can't do it directly with crossterm
, there is a way to do it. Namely, I used the device_query
crate which provides the state of keys pressed and not pressed. It is harder to wire up everything since you need to do it poll-based, and maybe it's un-idiomatic, but it is possible!
To be more specific, in my case, I wanted to check when the spacebar is released, so when pressing down the spacebar I do a very quick loop (almost busy looping) checking if the spacebar is at any moment not pressed, which indicates the key has been released.
Again, it's better to avoid this if possible, but in my case it was crucial and so I'm writing the answer here if anyone else is in the same scenario and stumbles upon this question just like I did :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With