use crate::geometry::Point;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Event {
MouseMove {
position: Point,
},
MouseDown {
position: Point,
button: MouseButton,
},
MouseUp {
position: Point,
button: MouseButton,
},
Scroll {
delta_x: f32,
delta_y: f32,
},
KeyDown {
key: Key,
},
KeyUp {
key: Key,
},
TextInput {
text: String,
},
FocusIn,
FocusOut,
MouseEnter,
MouseLeave,
Resize {
width: f32,
height: f32,
},
TouchStart {
id: TouchId,
position: Point,
pressure: f32,
},
TouchMove {
id: TouchId,
position: Point,
pressure: f32,
},
TouchEnd {
id: TouchId,
position: Point,
},
TouchCancel {
id: TouchId,
},
PointerDown {
pointer_id: PointerId,
pointer_type: PointerType,
position: Point,
pressure: f32,
is_primary: bool,
button: Option<MouseButton>,
},
PointerMove {
pointer_id: PointerId,
pointer_type: PointerType,
position: Point,
pressure: f32,
is_primary: bool,
},
PointerUp {
pointer_id: PointerId,
pointer_type: PointerType,
position: Point,
is_primary: bool,
button: Option<MouseButton>,
},
PointerCancel {
pointer_id: PointerId,
},
PointerEnter {
pointer_id: PointerId,
pointer_type: PointerType,
},
PointerLeave {
pointer_id: PointerId,
pointer_type: PointerType,
},
GesturePinch {
scale: f32,
center: Point,
state: GestureState,
},
GestureRotate {
angle: f32,
center: Point,
state: GestureState,
},
GesturePan {
delta: Point,
velocity: Point,
state: GestureState,
},
GestureLongPress {
position: Point,
},
GestureTap {
position: Point,
count: u8,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub struct TouchId(pub u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub struct PointerId(pub u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub enum PointerType {
#[default]
Mouse,
Touch,
Pen,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub enum GestureState {
#[default]
Started,
Changed,
Ended,
Cancelled,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum MouseButton {
Left,
Right,
Middle,
Button4,
Button5,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Key {
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
Num0,
Num1,
Num2,
Num3,
Num4,
Num5,
Num6,
Num7,
Num8,
Num9,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
Enter,
Escape,
Backspace,
Tab,
Space,
Delete,
Insert,
Home,
End,
PageUp,
PageDown,
Up,
Down,
Left,
Right,
ShiftLeft,
ShiftRight,
ControlLeft,
ControlRight,
AltLeft,
AltRight,
MetaLeft,
MetaRight,
Minus,
Equal,
BracketLeft,
BracketRight,
Backslash,
Semicolon,
Quote,
Grave,
Comma,
Period,
Slash,
}
impl Event {
#[must_use]
pub const fn is_mouse(&self) -> bool {
matches!(
self,
Self::MouseMove { .. }
| Self::MouseDown { .. }
| Self::MouseUp { .. }
| Self::MouseEnter
| Self::MouseLeave
)
}
#[must_use]
pub const fn is_keyboard(&self) -> bool {
matches!(
self,
Self::KeyDown { .. } | Self::KeyUp { .. } | Self::TextInput { .. }
)
}
#[must_use]
pub const fn is_focus(&self) -> bool {
matches!(self, Self::FocusIn | Self::FocusOut)
}
#[must_use]
pub const fn is_touch(&self) -> bool {
matches!(
self,
Self::TouchStart { .. }
| Self::TouchMove { .. }
| Self::TouchEnd { .. }
| Self::TouchCancel { .. }
)
}
#[must_use]
pub const fn is_pointer(&self) -> bool {
matches!(
self,
Self::PointerDown { .. }
| Self::PointerMove { .. }
| Self::PointerUp { .. }
| Self::PointerCancel { .. }
| Self::PointerEnter { .. }
| Self::PointerLeave { .. }
)
}
#[must_use]
pub const fn is_gesture(&self) -> bool {
matches!(
self,
Self::GesturePinch { .. }
| Self::GestureRotate { .. }
| Self::GesturePan { .. }
| Self::GestureLongPress { .. }
| Self::GestureTap { .. }
)
}
#[must_use]
pub const fn position(&self) -> Option<Point> {
match self {
Self::MouseMove { position }
| Self::MouseDown { position, .. }
| Self::MouseUp { position, .. }
| Self::TouchStart { position, .. }
| Self::TouchMove { position, .. }
| Self::TouchEnd { position, .. }
| Self::PointerDown { position, .. }
| Self::PointerMove { position, .. }
| Self::PointerUp { position, .. }
| Self::GestureLongPress { position }
| Self::GestureTap { position, .. } => Some(*position),
Self::GesturePinch { center, .. } | Self::GestureRotate { center, .. } => Some(*center),
_ => None,
}
}
#[must_use]
pub const fn touch_id(&self) -> Option<TouchId> {
match self {
Self::TouchStart { id, .. }
| Self::TouchMove { id, .. }
| Self::TouchEnd { id, .. }
| Self::TouchCancel { id } => Some(*id),
_ => None,
}
}
#[must_use]
pub const fn pointer_id(&self) -> Option<PointerId> {
match self {
Self::PointerDown { pointer_id, .. }
| Self::PointerMove { pointer_id, .. }
| Self::PointerUp { pointer_id, .. }
| Self::PointerCancel { pointer_id }
| Self::PointerEnter { pointer_id, .. }
| Self::PointerLeave { pointer_id, .. } => Some(*pointer_id),
_ => None,
}
}
#[must_use]
pub const fn pointer_type(&self) -> Option<PointerType> {
match self {
Self::PointerDown { pointer_type, .. }
| Self::PointerMove { pointer_type, .. }
| Self::PointerUp { pointer_type, .. }
| Self::PointerEnter { pointer_type, .. }
| Self::PointerLeave { pointer_type, .. } => Some(*pointer_type),
_ => None,
}
}
#[must_use]
pub const fn pressure(&self) -> Option<f32> {
match self {
Self::TouchStart { pressure, .. }
| Self::TouchMove { pressure, .. }
| Self::PointerDown { pressure, .. }
| Self::PointerMove { pressure, .. } => Some(*pressure),
_ => None,
}
}
#[must_use]
pub const fn gesture_state(&self) -> Option<GestureState> {
match self {
Self::GesturePinch { state, .. }
| Self::GestureRotate { state, .. }
| Self::GesturePan { state, .. } => Some(*state),
_ => None,
}
}
}
impl TouchId {
#[must_use]
pub const fn new(id: u32) -> Self {
Self(id)
}
}
impl PointerId {
#[must_use]
pub const fn new(id: u32) -> Self {
Self(id)
}
}
impl PointerType {
#[must_use]
pub const fn is_mouse(&self) -> bool {
matches!(self, Self::Mouse)
}
#[must_use]
pub const fn is_touch(&self) -> bool {
matches!(self, Self::Touch)
}
#[must_use]
pub const fn is_pen(&self) -> bool {
matches!(self, Self::Pen)
}
}
impl GestureState {
#[must_use]
pub const fn is_start(&self) -> bool {
matches!(self, Self::Started)
}
#[must_use]
pub const fn is_active(&self) -> bool {
matches!(self, Self::Started | Self::Changed)
}
#[must_use]
pub const fn is_end(&self) -> bool {
matches!(self, Self::Ended | Self::Cancelled)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_event_is_mouse() {
assert!(Event::MouseMove {
position: Point::ORIGIN
}
.is_mouse());
assert!(Event::MouseEnter.is_mouse());
assert!(!Event::KeyDown { key: Key::Enter }.is_mouse());
}
#[test]
fn test_event_is_keyboard() {
assert!(Event::KeyDown { key: Key::A }.is_keyboard());
assert!(Event::TextInput {
text: "x".to_string()
}
.is_keyboard());
assert!(!Event::MouseMove {
position: Point::ORIGIN
}
.is_keyboard());
}
#[test]
fn test_event_is_focus() {
assert!(Event::FocusIn.is_focus());
assert!(Event::FocusOut.is_focus());
assert!(!Event::KeyDown { key: Key::Tab }.is_focus());
}
#[test]
fn test_event_position() {
let pos = Point::new(100.0, 200.0);
assert_eq!(Event::MouseMove { position: pos }.position(), Some(pos));
assert_eq!(
Event::MouseDown {
position: pos,
button: MouseButton::Left
}
.position(),
Some(pos)
);
assert_eq!(Event::FocusIn.position(), None);
}
#[test]
fn test_event_mouse_up_position() {
let pos = Point::new(50.0, 75.0);
let event = Event::MouseUp {
position: pos,
button: MouseButton::Right,
};
assert_eq!(event.position(), Some(pos));
assert!(event.is_mouse());
}
#[test]
fn test_event_scroll() {
let event = Event::Scroll {
delta_x: 10.0,
delta_y: -5.0,
};
assert!(!event.is_mouse());
assert!(!event.is_keyboard());
assert!(event.position().is_none());
}
#[test]
fn test_event_resize() {
let event = Event::Resize {
width: 800.0,
height: 600.0,
};
assert!(!event.is_mouse());
assert!(!event.is_keyboard());
assert!(!event.is_focus());
}
#[test]
fn test_event_key_up() {
let event = Event::KeyUp { key: Key::Space };
assert!(event.is_keyboard());
assert!(!event.is_mouse());
}
#[test]
fn test_mouse_button_equality() {
assert_eq!(MouseButton::Left, MouseButton::Left);
assert_ne!(MouseButton::Left, MouseButton::Right);
}
#[test]
fn test_key_equality() {
assert_eq!(Key::Enter, Key::Enter);
assert_ne!(Key::Enter, Key::Space);
}
#[test]
fn test_event_mouse_leave() {
let event = Event::MouseLeave;
assert!(event.is_mouse());
assert!(event.position().is_none());
}
#[test]
fn test_touch_start() {
let event = Event::TouchStart {
id: TouchId::new(1),
position: Point::new(100.0, 200.0),
pressure: 0.8,
};
assert!(event.is_touch());
assert!(!event.is_mouse());
assert!(!event.is_pointer());
assert_eq!(event.touch_id(), Some(TouchId(1)));
assert_eq!(event.position(), Some(Point::new(100.0, 200.0)));
assert_eq!(event.pressure(), Some(0.8));
}
#[test]
fn test_touch_move() {
let event = Event::TouchMove {
id: TouchId::new(2),
position: Point::new(150.0, 250.0),
pressure: 0.5,
};
assert!(event.is_touch());
assert_eq!(event.touch_id(), Some(TouchId(2)));
assert_eq!(event.position(), Some(Point::new(150.0, 250.0)));
assert_eq!(event.pressure(), Some(0.5));
}
#[test]
fn test_touch_end() {
let event = Event::TouchEnd {
id: TouchId::new(3),
position: Point::new(200.0, 300.0),
};
assert!(event.is_touch());
assert_eq!(event.touch_id(), Some(TouchId(3)));
assert_eq!(event.position(), Some(Point::new(200.0, 300.0)));
assert!(event.pressure().is_none());
}
#[test]
fn test_touch_cancel() {
let event = Event::TouchCancel {
id: TouchId::new(4),
};
assert!(event.is_touch());
assert_eq!(event.touch_id(), Some(TouchId(4)));
assert!(event.position().is_none());
}
#[test]
fn test_touch_id_creation() {
let id = TouchId::new(42);
assert_eq!(id.0, 42);
let default_id = TouchId::default();
assert_eq!(default_id.0, 0);
}
#[test]
fn test_pointer_down() {
let event = Event::PointerDown {
pointer_id: PointerId::new(1),
pointer_type: PointerType::Touch,
position: Point::new(100.0, 200.0),
pressure: 0.7,
is_primary: true,
button: None,
};
assert!(event.is_pointer());
assert!(!event.is_touch());
assert!(!event.is_mouse());
assert_eq!(event.pointer_id(), Some(PointerId(1)));
assert_eq!(event.pointer_type(), Some(PointerType::Touch));
assert_eq!(event.position(), Some(Point::new(100.0, 200.0)));
assert_eq!(event.pressure(), Some(0.7));
}
#[test]
fn test_pointer_down_with_mouse_button() {
let event = Event::PointerDown {
pointer_id: PointerId::new(1),
pointer_type: PointerType::Mouse,
position: Point::new(50.0, 75.0),
pressure: 0.5,
is_primary: true,
button: Some(MouseButton::Left),
};
assert!(event.is_pointer());
assert_eq!(event.pointer_type(), Some(PointerType::Mouse));
}
#[test]
fn test_pointer_move() {
let event = Event::PointerMove {
pointer_id: PointerId::new(2),
pointer_type: PointerType::Pen,
position: Point::new(150.0, 250.0),
pressure: 0.9,
is_primary: false,
};
assert!(event.is_pointer());
assert_eq!(event.pointer_id(), Some(PointerId(2)));
assert_eq!(event.pointer_type(), Some(PointerType::Pen));
assert_eq!(event.pressure(), Some(0.9));
}
#[test]
fn test_pointer_up() {
let event = Event::PointerUp {
pointer_id: PointerId::new(3),
pointer_type: PointerType::Mouse,
position: Point::new(200.0, 300.0),
is_primary: true,
button: Some(MouseButton::Right),
};
assert!(event.is_pointer());
assert_eq!(event.pointer_id(), Some(PointerId(3)));
assert!(event.pressure().is_none());
}
#[test]
fn test_pointer_cancel() {
let event = Event::PointerCancel {
pointer_id: PointerId::new(4),
};
assert!(event.is_pointer());
assert_eq!(event.pointer_id(), Some(PointerId(4)));
assert!(event.pointer_type().is_none());
assert!(event.position().is_none());
}
#[test]
fn test_pointer_enter() {
let event = Event::PointerEnter {
pointer_id: PointerId::new(5),
pointer_type: PointerType::Mouse,
};
assert!(event.is_pointer());
assert_eq!(event.pointer_id(), Some(PointerId(5)));
assert_eq!(event.pointer_type(), Some(PointerType::Mouse));
assert!(event.position().is_none());
}
#[test]
fn test_pointer_leave() {
let event = Event::PointerLeave {
pointer_id: PointerId::new(6),
pointer_type: PointerType::Touch,
};
assert!(event.is_pointer());
assert_eq!(event.pointer_id(), Some(PointerId(6)));
assert_eq!(event.pointer_type(), Some(PointerType::Touch));
}
#[test]
fn test_pointer_id_creation() {
let id = PointerId::new(99);
assert_eq!(id.0, 99);
let default_id = PointerId::default();
assert_eq!(default_id.0, 0);
}
#[test]
fn test_pointer_type_helpers() {
assert!(PointerType::Mouse.is_mouse());
assert!(!PointerType::Mouse.is_touch());
assert!(!PointerType::Mouse.is_pen());
assert!(!PointerType::Touch.is_mouse());
assert!(PointerType::Touch.is_touch());
assert!(!PointerType::Touch.is_pen());
assert!(!PointerType::Pen.is_mouse());
assert!(!PointerType::Pen.is_touch());
assert!(PointerType::Pen.is_pen());
}
#[test]
fn test_pointer_type_default() {
let default = PointerType::default();
assert_eq!(default, PointerType::Mouse);
}
#[test]
fn test_gesture_pinch() {
let event = Event::GesturePinch {
scale: 1.5,
center: Point::new(200.0, 200.0),
state: GestureState::Changed,
};
assert!(event.is_gesture());
assert!(!event.is_touch());
assert!(!event.is_pointer());
assert_eq!(event.gesture_state(), Some(GestureState::Changed));
assert_eq!(event.position(), Some(Point::new(200.0, 200.0)));
}
#[test]
fn test_gesture_rotate() {
let event = Event::GestureRotate {
angle: std::f32::consts::PI / 4.0,
center: Point::new(150.0, 150.0),
state: GestureState::Started,
};
assert!(event.is_gesture());
assert_eq!(event.gesture_state(), Some(GestureState::Started));
assert_eq!(event.position(), Some(Point::new(150.0, 150.0)));
}
#[test]
fn test_gesture_pan() {
let event = Event::GesturePan {
delta: Point::new(10.0, -5.0),
velocity: Point::new(100.0, -50.0),
state: GestureState::Ended,
};
assert!(event.is_gesture());
assert_eq!(event.gesture_state(), Some(GestureState::Ended));
assert!(event.position().is_none());
}
#[test]
fn test_gesture_long_press() {
let event = Event::GestureLongPress {
position: Point::new(100.0, 100.0),
};
assert!(event.is_gesture());
assert_eq!(event.position(), Some(Point::new(100.0, 100.0)));
assert!(event.gesture_state().is_none());
}
#[test]
fn test_gesture_tap() {
let single_tap = Event::GestureTap {
position: Point::new(50.0, 50.0),
count: 1,
};
assert!(single_tap.is_gesture());
assert_eq!(single_tap.position(), Some(Point::new(50.0, 50.0)));
let double_tap = Event::GestureTap {
position: Point::new(50.0, 50.0),
count: 2,
};
assert!(double_tap.is_gesture());
}
#[test]
fn test_gesture_state_helpers() {
assert!(GestureState::Started.is_start());
assert!(GestureState::Started.is_active());
assert!(!GestureState::Started.is_end());
assert!(!GestureState::Changed.is_start());
assert!(GestureState::Changed.is_active());
assert!(!GestureState::Changed.is_end());
assert!(!GestureState::Ended.is_start());
assert!(!GestureState::Ended.is_active());
assert!(GestureState::Ended.is_end());
assert!(!GestureState::Cancelled.is_start());
assert!(!GestureState::Cancelled.is_active());
assert!(GestureState::Cancelled.is_end());
}
#[test]
fn test_gesture_state_default() {
let default = GestureState::default();
assert_eq!(default, GestureState::Started);
}
#[test]
fn test_event_category_exclusivity() {
let touch = Event::TouchStart {
id: TouchId::new(1),
position: Point::ORIGIN,
pressure: 0.5,
};
assert!(touch.is_touch());
assert!(!touch.is_pointer());
assert!(!touch.is_gesture());
assert!(!touch.is_mouse());
let pointer = Event::PointerDown {
pointer_id: PointerId::new(1),
pointer_type: PointerType::Touch,
position: Point::ORIGIN,
pressure: 0.5,
is_primary: true,
button: None,
};
assert!(!pointer.is_touch());
assert!(pointer.is_pointer());
assert!(!pointer.is_gesture());
assert!(!pointer.is_mouse());
let gesture = Event::GesturePinch {
scale: 1.0,
center: Point::ORIGIN,
state: GestureState::Started,
};
assert!(!gesture.is_touch());
assert!(!gesture.is_pointer());
assert!(gesture.is_gesture());
assert!(!gesture.is_mouse());
}
#[test]
fn test_mouse_event_has_no_touch_or_pointer_id() {
let mouse = Event::MouseDown {
position: Point::ORIGIN,
button: MouseButton::Left,
};
assert!(mouse.touch_id().is_none());
assert!(mouse.pointer_id().is_none());
assert!(mouse.pointer_type().is_none());
assert!(mouse.pressure().is_none());
assert!(mouse.gesture_state().is_none());
}
#[test]
fn test_serialization_roundtrip() {
let events = vec![
Event::TouchStart {
id: TouchId::new(1),
position: Point::new(100.0, 200.0),
pressure: 0.8,
},
Event::PointerDown {
pointer_id: PointerId::new(2),
pointer_type: PointerType::Pen,
position: Point::new(50.0, 75.0),
pressure: 0.6,
is_primary: true,
button: None,
},
Event::GesturePinch {
scale: 2.0,
center: Point::new(200.0, 200.0),
state: GestureState::Changed,
},
];
for event in events {
let json = serde_json::to_string(&event).unwrap();
let deserialized: Event = serde_json::from_str(&json).unwrap();
assert_eq!(event, deserialized);
}
}
#[test]
fn test_mouse_button_all_variants() {
let buttons = [
MouseButton::Left,
MouseButton::Right,
MouseButton::Middle,
MouseButton::Button4,
MouseButton::Button5,
];
for button in &buttons {
let event = Event::MouseDown {
position: Point::ORIGIN,
button: *button,
};
assert!(event.is_mouse());
}
}
#[test]
fn test_mouse_button_debug() {
assert_eq!(format!("{:?}", MouseButton::Left), "Left");
assert_eq!(format!("{:?}", MouseButton::Middle), "Middle");
}
#[test]
fn test_key_letters() {
let letters = [
Key::A,
Key::B,
Key::C,
Key::D,
Key::E,
Key::F,
Key::G,
Key::H,
Key::I,
Key::J,
Key::K,
Key::L,
Key::M,
Key::N,
Key::O,
Key::P,
Key::Q,
Key::R,
Key::S,
Key::T,
Key::U,
Key::V,
Key::W,
Key::X,
Key::Y,
Key::Z,
];
for key in &letters {
let event = Event::KeyDown { key: *key };
assert!(event.is_keyboard());
}
}
#[test]
fn test_key_numbers() {
let numbers = [
Key::Num0,
Key::Num1,
Key::Num2,
Key::Num3,
Key::Num4,
Key::Num5,
Key::Num6,
Key::Num7,
Key::Num8,
Key::Num9,
];
for key in &numbers {
let event = Event::KeyDown { key: *key };
assert!(event.is_keyboard());
}
}
#[test]
fn test_key_function_keys() {
let function_keys = [
Key::F1,
Key::F2,
Key::F3,
Key::F4,
Key::F5,
Key::F6,
Key::F7,
Key::F8,
Key::F9,
Key::F10,
Key::F11,
Key::F12,
];
for key in &function_keys {
let event = Event::KeyDown { key: *key };
assert!(event.is_keyboard());
}
}
#[test]
fn test_key_control_keys() {
let control_keys = [
Key::Enter,
Key::Escape,
Key::Backspace,
Key::Tab,
Key::Space,
Key::Delete,
Key::Insert,
Key::Home,
Key::End,
Key::PageUp,
Key::PageDown,
];
for key in &control_keys {
let event = Event::KeyDown { key: *key };
assert!(event.is_keyboard());
}
}
#[test]
fn test_key_arrow_keys() {
let arrows = [Key::Up, Key::Down, Key::Left, Key::Right];
for key in &arrows {
let event = Event::KeyDown { key: *key };
assert!(event.is_keyboard());
}
}
#[test]
fn test_key_modifiers() {
let modifiers = [
Key::ShiftLeft,
Key::ShiftRight,
Key::ControlLeft,
Key::ControlRight,
Key::AltLeft,
Key::AltRight,
Key::MetaLeft,
Key::MetaRight,
];
for key in &modifiers {
let event = Event::KeyDown { key: *key };
assert!(event.is_keyboard());
}
}
#[test]
fn test_key_punctuation() {
let punctuation = [
Key::Minus,
Key::Equal,
Key::BracketLeft,
Key::BracketRight,
Key::Backslash,
Key::Semicolon,
Key::Quote,
Key::Grave,
Key::Comma,
Key::Period,
Key::Slash,
];
for key in &punctuation {
let event = Event::KeyDown { key: *key };
assert!(event.is_keyboard());
}
}
#[test]
fn test_key_debug() {
assert_eq!(format!("{:?}", Key::Enter), "Enter");
assert_eq!(format!("{:?}", Key::F1), "F1");
}
#[test]
fn test_touch_id_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(TouchId::new(1));
set.insert(TouchId::new(2));
set.insert(TouchId::new(1)); assert_eq!(set.len(), 2);
}
#[test]
fn test_pointer_id_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(PointerId::new(1));
set.insert(PointerId::new(2));
set.insert(PointerId::new(1)); assert_eq!(set.len(), 2);
}
#[test]
fn test_pointer_type_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(PointerType::Mouse);
set.insert(PointerType::Touch);
set.insert(PointerType::Pen);
set.insert(PointerType::Mouse); assert_eq!(set.len(), 3);
}
#[test]
fn test_gesture_state_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(GestureState::Started);
set.insert(GestureState::Changed);
set.insert(GestureState::Ended);
set.insert(GestureState::Cancelled);
assert_eq!(set.len(), 4);
}
#[test]
fn test_event_debug() {
let event = Event::FocusIn;
let debug = format!("{event:?}");
assert!(debug.contains("FocusIn"));
}
#[test]
fn test_event_clone() {
let event = Event::MouseMove {
position: Point::new(100.0, 200.0),
};
let cloned = event.clone();
assert_eq!(event, cloned);
}
#[test]
fn test_text_input_event() {
let event = Event::TextInput {
text: "Hello, 世界!".to_string(),
};
assert!(event.is_keyboard());
assert!(!event.is_mouse());
assert!(event.position().is_none());
}
#[test]
fn test_scroll_event_deltas() {
let event = Event::Scroll {
delta_x: -10.5,
delta_y: 20.3,
};
assert!(!event.is_mouse());
assert!(!event.is_touch());
assert!(!event.is_pointer());
}
#[test]
fn test_resize_event() {
let event = Event::Resize {
width: 1920.0,
height: 1080.0,
};
assert!(!event.is_mouse());
assert!(event.position().is_none());
}
#[test]
fn test_gesture_pan_no_position() {
let event = Event::GesturePan {
delta: Point::new(50.0, 30.0),
velocity: Point::new(200.0, 150.0),
state: GestureState::Changed,
};
assert!(event.is_gesture());
assert!(event.position().is_none());
}
#[test]
fn test_all_event_serialization() {
let events = vec![
Event::MouseMove {
position: Point::new(1.0, 2.0),
},
Event::MouseDown {
position: Point::new(1.0, 2.0),
button: MouseButton::Left,
},
Event::MouseUp {
position: Point::new(1.0, 2.0),
button: MouseButton::Right,
},
Event::Scroll {
delta_x: 1.0,
delta_y: -1.0,
},
Event::KeyDown { key: Key::A },
Event::KeyUp { key: Key::B },
Event::TextInput {
text: "test".to_string(),
},
Event::FocusIn,
Event::FocusOut,
Event::MouseEnter,
Event::MouseLeave,
Event::Resize {
width: 800.0,
height: 600.0,
},
];
for event in events {
let json = serde_json::to_string(&event).unwrap();
let deserialized: Event = serde_json::from_str(&json).unwrap();
assert_eq!(event, deserialized);
}
}
#[test]
fn test_touch_events_serialization() {
let events = vec![
Event::TouchStart {
id: TouchId(1),
position: Point::new(10.0, 20.0),
pressure: 0.5,
},
Event::TouchMove {
id: TouchId(1),
position: Point::new(15.0, 25.0),
pressure: 0.6,
},
Event::TouchEnd {
id: TouchId(1),
position: Point::new(20.0, 30.0),
},
Event::TouchCancel { id: TouchId(1) },
];
for event in events {
let json = serde_json::to_string(&event).unwrap();
let deserialized: Event = serde_json::from_str(&json).unwrap();
assert_eq!(event, deserialized);
}
}
#[test]
fn test_gesture_events_serialization() {
let events = vec![
Event::GesturePinch {
scale: 1.5,
center: Point::new(100.0, 100.0),
state: GestureState::Started,
},
Event::GestureRotate {
angle: 0.5,
center: Point::new(100.0, 100.0),
state: GestureState::Changed,
},
Event::GesturePan {
delta: Point::new(10.0, 5.0),
velocity: Point::new(50.0, 25.0),
state: GestureState::Ended,
},
Event::GestureLongPress {
position: Point::new(50.0, 50.0),
},
Event::GestureTap {
position: Point::new(50.0, 50.0),
count: 2,
},
];
for event in events {
let json = serde_json::to_string(&event).unwrap();
let deserialized: Event = serde_json::from_str(&json).unwrap();
assert_eq!(event, deserialized);
}
}
#[test]
fn test_pointer_events_serialization() {
let events = vec![
Event::PointerDown {
pointer_id: PointerId(1),
pointer_type: PointerType::Mouse,
position: Point::new(10.0, 20.0),
pressure: 0.5,
is_primary: true,
button: Some(MouseButton::Left),
},
Event::PointerMove {
pointer_id: PointerId(1),
pointer_type: PointerType::Touch,
position: Point::new(15.0, 25.0),
pressure: 0.6,
is_primary: true,
},
Event::PointerUp {
pointer_id: PointerId(1),
pointer_type: PointerType::Pen,
position: Point::new(20.0, 30.0),
is_primary: false,
button: None,
},
Event::PointerCancel {
pointer_id: PointerId(1),
},
Event::PointerEnter {
pointer_id: PointerId(2),
pointer_type: PointerType::Mouse,
},
Event::PointerLeave {
pointer_id: PointerId(2),
pointer_type: PointerType::Touch,
},
];
for event in events {
let json = serde_json::to_string(&event).unwrap();
let deserialized: Event = serde_json::from_str(&json).unwrap();
assert_eq!(event, deserialized);
}
}
#[test]
fn test_key_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(Key::A);
set.insert(Key::B);
set.insert(Key::A); assert_eq!(set.len(), 2);
}
#[test]
fn test_mouse_button_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(MouseButton::Left);
set.insert(MouseButton::Right);
set.insert(MouseButton::Left); assert_eq!(set.len(), 2);
}
}