Emit focus events (#689)
This commit is contained in:
parent
c6a8952201
commit
069497b43b
@ -7,7 +7,10 @@ use std::io::stdout;
|
||||
use crossterm::event::poll;
|
||||
use crossterm::{
|
||||
cursor::position,
|
||||
event::{read, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
|
||||
event::{
|
||||
read, DisableFocusChange, DisableMouseCapture, EnableFocusChange, EnableMouseCapture,
|
||||
Event, KeyCode,
|
||||
},
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode},
|
||||
Result,
|
||||
@ -15,7 +18,7 @@ use crossterm::{
|
||||
use std::time::Duration;
|
||||
|
||||
const HELP: &str = r#"Blocking read()
|
||||
- Keyboard, mouse and terminal resize events enabled
|
||||
- Keyboard, mouse, focus and terminal resize events enabled
|
||||
- Hit "c" to print current cursor position
|
||||
- Use Esc to quit
|
||||
"#;
|
||||
@ -67,13 +70,13 @@ fn main() -> Result<()> {
|
||||
enable_raw_mode()?;
|
||||
|
||||
let mut stdout = stdout();
|
||||
execute!(stdout, EnableMouseCapture)?;
|
||||
execute!(stdout, EnableFocusChange, EnableMouseCapture)?;
|
||||
|
||||
if let Err(e) = print_events() {
|
||||
println!("Error: {:?}\r", e);
|
||||
}
|
||||
|
||||
execute!(stdout, DisableMouseCapture)?;
|
||||
execute!(stdout, DisableFocusChange, DisableMouseCapture)?;
|
||||
|
||||
disable_raw_mode()
|
||||
}
|
||||
|
45
src/event.rs
45
src/event.rs
@ -34,6 +34,8 @@
|
||||
//! loop {
|
||||
//! // `read()` blocks until an `Event` is available
|
||||
//! match read()? {
|
||||
//! Event::FocusGained => println!("FocusGained"),
|
||||
//! Event::FocusLost => println!("FocusLost"),
|
||||
//! Event::Key(event) => println!("{:?}", event),
|
||||
//! Event::Mouse(event) => println!("{:?}", event),
|
||||
//! Event::Resize(width, height) => println!("New size {}x{}", width, height),
|
||||
@ -57,6 +59,8 @@
|
||||
//! // It's guaranteed that the `read()` won't block when the `poll()`
|
||||
//! // function returns `true`
|
||||
//! match read()? {
|
||||
//! Event::FocusGained => println!("FocusGained"),
|
||||
//! Event::FocusLost => println!("FocusLost"),
|
||||
//! Event::Key(event) => println!("{:?}", event),
|
||||
//! Event::Mouse(event) => println!("{:?}", event),
|
||||
//! Event::Resize(width, height) => println!("New size {}x{}", width, height),
|
||||
@ -74,6 +78,7 @@
|
||||
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
#[cfg(windows)]
|
||||
use std::io;
|
||||
use std::time::Duration;
|
||||
|
||||
@ -409,10 +414,50 @@ impl Command for PopKeyboardEnhancementFlags {
|
||||
}
|
||||
}
|
||||
|
||||
/// A command that enables focus event emission.
|
||||
///
|
||||
/// Focus events can be captured with [read](./fn.read.html)/[poll](./fn.poll.html).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct EnableFocusChange;
|
||||
|
||||
impl Command for EnableFocusChange {
|
||||
fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
|
||||
f.write_str(csi!("?1004h"))
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn execute_winapi(&self) -> Result<()> {
|
||||
// Focus events are always enabled on Windows
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A command that disables focus event emission.
|
||||
///
|
||||
/// Focus events can be captured with [read](./fn.read.html)/[poll](./fn.poll.html).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct DisableFocusChange;
|
||||
|
||||
impl Command for DisableFocusChange {
|
||||
fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
|
||||
f.write_str(csi!("?1004l"))
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn execute_winapi(&self) -> Result<()> {
|
||||
// Focus events can't be disabled on Windows
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an event.
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
pub enum Event {
|
||||
/// The terminal gained focus
|
||||
FocusGained,
|
||||
/// The terminal lost focus
|
||||
FocusLost,
|
||||
/// A single key event with additional pressed modifiers.
|
||||
Key(KeyEvent),
|
||||
/// A single mouse event with additional pressed modifiers.
|
||||
|
@ -66,6 +66,14 @@ impl EventSource for WindowsEventSource {
|
||||
InputRecord::WindowBufferSizeEvent(record) => {
|
||||
Some(Event::Resize(record.size.x as u16, record.size.y as u16))
|
||||
}
|
||||
InputRecord::FocusEvent(record) => {
|
||||
let event = if record.set_focus {
|
||||
Event::FocusGained
|
||||
} else {
|
||||
Event::FocusLost
|
||||
};
|
||||
Some(event)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
@ -167,6 +167,8 @@ pub(crate) fn parse_csi(buffer: &[u8]) -> Result<Option<InternalEvent>> {
|
||||
})),
|
||||
b'M' => return parse_csi_normal_mouse(buffer),
|
||||
b'<' => return parse_csi_sgr_mouse(buffer),
|
||||
b'I' => Some(Event::FocusGained),
|
||||
b'O' => Some(Event::FocusLost),
|
||||
b'0'..=b'9' => {
|
||||
// Numbered escape code.
|
||||
if buffer.len() == 3 {
|
||||
@ -745,6 +747,14 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_csi_focus() {
|
||||
assert_eq!(
|
||||
parse_csi(b"\x1B[O").unwrap(),
|
||||
Some(InternalEvent::Event(Event::FocusLost))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_csi_rxvt_mouse() {
|
||||
assert_eq!(
|
||||
|
@ -350,7 +350,6 @@ pub struct SetStyle(pub ContentStyle);
|
||||
|
||||
impl Command for SetStyle {
|
||||
fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
|
||||
|
||||
if let Some(bg) = self.0.background_color {
|
||||
execute_fmt(f, SetBackgroundColor(bg)).map_err(|_| fmt::Error)?;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user