Skip to main content

zond_engine/core/
input.rs

1// Copyright (c) 2026 Erik Lening (hollowpointer) and Contributors
2//
3// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
4// If a copy of the MPL was not distributed with this file, You can obtain one at
5// https://mozilla.org/MPL/2.0/.
6
7use crossterm::{
8    event::{self, Event, KeyCode, KeyEventKind, KeyModifiers},
9    terminal::{disable_raw_mode, enable_raw_mode},
10};
11use std::{sync::mpsc, thread};
12
13pub struct InputHandle {
14    rx: mpsc::Receiver<Event>,
15    tx: Option<mpsc::Sender<Event>>,
16}
17
18impl Default for InputHandle {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl InputHandle {
25    pub fn new() -> Self {
26        let (tx, rx) = mpsc::channel();
27        Self { rx, tx: Some(tx) }
28    }
29
30    pub fn start(&mut self) {
31        if let Some(tx) = self.tx.take() {
32            thread::spawn(move || {
33                enable_raw_mode().expect("failed to enable raw mode");
34                loop {
35                    if let Ok(Event::Key(key_event)) = event::read() {
36                        let is_q = key_event.code == KeyCode::Char('q');
37                        let is_ctrl_c = key_event.code == KeyCode::Char('c')
38                            && key_event.modifiers.contains(KeyModifiers::CONTROL);
39
40                        if (is_q || is_ctrl_c) && key_event.kind == KeyEventKind::Press {
41                            let _ = tx.send(Event::Key(key_event));
42                            break;
43                        }
44                    }
45                }
46                let _ = disable_raw_mode();
47            });
48        }
49    }
50
51    pub fn should_interrupt(&self) -> bool {
52        match self.rx.try_recv() {
53            Ok(Event::Key(event)) => {
54                event.code == KeyCode::Char('q') || event.code == KeyCode::Char('c')
55            }
56            _ => false,
57        }
58    }
59}
60
61impl Drop for InputHandle {
62    fn drop(&mut self) {
63        let _ = disable_raw_mode();
64    }
65}