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#[derive(Clone, Debug, PartialEq)]
88pub enum PlatformEvent {
89 Mouse {
91 name: MouseEventName,
92 cursor: CursorPoint,
93 button: Option<MouseButton>,
94 },
95 PointerExit { cursor: CursorPoint },
97 Keyboard {
99 name: KeyboardEventName,
100 key: Key,
101 code: Code,
102 modifiers: Modifiers,
103 },
104 Wheel {
106 name: WheelEventName,
107 scroll: CursorPoint,
108 cursor: CursorPoint,
109 source: WheelSource,
110 phase: TouchPhase,
111 },
112 Touch {
114 name: TouchEventName,
115 location: CursorPoint,
116 finger_id: u64,
117 phase: TouchPhase,
118 force: Option<Force>,
119 },
120 ImePreedit {
122 name: ImeEventName,
123 text: String,
124 cursor: Option<(usize, usize)>,
125 },
126 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 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 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 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}