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}