input_device/event.rs
1//! The `Event` enum and assorted supporting types.
2//!
3use bitflags::bitflags;
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7/// Identifier for a specific analog axis on some device.
8pub type AxisId = u32;
9
10/// Identifier for a specific button on some device.
11#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
12pub struct ButtonId(pub u32);
13
14impl From<ButtonId> for u32 {
15 fn from(val: ButtonId) -> Self {
16 val.0
17 }
18}
19
20pub use crate::DeviceId;
21
22/// Represents raw hardware events that are not associated with any particular window.
23///
24/// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera or first-person
25/// game controls. Many physical actions, such as mouse movement, can produce both device and window events. Because
26/// window events typically arise from virtual devices (corresponding to GUI cursors and keyboard focus) the device IDs
27/// may not match.
28///
29/// Note that these events are delivered regardless of input focus.
30#[derive(Clone, Debug, PartialEq)]
31pub enum Event {
32 Dummy,
33 Added,
34 Removed,
35
36 MouseButton {
37 button: MouseButton,
38 state: ElementState,
39 },
40
41 /// Change in physical position of a pointing device.
42 ///
43 /// This represents raw, unfiltered physical motion. Not to be confused with `WindowEvent::CursorMoved`.
44 MouseMotion {
45 /// (x, y) change in position in unspecified units.
46 ///
47 /// Different devices may use different units.
48 delta: (f64, f64),
49 },
50
51 /// Physical scroll event
52 MouseWheel {
53 delta: MouseScrollDelta,
54 },
55
56 /// Motion on some analog axis. This event will be reported for all arbitrary input devices
57 /// that winit supports on this platform, including mouse devices. If the device is a mouse
58 /// device then this will be reported alongside the MouseMotion event.
59 Motion {
60 axis: AxisId,
61 value: f64,
62 },
63
64 Button {
65 button: ButtonId,
66 state: ElementState,
67 },
68
69 Key(KeyboardInput),
70
71 Text {
72 codepoint: char,
73 },
74}
75
76/// Describes the input state of a key.
77#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
78#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
79pub enum ElementState {
80 Pressed,
81 Released,
82 Repeated,
83 Unknown,
84}
85
86impl Default for ElementState {
87 fn default() -> Self {
88 Self::Unknown
89 }
90}
91
92/// Describes a keyboard input event.
93#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
94#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
95pub struct KeyboardInput {
96 /// Identifies the physical key pressed
97 ///
98 /// This should not change if the user adjusts the host's keyboard map. Use when the physical location of the
99 /// key is more important than the key's host GUI semantics, such as for movement controls in a first-person
100 /// game.
101 pub scancode: ScanCode,
102
103 /// Identifies the key is pressed, released or repeated.
104 pub state: ElementState,
105
106 /// Identifies the semantic meaning of the key
107 ///
108 /// Use when the semantics of the key are more important than the physical location of the key, such as when
109 /// implementing appropriate behavior for "page up."
110 pub virtual_keycode: Option<VirtualKeyCode>,
111}
112
113impl KeyboardInput {
114 // Determine the Key with `key_code` is in `Pressed` state.
115 pub fn is_key_pressed(&self, key_code: VirtualKeyCode) -> bool {
116 self.virtual_keycode == Some(key_code) && self.state == ElementState::Pressed
117 }
118
119 // Determine the Key with `key_code` is in `Released` state.
120 pub fn is_key_released(&self, key_code: VirtualKeyCode) -> bool {
121 self.virtual_keycode == Some(key_code) && self.state == ElementState::Released
122 }
123
124 // Determine the Key with `key_code` is in `Repeated` state.
125 pub fn is_key_repeated(&self, key_code: VirtualKeyCode) -> bool {
126 self.virtual_keycode == Some(key_code) && self.state == ElementState::Repeated
127 }
128
129 // Determine the Key with `key_code` is in `Pressed` or `Repeated` state.
130 pub fn is_key_triggered(&self, key_code: VirtualKeyCode) -> bool {
131 self.virtual_keycode == Some(key_code)
132 && (self.state == ElementState::Pressed || self.state == ElementState::Repeated)
133 }
134}
135
136/// Describes touch-screen input state.
137#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
138#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
139pub enum TouchPhase {
140 Started,
141 Moved,
142 Ended,
143 Cancelled,
144}
145
146/// Represents a touch event
147///
148/// Every time the user touches the screen, a new `Start` event with an unique
149/// identifier for the finger is generated. When the finger is lifted, an `End`
150/// event is generated with the same finger id.
151///
152/// After a `Start` event has been emitted, there may be zero or more `Move`
153/// events when the finger is moved or the touch pressure changes.
154///
155/// The finger id may be reused by the system after an `End` event. The user
156/// should assume that a new `Start` event received with the same id has nothing
157/// to do with the old finger and is a new finger.
158///
159/// A `Cancelled` event is emitted when the system has canceled tracking this
160/// touch, such as when the window loses focus, or on iOS if the user moves the
161/// device against their face.
162#[derive(Debug, Clone, Copy, PartialEq)]
163pub struct Touch {
164 pub device_id: DeviceId,
165 pub phase: TouchPhase,
166 pub location: PhysicalPosition<f64>,
167 /// Describes how hard the screen was pressed. May be `None` if the platform
168 /// does not support pressure sensitivity.
169 ///
170 /// ## Platform-specific
171 ///
172 /// - Only available on **iOS** 9.0+ and **Windows** 8+.
173 pub force: Option<Force>,
174 /// Unique identifier of a finger.
175 pub id: u64,
176}
177
178/// Describes the force of a touch event
179#[derive(Debug, Clone, Copy, PartialEq)]
180pub enum Force {
181 /// On iOS, the force is calibrated so that the same number corresponds to
182 /// roughly the same amount of pressure on the screen regardless of the
183 /// device.
184 Calibrated {
185 /// The force of the touch, where a value of 1.0 represents the force of
186 /// an average touch (predetermined by the system, not user-specific).
187 ///
188 /// The force reported by Apple Pencil is measured along the axis of the
189 /// pencil. If you want a force perpendicular to the device, you need to
190 /// calculate this value using the `altitude_angle` value.
191 force: f64,
192 /// The maximum possible force for a touch.
193 ///
194 /// The value of this field is sufficiently high to provide a wide
195 /// dynamic range for values of the `force` field.
196 max_possible_force: f64,
197 /// The altitude (in radians) of the stylus.
198 ///
199 /// A value of 0 radians indicates that the stylus is parallel to the
200 /// surface. The value of this property is Pi/2 when the stylus is
201 /// perpendicular to the surface.
202 altitude_angle: Option<f64>,
203 },
204 /// If the platform reports the force as normalized, we have no way of
205 /// knowing how much pressure 1.0 corresponds to – we know it's the maximum
206 /// amount of force, but as to how much force, you might either have to
207 /// press really really hard, or not hard at all, depending on the device.
208 Normalized(f64),
209}
210
211impl Force {
212 /// Returns the force normalized to the range between 0.0 and 1.0 inclusive.
213 /// Instead of normalizing the force, you should prefer to handle
214 /// `Force::Calibrated` so that the amount of force the user has to apply is
215 /// consistent across devices.
216 pub fn normalized(&self) -> f64 {
217 match self {
218 Force::Calibrated {
219 force,
220 max_possible_force,
221 altitude_angle,
222 } => {
223 let force = match altitude_angle {
224 Some(altitude_angle) => force / altitude_angle.sin(),
225 None => *force,
226 };
227 force / max_possible_force
228 }
229 Force::Normalized(force) => *force,
230 }
231 }
232}
233
234/// Hardware-dependent keyboard scan code.
235pub type ScanCode = u32;
236
237bitflags! {
238 /// Represents the current state of the keyboard modifiers
239 ///
240 /// Each flag represents a modifier and is set if this modifier is active.
241 #[derive(Default)]
242 pub struct ModifiersState: u32 {
243 // left and right modifiers are currently commented out, but we should be able to support
244 // them in a future release
245 /// The "shift" key.
246 const SHIFT = 0b100;
247 const LSHIFT = 0b010;
248 const RSHIFT = 0b001;
249 /// The "control" key.
250 const CTRL = 0b100 << 3;
251 const LCTRL = 0b010 << 3;
252 const RCTRL = 0b001 << 3;
253 /// The "alt" key.
254 const ALT = 0b100 << 6;
255 const LALT = 0b010 << 6;
256 const RALT = 0b001 << 6;
257 /// This is the "windows" key on PC and "command" key on Mac.
258 const LOGO = 0b100 << 9;
259 const LLOGO = 0b010 << 9;
260 const RLOGO = 0b001 << 9;
261 }
262}
263
264impl ModifiersState {
265 /// Returns `true` if the shift key is pressed.
266 pub fn shift(&self) -> bool {
267 self.intersects(Self::SHIFT)
268 }
269 /// Returns `true` if the control key is pressed.
270 pub fn ctrl(&self) -> bool {
271 self.intersects(Self::CTRL)
272 }
273 /// Returns `true` if the alt key is pressed.
274 pub fn alt(&self) -> bool {
275 self.intersects(Self::ALT)
276 }
277 /// Returns `true` if the logo key is pressed.
278 pub fn logo(&self) -> bool {
279 self.intersects(Self::LOGO)
280 }
281}
282
283#[cfg(feature = "serde")]
284mod modifiers_serde {
285 use super::ModifiersState;
286 use serde::{Deserialize, Deserializer, Serialize, Serializer};
287
288 #[derive(Default, Serialize, Deserialize)]
289 #[serde(default)]
290 #[serde(rename = "ModifiersState")]
291 pub struct ModifiersStateSerialize {
292 pub shift: bool,
293 pub ctrl: bool,
294 pub alt: bool,
295 pub logo: bool,
296 }
297
298 impl Serialize for ModifiersState {
299 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
300 where
301 S: Serializer,
302 {
303 let s = ModifiersStateSerialize {
304 shift: self.shift(),
305 ctrl: self.ctrl(),
306 alt: self.alt(),
307 logo: self.logo(),
308 };
309 s.serialize(serializer)
310 }
311 }
312
313 impl<'de> Deserialize<'de> for ModifiersState {
314 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
315 where
316 D: Deserializer<'de>,
317 {
318 let ModifiersStateSerialize {
319 shift,
320 ctrl,
321 alt,
322 logo,
323 } = ModifiersStateSerialize::deserialize(deserializer)?;
324 let mut m = ModifiersState::empty();
325 m.set(ModifiersState::SHIFT, shift);
326 m.set(ModifiersState::CTRL, ctrl);
327 m.set(ModifiersState::ALT, alt);
328 m.set(ModifiersState::LOGO, logo);
329 Ok(m)
330 }
331 }
332}
333
334/// Describes a button of a mouse controller.
335#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
337pub enum MouseButton {
338 Left,
339 Right,
340 Middle,
341 Other(u8),
342}
343
344/// Describes a difference in the mouse scroll wheel state.
345#[derive(Debug, Clone, Copy, PartialEq)]
346#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
347pub enum MouseScrollDelta {
348 /// Amount in lines or rows to scroll in the horizontal
349 /// and vertical directions.
350 ///
351 /// Positive values indicate movement forward
352 /// (away from the user) or rightwards.
353 LineDelta(f32, f32),
354 /// Amount in pixels to scroll in the horizontal and
355 /// vertical direction.
356 ///
357 /// Scroll events are expressed as a PixelDelta if
358 /// supported by the device (eg. a touchpad) and
359 /// platform.
360 PixelDelta(PhysicalPosition<f64>),
361}
362
363/// A position represented in physical pixels.
364#[derive(Debug, Copy, Clone, PartialEq)]
365#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
366pub struct PhysicalPosition<P> {
367 pub x: P,
368 pub y: P,
369}
370
371impl<P> PhysicalPosition<P> {
372 #[inline]
373 pub const fn new(x: P, y: P) -> Self {
374 PhysicalPosition { x, y }
375 }
376}
377
378/// Symbolic name for a keyboard key.
379#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
380#[repr(u32)]
381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
382pub enum VirtualKeyCode {
383 /// The '1' key over the letters.
384 Key1,
385 /// The '2' key over the letters.
386 Key2,
387 /// The '3' key over the letters.
388 Key3,
389 /// The '4' key over the letters.
390 Key4,
391 /// The '5' key over the letters.
392 Key5,
393 /// The '6' key over the letters.
394 Key6,
395 /// The '7' key over the letters.
396 Key7,
397 /// The '8' key over the letters.
398 Key8,
399 /// The '9' key over the letters.
400 Key9,
401 /// The '0' key over the 'O' and 'P' keys.
402 Key0,
403
404 A,
405 B,
406 C,
407 D,
408 E,
409 F,
410 G,
411 H,
412 I,
413 J,
414 K,
415 L,
416 M,
417 N,
418 O,
419 P,
420 Q,
421 R,
422 S,
423 T,
424 U,
425 V,
426 W,
427 X,
428 Y,
429 Z,
430
431 /// The Escape key, next to F1.
432 Escape,
433
434 F1,
435 F2,
436 F3,
437 F4,
438 F5,
439 F6,
440 F7,
441 F8,
442 F9,
443 F10,
444 F11,
445 F12,
446 F13,
447 F14,
448 F15,
449 F16,
450 F17,
451 F18,
452 F19,
453 F20,
454 F21,
455 F22,
456 F23,
457 F24,
458
459 /// Print Screen/SysRq.
460 Snapshot,
461 /// Scroll Lock.
462 Scroll,
463 /// Pause/Break key, next to Scroll lock.
464 Pause,
465
466 /// `Insert`, next to Backspace.
467 Insert,
468 Home,
469 Delete,
470 End,
471 PageDown,
472 PageUp,
473
474 Left,
475 Up,
476 Right,
477 Down,
478
479 /// The Backspace key, right over Enter.
480 // TODO: rename
481 Back,
482 /// The Enter key.
483 Return,
484 /// The space bar.
485 Space,
486
487 /// The "Compose" key on Linux.
488 Compose,
489
490 Caret,
491
492 Numlock,
493 Numpad0,
494 Numpad1,
495 Numpad2,
496 Numpad3,
497 Numpad4,
498 Numpad5,
499 Numpad6,
500 Numpad7,
501 Numpad8,
502 Numpad9,
503 NumpadComma,
504 NumpadEnter,
505 NumpadEquals,
506 NumpadSubtract,
507
508 AbntC1,
509 AbntC2,
510 Apostrophe,
511 Apps,
512 At,
513 Ax,
514 Backslash,
515 Calculator,
516 Capital,
517 Colon,
518 Comma,
519 Convert,
520 Decimal,
521 Divide,
522 Equals,
523 Grave,
524 Kana,
525 Kanji,
526 LAlt,
527 LBracket,
528 LControl,
529 LShift,
530 LWin,
531 Mail,
532 MediaSelect,
533 MediaStop,
534 Minus,
535 Multiply,
536 Mute,
537 MyComputer,
538 // also called "Next"
539 NavigateForward,
540 // also called "Prior"
541 NavigateBackward,
542 NextTrack,
543 NoConvert,
544 OEM102,
545 Period,
546 PlayPause,
547 Plus, // +
548 Power,
549 PrevTrack,
550 RAlt,
551 RBracket,
552 RControl,
553 RShift,
554 RWin,
555 Semicolon,
556 Slash,
557 Sleep,
558 Stop,
559 Sysrq,
560 Tab,
561 Underline,
562 Unlabeled,
563 VolumeDown,
564 VolumeUp,
565 Wake,
566 WebBack,
567 WebFavorites,
568 WebForward,
569 WebHome,
570 WebRefresh,
571 WebSearch,
572 WebStop,
573 Yen,
574 Copy,
575 Paste,
576 Cut,
577}