mirror of
https://github.com/crossterm-rs/crossterm.git
synced 2025-09-27 04:50:48 +00:00
refactor: move internal items from event to event::internal (#999)
* refactor: move internal event code to event::internal * refactor: drop internal suffix from methods in event::internal (prefix calls with internal::)
This commit is contained in:
parent
fab72d12fe
commit
2ba0160831
@ -4,7 +4,10 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
event::{filter::CursorPositionFilter, poll_internal, read_internal, InternalEvent},
|
||||
event::{
|
||||
filter::CursorPositionFilter,
|
||||
internal::{self, InternalEvent},
|
||||
},
|
||||
terminal::{disable_raw_mode, enable_raw_mode, sys::is_raw_mode_enabled},
|
||||
};
|
||||
|
||||
@ -36,10 +39,10 @@ fn read_position_raw() -> io::Result<(u16, u16)> {
|
||||
stdout.flush()?;
|
||||
|
||||
loop {
|
||||
match poll_internal(Some(Duration::from_millis(2000)), &CursorPositionFilter) {
|
||||
match internal::poll(Some(Duration::from_millis(2000)), &CursorPositionFilter) {
|
||||
Ok(true) => {
|
||||
if let Ok(InternalEvent::CursorPosition(x, y)) =
|
||||
read_internal(&CursorPositionFilter)
|
||||
internal::read(&CursorPositionFilter)
|
||||
{
|
||||
return Ok((x, y));
|
||||
}
|
||||
|
79
src/event.rs
79
src/event.rs
@ -119,6 +119,7 @@
|
||||
//! them (`event-*`).
|
||||
|
||||
pub(crate) mod filter;
|
||||
pub(crate) mod internal;
|
||||
pub(crate) mod read;
|
||||
pub(crate) mod source;
|
||||
#[cfg(feature = "event-stream")]
|
||||
@ -131,37 +132,13 @@ use derive_more::derive::IsVariant;
|
||||
#[cfg(feature = "event-stream")]
|
||||
pub use stream::EventStream;
|
||||
|
||||
use crate::event::{
|
||||
filter::{EventFilter, Filter},
|
||||
read::InternalEventReader,
|
||||
timeout::PollTimeout,
|
||||
};
|
||||
use crate::{csi, Command};
|
||||
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
|
||||
use crate::{csi, event::filter::EventFilter, Command};
|
||||
use std::fmt::{self, Display};
|
||||
use std::time::Duration;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
/// Static instance of `InternalEventReader`.
|
||||
/// This needs to be static because there can be one event reader.
|
||||
static INTERNAL_EVENT_READER: Mutex<Option<InternalEventReader>> = parking_lot::const_mutex(None);
|
||||
|
||||
pub(crate) fn lock_internal_event_reader() -> MappedMutexGuard<'static, InternalEventReader> {
|
||||
MutexGuard::map(INTERNAL_EVENT_READER.lock(), |reader| {
|
||||
reader.get_or_insert_with(InternalEventReader::default)
|
||||
})
|
||||
}
|
||||
fn try_lock_internal_event_reader_for(
|
||||
duration: Duration,
|
||||
) -> Option<MappedMutexGuard<'static, InternalEventReader>> {
|
||||
Some(MutexGuard::map(
|
||||
INTERNAL_EVENT_READER.try_lock_for(duration)?,
|
||||
|reader| reader.get_or_insert_with(InternalEventReader::default),
|
||||
))
|
||||
}
|
||||
|
||||
/// Checks if there is an [`Event`](enum.Event.html) available.
|
||||
///
|
||||
/// Returns `Ok(true)` if an [`Event`](enum.Event.html) is available otherwise it returns `Ok(false)`.
|
||||
@ -202,7 +179,7 @@ fn try_lock_internal_event_reader_for(
|
||||
/// }
|
||||
/// ```
|
||||
pub fn poll(timeout: Duration) -> std::io::Result<bool> {
|
||||
poll_internal(Some(timeout), &EventFilter)
|
||||
internal::poll(Some(timeout), &EventFilter)
|
||||
}
|
||||
|
||||
/// Reads a single [`Event`](enum.Event.html).
|
||||
@ -247,40 +224,13 @@ pub fn poll(timeout: Duration) -> std::io::Result<bool> {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn read() -> std::io::Result<Event> {
|
||||
match read_internal(&EventFilter)? {
|
||||
InternalEvent::Event(event) => Ok(event),
|
||||
match internal::read(&EventFilter)? {
|
||||
internal::InternalEvent::Event(event) => Ok(event),
|
||||
#[cfg(unix)]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Polls to check if there are any `InternalEvent`s that can be read within the given duration.
|
||||
pub(crate) fn poll_internal<F>(timeout: Option<Duration>, filter: &F) -> std::io::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) = try_lock_internal_event_reader_for(timeout) {
|
||||
(reader, poll_timeout.leftover())
|
||||
} else {
|
||||
return Ok(false);
|
||||
}
|
||||
} else {
|
||||
(lock_internal_event_reader(), None)
|
||||
};
|
||||
reader.poll(timeout, filter)
|
||||
}
|
||||
|
||||
/// Reads a single `InternalEvent`.
|
||||
pub(crate) fn read_internal<F>(filter: &F) -> std::io::Result<InternalEvent>
|
||||
where
|
||||
F: Filter,
|
||||
{
|
||||
let mut reader = lock_internal_event_reader();
|
||||
reader.read(filter)
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Represents special flags that tell compatible terminals to add extra information to keyboard events.
|
||||
///
|
||||
@ -1467,25 +1417,6 @@ impl Display for KeyCode {
|
||||
}
|
||||
}
|
||||
|
||||
/// An internal event.
|
||||
///
|
||||
/// Encapsulates publicly available `Event` with additional internal
|
||||
/// events that shouldn't be publicly available to the crate users.
|
||||
#[derive(Debug, PartialOrd, PartialEq, Hash, Clone, Eq)]
|
||||
pub(crate) enum InternalEvent {
|
||||
/// An event.
|
||||
Event(Event),
|
||||
/// A cursor position (`col`, `row`).
|
||||
#[cfg(unix)]
|
||||
CursorPosition(u16, u16),
|
||||
/// The progressive keyboard enhancement flags enabled by the terminal.
|
||||
#[cfg(unix)]
|
||||
KeyboardEnhancementFlags(KeyboardEnhancementFlags),
|
||||
/// Attributes and architectural class of the terminal.
|
||||
#[cfg(unix)]
|
||||
PrimaryDeviceAttributes,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::event::InternalEvent;
|
||||
use crate::event::internal::InternalEvent;
|
||||
|
||||
/// Interface for filtering an `InternalEvent`.
|
||||
pub(crate) trait Filter: Send + Sync + 'static {
|
||||
|
72
src/event/internal.rs
Normal file
72
src/event/internal.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
|
||||
|
||||
#[cfg(unix)]
|
||||
use crate::event::KeyboardEnhancementFlags;
|
||||
use crate::event::{filter::Filter, read::InternalEventReader, timeout::PollTimeout, Event};
|
||||
|
||||
/// Static instance of `InternalEventReader`.
|
||||
/// This needs to be static because there can be one event reader.
|
||||
static EVENT_READER: Mutex<Option<InternalEventReader>> = parking_lot::const_mutex(None);
|
||||
|
||||
pub(crate) fn lock_event_reader() -> MappedMutexGuard<'static, InternalEventReader> {
|
||||
MutexGuard::map(EVENT_READER.lock(), |reader| {
|
||||
reader.get_or_insert_with(InternalEventReader::default)
|
||||
})
|
||||
}
|
||||
|
||||
fn try_lock_event_reader_for(
|
||||
duration: Duration,
|
||||
) -> Option<MappedMutexGuard<'static, InternalEventReader>> {
|
||||
Some(MutexGuard::map(
|
||||
EVENT_READER.try_lock_for(duration)?,
|
||||
|reader| reader.get_or_insert_with(InternalEventReader::default),
|
||||
))
|
||||
}
|
||||
|
||||
/// Polls to check if there are any `InternalEvent`s that can be read within the given duration.
|
||||
pub(crate) fn poll<F>(timeout: Option<Duration>, filter: &F) -> std::io::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) = try_lock_event_reader_for(timeout) {
|
||||
(reader, poll_timeout.leftover())
|
||||
} else {
|
||||
return Ok(false);
|
||||
}
|
||||
} else {
|
||||
(lock_event_reader(), None)
|
||||
};
|
||||
reader.poll(timeout, filter)
|
||||
}
|
||||
|
||||
/// Reads a single `InternalEvent`.
|
||||
pub(crate) fn read<F>(filter: &F) -> std::io::Result<InternalEvent>
|
||||
where
|
||||
F: Filter,
|
||||
{
|
||||
let mut reader = lock_event_reader();
|
||||
reader.read(filter)
|
||||
}
|
||||
|
||||
/// An internal event.
|
||||
///
|
||||
/// Encapsulates publicly available `Event` with additional internal
|
||||
/// events that shouldn't be publicly available to the crate users.
|
||||
#[derive(Debug, PartialOrd, PartialEq, Hash, Clone, Eq)]
|
||||
pub(crate) enum InternalEvent {
|
||||
/// An event.
|
||||
Event(Event),
|
||||
/// A cursor position (`col`, `row`).
|
||||
#[cfg(unix)]
|
||||
CursorPosition(u16, u16),
|
||||
/// The progressive keyboard enhancement flags enabled by the terminal.
|
||||
#[cfg(unix)]
|
||||
KeyboardEnhancementFlags(KeyboardEnhancementFlags),
|
||||
/// Attributes and architectural class of the terminal.
|
||||
#[cfg(unix)]
|
||||
PrimaryDeviceAttributes,
|
||||
}
|
@ -6,7 +6,9 @@ use crate::event::source::unix::UnixInternalEventSource;
|
||||
use crate::event::source::windows::WindowsEventSource;
|
||||
#[cfg(feature = "event-stream")]
|
||||
use crate::event::sys::Waker;
|
||||
use crate::event::{filter::Filter, source::EventSource, timeout::PollTimeout, InternalEvent};
|
||||
use crate::event::{
|
||||
filter::Filter, internal::InternalEvent, source::EventSource, timeout::PollTimeout,
|
||||
};
|
||||
|
||||
/// Can be used to read `InternalEvent`s.
|
||||
pub(crate) struct InternalEventReader {
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::{io, time::Duration};
|
||||
|
||||
use super::internal::InternalEvent;
|
||||
#[cfg(feature = "event-stream")]
|
||||
use super::sys::Waker;
|
||||
use super::InternalEvent;
|
||||
|
||||
#[cfg(unix)]
|
||||
pub(crate) mod unix;
|
||||
|
@ -6,7 +6,8 @@ use signal_hook_mio::v1_0::Signals;
|
||||
#[cfg(feature = "event-stream")]
|
||||
use crate::event::sys::Waker;
|
||||
use crate::event::{
|
||||
source::EventSource, sys::unix::parse::parse_event, timeout::PollTimeout, Event, InternalEvent,
|
||||
internal::InternalEvent, source::EventSource, sys::unix::parse::parse_event,
|
||||
timeout::PollTimeout, Event,
|
||||
};
|
||||
use crate::terminal::sys::file_descriptor::{tty_fd, FileDesc};
|
||||
|
||||
|
@ -13,7 +13,7 @@ use filedescriptor::{poll, pollfd, POLLIN};
|
||||
|
||||
#[cfg(feature = "event-stream")]
|
||||
use crate::event::sys::Waker;
|
||||
use crate::event::{source::EventSource, sys::unix::parse::parse_event, InternalEvent};
|
||||
use crate::event::{internal::InternalEvent, source::EventSource, sys::unix::parse::parse_event};
|
||||
use crate::terminal::sys::file_descriptor::{tty_fd, FileDesc};
|
||||
|
||||
/// Holds a prototypical Waker and a receiver we can wait on when doing select().
|
||||
|
@ -10,10 +10,10 @@ use crate::event::{
|
||||
#[cfg(feature = "event-stream")]
|
||||
use crate::event::sys::Waker;
|
||||
use crate::event::{
|
||||
internal::InternalEvent,
|
||||
source::EventSource,
|
||||
sys::windows::parse::{handle_key_event, handle_mouse_event},
|
||||
timeout::PollTimeout,
|
||||
InternalEvent,
|
||||
};
|
||||
|
||||
pub(crate) struct WindowsEventSource {
|
||||
|
@ -14,8 +14,10 @@ use std::{
|
||||
use futures_core::stream::Stream;
|
||||
|
||||
use crate::event::{
|
||||
filter::EventFilter, lock_internal_event_reader, poll_internal, read_internal, sys::Waker,
|
||||
Event, InternalEvent,
|
||||
filter::EventFilter,
|
||||
internal::{self, InternalEvent},
|
||||
sys::Waker,
|
||||
Event,
|
||||
};
|
||||
|
||||
/// A stream of `Result<Event>`.
|
||||
@ -44,7 +46,7 @@ impl Default for EventStream {
|
||||
thread::spawn(move || {
|
||||
while let Ok(task) = receiver.recv() {
|
||||
loop {
|
||||
if let Ok(true) = poll_internal(None, &EventFilter) {
|
||||
if let Ok(true) = internal::poll(None, &EventFilter) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -59,7 +61,7 @@ impl Default for EventStream {
|
||||
});
|
||||
|
||||
EventStream {
|
||||
poll_internal_waker: lock_internal_event_reader().waker(),
|
||||
poll_internal_waker: internal::lock_event_reader().waker(),
|
||||
stream_wake_task_executed: Arc::new(AtomicBool::new(false)),
|
||||
stream_wake_task_should_shutdown: Arc::new(AtomicBool::new(false)),
|
||||
task_sender,
|
||||
@ -102,8 +104,8 @@ impl Stream for EventStream {
|
||||
type Item = io::Result<Event>;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
let result = match poll_internal(Some(Duration::from_secs(0)), &EventFilter) {
|
||||
Ok(true) => match read_internal(&EventFilter) {
|
||||
let result = match internal::poll(Some(Duration::from_secs(0)), &EventFilter) {
|
||||
Ok(true) => match internal::read(&EventFilter) {
|
||||
Ok(InternalEvent::Event(event)) => Poll::Ready(Some(Ok(event))),
|
||||
Err(e) => Poll::Ready(Some(Err(e))),
|
||||
#[cfg(unix)]
|
||||
|
@ -5,7 +5,7 @@ use crate::event::{
|
||||
MediaKeyCode, ModifierKeyCode, MouseButton, MouseEvent, MouseEventKind,
|
||||
};
|
||||
|
||||
use super::super::super::InternalEvent;
|
||||
use crate::event::internal::InternalEvent;
|
||||
|
||||
// Event parsing
|
||||
//
|
||||
|
@ -214,7 +214,7 @@ fn query_keyboard_enhancement_flags_nonraw() -> io::Result<Option<KeyboardEnhanc
|
||||
fn query_keyboard_enhancement_flags_raw() -> io::Result<Option<KeyboardEnhancementFlags>> {
|
||||
use crate::event::{
|
||||
filter::{KeyboardEnhancementFlagsFilter, PrimaryDeviceAttributesFilter},
|
||||
poll_internal, read_internal, InternalEvent,
|
||||
internal::{self, InternalEvent},
|
||||
};
|
||||
use std::io::Write;
|
||||
use std::time::Duration;
|
||||
@ -241,15 +241,15 @@ fn query_keyboard_enhancement_flags_raw() -> io::Result<Option<KeyboardEnhanceme
|
||||
}
|
||||
|
||||
loop {
|
||||
match poll_internal(
|
||||
match internal::poll(
|
||||
Some(Duration::from_millis(2000)),
|
||||
&KeyboardEnhancementFlagsFilter,
|
||||
) {
|
||||
Ok(true) => {
|
||||
match read_internal(&KeyboardEnhancementFlagsFilter) {
|
||||
match internal::read(&KeyboardEnhancementFlagsFilter) {
|
||||
Ok(InternalEvent::KeyboardEnhancementFlags(current_flags)) => {
|
||||
// Flush the PrimaryDeviceAttributes out of the event queue.
|
||||
read_internal(&PrimaryDeviceAttributesFilter).ok();
|
||||
internal::read(&PrimaryDeviceAttributesFilter).ok();
|
||||
return Ok(Some(current_flags));
|
||||
}
|
||||
_ => return Ok(None),
|
||||
|
Loading…
x
Reference in New Issue
Block a user