Skip to main content

freya_core/events/
platform.rs

1use std::path::PathBuf;
2
3use keyboard_types::{
4    Code,
5    Key,
6    Modifiers,
7};
8use torin::prelude::CursorPoint;
9
10use crate::{
11    events::{
12        data::{
13            MouseButton,
14            WheelSource,
15        },
16        name::EventName,
17    },
18    prelude::{
19        Force,
20        TouchPhase,
21    },
22};
23
24#[derive(Clone, Debug, PartialEq, Copy, Eq, Hash)]
25pub enum MouseEventName {
26    MouseUp,
27    MouseDown,
28    MouseMove,
29}
30
31impl From<MouseEventName> for EventName {
32    fn from(value: MouseEventName) -> Self {
33        match value {
34            MouseEventName::MouseUp => EventName::MouseUp,
35            MouseEventName::MouseMove => EventName::MouseMove,
36            MouseEventName::MouseDown => EventName::MouseDown,
37        }
38    }
39}
40
41#[derive(Clone, Debug, PartialEq, Copy, Eq, Hash)]
42pub enum WheelEventName {
43    Wheel,
44}
45
46impl From<WheelEventName> for EventName {
47    fn from(value: WheelEventName) -> Self {
48        match value {
49            WheelEventName::Wheel => EventName::Wheel,
50        }
51    }
52}
53
54#[derive(Clone, Debug, PartialEq, Copy, Eq, Hash)]
55pub enum KeyboardEventName {
56    KeyDown,
57    KeyUp,
58}
59
60impl From<KeyboardEventName> for EventName {
61    fn from(value: KeyboardEventName) -> Self {
62        match value {
63            KeyboardEventName::KeyDown => EventName::KeyDown,
64            KeyboardEventName::KeyUp => EventName::KeyUp,
65        }
66    }
67}
68
69#[derive(Clone, Debug, PartialEq, Copy, Eq, Hash)]
70pub enum FileEventName {
71    FileDrop,
72    FileHover,
73    FileHoverCancelled,
74}
75
76impl From<FileEventName> for EventName {
77    fn from(value: FileEventName) -> Self {
78        match value {
79            FileEventName::FileDrop => EventName::FileDrop,
80            FileEventName::FileHover => EventName::GlobalFileHover,
81            FileEventName::FileHoverCancelled => EventName::GlobalFileHoverCancelled,
82        }
83    }
84}
85
86/// Data for [PlatformEvent].
87#[derive(Clone, Debug, PartialEq)]
88pub enum PlatformEvent {
89    /// A Mouse Event.
90    Mouse {
91        name: MouseEventName,
92        cursor: CursorPoint,
93        button: Option<MouseButton>,
94    },
95    /// The pointer exited the window at its last known position.
96    PointerExit { cursor: CursorPoint },
97    /// A Keyboard Event.
98    Keyboard {
99        name: KeyboardEventName,
100        key: Key,
101        code: Code,
102        modifiers: Modifiers,
103    },
104    /// A Wheel Event.
105    Wheel {
106        name: WheelEventName,
107        scroll: CursorPoint,
108        cursor: CursorPoint,
109        source: WheelSource,
110        phase: TouchPhase,
111    },
112    /// A Touch Event.
113    Touch {
114        name: TouchEventName,
115        location: CursorPoint,
116        finger_id: u64,
117        phase: TouchPhase,
118        force: Option<Force>,
119    },
120    /// An IME event.
121    ImePreedit {
122        name: ImeEventName,
123        text: String,
124        cursor: Option<(usize, usize)>,
125    },
126    /// A File event.
127    File {
128        name: FileEventName,
129        cursor: CursorPoint,
130        file_paths: Vec<PathBuf>,
131    },
132}
133
134#[derive(Clone, Debug, PartialEq, Copy, Eq, Hash)]
135pub enum ImeEventName {
136    Preedit,
137}
138
139impl From<ImeEventName> for EventName {
140    fn from(value: ImeEventName) -> Self {
141        match value {
142            ImeEventName::Preedit => EventName::ImePreedit,
143        }
144    }
145}
146
147#[derive(Clone, Debug, PartialEq, Copy, Eq, Hash)]
148pub enum TouchEventName {
149    TouchStart,
150    TouchMove,
151    TouchEnd,
152    TouchCancel,
153}
154
155impl From<TouchEventName> for EventName {
156    fn from(value: TouchEventName) -> Self {
157        match value {
158            TouchEventName::TouchStart => EventName::TouchStart,
159            TouchEventName::TouchMove => EventName::TouchMove,
160            TouchEventName::TouchEnd => EventName::TouchEnd,
161            TouchEventName::TouchCancel => EventName::TouchCancel,
162        }
163    }
164}
165
166impl ragnarok::SourceEvent for PlatformEvent {
167    type Name = EventName;
168
169    fn can_coalesce_with(&self, next: &Self) -> bool {
170        match (self, next) {
171            (
172                Self::Mouse {
173                    name: MouseEventName::MouseMove,
174                    button: previous,
175                    ..
176                },
177                Self::Mouse {
178                    name: MouseEventName::MouseMove,
179                    button,
180                    ..
181                },
182            ) => previous == button,
183            (
184                Self::Wheel {
185                    scroll: previous,
186                    cursor: previous_cursor,
187                    source: WheelSource::Line,
188                    phase: TouchPhase::Moved,
189                    ..
190                },
191                Self::Wheel {
192                    scroll,
193                    cursor,
194                    source: WheelSource::Line,
195                    phase: TouchPhase::Moved,
196                    ..
197                },
198            ) => {
199                previous_cursor == cursor
200                    && previous.x.partial_cmp(&0.0) == scroll.x.partial_cmp(&0.0)
201                    && previous.y.partial_cmp(&0.0) == scroll.y.partial_cmp(&0.0)
202                    && (previous.x + scroll.x).is_finite()
203                    && (previous.y + scroll.y).is_finite()
204            }
205            _ => false,
206        }
207    }
208
209    fn coalesce_with(&mut self, next: Self) {
210        match (self, next) {
211            (Self::Wheel { scroll, .. }, Self::Wheel { scroll: next, .. }) => {
212                scroll.x += next.x;
213                scroll.y += next.y;
214            }
215            (event, next) => *event = next,
216        }
217    }
218
219    /// Check if the event means the cursor was moved.
220    fn is_moved(&self) -> bool {
221        matches!(
222            &self,
223            Self::Mouse {
224                name: MouseEventName::MouseMove,
225                ..
226            } | Self::Touch {
227                phase: TouchPhase::Moved,
228                ..
229            }
230        )
231    }
232
233    /// Check if this event can press state of a Node.
234    fn is_pressed(&self) -> bool {
235        matches!(
236            &self,
237            Self::Mouse {
238                name: MouseEventName::MouseDown,
239                ..
240            } | Self::Touch {
241                name: TouchEventName::TouchStart,
242                ..
243            }
244        )
245    }
246
247    fn is_pointer_exit(&self) -> bool {
248        matches!(self, Self::PointerExit { .. })
249    }
250
251    /// Check if this event ends or cancels a touch.
252    fn is_touch_released(&self) -> bool {
253        matches!(
254            &self,
255            Self::Touch {
256                phase: TouchPhase::Ended | TouchPhase::Cancelled,
257                ..
258            }
259        )
260    }
261
262    fn as_event_name(&self) -> EventName {
263        match self {
264            Self::Mouse { name, .. } => (*name).into(),
265            Self::PointerExit { .. } => EventName::MouseMove,
266            Self::Keyboard { name, .. } => (*name).into(),
267            Self::Wheel { name, .. } => (*name).into(),
268            Self::ImePreedit { name, .. } => (*name).into(),
269            Self::Touch { name, .. } => (*name).into(),
270            Self::File { name, .. } => (*name).into(),
271        }
272    }
273
274    fn try_location(&self) -> Option<ragnarok::CursorPoint> {
275        match self {
276            PlatformEvent::Mouse { cursor, .. } => Some(*cursor),
277            PlatformEvent::Wheel { cursor, .. } => Some(*cursor),
278            PlatformEvent::Touch { location, .. } => Some(*location),
279            PlatformEvent::File { cursor, .. } => Some(*cursor),
280            _ => None,
281        }
282    }
283}