1use crate::{Offset, Size};
4
5#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
11pub struct NormalizedPressure(f32);
12
13impl NormalizedPressure {
14 #[must_use]
15 pub fn new(value: f64) -> Option<Self> {
16 value
17 .is_finite()
18 .then(|| Self(value.clamp(0.0, 1.0) as f32))
19 }
20
21 #[must_use]
22 pub fn from_range(value: f64, maximum: f64) -> Option<Self> {
23 (value.is_finite() && maximum.is_finite() && maximum > 0.0)
24 .then(|| Self((value / maximum).clamp(0.0, 1.0) as f32))
25 }
26
27 #[must_use]
28 pub const fn get(self) -> f32 {
29 self.0
30 }
31}
32
33#[derive(Clone, Copy, Debug, PartialEq)]
39pub struct StylusOrientation {
40 pub altitude: f32,
41 pub azimuth: f32,
42}
43
44impl StylusOrientation {
45 #[must_use]
48 pub fn from_tilt_degrees(tilt_x: f64, tilt_y: f64) -> Option<Self> {
49 if !tilt_x.is_finite()
50 || !tilt_y.is_finite()
51 || !(-90.0..=90.0).contains(&tilt_x)
52 || !(-90.0..=90.0).contains(&tilt_y)
53 {
54 return None;
55 }
56 let x = tilt_x.to_radians().tan();
57 let y = tilt_y.to_radians().tan();
58 if !x.is_finite() || !y.is_finite() {
59 return None;
60 }
61 let altitude = 1.0_f64.atan2(x.hypot(y));
62 let azimuth = y.atan2(x).rem_euclid(std::f64::consts::TAU);
63 Some(Self {
64 altitude: altitude as f32,
65 azimuth: azimuth as f32,
66 })
67 }
68}
69
70#[derive(Clone, Copy, Debug, Default, PartialEq)]
72pub struct StylusMetadata {
73 pub orientation: Option<StylusOrientation>,
74 pub barrel_button: bool,
76}
77
78#[derive(Clone, Copy, Debug, Default, PartialEq)]
80pub struct PointerSampleMetadata {
81 pub pressure: Option<NormalizedPressure>,
82 pub stylus: Option<StylusMetadata>,
83}
84
85impl PointerSampleMetadata {
86 pub const EMPTY: Self = Self {
87 pressure: None,
88 stylus: None,
89 };
90}
91
92#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
93pub enum TrackpadGesturePhase {
94 Started,
95 Updated,
96 Ended,
97 Cancelled,
98}
99
100#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
101pub enum TrackpadGestureKind {
102 Pinch,
103 Rotation,
104 Pan,
105 SmartMagnify,
106 Pressure,
107}
108
109#[derive(Clone, Copy, Debug, PartialEq)]
113pub enum TrackpadGesture {
114 Pinch {
115 device: u64,
116 phase: TrackpadGesturePhase,
117 magnification_delta: f32,
118 },
119 Rotation {
120 device: u64,
121 phase: TrackpadGesturePhase,
122 delta_radians: f32,
124 },
125 Pan {
126 device: u64,
127 phase: TrackpadGesturePhase,
128 delta: Offset,
129 },
130 SmartMagnify {
131 device: u64,
132 },
133 Pressure {
134 device: u64,
135 pressure: NormalizedPressure,
136 stage: i64,
137 },
138}
139
140impl TrackpadGesture {
141 #[must_use]
142 pub const fn device(self) -> u64 {
143 match self {
144 Self::Pinch { device, .. }
145 | Self::Rotation { device, .. }
146 | Self::Pan { device, .. }
147 | Self::SmartMagnify { device }
148 | Self::Pressure { device, .. } => device,
149 }
150 }
151
152 #[must_use]
153 pub const fn kind(self) -> TrackpadGestureKind {
154 match self {
155 Self::Pinch { .. } => TrackpadGestureKind::Pinch,
156 Self::Rotation { .. } => TrackpadGestureKind::Rotation,
157 Self::Pan { .. } => TrackpadGestureKind::Pan,
158 Self::SmartMagnify { .. } => TrackpadGestureKind::SmartMagnify,
159 Self::Pressure { .. } => TrackpadGestureKind::Pressure,
160 }
161 }
162
163 #[must_use]
164 pub const fn phase(self) -> Option<TrackpadGesturePhase> {
165 match self {
166 Self::Pinch { phase, .. } | Self::Rotation { phase, .. } | Self::Pan { phase, .. } => {
167 Some(phase)
168 }
169 Self::SmartMagnify { .. } | Self::Pressure { .. } => None,
170 }
171 }
172}
173
174pub use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers, NamedKey};
180
181#[derive(Clone, Copy, Debug, PartialEq)]
182pub enum PointerPhase {
183 Enter,
186 Move,
187 Down,
188 Up,
189 Cancel,
190 Exit,
192}
193
194#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
197pub enum PointerDeviceKind {
198 #[default]
199 Mouse,
200 Touch,
201 Stylus,
202 InvertedStylus,
203 Trackpad,
204 Unknown,
205}
206
207#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
212pub enum WindowResizeDirection {
213 East,
214 North,
215 NorthEast,
216 NorthWest,
217 South,
218 SouthEast,
219 SouthWest,
220 West,
221}
222
223pub const PRIMARY_POINTER_BUTTON: u32 = 1 << 0;
229pub const SECONDARY_POINTER_BUTTON: u32 = 1 << 1;
231pub const TERTIARY_POINTER_BUTTON: u32 = 1 << 2;
233pub const BACK_POINTER_BUTTON: u32 = 1 << 3;
235pub const FORWARD_POINTER_BUTTON: u32 = 1 << 4;
237
238#[must_use]
245pub const fn additional_pointer_button_mask(index: u16) -> Option<u32> {
246 let bit = 5_u32 + index as u32;
247 if bit < u32::BITS {
248 Some(1_u32 << bit)
249 } else {
250 None
251 }
252}
253
254#[derive(Clone, Debug, PartialEq, Eq)]
257pub enum ImeEvent {
258 Preedit {
259 text: String,
260 selection: Option<(usize, usize)>,
261 },
262 Commit(String),
263 End,
264}
265
266#[derive(Clone, Debug, PartialEq)]
267pub enum InputEvent {
268 Pointer {
269 phase: PointerPhase,
270 position: Offset,
271 },
272 PointerWithId {
276 pointer: u64,
278 phase: PointerPhase,
279 position: Offset,
280 },
281 PointerWithMetadata {
284 pointer: u64,
286 device: u64,
288 kind: PointerDeviceKind,
290 buttons: u32,
292 button: Option<u32>,
296 sample: PointerSampleMetadata,
298 phase: PointerPhase,
299 position: Offset,
300 },
301 TrackpadGesture(TrackpadGesture),
304 Scroll {
305 delta: Offset,
306 },
307 Key(KeyboardEvent),
308 Text(String),
309 Ime(ImeEvent),
310 WindowResized {
311 size: Size,
312 scale_factor: f64,
313 },
314}