use alloc::string::{String, ToString};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Modifiers(pub u32);
impl Modifiers {
pub const NONE: Self = Self(0);
pub const SHIFT: Self = Self(1);
pub const CTRL: Self = Self(2);
pub const ALT: Self = Self(4);
pub const SUPER: Self = Self(8);
pub const fn contains(self, other: Self) -> bool {
self.0 & other.0 == other.0 && other.0 != 0
}
pub const fn shift(self) -> bool {
self.contains(Self::SHIFT)
}
pub const fn ctrl(self) -> bool {
self.contains(Self::CTRL)
}
pub const fn alt(self) -> bool {
self.contains(Self::ALT)
}
pub const fn super_key(self) -> bool {
self.contains(Self::SUPER)
}
pub const fn is_empty(self) -> bool {
self.0 == 0
}
}
impl core::ops::BitOr for Modifiers {
type Output = Self;
fn bitor(self, other: Self) -> Self {
Self(self.0 | other.0)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum KeyCode {
Char(char),
Enter,
Tab,
BackTab,
Backspace,
Delete,
Insert,
Space,
Left,
Right,
Up,
Down,
Home,
End,
PageUp,
PageDown,
F(u8),
Other(String),
}
impl KeyCode {
pub fn parse(code: &str) -> Self {
let mut chars = code.chars();
if let (Some(character), None) = (chars.next(), chars.next()) {
return Self::Char(character);
}
match code {
"enter" => Self::Enter,
"tab" => Self::Tab,
"backtab" => Self::BackTab,
"backspace" => Self::Backspace,
"delete" => Self::Delete,
"insert" => Self::Insert,
"space" => Self::Space,
"left" => Self::Left,
"right" => Self::Right,
"up" => Self::Up,
"down" => Self::Down,
"home" => Self::Home,
"end" => Self::End,
"pageup" => Self::PageUp,
"pagedown" => Self::PageDown,
other => match other.strip_prefix('f').and_then(|n| n.parse::<u8>().ok()) {
Some(n @ 1..=12) => Self::F(n),
_ => Self::Other(other.to_string()),
},
}
}
pub fn name(&self) -> String {
match self {
Self::Char(character) => character.to_string(),
Self::Enter => "enter".into(),
Self::Tab => "tab".into(),
Self::BackTab => "backtab".into(),
Self::Backspace => "backspace".into(),
Self::Delete => "delete".into(),
Self::Insert => "insert".into(),
Self::Space => "space".into(),
Self::Left => "left".into(),
Self::Right => "right".into(),
Self::Up => "up".into(),
Self::Down => "down".into(),
Self::Home => "home".into(),
Self::End => "end".into(),
Self::PageUp => "pageup".into(),
Self::PageDown => "pagedown".into(),
Self::F(n) => alloc::format!("f{n}"),
Self::Other(name) => name.clone(),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum KeyPhase {
#[default]
Press,
Repeat,
Release,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Key {
pub surface: String,
pub code: KeyCode,
pub text: Option<String>,
pub modifiers: Modifiers,
pub phase: KeyPhase,
}
impl Key {
pub fn press(surface: &str, code: KeyCode) -> Self {
let text = match &code {
KeyCode::Char(character) => Some(character.to_string()),
KeyCode::Space => Some(" ".into()),
_ => None,
};
Self {
surface: surface.into(),
code,
text,
modifiers: Modifiers::NONE,
phase: KeyPhase::Press,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum PointerKind {
Down,
Up,
Move,
Drag,
Wheel,
Enter,
Leave,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Button {
None,
Left,
Middle,
Right,
WheelUp,
WheelDown,
WheelLeft,
WheelRight,
Other(u8),
}
impl Button {
pub fn from_wire(button: u8) -> Self {
match button {
0 => Self::None,
1 => Self::Left,
2 => Self::Middle,
3 => Self::Right,
4 => Self::WheelUp,
5 => Self::WheelDown,
6 => Self::WheelLeft,
7 => Self::WheelRight,
other => Self::Other(other),
}
}
pub fn wire(self) -> u8 {
match self {
Self::None => 0,
Self::Left => 1,
Self::Middle => 2,
Self::Right => 3,
Self::WheelUp => 4,
Self::WheelDown => 5,
Self::WheelLeft => 6,
Self::WheelRight => 7,
Self::Other(other) => other,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Pointer {
pub surface: String,
pub x: u32,
pub y: u32,
pub col: u32,
pub row: u32,
pub button: Button,
pub kind: PointerKind,
pub modifiers: Modifiers,
}