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, Default, PartialEq, Eq, Hash)]
213pub enum DragStartBehavior {
214 #[default]
216 Start,
217 Down,
219}
220
221#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
226pub enum WindowResizeDirection {
227 East,
228 North,
229 NorthEast,
230 NorthWest,
231 South,
232 SouthEast,
233 SouthWest,
234 West,
235}
236
237pub const PRIMARY_POINTER_BUTTON: u32 = 1 << 0;
243pub const SECONDARY_POINTER_BUTTON: u32 = 1 << 1;
245pub const TERTIARY_POINTER_BUTTON: u32 = 1 << 2;
247pub const BACK_POINTER_BUTTON: u32 = 1 << 3;
249pub const FORWARD_POINTER_BUTTON: u32 = 1 << 4;
251
252#[must_use]
259pub const fn additional_pointer_button_mask(index: u16) -> Option<u32> {
260 let bit = 5_u32 + index as u32;
261 if bit < u32::BITS {
262 Some(1_u32 << bit)
263 } else {
264 None
265 }
266}
267
268#[derive(Clone, Debug, PartialEq, Eq)]
271pub enum ImeEvent {
272 Preedit {
273 text: String,
274 selection: Option<(usize, usize)>,
275 },
276 Commit(String),
277 End,
278}
279
280#[derive(Clone, Debug, PartialEq)]
281pub enum InputEvent {
282 Pointer {
283 phase: PointerPhase,
284 position: Offset,
285 },
286 PointerWithId {
290 pointer: u64,
292 phase: PointerPhase,
293 position: Offset,
294 },
295 PointerWithMetadata {
298 pointer: u64,
300 device: u64,
302 kind: PointerDeviceKind,
304 buttons: u32,
306 button: Option<u32>,
310 sample: PointerSampleMetadata,
312 phase: PointerPhase,
313 position: Offset,
314 },
315 TrackpadGesture(TrackpadGesture),
318 Scroll {
319 delta: Offset,
320 },
321 Key(KeyboardEvent),
322 Text(String),
323 Ime(ImeEvent),
324 WindowResized {
325 size: Size,
326 scale_factor: f64,
327 },
328}