Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make release event an opt-in feature #778

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Expand Up @@ -33,6 +33,7 @@ event-stream = ["dep:futures-core", "events"] # Enables async events
use-dev-tty = ["filedescriptor"] # Enables raw file descriptor polling / selecting instead of mio.
events = ["dep:mio", "dep:signal-hook", "dep:signal-hook-mio"] # Enables reading input/events from the system.
serde = ["dep:serde", "bitflags/serde"] # Enables 'serde' for various types.
event-kind = ["events"] # Enables a 'release' event for input for windows and kitty protocol.

#
# Shared dependencies
Expand Down Expand Up @@ -81,7 +82,7 @@ serde_json = "1.0"
#
[[example]]
name = "event-read"
required-features = ["bracketed-paste", "events"]
required-features = ["bracketed-paste", "events", "event-kind"]

[[example]]
name = "event-match-modifiers"
Expand Down
1 change: 0 additions & 1 deletion examples/interactive-demo/src/test/color.rs
@@ -1,6 +1,5 @@
#![allow(clippy::cognitive_complexity)]

use crate::Result;
use crossterm::{cursor, queue, style, style::Color};
use std::io::Write;

Expand Down
7 changes: 7 additions & 0 deletions src/event.rs
Expand Up @@ -255,6 +255,8 @@ bitflags! {
const DISAMBIGUATE_ESCAPE_CODES = 0b0000_0001;
/// Add extra events with [`KeyEvent.kind`] set to [`KeyEventKind::Repeat`] or
/// [`KeyEventKind::Release`] when keys are autorepeated or released.
/// IMPORTANT: Requires feature `event-kind` to be enabled.
#[cfg(feature="event-kind")]
const REPORT_EVENT_TYPES = 0b0000_0010;
// Send [alternate keycodes](https://sw.kovidgoyal.net/kitty/keyboard-protocol/#key-codes)
// in addition to the base keycode. The alternate keycode overrides the base keycode in
Expand Down Expand Up @@ -609,11 +611,15 @@ bitflags! {
}

/// Represents a keyboard event kind.
///
/// Enable `event-kind` feature to get release events on windows, and on unix when kitty-protocol is enabled and `KeyboardEnhancementFlags::REPORT_EVENT_TYPES` is set.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub enum KeyEventKind {
Press,
#[cfg(feature = "event-kind")]
Repeat,
#[cfg(feature = "event-kind")]
Release,
}

Expand Down Expand Up @@ -649,6 +655,7 @@ pub struct KeyEvent {
/// Additional key modifiers.
pub modifiers: KeyModifiers,
/// Kind of event.
/// By default `KeyEventKind::Press`.
///
/// Only set if:
/// - Unix: [`KeyboardEnhancementFlags::REPORT_EVENT_TYPES`] has been enabled with [`PushKeyboardEnhancementFlags`].
Expand Down
13 changes: 11 additions & 2 deletions src/event/sys/unix/parse.rs
@@ -1,8 +1,9 @@
use std::io;

use crate::event::{
Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers, KeyboardEnhancementFlags,
MediaKeyCode, ModifierKeyCode, MouseButton, MouseEvent, MouseEventKind,
Event, KeyCode, KeyEvent, KeyEventKind::Release, KeyEventState, KeyModifiers,

Check failure on line 4 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / stable on ubuntu-latest

unresolved import `crate::event::KeyEventKind::Release`

Check failure on line 4 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

unresolved import `crate::event::KeyEventKind::Release`

Check failure on line 4 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

unresolved import `crate::event::KeyEventKind::Release`

Check failure on line 4 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

unresolved import `crate::event::KeyEventKind::Release`

Check failure on line 4 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

unresolved import `crate::event::KeyEventKind::Release`

Check failure on line 4 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

unresolved import `crate::event::KeyEventKind::Release`
KeyboardEnhancementFlags, MediaKeyCode, ModifierKeyCode, MouseButton, MouseEvent,
MouseEventKind,
};

use super::super::super::InternalEvent;
Expand Down Expand Up @@ -163,7 +164,7 @@
b'Z' => Some(Event::Key(KeyEvent::new_with_kind(
KeyCode::BackTab,
KeyModifiers::SHIFT,
KeyEventKind::Press,

Check failure on line 167 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / stable on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 167 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 167 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 167 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 167 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 167 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`
))),
b'M' => return parse_csi_normal_mouse(buffer),
b'<' => return parse_csi_sgr_mouse(buffer),
Expand Down Expand Up @@ -271,6 +272,7 @@
if bits & 1 != 0 {
flags |= KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES;
}
#[cfg(feature = "event-kind")]
if bits & 2 != 0 {
flags |= KeyboardEnhancementFlags::REPORT_EVENT_TYPES;
}
Expand Down Expand Up @@ -336,12 +338,14 @@
state
}

fn parse_key_event_kind(kind: u8) -> KeyEventKind {

Check failure on line 341 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / stable on ubuntu-latest

cannot find type `KeyEventKind` in this scope

Check failure on line 341 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

cannot find type `KeyEventKind` in this scope

Check failure on line 341 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

cannot find type `KeyEventKind` in this scope
match kind {
1 => KeyEventKind::Press,

Check failure on line 343 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / stable on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 343 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 343 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 343 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 343 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 343 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`
#[cfg(feature = "event-kind")]
2 => KeyEventKind::Repeat,
#[cfg(feature = "event-kind")]
3 => KeyEventKind::Release,
_ => KeyEventKind::Press,

Check failure on line 348 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / stable on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 348 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 348 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 348 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 348 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 348 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`
}
}

Expand All @@ -367,10 +371,10 @@
.to_digit(10)
.ok_or_else(could_not_parse_event_error)? as u8,
),
KeyEventKind::Press,

Check failure on line 374 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / stable on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 374 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 374 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 374 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 374 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 374 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`
)
} else {
(KeyModifiers::NONE, KeyEventKind::Press)

Check failure on line 377 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / stable on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 377 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 377 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 377 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 377 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 377 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`
};
let key = buffer[buffer.len() - 1];

Expand Down Expand Up @@ -534,7 +538,7 @@
parse_modifiers_to_state(modifier_mask),
)
} else {
(KeyModifiers::NONE, KeyEventKind::Press, KeyEventState::NONE)

Check failure on line 541 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / stable on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 541 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 541 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 541 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 541 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 541 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`
};

let (mut keycode, state_from_keycode) = {
Expand Down Expand Up @@ -635,7 +639,7 @@
parse_modifiers_to_state(modifier_mask),
)
} else {
(KeyModifiers::NONE, KeyEventKind::Press, KeyEventState::NONE)

Check failure on line 642 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / stable on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 642 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 642 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 642 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 642 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 642 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`
};

let keycode = match first {
Expand Down Expand Up @@ -1288,7 +1292,7 @@
KeyEvent::new_with_kind_and_state(
KeyCode::Char('0'),
KeyModifiers::empty(),
KeyEventKind::Press,

Check failure on line 1295 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 1295 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`
KeyEventState::KEYPAD,
)
))),
Expand All @@ -1299,7 +1303,7 @@
KeyEvent::new_with_kind_and_state(
KeyCode::Up,
KeyModifiers::empty(),
KeyEventKind::Press,

Check failure on line 1306 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`

Check failure on line 1306 in src/event/sys/unix/parse.rs

View workflow job for this annotation

GitHub Actions / nightly on ubuntu-latest

failed to resolve: use of undeclared type `KeyEventKind`
KeyEventState::KEYPAD,
)
))),
Expand Down Expand Up @@ -1332,6 +1336,7 @@
KeyEventKind::Press,
)))),
);
#[cfg(feature = "event-kind")]
assert_eq!(
parse_csi_u_encoded_key_code(b"\x1B[97;1:2u").unwrap(),
Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
Expand All @@ -1340,6 +1345,7 @@
KeyEventKind::Repeat,
)))),
);
#[cfg(feature = "event-kind")]
assert_eq!(
parse_csi_u_encoded_key_code(b"\x1B[97;1:3u").unwrap(),
Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
Expand All @@ -1360,6 +1366,7 @@
KeyEventKind::Press,
)))),
);
#[cfg(feature = "event-kind")]
assert_eq!(
parse_csi_u_encoded_key_code(b"\x1B[57449;3:3u").unwrap(),
Some(InternalEvent::Event(Event::Key(KeyEvent::new_with_kind(
Expand Down Expand Up @@ -1463,6 +1470,7 @@
}

#[test]
#[cfg(feature = "event-kind")]
fn test_parse_csi_special_key_code_with_types() {
assert_eq!(
parse_event(b"\x1B[;1:3B", false).unwrap(),
Expand All @@ -1483,6 +1491,7 @@
}

#[test]
#[cfg(feature = "event-kind")]
fn test_parse_csi_numbered_escape_code_with_types() {
assert_eq!(
parse_event(b"\x1B[5;1:3~", false).unwrap(),
Expand Down
26 changes: 24 additions & 2 deletions src/event/sys/windows/parse.rs
Expand Up @@ -223,7 +223,13 @@ fn parse_key_event_record(key_event: &KeyEventRecord) -> Option<WindowsKeyEvent>
let kind = if key_event.key_down {
KeyEventKind::Press
} else {
KeyEventKind::Release
#[cfg(feature = "event-kind")]
{
KeyEventKind::Release
}
// Dont register key up event.
#[cfg(not(feature = "event-kind"))]
return None;
};
let key_event = KeyEvent::new_with_kind(key_code, modifiers, kind);
return Some(WindowsKeyEvent::KeyEvent(key_event));
Expand All @@ -235,10 +241,20 @@ fn parse_key_event_record(key_event: &KeyEventRecord) -> Option<WindowsKeyEvent>
let is_numpad_numeric_key = (VK_NUMPAD0..=VK_NUMPAD9).contains(&virtual_key_code);
let is_only_alt_modifier = modifiers.contains(KeyModifiers::ALT)
&& !modifiers.contains(KeyModifiers::SHIFT | KeyModifiers::CONTROL);

if is_only_alt_modifier && is_numpad_numeric_key {
return None;
}

if !key_event.key_down && virtual_key_code == VK_RETURN {
// For some reason in some cases we receive a release ENTER event here at the application start.
// This might have to do with the initial enter when running a CLI command.
// We early exit here to prevent confusion.
//
// https://github.com/crossterm-rs/crossterm/issues/752
return None;
}

let parse_result = match virtual_key_code {
VK_SHIFT | VK_CONTROL | VK_MENU => None,
VK_BACK => Some(KeyCode::Backspace),
Expand Down Expand Up @@ -286,7 +302,13 @@ fn parse_key_event_record(key_event: &KeyEventRecord) -> Option<WindowsKeyEvent>
let kind = if key_event.key_down {
KeyEventKind::Press
} else {
KeyEventKind::Release
#[cfg(feature = "event-kind")]
{
KeyEventKind::Release
}
// Dont register key up event.
#[cfg(not(feature = "event-kind"))]
return None;
};
let key_event = KeyEvent::new_with_kind(key_code, modifiers, kind);
return Some(WindowsKeyEvent::KeyEvent(key_event));
Expand Down