presentar_core/
event.rs

1//! Input events for widgets.
2
3use crate::geometry::Point;
4use serde::{Deserialize, Serialize};
5
6/// Input event types.
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub enum Event {
9    /// Mouse moved to position
10    MouseMove {
11        /// New position
12        position: Point,
13    },
14    /// Mouse button pressed
15    MouseDown {
16        /// Position of click
17        position: Point,
18        /// Button pressed
19        button: MouseButton,
20    },
21    /// Mouse button released
22    MouseUp {
23        /// Position of release
24        position: Point,
25        /// Button released
26        button: MouseButton,
27    },
28    /// Mouse wheel scrolled
29    Scroll {
30        /// Horizontal scroll delta
31        delta_x: f32,
32        /// Vertical scroll delta
33        delta_y: f32,
34    },
35    /// Key pressed
36    KeyDown {
37        /// Key pressed
38        key: Key,
39    },
40    /// Key released
41    KeyUp {
42        /// Key released
43        key: Key,
44    },
45    /// Text input received
46    TextInput {
47        /// Input text
48        text: String,
49    },
50    /// Widget gained focus
51    FocusIn,
52    /// Widget lost focus
53    FocusOut,
54    /// Mouse entered widget bounds
55    MouseEnter,
56    /// Mouse left widget bounds
57    MouseLeave,
58    /// Window resized
59    Resize {
60        /// New width
61        width: f32,
62        /// New height
63        height: f32,
64    },
65    // Touch events
66    /// Touch started
67    TouchStart {
68        /// Touch identifier
69        id: TouchId,
70        /// Touch position
71        position: Point,
72        /// Touch pressure (0.0 to 1.0)
73        pressure: f32,
74    },
75    /// Touch moved
76    TouchMove {
77        /// Touch identifier
78        id: TouchId,
79        /// New position
80        position: Point,
81        /// Touch pressure
82        pressure: f32,
83    },
84    /// Touch ended
85    TouchEnd {
86        /// Touch identifier
87        id: TouchId,
88        /// Final position
89        position: Point,
90    },
91    /// Touch cancelled (e.g., palm rejection)
92    TouchCancel {
93        /// Touch identifier
94        id: TouchId,
95    },
96    // Pointer events (unified mouse/touch/pen)
97    /// Pointer down
98    PointerDown {
99        /// Pointer ID
100        pointer_id: PointerId,
101        /// Pointer type
102        pointer_type: PointerType,
103        /// Position
104        position: Point,
105        /// Pressure
106        pressure: f32,
107        /// Is primary pointer
108        is_primary: bool,
109        /// Button (for mouse pointers)
110        button: Option<MouseButton>,
111    },
112    /// Pointer moved
113    PointerMove {
114        /// Pointer ID
115        pointer_id: PointerId,
116        /// Pointer type
117        pointer_type: PointerType,
118        /// Position
119        position: Point,
120        /// Pressure
121        pressure: f32,
122        /// Is primary pointer
123        is_primary: bool,
124    },
125    /// Pointer up
126    PointerUp {
127        /// Pointer ID
128        pointer_id: PointerId,
129        /// Pointer type
130        pointer_type: PointerType,
131        /// Position
132        position: Point,
133        /// Is primary pointer
134        is_primary: bool,
135        /// Button (for mouse pointers)
136        button: Option<MouseButton>,
137    },
138    /// Pointer cancelled
139    PointerCancel {
140        /// Pointer ID
141        pointer_id: PointerId,
142    },
143    /// Pointer entered element
144    PointerEnter {
145        /// Pointer ID
146        pointer_id: PointerId,
147        /// Pointer type
148        pointer_type: PointerType,
149    },
150    /// Pointer left element
151    PointerLeave {
152        /// Pointer ID
153        pointer_id: PointerId,
154        /// Pointer type
155        pointer_type: PointerType,
156    },
157    // Gesture events
158    /// Pinch gesture
159    GesturePinch {
160        /// Scale factor
161        scale: f32,
162        /// Center point
163        center: Point,
164        /// Gesture state
165        state: GestureState,
166    },
167    /// Rotate gesture
168    GestureRotate {
169        /// Rotation angle in radians
170        angle: f32,
171        /// Center point
172        center: Point,
173        /// Gesture state
174        state: GestureState,
175    },
176    /// Pan/drag gesture
177    GesturePan {
178        /// Translation delta
179        delta: Point,
180        /// Velocity
181        velocity: Point,
182        /// Gesture state
183        state: GestureState,
184    },
185    /// Long press gesture
186    GestureLongPress {
187        /// Position
188        position: Point,
189    },
190    /// Tap gesture
191    GestureTap {
192        /// Position
193        position: Point,
194        /// Number of taps (1 = single, 2 = double)
195        count: u8,
196    },
197}
198
199/// Touch identifier for multi-touch tracking.
200#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
201pub struct TouchId(pub u32);
202
203/// Pointer identifier for pointer events.
204#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
205pub struct PointerId(pub u32);
206
207/// Type of pointer device.
208#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
209pub enum PointerType {
210    /// Mouse pointer
211    #[default]
212    Mouse,
213    /// Touch pointer
214    Touch,
215    /// Pen/stylus pointer
216    Pen,
217}
218
219/// State of a gesture.
220#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
221pub enum GestureState {
222    /// Gesture started
223    #[default]
224    Started,
225    /// Gesture in progress (changed)
226    Changed,
227    /// Gesture ended
228    Ended,
229    /// Gesture cancelled
230    Cancelled,
231}
232
233/// Mouse button identifiers.
234#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
235pub enum MouseButton {
236    /// Left mouse button
237    Left,
238    /// Right mouse button
239    Right,
240    /// Middle mouse button (wheel click)
241    Middle,
242    /// Additional button 1
243    Button4,
244    /// Additional button 2
245    Button5,
246}
247
248/// Keyboard key identifiers.
249#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
250pub enum Key {
251    // Letters
252    /// A key
253    A,
254    /// B key
255    B,
256    /// C key
257    C,
258    /// D key
259    D,
260    /// E key
261    E,
262    /// F key
263    F,
264    /// G key
265    G,
266    /// H key
267    H,
268    /// I key
269    I,
270    /// J key
271    J,
272    /// K key
273    K,
274    /// L key
275    L,
276    /// M key
277    M,
278    /// N key
279    N,
280    /// O key
281    O,
282    /// P key
283    P,
284    /// Q key
285    Q,
286    /// R key
287    R,
288    /// S key
289    S,
290    /// T key
291    T,
292    /// U key
293    U,
294    /// V key
295    V,
296    /// W key
297    W,
298    /// X key
299    X,
300    /// Y key
301    Y,
302    /// Z key
303    Z,
304
305    // Numbers
306    /// 0 key
307    Num0,
308    /// 1 key
309    Num1,
310    /// 2 key
311    Num2,
312    /// 3 key
313    Num3,
314    /// 4 key
315    Num4,
316    /// 5 key
317    Num5,
318    /// 6 key
319    Num6,
320    /// 7 key
321    Num7,
322    /// 8 key
323    Num8,
324    /// 9 key
325    Num9,
326
327    // Function keys
328    /// F1 key
329    F1,
330    /// F2 key
331    F2,
332    /// F3 key
333    F3,
334    /// F4 key
335    F4,
336    /// F5 key
337    F5,
338    /// F6 key
339    F6,
340    /// F7 key
341    F7,
342    /// F8 key
343    F8,
344    /// F9 key
345    F9,
346    /// F10 key
347    F10,
348    /// F11 key
349    F11,
350    /// F12 key
351    F12,
352
353    // Control keys
354    /// Enter/Return key
355    Enter,
356    /// Escape key
357    Escape,
358    /// Backspace key
359    Backspace,
360    /// Tab key
361    Tab,
362    /// Space key
363    Space,
364    /// Delete key
365    Delete,
366    /// Insert key
367    Insert,
368    /// Home key
369    Home,
370    /// End key
371    End,
372    /// Page Up key
373    PageUp,
374    /// Page Down key
375    PageDown,
376
377    // Arrow keys
378    /// Up arrow
379    Up,
380    /// Down arrow
381    Down,
382    /// Left arrow
383    Left,
384    /// Right arrow
385    Right,
386
387    // Modifiers
388    /// Left Shift
389    ShiftLeft,
390    /// Right Shift
391    ShiftRight,
392    /// Left Control
393    ControlLeft,
394    /// Right Control
395    ControlRight,
396    /// Left Alt
397    AltLeft,
398    /// Right Alt
399    AltRight,
400    /// Left Meta (Windows/Command)
401    MetaLeft,
402    /// Right Meta (Windows/Command)
403    MetaRight,
404
405    // Punctuation
406    /// Minus key
407    Minus,
408    /// Equals key
409    Equal,
410    /// Left bracket
411    BracketLeft,
412    /// Right bracket
413    BracketRight,
414    /// Backslash
415    Backslash,
416    /// Semicolon
417    Semicolon,
418    /// Quote/apostrophe
419    Quote,
420    /// Grave/backtick
421    Grave,
422    /// Comma
423    Comma,
424    /// Period
425    Period,
426    /// Slash
427    Slash,
428}
429
430impl Event {
431    /// Check if this is a mouse event.
432    #[must_use]
433    pub const fn is_mouse(&self) -> bool {
434        matches!(
435            self,
436            Self::MouseMove { .. }
437                | Self::MouseDown { .. }
438                | Self::MouseUp { .. }
439                | Self::MouseEnter
440                | Self::MouseLeave
441        )
442    }
443
444    /// Check if this is a keyboard event.
445    #[must_use]
446    pub const fn is_keyboard(&self) -> bool {
447        matches!(
448            self,
449            Self::KeyDown { .. } | Self::KeyUp { .. } | Self::TextInput { .. }
450        )
451    }
452
453    /// Check if this is a focus event.
454    #[must_use]
455    pub const fn is_focus(&self) -> bool {
456        matches!(self, Self::FocusIn | Self::FocusOut)
457    }
458
459    /// Check if this is a touch event.
460    #[must_use]
461    pub const fn is_touch(&self) -> bool {
462        matches!(
463            self,
464            Self::TouchStart { .. }
465                | Self::TouchMove { .. }
466                | Self::TouchEnd { .. }
467                | Self::TouchCancel { .. }
468        )
469    }
470
471    /// Check if this is a pointer event.
472    #[must_use]
473    pub const fn is_pointer(&self) -> bool {
474        matches!(
475            self,
476            Self::PointerDown { .. }
477                | Self::PointerMove { .. }
478                | Self::PointerUp { .. }
479                | Self::PointerCancel { .. }
480                | Self::PointerEnter { .. }
481                | Self::PointerLeave { .. }
482        )
483    }
484
485    /// Check if this is a gesture event.
486    #[must_use]
487    pub const fn is_gesture(&self) -> bool {
488        matches!(
489            self,
490            Self::GesturePinch { .. }
491                | Self::GestureRotate { .. }
492                | Self::GesturePan { .. }
493                | Self::GestureLongPress { .. }
494                | Self::GestureTap { .. }
495        )
496    }
497
498    /// Get the position if this is a positional event.
499    #[must_use]
500    pub const fn position(&self) -> Option<Point> {
501        match self {
502            Self::MouseMove { position }
503            | Self::MouseDown { position, .. }
504            | Self::MouseUp { position, .. }
505            | Self::TouchStart { position, .. }
506            | Self::TouchMove { position, .. }
507            | Self::TouchEnd { position, .. }
508            | Self::PointerDown { position, .. }
509            | Self::PointerMove { position, .. }
510            | Self::PointerUp { position, .. }
511            | Self::GestureLongPress { position }
512            | Self::GestureTap { position, .. } => Some(*position),
513            Self::GesturePinch { center, .. } | Self::GestureRotate { center, .. } => Some(*center),
514            _ => None,
515        }
516    }
517
518    /// Get the touch ID if this is a touch event.
519    #[must_use]
520    pub const fn touch_id(&self) -> Option<TouchId> {
521        match self {
522            Self::TouchStart { id, .. }
523            | Self::TouchMove { id, .. }
524            | Self::TouchEnd { id, .. }
525            | Self::TouchCancel { id } => Some(*id),
526            _ => None,
527        }
528    }
529
530    /// Get the pointer ID if this is a pointer event.
531    #[must_use]
532    pub const fn pointer_id(&self) -> Option<PointerId> {
533        match self {
534            Self::PointerDown { pointer_id, .. }
535            | Self::PointerMove { pointer_id, .. }
536            | Self::PointerUp { pointer_id, .. }
537            | Self::PointerCancel { pointer_id }
538            | Self::PointerEnter { pointer_id, .. }
539            | Self::PointerLeave { pointer_id, .. } => Some(*pointer_id),
540            _ => None,
541        }
542    }
543
544    /// Get the pointer type if this is a pointer event.
545    #[must_use]
546    pub const fn pointer_type(&self) -> Option<PointerType> {
547        match self {
548            Self::PointerDown { pointer_type, .. }
549            | Self::PointerMove { pointer_type, .. }
550            | Self::PointerUp { pointer_type, .. }
551            | Self::PointerEnter { pointer_type, .. }
552            | Self::PointerLeave { pointer_type, .. } => Some(*pointer_type),
553            _ => None,
554        }
555    }
556
557    /// Get pressure if available (0.0 to 1.0).
558    #[must_use]
559    pub const fn pressure(&self) -> Option<f32> {
560        match self {
561            Self::TouchStart { pressure, .. }
562            | Self::TouchMove { pressure, .. }
563            | Self::PointerDown { pressure, .. }
564            | Self::PointerMove { pressure, .. } => Some(*pressure),
565            _ => None,
566        }
567    }
568
569    /// Get gesture state if this is a gesture event.
570    #[must_use]
571    pub const fn gesture_state(&self) -> Option<GestureState> {
572        match self {
573            Self::GesturePinch { state, .. }
574            | Self::GestureRotate { state, .. }
575            | Self::GesturePan { state, .. } => Some(*state),
576            _ => None,
577        }
578    }
579}
580
581impl TouchId {
582    /// Create a new touch ID.
583    #[must_use]
584    pub const fn new(id: u32) -> Self {
585        Self(id)
586    }
587}
588
589impl PointerId {
590    /// Create a new pointer ID.
591    #[must_use]
592    pub const fn new(id: u32) -> Self {
593        Self(id)
594    }
595}
596
597impl PointerType {
598    /// Check if this is a mouse pointer.
599    #[must_use]
600    pub const fn is_mouse(&self) -> bool {
601        matches!(self, Self::Mouse)
602    }
603
604    /// Check if this is a touch pointer.
605    #[must_use]
606    pub const fn is_touch(&self) -> bool {
607        matches!(self, Self::Touch)
608    }
609
610    /// Check if this is a pen pointer.
611    #[must_use]
612    pub const fn is_pen(&self) -> bool {
613        matches!(self, Self::Pen)
614    }
615}
616
617impl GestureState {
618    /// Check if gesture is starting.
619    #[must_use]
620    pub const fn is_start(&self) -> bool {
621        matches!(self, Self::Started)
622    }
623
624    /// Check if gesture is in progress.
625    #[must_use]
626    pub const fn is_active(&self) -> bool {
627        matches!(self, Self::Started | Self::Changed)
628    }
629
630    /// Check if gesture has ended.
631    #[must_use]
632    pub const fn is_end(&self) -> bool {
633        matches!(self, Self::Ended | Self::Cancelled)
634    }
635}
636
637#[cfg(test)]
638mod tests {
639    use super::*;
640
641    #[test]
642    fn test_event_is_mouse() {
643        assert!(Event::MouseMove {
644            position: Point::ORIGIN
645        }
646        .is_mouse());
647        assert!(Event::MouseEnter.is_mouse());
648        assert!(!Event::KeyDown { key: Key::Enter }.is_mouse());
649    }
650
651    #[test]
652    fn test_event_is_keyboard() {
653        assert!(Event::KeyDown { key: Key::A }.is_keyboard());
654        assert!(Event::TextInput {
655            text: "x".to_string()
656        }
657        .is_keyboard());
658        assert!(!Event::MouseMove {
659            position: Point::ORIGIN
660        }
661        .is_keyboard());
662    }
663
664    #[test]
665    fn test_event_is_focus() {
666        assert!(Event::FocusIn.is_focus());
667        assert!(Event::FocusOut.is_focus());
668        assert!(!Event::KeyDown { key: Key::Tab }.is_focus());
669    }
670
671    #[test]
672    fn test_event_position() {
673        let pos = Point::new(100.0, 200.0);
674        assert_eq!(Event::MouseMove { position: pos }.position(), Some(pos));
675        assert_eq!(
676            Event::MouseDown {
677                position: pos,
678                button: MouseButton::Left
679            }
680            .position(),
681            Some(pos)
682        );
683        assert_eq!(Event::FocusIn.position(), None);
684    }
685
686    #[test]
687    fn test_event_mouse_up_position() {
688        let pos = Point::new(50.0, 75.0);
689        let event = Event::MouseUp {
690            position: pos,
691            button: MouseButton::Right,
692        };
693        assert_eq!(event.position(), Some(pos));
694        assert!(event.is_mouse());
695    }
696
697    #[test]
698    fn test_event_scroll() {
699        let event = Event::Scroll {
700            delta_x: 10.0,
701            delta_y: -5.0,
702        };
703        assert!(!event.is_mouse());
704        assert!(!event.is_keyboard());
705        assert!(event.position().is_none());
706    }
707
708    #[test]
709    fn test_event_resize() {
710        let event = Event::Resize {
711            width: 800.0,
712            height: 600.0,
713        };
714        assert!(!event.is_mouse());
715        assert!(!event.is_keyboard());
716        assert!(!event.is_focus());
717    }
718
719    #[test]
720    fn test_event_key_up() {
721        let event = Event::KeyUp { key: Key::Space };
722        assert!(event.is_keyboard());
723        assert!(!event.is_mouse());
724    }
725
726    #[test]
727    fn test_mouse_button_equality() {
728        assert_eq!(MouseButton::Left, MouseButton::Left);
729        assert_ne!(MouseButton::Left, MouseButton::Right);
730    }
731
732    #[test]
733    fn test_key_equality() {
734        assert_eq!(Key::Enter, Key::Enter);
735        assert_ne!(Key::Enter, Key::Space);
736    }
737
738    #[test]
739    fn test_event_mouse_leave() {
740        let event = Event::MouseLeave;
741        assert!(event.is_mouse());
742        assert!(event.position().is_none());
743    }
744
745    // Touch event tests
746    #[test]
747    fn test_touch_start() {
748        let event = Event::TouchStart {
749            id: TouchId::new(1),
750            position: Point::new(100.0, 200.0),
751            pressure: 0.8,
752        };
753        assert!(event.is_touch());
754        assert!(!event.is_mouse());
755        assert!(!event.is_pointer());
756        assert_eq!(event.touch_id(), Some(TouchId(1)));
757        assert_eq!(event.position(), Some(Point::new(100.0, 200.0)));
758        assert_eq!(event.pressure(), Some(0.8));
759    }
760
761    #[test]
762    fn test_touch_move() {
763        let event = Event::TouchMove {
764            id: TouchId::new(2),
765            position: Point::new(150.0, 250.0),
766            pressure: 0.5,
767        };
768        assert!(event.is_touch());
769        assert_eq!(event.touch_id(), Some(TouchId(2)));
770        assert_eq!(event.position(), Some(Point::new(150.0, 250.0)));
771        assert_eq!(event.pressure(), Some(0.5));
772    }
773
774    #[test]
775    fn test_touch_end() {
776        let event = Event::TouchEnd {
777            id: TouchId::new(3),
778            position: Point::new(200.0, 300.0),
779        };
780        assert!(event.is_touch());
781        assert_eq!(event.touch_id(), Some(TouchId(3)));
782        assert_eq!(event.position(), Some(Point::new(200.0, 300.0)));
783        assert!(event.pressure().is_none());
784    }
785
786    #[test]
787    fn test_touch_cancel() {
788        let event = Event::TouchCancel {
789            id: TouchId::new(4),
790        };
791        assert!(event.is_touch());
792        assert_eq!(event.touch_id(), Some(TouchId(4)));
793        assert!(event.position().is_none());
794    }
795
796    #[test]
797    fn test_touch_id_creation() {
798        let id = TouchId::new(42);
799        assert_eq!(id.0, 42);
800        let default_id = TouchId::default();
801        assert_eq!(default_id.0, 0);
802    }
803
804    // Pointer event tests
805    #[test]
806    fn test_pointer_down() {
807        let event = Event::PointerDown {
808            pointer_id: PointerId::new(1),
809            pointer_type: PointerType::Touch,
810            position: Point::new(100.0, 200.0),
811            pressure: 0.7,
812            is_primary: true,
813            button: None,
814        };
815        assert!(event.is_pointer());
816        assert!(!event.is_touch());
817        assert!(!event.is_mouse());
818        assert_eq!(event.pointer_id(), Some(PointerId(1)));
819        assert_eq!(event.pointer_type(), Some(PointerType::Touch));
820        assert_eq!(event.position(), Some(Point::new(100.0, 200.0)));
821        assert_eq!(event.pressure(), Some(0.7));
822    }
823
824    #[test]
825    fn test_pointer_down_with_mouse_button() {
826        let event = Event::PointerDown {
827            pointer_id: PointerId::new(1),
828            pointer_type: PointerType::Mouse,
829            position: Point::new(50.0, 75.0),
830            pressure: 0.5,
831            is_primary: true,
832            button: Some(MouseButton::Left),
833        };
834        assert!(event.is_pointer());
835        assert_eq!(event.pointer_type(), Some(PointerType::Mouse));
836    }
837
838    #[test]
839    fn test_pointer_move() {
840        let event = Event::PointerMove {
841            pointer_id: PointerId::new(2),
842            pointer_type: PointerType::Pen,
843            position: Point::new(150.0, 250.0),
844            pressure: 0.9,
845            is_primary: false,
846        };
847        assert!(event.is_pointer());
848        assert_eq!(event.pointer_id(), Some(PointerId(2)));
849        assert_eq!(event.pointer_type(), Some(PointerType::Pen));
850        assert_eq!(event.pressure(), Some(0.9));
851    }
852
853    #[test]
854    fn test_pointer_up() {
855        let event = Event::PointerUp {
856            pointer_id: PointerId::new(3),
857            pointer_type: PointerType::Mouse,
858            position: Point::new(200.0, 300.0),
859            is_primary: true,
860            button: Some(MouseButton::Right),
861        };
862        assert!(event.is_pointer());
863        assert_eq!(event.pointer_id(), Some(PointerId(3)));
864        assert!(event.pressure().is_none());
865    }
866
867    #[test]
868    fn test_pointer_cancel() {
869        let event = Event::PointerCancel {
870            pointer_id: PointerId::new(4),
871        };
872        assert!(event.is_pointer());
873        assert_eq!(event.pointer_id(), Some(PointerId(4)));
874        assert!(event.pointer_type().is_none());
875        assert!(event.position().is_none());
876    }
877
878    #[test]
879    fn test_pointer_enter() {
880        let event = Event::PointerEnter {
881            pointer_id: PointerId::new(5),
882            pointer_type: PointerType::Mouse,
883        };
884        assert!(event.is_pointer());
885        assert_eq!(event.pointer_id(), Some(PointerId(5)));
886        assert_eq!(event.pointer_type(), Some(PointerType::Mouse));
887        assert!(event.position().is_none());
888    }
889
890    #[test]
891    fn test_pointer_leave() {
892        let event = Event::PointerLeave {
893            pointer_id: PointerId::new(6),
894            pointer_type: PointerType::Touch,
895        };
896        assert!(event.is_pointer());
897        assert_eq!(event.pointer_id(), Some(PointerId(6)));
898        assert_eq!(event.pointer_type(), Some(PointerType::Touch));
899    }
900
901    #[test]
902    fn test_pointer_id_creation() {
903        let id = PointerId::new(99);
904        assert_eq!(id.0, 99);
905        let default_id = PointerId::default();
906        assert_eq!(default_id.0, 0);
907    }
908
909    #[test]
910    fn test_pointer_type_helpers() {
911        assert!(PointerType::Mouse.is_mouse());
912        assert!(!PointerType::Mouse.is_touch());
913        assert!(!PointerType::Mouse.is_pen());
914
915        assert!(!PointerType::Touch.is_mouse());
916        assert!(PointerType::Touch.is_touch());
917        assert!(!PointerType::Touch.is_pen());
918
919        assert!(!PointerType::Pen.is_mouse());
920        assert!(!PointerType::Pen.is_touch());
921        assert!(PointerType::Pen.is_pen());
922    }
923
924    #[test]
925    fn test_pointer_type_default() {
926        let default = PointerType::default();
927        assert_eq!(default, PointerType::Mouse);
928    }
929
930    // Gesture event tests
931    #[test]
932    fn test_gesture_pinch() {
933        let event = Event::GesturePinch {
934            scale: 1.5,
935            center: Point::new(200.0, 200.0),
936            state: GestureState::Changed,
937        };
938        assert!(event.is_gesture());
939        assert!(!event.is_touch());
940        assert!(!event.is_pointer());
941        assert_eq!(event.gesture_state(), Some(GestureState::Changed));
942        assert_eq!(event.position(), Some(Point::new(200.0, 200.0)));
943    }
944
945    #[test]
946    fn test_gesture_rotate() {
947        let event = Event::GestureRotate {
948            angle: std::f32::consts::PI / 4.0,
949            center: Point::new(150.0, 150.0),
950            state: GestureState::Started,
951        };
952        assert!(event.is_gesture());
953        assert_eq!(event.gesture_state(), Some(GestureState::Started));
954        assert_eq!(event.position(), Some(Point::new(150.0, 150.0)));
955    }
956
957    #[test]
958    fn test_gesture_pan() {
959        let event = Event::GesturePan {
960            delta: Point::new(10.0, -5.0),
961            velocity: Point::new(100.0, -50.0),
962            state: GestureState::Ended,
963        };
964        assert!(event.is_gesture());
965        assert_eq!(event.gesture_state(), Some(GestureState::Ended));
966        assert!(event.position().is_none());
967    }
968
969    #[test]
970    fn test_gesture_long_press() {
971        let event = Event::GestureLongPress {
972            position: Point::new(100.0, 100.0),
973        };
974        assert!(event.is_gesture());
975        assert_eq!(event.position(), Some(Point::new(100.0, 100.0)));
976        assert!(event.gesture_state().is_none());
977    }
978
979    #[test]
980    fn test_gesture_tap() {
981        let single_tap = Event::GestureTap {
982            position: Point::new(50.0, 50.0),
983            count: 1,
984        };
985        assert!(single_tap.is_gesture());
986        assert_eq!(single_tap.position(), Some(Point::new(50.0, 50.0)));
987
988        let double_tap = Event::GestureTap {
989            position: Point::new(50.0, 50.0),
990            count: 2,
991        };
992        assert!(double_tap.is_gesture());
993    }
994
995    #[test]
996    fn test_gesture_state_helpers() {
997        assert!(GestureState::Started.is_start());
998        assert!(GestureState::Started.is_active());
999        assert!(!GestureState::Started.is_end());
1000
1001        assert!(!GestureState::Changed.is_start());
1002        assert!(GestureState::Changed.is_active());
1003        assert!(!GestureState::Changed.is_end());
1004
1005        assert!(!GestureState::Ended.is_start());
1006        assert!(!GestureState::Ended.is_active());
1007        assert!(GestureState::Ended.is_end());
1008
1009        assert!(!GestureState::Cancelled.is_start());
1010        assert!(!GestureState::Cancelled.is_active());
1011        assert!(GestureState::Cancelled.is_end());
1012    }
1013
1014    #[test]
1015    fn test_gesture_state_default() {
1016        let default = GestureState::default();
1017        assert_eq!(default, GestureState::Started);
1018    }
1019
1020    // Cross-category tests
1021    #[test]
1022    fn test_event_category_exclusivity() {
1023        let touch = Event::TouchStart {
1024            id: TouchId::new(1),
1025            position: Point::ORIGIN,
1026            pressure: 0.5,
1027        };
1028        assert!(touch.is_touch());
1029        assert!(!touch.is_pointer());
1030        assert!(!touch.is_gesture());
1031        assert!(!touch.is_mouse());
1032
1033        let pointer = Event::PointerDown {
1034            pointer_id: PointerId::new(1),
1035            pointer_type: PointerType::Touch,
1036            position: Point::ORIGIN,
1037            pressure: 0.5,
1038            is_primary: true,
1039            button: None,
1040        };
1041        assert!(!pointer.is_touch());
1042        assert!(pointer.is_pointer());
1043        assert!(!pointer.is_gesture());
1044        assert!(!pointer.is_mouse());
1045
1046        let gesture = Event::GesturePinch {
1047            scale: 1.0,
1048            center: Point::ORIGIN,
1049            state: GestureState::Started,
1050        };
1051        assert!(!gesture.is_touch());
1052        assert!(!gesture.is_pointer());
1053        assert!(gesture.is_gesture());
1054        assert!(!gesture.is_mouse());
1055    }
1056
1057    #[test]
1058    fn test_mouse_event_has_no_touch_or_pointer_id() {
1059        let mouse = Event::MouseDown {
1060            position: Point::ORIGIN,
1061            button: MouseButton::Left,
1062        };
1063        assert!(mouse.touch_id().is_none());
1064        assert!(mouse.pointer_id().is_none());
1065        assert!(mouse.pointer_type().is_none());
1066        assert!(mouse.pressure().is_none());
1067        assert!(mouse.gesture_state().is_none());
1068    }
1069
1070    #[test]
1071    fn test_serialization_roundtrip() {
1072        let events = vec![
1073            Event::TouchStart {
1074                id: TouchId::new(1),
1075                position: Point::new(100.0, 200.0),
1076                pressure: 0.8,
1077            },
1078            Event::PointerDown {
1079                pointer_id: PointerId::new(2),
1080                pointer_type: PointerType::Pen,
1081                position: Point::new(50.0, 75.0),
1082                pressure: 0.6,
1083                is_primary: true,
1084                button: None,
1085            },
1086            Event::GesturePinch {
1087                scale: 2.0,
1088                center: Point::new(200.0, 200.0),
1089                state: GestureState::Changed,
1090            },
1091        ];
1092
1093        for event in events {
1094            let json = serde_json::to_string(&event).unwrap();
1095            let deserialized: Event = serde_json::from_str(&json).unwrap();
1096            assert_eq!(event, deserialized);
1097        }
1098    }
1099
1100    // ========== Additional edge case tests ==========
1101
1102    #[test]
1103    fn test_mouse_button_all_variants() {
1104        let buttons = [
1105            MouseButton::Left,
1106            MouseButton::Right,
1107            MouseButton::Middle,
1108            MouseButton::Button4,
1109            MouseButton::Button5,
1110        ];
1111        for button in &buttons {
1112            let event = Event::MouseDown {
1113                position: Point::ORIGIN,
1114                button: *button,
1115            };
1116            assert!(event.is_mouse());
1117        }
1118    }
1119
1120    #[test]
1121    fn test_mouse_button_debug() {
1122        assert_eq!(format!("{:?}", MouseButton::Left), "Left");
1123        assert_eq!(format!("{:?}", MouseButton::Middle), "Middle");
1124    }
1125
1126    #[test]
1127    fn test_key_letters() {
1128        let letters = [
1129            Key::A,
1130            Key::B,
1131            Key::C,
1132            Key::D,
1133            Key::E,
1134            Key::F,
1135            Key::G,
1136            Key::H,
1137            Key::I,
1138            Key::J,
1139            Key::K,
1140            Key::L,
1141            Key::M,
1142            Key::N,
1143            Key::O,
1144            Key::P,
1145            Key::Q,
1146            Key::R,
1147            Key::S,
1148            Key::T,
1149            Key::U,
1150            Key::V,
1151            Key::W,
1152            Key::X,
1153            Key::Y,
1154            Key::Z,
1155        ];
1156        for key in &letters {
1157            let event = Event::KeyDown { key: *key };
1158            assert!(event.is_keyboard());
1159        }
1160    }
1161
1162    #[test]
1163    fn test_key_numbers() {
1164        let numbers = [
1165            Key::Num0,
1166            Key::Num1,
1167            Key::Num2,
1168            Key::Num3,
1169            Key::Num4,
1170            Key::Num5,
1171            Key::Num6,
1172            Key::Num7,
1173            Key::Num8,
1174            Key::Num9,
1175        ];
1176        for key in &numbers {
1177            let event = Event::KeyDown { key: *key };
1178            assert!(event.is_keyboard());
1179        }
1180    }
1181
1182    #[test]
1183    fn test_key_function_keys() {
1184        let function_keys = [
1185            Key::F1,
1186            Key::F2,
1187            Key::F3,
1188            Key::F4,
1189            Key::F5,
1190            Key::F6,
1191            Key::F7,
1192            Key::F8,
1193            Key::F9,
1194            Key::F10,
1195            Key::F11,
1196            Key::F12,
1197        ];
1198        for key in &function_keys {
1199            let event = Event::KeyDown { key: *key };
1200            assert!(event.is_keyboard());
1201        }
1202    }
1203
1204    #[test]
1205    fn test_key_control_keys() {
1206        let control_keys = [
1207            Key::Enter,
1208            Key::Escape,
1209            Key::Backspace,
1210            Key::Tab,
1211            Key::Space,
1212            Key::Delete,
1213            Key::Insert,
1214            Key::Home,
1215            Key::End,
1216            Key::PageUp,
1217            Key::PageDown,
1218        ];
1219        for key in &control_keys {
1220            let event = Event::KeyDown { key: *key };
1221            assert!(event.is_keyboard());
1222        }
1223    }
1224
1225    #[test]
1226    fn test_key_arrow_keys() {
1227        let arrows = [Key::Up, Key::Down, Key::Left, Key::Right];
1228        for key in &arrows {
1229            let event = Event::KeyDown { key: *key };
1230            assert!(event.is_keyboard());
1231        }
1232    }
1233
1234    #[test]
1235    fn test_key_modifiers() {
1236        let modifiers = [
1237            Key::ShiftLeft,
1238            Key::ShiftRight,
1239            Key::ControlLeft,
1240            Key::ControlRight,
1241            Key::AltLeft,
1242            Key::AltRight,
1243            Key::MetaLeft,
1244            Key::MetaRight,
1245        ];
1246        for key in &modifiers {
1247            let event = Event::KeyDown { key: *key };
1248            assert!(event.is_keyboard());
1249        }
1250    }
1251
1252    #[test]
1253    fn test_key_punctuation() {
1254        let punctuation = [
1255            Key::Minus,
1256            Key::Equal,
1257            Key::BracketLeft,
1258            Key::BracketRight,
1259            Key::Backslash,
1260            Key::Semicolon,
1261            Key::Quote,
1262            Key::Grave,
1263            Key::Comma,
1264            Key::Period,
1265            Key::Slash,
1266        ];
1267        for key in &punctuation {
1268            let event = Event::KeyDown { key: *key };
1269            assert!(event.is_keyboard());
1270        }
1271    }
1272
1273    #[test]
1274    fn test_key_debug() {
1275        assert_eq!(format!("{:?}", Key::Enter), "Enter");
1276        assert_eq!(format!("{:?}", Key::F1), "F1");
1277    }
1278
1279    #[test]
1280    fn test_touch_id_hash() {
1281        use std::collections::HashSet;
1282        let mut set = HashSet::new();
1283        set.insert(TouchId::new(1));
1284        set.insert(TouchId::new(2));
1285        set.insert(TouchId::new(1)); // Duplicate
1286        assert_eq!(set.len(), 2);
1287    }
1288
1289    #[test]
1290    fn test_pointer_id_hash() {
1291        use std::collections::HashSet;
1292        let mut set = HashSet::new();
1293        set.insert(PointerId::new(1));
1294        set.insert(PointerId::new(2));
1295        set.insert(PointerId::new(1)); // Duplicate
1296        assert_eq!(set.len(), 2);
1297    }
1298
1299    #[test]
1300    fn test_pointer_type_hash() {
1301        use std::collections::HashSet;
1302        let mut set = HashSet::new();
1303        set.insert(PointerType::Mouse);
1304        set.insert(PointerType::Touch);
1305        set.insert(PointerType::Pen);
1306        set.insert(PointerType::Mouse); // Duplicate
1307        assert_eq!(set.len(), 3);
1308    }
1309
1310    #[test]
1311    fn test_gesture_state_hash() {
1312        use std::collections::HashSet;
1313        let mut set = HashSet::new();
1314        set.insert(GestureState::Started);
1315        set.insert(GestureState::Changed);
1316        set.insert(GestureState::Ended);
1317        set.insert(GestureState::Cancelled);
1318        assert_eq!(set.len(), 4);
1319    }
1320
1321    #[test]
1322    fn test_event_debug() {
1323        let event = Event::FocusIn;
1324        let debug = format!("{event:?}");
1325        assert!(debug.contains("FocusIn"));
1326    }
1327
1328    #[test]
1329    fn test_event_clone() {
1330        let event = Event::MouseMove {
1331            position: Point::new(100.0, 200.0),
1332        };
1333        let cloned = event.clone();
1334        assert_eq!(event, cloned);
1335    }
1336
1337    #[test]
1338    fn test_text_input_event() {
1339        let event = Event::TextInput {
1340            text: "Hello, 世界!".to_string(),
1341        };
1342        assert!(event.is_keyboard());
1343        assert!(!event.is_mouse());
1344        assert!(event.position().is_none());
1345    }
1346
1347    #[test]
1348    fn test_scroll_event_deltas() {
1349        let event = Event::Scroll {
1350            delta_x: -10.5,
1351            delta_y: 20.3,
1352        };
1353        assert!(!event.is_mouse());
1354        assert!(!event.is_touch());
1355        assert!(!event.is_pointer());
1356    }
1357
1358    #[test]
1359    fn test_resize_event() {
1360        let event = Event::Resize {
1361            width: 1920.0,
1362            height: 1080.0,
1363        };
1364        assert!(!event.is_mouse());
1365        assert!(event.position().is_none());
1366    }
1367
1368    #[test]
1369    fn test_gesture_pan_no_position() {
1370        let event = Event::GesturePan {
1371            delta: Point::new(50.0, 30.0),
1372            velocity: Point::new(200.0, 150.0),
1373            state: GestureState::Changed,
1374        };
1375        assert!(event.is_gesture());
1376        // GesturePan has delta/velocity, not position
1377        assert!(event.position().is_none());
1378    }
1379
1380    #[test]
1381    fn test_all_event_serialization() {
1382        let events = vec![
1383            Event::MouseMove {
1384                position: Point::new(1.0, 2.0),
1385            },
1386            Event::MouseDown {
1387                position: Point::new(1.0, 2.0),
1388                button: MouseButton::Left,
1389            },
1390            Event::MouseUp {
1391                position: Point::new(1.0, 2.0),
1392                button: MouseButton::Right,
1393            },
1394            Event::Scroll {
1395                delta_x: 1.0,
1396                delta_y: -1.0,
1397            },
1398            Event::KeyDown { key: Key::A },
1399            Event::KeyUp { key: Key::B },
1400            Event::TextInput {
1401                text: "test".to_string(),
1402            },
1403            Event::FocusIn,
1404            Event::FocusOut,
1405            Event::MouseEnter,
1406            Event::MouseLeave,
1407            Event::Resize {
1408                width: 800.0,
1409                height: 600.0,
1410            },
1411        ];
1412
1413        for event in events {
1414            let json = serde_json::to_string(&event).unwrap();
1415            let deserialized: Event = serde_json::from_str(&json).unwrap();
1416            assert_eq!(event, deserialized);
1417        }
1418    }
1419
1420    #[test]
1421    fn test_touch_events_serialization() {
1422        let events = vec![
1423            Event::TouchStart {
1424                id: TouchId(1),
1425                position: Point::new(10.0, 20.0),
1426                pressure: 0.5,
1427            },
1428            Event::TouchMove {
1429                id: TouchId(1),
1430                position: Point::new(15.0, 25.0),
1431                pressure: 0.6,
1432            },
1433            Event::TouchEnd {
1434                id: TouchId(1),
1435                position: Point::new(20.0, 30.0),
1436            },
1437            Event::TouchCancel { id: TouchId(1) },
1438        ];
1439
1440        for event in events {
1441            let json = serde_json::to_string(&event).unwrap();
1442            let deserialized: Event = serde_json::from_str(&json).unwrap();
1443            assert_eq!(event, deserialized);
1444        }
1445    }
1446
1447    #[test]
1448    fn test_gesture_events_serialization() {
1449        let events = vec![
1450            Event::GesturePinch {
1451                scale: 1.5,
1452                center: Point::new(100.0, 100.0),
1453                state: GestureState::Started,
1454            },
1455            Event::GestureRotate {
1456                angle: 0.5,
1457                center: Point::new(100.0, 100.0),
1458                state: GestureState::Changed,
1459            },
1460            Event::GesturePan {
1461                delta: Point::new(10.0, 5.0),
1462                velocity: Point::new(50.0, 25.0),
1463                state: GestureState::Ended,
1464            },
1465            Event::GestureLongPress {
1466                position: Point::new(50.0, 50.0),
1467            },
1468            Event::GestureTap {
1469                position: Point::new(50.0, 50.0),
1470                count: 2,
1471            },
1472        ];
1473
1474        for event in events {
1475            let json = serde_json::to_string(&event).unwrap();
1476            let deserialized: Event = serde_json::from_str(&json).unwrap();
1477            assert_eq!(event, deserialized);
1478        }
1479    }
1480
1481    #[test]
1482    fn test_pointer_events_serialization() {
1483        let events = vec![
1484            Event::PointerDown {
1485                pointer_id: PointerId(1),
1486                pointer_type: PointerType::Mouse,
1487                position: Point::new(10.0, 20.0),
1488                pressure: 0.5,
1489                is_primary: true,
1490                button: Some(MouseButton::Left),
1491            },
1492            Event::PointerMove {
1493                pointer_id: PointerId(1),
1494                pointer_type: PointerType::Touch,
1495                position: Point::new(15.0, 25.0),
1496                pressure: 0.6,
1497                is_primary: true,
1498            },
1499            Event::PointerUp {
1500                pointer_id: PointerId(1),
1501                pointer_type: PointerType::Pen,
1502                position: Point::new(20.0, 30.0),
1503                is_primary: false,
1504                button: None,
1505            },
1506            Event::PointerCancel {
1507                pointer_id: PointerId(1),
1508            },
1509            Event::PointerEnter {
1510                pointer_id: PointerId(2),
1511                pointer_type: PointerType::Mouse,
1512            },
1513            Event::PointerLeave {
1514                pointer_id: PointerId(2),
1515                pointer_type: PointerType::Touch,
1516            },
1517        ];
1518
1519        for event in events {
1520            let json = serde_json::to_string(&event).unwrap();
1521            let deserialized: Event = serde_json::from_str(&json).unwrap();
1522            assert_eq!(event, deserialized);
1523        }
1524    }
1525
1526    #[test]
1527    fn test_key_hash() {
1528        use std::collections::HashSet;
1529        let mut set = HashSet::new();
1530        set.insert(Key::A);
1531        set.insert(Key::B);
1532        set.insert(Key::A); // Duplicate
1533        assert_eq!(set.len(), 2);
1534    }
1535
1536    #[test]
1537    fn test_mouse_button_hash() {
1538        use std::collections::HashSet;
1539        let mut set = HashSet::new();
1540        set.insert(MouseButton::Left);
1541        set.insert(MouseButton::Right);
1542        set.insert(MouseButton::Left); // Duplicate
1543        assert_eq!(set.len(), 2);
1544    }
1545}