use std::time::Duration;
use parking_lot::RwLock;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use bitflags::bitflags;
use filter::{EventFilter, Filter};
use lazy_static::lazy_static;
#[cfg(feature = "event-stream")]
pub use stream::EventStream;
use timeout::PollTimeout;
use crate::{Command, Result};
mod ansi;
pub(crate) mod filter;
mod read;
mod source;
#[cfg(feature = "event-stream")]
mod stream;
pub(crate) mod sys;
mod timeout;
lazy_static! {
static ref INTERNAL_EVENT_READER: RwLock<read::InternalEventReader> = RwLock::new(read::InternalEventReader::default());
}
pub fn poll(timeout: Duration) -> Result<bool> {
poll_internal(Some(timeout), &EventFilter)
}
pub fn read() -> Result<Event> {
match read_internal(&EventFilter)? {
InternalEvent::Event(event) => Ok(event),
#[cfg(unix)]
_ => unreachable!(),
}
}
pub(crate) fn poll_internal<F>(timeout: Option<Duration>, filter: &F) -> Result<bool>
where
F: Filter,
{
let (mut reader, timeout) = if let Some(timeout) = timeout {
let poll_timeout = PollTimeout::new(Some(timeout));
if let Some(reader) = INTERNAL_EVENT_READER.try_write_for(timeout) {
(reader, poll_timeout.leftover())
} else {
return Ok(false);
}
} else {
(INTERNAL_EVENT_READER.write(), None)
};
reader.poll(timeout, filter)
}
pub(crate) fn read_internal<F>(filter: &F) -> Result<InternalEvent>
where
F: Filter,
{
let mut reader = INTERNAL_EVENT_READER.write();
reader.read(filter)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EnableMouseCapture;
impl Command for EnableMouseCapture {
type AnsiType = &'static str;
fn ansi_code(&self) -> Self::AnsiType {
ansi::ENABLE_MOUSE_MODE_CSI_SEQUENCE
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
sys::windows::enable_mouse_capture()
}
#[cfg(windows)]
fn is_ansi_code_supported(&self) -> bool {
false
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DisableMouseCapture;
impl Command for DisableMouseCapture {
type AnsiType = &'static str;
fn ansi_code(&self) -> Self::AnsiType {
ansi::DISABLE_MOUSE_MODE_CSI_SEQUENCE
}
#[cfg(windows)]
fn execute_winapi(&self) -> Result<()> {
sys::windows::disable_mouse_capture()
}
#[cfg(windows)]
fn is_ansi_code_supported(&self) -> bool {
false
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Event {
Key(KeyEvent),
Mouse(MouseEvent),
Resize(u16, u16),
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub enum MouseEvent {
Down(MouseButton, u16, u16, KeyModifiers),
Up(MouseButton, u16, u16, KeyModifiers),
Drag(MouseButton, u16, u16, KeyModifiers),
ScrollDown(u16, u16, KeyModifiers),
ScrollUp(u16, u16, KeyModifiers),
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub enum MouseButton {
Left,
Right,
Middle,
}
bitflags! {
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct KeyModifiers: u8 {
const SHIFT = 0b0000_0001;
const CONTROL = 0b0000_0010;
const ALT = 0b0000_0100;
const NONE = 0b0000_0000;
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub struct KeyEvent {
pub code: KeyCode,
pub modifiers: KeyModifiers,
}
impl KeyEvent {
pub fn new(code: KeyCode, modifiers: KeyModifiers) -> KeyEvent {
KeyEvent { code, modifiers }
}
}
impl From<KeyCode> for KeyEvent {
fn from(code: KeyCode) -> Self {
KeyEvent {
code,
modifiers: KeyModifiers::empty(),
}
}
}
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum KeyCode {
Backspace,
Enter,
Left,
Right,
Up,
Down,
Home,
End,
PageUp,
PageDown,
Tab,
BackTab,
Delete,
Insert,
F(u8),
Char(char),
Null,
Esc,
}
#[derive(Debug, PartialOrd, PartialEq, Hash, Clone, Eq)]
pub(crate) enum InternalEvent {
Event(Event),
#[cfg(unix)]
CursorPosition(u16, u16),
}