1

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!

Mithrandir
  • 46
  • 5

1 Answers1

0

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.

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
  • Thanks! It seems the right way, although I'm using the windows regular terminal and it doesn't seems fit the kitty protocol. But, I'm wondering why - I tried to use the winit crate for the same purpose and it actually worked without any flags. The problem there was that winit doesn't support async functions - which is a problem for me right now. – Mithrandir Nov 13 '22 at 21:51
  • @Mithrandir Different legacies. GUI event systems, such as those `winit` is a wrapper around, have supported key-up events pretty much forever, because they are built around the idea that the GUI application controls the entire response to input (except for the parts the window system does), and it's 100% real-time interactive. Modern terminals are a distant descendant of teletypes — machines at the ends of (very slow) _communication channels_ saying "put this character on your piece of paper, er, screen" to each other, not “please respond as you see fit to the buttons the human is pushing”. – Kevin Reid Nov 14 '22 at 01:10
  • Oh, good to know that! Thanks for the explanation, I think I know better now what to look for... – Mithrandir Nov 14 '22 at 21:50