use bitflags::bitflags;
use std::hash::{Hash, Hasher};
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Hash)]
pub enum Event {
Key(KeyEvent),
Mouse(MouseEvent),
}
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub struct MouseEvent {
pub kind: MouseEventKind,
pub column: u16,
pub row: u16,
pub modifiers: KeyModifiers,
}
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub enum MouseEventKind {
Down(MouseButton),
Up(MouseButton),
Drag(MouseButton),
Moved,
}
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub enum MouseButton {
Left,
Right,
Middle,
}
bitflags! {
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub struct KeyModifiers: u8 {
const SHIFT = 0b0000_0001;
const CONTROL = 0b0000_0010;
const ALT = 0b0000_0100;
const SUPER = 0b0000_1000;
const HYPER = 0b0001_0000;
const META = 0b0010_0000;
const NONE = 0b0000_0000;
}
}
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub enum KeyEventKind {
Press,
Repeat,
Release,
}
bitflags! {
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub struct KeyEventState: u8 {
const KEYPAD = 0b0000_0001;
const CAPS_LOCK = 0b0000_1000;
const NUM_LOCK = 0b0000_1000;
const NONE = 0b0000_0000;
}
}
#[derive(Debug, PartialOrd, Clone, Copy)]
pub struct KeyEvent {
pub code: KeyCode,
pub modifiers: KeyModifiers,
pub kind: KeyEventKind,
pub state: KeyEventState,
}
impl KeyEvent {
pub const fn new(code: KeyCode, modifiers: KeyModifiers) -> KeyEvent {
KeyEvent {
code,
modifiers,
kind: KeyEventKind::Press,
state: KeyEventState::empty(),
}
}
pub const fn new_with_kind(
code: KeyCode,
modifiers: KeyModifiers,
kind: KeyEventKind,
) -> KeyEvent {
KeyEvent {
code,
modifiers,
kind,
state: KeyEventState::empty(),
}
}
pub const fn new_with_kind_and_state(
code: KeyCode,
modifiers: KeyModifiers,
kind: KeyEventKind,
state: KeyEventState,
) -> KeyEvent {
KeyEvent {
code,
modifiers,
kind,
state,
}
}
fn normalize_case(mut self) -> KeyEvent {
let c = match self.code {
KeyCode::Char(c) => c,
_ => return self,
};
if c.is_ascii_uppercase() {
self.modifiers.insert(KeyModifiers::SHIFT);
} else if self.modifiers.contains(KeyModifiers::SHIFT) {
self.code = KeyCode::Char(c.to_ascii_uppercase())
}
self
}
}
impl From<KeyCode> for KeyEvent {
fn from(code: KeyCode) -> Self {
KeyEvent {
code,
modifiers: KeyModifiers::empty(),
kind: KeyEventKind::Press,
state: KeyEventState::empty(),
}
}
}
impl PartialEq for KeyEvent {
fn eq(&self, other: &KeyEvent) -> bool {
let KeyEvent {
code: lhs_code,
modifiers: lhs_modifiers,
kind: lhs_kind,
state: lhs_state,
} = self.normalize_case();
let KeyEvent {
code: rhs_code,
modifiers: rhs_modifiers,
kind: rhs_kind,
state: rhs_state,
} = other.normalize_case();
(lhs_code == rhs_code)
&& (lhs_modifiers == rhs_modifiers)
&& (lhs_kind == rhs_kind)
&& (lhs_state == rhs_state)
}
}
impl Eq for KeyEvent {}
impl Hash for KeyEvent {
fn hash<H: Hasher>(&self, hash_state: &mut H) {
let KeyEvent {
code,
modifiers,
kind,
state,
} = self.normalize_case();
code.hash(hash_state);
modifiers.hash(hash_state);
kind.hash(hash_state);
state.hash(hash_state);
}
}
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub enum ModifierKeyCode {
LeftShift,
LeftControl,
LeftAlt,
LeftSuper,
LeftHyper,
LeftMeta,
RightShift,
RightControl,
RightAlt,
RightSuper,
RightHyper,
RightMeta,
}
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash)]
pub enum KeyCode {
Backspace,
Enter,
Left,
Right,
Up,
Down,
Home,
End,
PageUp,
PageDown,
Tab,
BackTab,
Delete,
Insert,
F(u8),
Char(char),
Null,
Esc,
CapsLock,
ScrollLock,
NumLock,
PrintScreen,
Pause,
Menu,
KeypadBegin,
Modifier(ModifierKeyCode),
}