1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! Events and utilities for the mouse.

use crate::geo::Point;
use crate::{bind, EnumInt};

pub mod cursor;
pub mod relative;

/// A kind of the mouse button.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum MouseButton {
    /// The left button of the mouse.
    Left,
    /// The middle or wheel button of the mouse.
    Middle,
    /// The right button of the mouse.
    Right,
    /// The x1 of the mouse.
    X1,
    /// The x2 of the mouse.
    X2,
}

impl MouseButton {
    pub(crate) fn from_bits(bits: u8) -> Option<Self> {
        Some(match bits {
            1 => MouseButton::Left,
            2 => MouseButton::Middle,
            3 => MouseButton::Right,
            4 => MouseButton::X1,
            5 => MouseButton::X2,
            _ => return None,
        })
    }
}

/// An event related on the mouse.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum MouseEvent {
    /// A motion event [`MouseMotionEvent`].
    Motion(MouseMotionEvent),
    /// A button event [`MouseButtonEvent`].
    Button(MouseButtonEvent),
    /// A wheel event [`MouseWheelEvent`].
    Wheel(MouseWheelEvent),
}

/// An event that the mouse was moved.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MouseMotionEvent {
    /// When this event occurred.
    pub timestamp: u32,
    /// The id of the window focused.
    pub window_id: u32,
    /// The id of the moved.
    pub mouse_id: u32,
    /// The button state of the mouse.
    pub button: Option<MouseButton>,
    /// The mouse position.
    pub pos: Point,
    /// The moved amount of the mouse.
    pub move_amount: Point,
}

impl From<bind::SDL_MouseMotionEvent> for MouseMotionEvent {
    fn from(raw: bind::SDL_MouseMotionEvent) -> Self {
        Self {
            timestamp: raw.timestamp,
            window_id: raw.windowID,
            mouse_id: raw.which,
            button: MouseButton::from_bits(raw.state as u8),
            pos: Point { x: raw.x, y: raw.y },
            move_amount: Point {
                x: raw.xrel,
                y: raw.yrel,
            },
        }
    }
}

/// An event that th mouse button was pressed/released.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MouseButtonEvent {
    /// When this event occurred.
    pub timestamp: u32,
    /// The id of the window focused.
    pub window_id: u32,
    /// The id of the moved.
    pub mouse_id: u32,
    /// The button state of the mouse.
    pub button: Option<MouseButton>,
    /// Whether the mouse button is pressed.
    pub is_pressed: bool,
    /// The click count of the button.
    pub clicks: u8,
    /// The mouse position.
    pub pos: Point,
}

impl From<bind::SDL_MouseButtonEvent> for MouseButtonEvent {
    fn from(raw: bind::SDL_MouseButtonEvent) -> Self {
        Self {
            timestamp: raw.timestamp,
            window_id: raw.windowID,
            mouse_id: raw.which,
            button: MouseButton::from_bits(raw.button),
            is_pressed: raw.state as u32 == bind::SDL_PRESSED,
            clicks: raw.clicks,
            pos: Point { x: raw.x, y: raw.y },
        }
    }
}

/// An event that the mouse wheel was scrolled.
#[derive(Debug, Clone, PartialEq)]
pub struct MouseWheelEvent {
    /// When this event occurred.
    pub timestamp: u32,
    /// The id of the window focused.
    pub window_id: u32,
    /// The id of the moved.
    pub mouse_id: u32,
    /// How much the wheel scrolled. X is the amount scrolled horizontally, positive to the right and negative to the left. Y is the amount scrolled vertically, positive away from the user and negative towards to the user.
    pub scroll_amount: Point,
    /// How much the wheel scrolled with float precision. The first element is the amount scrolled horizontally, positive to the right and negative to the left. The second element is the amount scrolled vertically, positive away from the user and negative towards to the user.
    ///
    /// The value returned from the API does not contain NaN or infinity number. You should not edit the value because that [`MouseWheelEvent`] implements [`Eq`].
    pub scroll_amount_precise: (f32, f32),
    /// Whether the scroll direction is inverted.
    pub is_flipped: bool,
}

impl Eq for MouseWheelEvent {}

impl From<bind::SDL_MouseWheelEvent> for MouseWheelEvent {
    fn from(raw: bind::SDL_MouseWheelEvent) -> Self {
        Self {
            timestamp: raw.timestamp,
            window_id: raw.windowID,
            mouse_id: raw.which,
            scroll_amount: Point { x: raw.x, y: raw.y },
            scroll_amount_precise: (raw.preciseX, raw.preciseY),
            is_flipped: raw.direction as EnumInt == bind::SDL_MOUSEWHEEL_FLIPPED,
        }
    }
}