winit/
event.rs

1//! The `Event` enum and assorted supporting types.
2//!
3//! These are sent to the closure given to [`EventLoop::run(...)`][event_loop_run], where they get
4//! processed and used to modify the program state. For more details, see the root-level documentation.
5//!
6//! Some of these events represent different "parts" of a traditional event-handling loop. You could
7//! approximate the basic ordering loop of [`EventLoop::run(...)`][event_loop_run] like this:
8//!
9//! ```rust,ignore
10//! let mut control_flow = ControlFlow::Poll;
11//! let mut start_cause = StartCause::Init;
12//!
13//! while control_flow != ControlFlow::Exit {
14//!     event_handler(NewEvents(start_cause), ..., &mut control_flow);
15//!
16//!     for e in (window events, user events, device events) {
17//!         event_handler(e, ..., &mut control_flow);
18//!     }
19//!     event_handler(MainEventsCleared, ..., &mut control_flow);
20//!
21//!     for w in (redraw windows) {
22//!         event_handler(RedrawRequested(w), ..., &mut control_flow);
23//!     }
24//!     event_handler(RedrawEventsCleared, ..., &mut control_flow);
25//!
26//!     start_cause = wait_if_necessary(control_flow);
27//! }
28//!
29//! event_handler(LoopDestroyed, ..., &mut control_flow);
30//! ```
31//!
32//! This leaves out timing details like `ControlFlow::WaitUntil` but hopefully
33//! describes what happens in what order.
34//!
35//! [event_loop_run]: crate::event_loop::EventLoop::run
36use instant::Instant;
37use std::path::PathBuf;
38
39use crate::{
40    dpi::{PhysicalPosition, PhysicalSize},
41    platform_impl,
42    window::{Theme, WindowId},
43};
44
45/// Describes a generic event.
46///
47/// See the module-level docs for more information on the event loop manages each event.
48#[derive(Debug, PartialEq)]
49pub enum Event<'a, T: 'static> {
50    /// Emitted when new events arrive from the OS to be processed.
51    ///
52    /// This event type is useful as a place to put code that should be done before you start
53    /// processing events, such as updating frame timing information for benchmarking or checking
54    /// the [`StartCause`][crate::event::StartCause] to see if a timer set by
55    /// [`ControlFlow::WaitUntil`](crate::event_loop::ControlFlow::WaitUntil) has elapsed.
56    NewEvents(StartCause),
57
58    /// Emitted when the OS sends an event to a winit window.
59    WindowEvent {
60        window_id: WindowId,
61        event: WindowEvent<'a>,
62    },
63
64    /// Emitted when the OS sends an event to a device.
65    DeviceEvent {
66        device_id: DeviceId,
67        event: DeviceEvent,
68    },
69
70    /// Emitted when an event is sent from [`EventLoopProxy::send_event`](crate::event_loop::EventLoopProxy::send_event)
71    UserEvent(T),
72
73    /// Emitted when the application has been suspended.
74    Suspended,
75
76    /// Emitted when the application has been resumed.
77    Resumed,
78
79    /// Emitted when all of the event loop's input events have been processed and redraw processing
80    /// is about to begin.
81    ///
82    /// This event is useful as a place to put your code that should be run after all
83    /// state-changing events have been handled and you want to do stuff (updating state, performing
84    /// calculations, etc) that happens as the "main body" of your event loop. If your program only draws
85    /// graphics when something changes, it's usually better to do it in response to
86    /// [`Event::RedrawRequested`](crate::event::Event::RedrawRequested), which gets emitted
87    /// immediately after this event. Programs that draw graphics continuously, like most games,
88    /// can render here unconditionally for simplicity.
89    MainEventsCleared,
90
91    /// Emitted after `MainEventsCleared` when a window should be redrawn.
92    ///
93    /// This gets triggered in two scenarios:
94    /// - The OS has performed an operation that's invalidated the window's contents (such as
95    ///   resizing the window).
96    /// - The application has explicitly requested a redraw via
97    ///   [`Window::request_redraw`](crate::window::Window::request_redraw).
98    ///
99    /// During each iteration of the event loop, Winit will aggregate duplicate redraw requests
100    /// into a single event, to help avoid duplicating rendering work.
101    ///
102    /// Mainly of interest to applications with mostly-static graphics that avoid redrawing unless
103    /// something changes, like most non-game GUIs.
104    RedrawRequested(WindowId),
105
106    /// Emitted after all `RedrawRequested` events have been processed and control flow is about to
107    /// be taken away from the program. If there are no `RedrawRequested` events, it is emitted
108    /// immediately after `MainEventsCleared`.
109    ///
110    /// This event is useful for doing any cleanup or bookkeeping work after all the rendering
111    /// tasks have been completed.
112    RedrawEventsCleared,
113
114    /// Emitted when the event loop is being shut down.
115    ///
116    /// This is irreversable - if this event is emitted, it is guaranteed to be the last event that
117    /// gets emitted. You generally want to treat this as an "do on quit" event.
118    LoopDestroyed,
119}
120
121impl<T: Clone> Clone for Event<'static, T> {
122    fn clone(&self) -> Self {
123        use self::Event::*;
124        match self {
125            WindowEvent { window_id, event } => WindowEvent {
126                window_id: *window_id,
127                event: event.clone(),
128            },
129            UserEvent(event) => UserEvent(event.clone()),
130            DeviceEvent { device_id, event } => DeviceEvent {
131                device_id: *device_id,
132                event: event.clone(),
133            },
134            NewEvents(cause) => NewEvents(cause.clone()),
135            MainEventsCleared => MainEventsCleared,
136            RedrawRequested(wid) => RedrawRequested(*wid),
137            RedrawEventsCleared => RedrawEventsCleared,
138            LoopDestroyed => LoopDestroyed,
139            Suspended => Suspended,
140            Resumed => Resumed,
141        }
142    }
143}
144
145impl<'a, T> Event<'a, T> {
146    pub fn map_nonuser_event<U>(self) -> Result<Event<'a, U>, Event<'a, T>> {
147        use self::Event::*;
148        match self {
149            UserEvent(_) => Err(self),
150            WindowEvent { window_id, event } => Ok(WindowEvent { window_id, event }),
151            DeviceEvent { device_id, event } => Ok(DeviceEvent { device_id, event }),
152            NewEvents(cause) => Ok(NewEvents(cause)),
153            MainEventsCleared => Ok(MainEventsCleared),
154            RedrawRequested(wid) => Ok(RedrawRequested(wid)),
155            RedrawEventsCleared => Ok(RedrawEventsCleared),
156            LoopDestroyed => Ok(LoopDestroyed),
157            Suspended => Ok(Suspended),
158            Resumed => Ok(Resumed),
159        }
160    }
161
162    /// If the event doesn't contain a reference, turn it into an event with a `'static` lifetime.
163    /// Otherwise, return `None`.
164    pub fn to_static(self) -> Option<Event<'static, T>> {
165        use self::Event::*;
166        match self {
167            WindowEvent { window_id, event } => event
168                .to_static()
169                .map(|event| WindowEvent { window_id, event }),
170            UserEvent(event) => Some(UserEvent(event)),
171            DeviceEvent { device_id, event } => Some(DeviceEvent { device_id, event }),
172            NewEvents(cause) => Some(NewEvents(cause)),
173            MainEventsCleared => Some(MainEventsCleared),
174            RedrawRequested(wid) => Some(RedrawRequested(wid)),
175            RedrawEventsCleared => Some(RedrawEventsCleared),
176            LoopDestroyed => Some(LoopDestroyed),
177            Suspended => Some(Suspended),
178            Resumed => Some(Resumed),
179        }
180    }
181}
182
183/// Describes the reason the event loop is resuming.
184#[derive(Debug, Clone, Copy, PartialEq, Eq)]
185pub enum StartCause {
186    /// Sent if the time specified by `ControlFlow::WaitUntil` has been reached. Contains the
187    /// moment the timeout was requested and the requested resume time. The actual resume time is
188    /// guaranteed to be equal to or after the requested resume time.
189    ResumeTimeReached {
190        start: Instant,
191        requested_resume: Instant,
192    },
193
194    /// Sent if the OS has new events to send to the window, after a wait was requested. Contains
195    /// the moment the wait was requested and the resume time, if requested.
196    WaitCancelled {
197        start: Instant,
198        requested_resume: Option<Instant>,
199    },
200
201    /// Sent if the event loop is being resumed after the loop's control flow was set to
202    /// `ControlFlow::Poll`.
203    Poll,
204
205    /// Sent once, immediately after `run` is called. Indicates that the loop was just initialized.
206    Init,
207}
208
209/// Describes an event from a `Window`.
210#[derive(Debug, PartialEq)]
211pub enum WindowEvent<'a> {
212    /// The size of the window has changed. Contains the client area's new dimensions.
213    Resized(PhysicalSize<u32>),
214
215    /// The position of the window has changed. Contains the window's new position.
216    Moved(PhysicalPosition<i32>),
217
218    /// The window has been requested to close.
219    CloseRequested,
220
221    /// The window has been destroyed.
222    Destroyed,
223
224    /// A file has been dropped into the window.
225    ///
226    /// When the user drops multiple files at once, this event will be emitted for each file
227    /// separately.
228    DroppedFile(PathBuf),
229
230    /// A file is being hovered over the window.
231    ///
232    /// When the user hovers multiple files at once, this event will be emitted for each file
233    /// separately.
234    HoveredFile(PathBuf),
235
236    /// A file was hovered, but has exited the window.
237    ///
238    /// There will be a single `HoveredFileCancelled` event triggered even if multiple files were
239    /// hovered.
240    HoveredFileCancelled,
241
242    /// The window received a unicode character.
243    ReceivedCharacter(char),
244
245    /// The window gained or lost focus.
246    ///
247    /// The parameter is true if the window has gained focus, and false if it has lost focus.
248    Focused(bool),
249
250    /// An event from the keyboard has been received.
251    KeyboardInput {
252        device_id: DeviceId,
253        input: KeyboardInput,
254        /// If `true`, the event was generated synthetically by winit
255        /// in one of the following circumstances:
256        ///
257        /// * Synthetic key press events are generated for all keys pressed
258        ///   when a window gains focus. Likewise, synthetic key release events
259        ///   are generated for all keys pressed when a window goes out of focus.
260        ///   ***Currently, this is only functional on X11 and Windows***
261        ///
262        /// Otherwise, this value is always `false`.
263        is_synthetic: bool,
264    },
265
266    /// The keyboard modifiers have changed.
267    ///
268    /// Platform-specific behavior:
269    /// - **Web**: This API is currently unimplemented on the web. This isn't by design - it's an
270    ///   issue, and it should get fixed - but it's the current state of the API.
271    ModifiersChanged(ModifiersState),
272
273    /// The cursor has moved on the window.
274    CursorMoved {
275        device_id: DeviceId,
276
277        /// (x,y) coords in pixels relative to the top-left corner of the window. Because the range of this data is
278        /// limited by the display area and it may have been transformed by the OS to implement effects such as cursor
279        /// acceleration, it should not be used to implement non-cursor-like interactions such as 3D camera control.
280        position: PhysicalPosition<f64>,
281        #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
282        modifiers: ModifiersState,
283    },
284
285    /// The cursor has entered the window.
286    CursorEntered { device_id: DeviceId },
287
288    /// The cursor has left the window.
289    CursorLeft { device_id: DeviceId },
290
291    /// A mouse wheel movement or touchpad scroll occurred.
292    MouseWheel {
293        device_id: DeviceId,
294        delta: MouseScrollDelta,
295        phase: TouchPhase,
296        #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
297        modifiers: ModifiersState,
298    },
299
300    /// An mouse button press has been received.
301    MouseInput {
302        device_id: DeviceId,
303        state: ElementState,
304        button: MouseButton,
305        #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
306        modifiers: ModifiersState,
307    },
308
309    /// Touchpad pressure event.
310    ///
311    /// At the moment, only supported on Apple forcetouch-capable macbooks.
312    /// The parameters are: pressure level (value between 0 and 1 representing how hard the touchpad
313    /// is being pressed) and stage (integer representing the click level).
314    TouchpadPressure {
315        device_id: DeviceId,
316        pressure: f32,
317        stage: i64,
318    },
319
320    /// Motion on some analog axis. May report data redundant to other, more specific events.
321    AxisMotion {
322        device_id: DeviceId,
323        axis: AxisId,
324        value: f64,
325    },
326
327    /// Touch event has been received
328    Touch(Touch),
329
330    /// The window's scale factor has changed.
331    ///
332    /// The following user actions can cause DPI changes:
333    ///
334    /// * Changing the display's resolution.
335    /// * Changing the display's scale factor (e.g. in Control Panel on Windows).
336    /// * Moving the window to a display with a different scale factor.
337    ///
338    /// After this event callback has been processed, the window will be resized to whatever value
339    /// is pointed to by the `new_inner_size` reference. By default, this will contain the size suggested
340    /// by the OS, but it can be changed to any value.
341    ///
342    /// For more information about DPI in general, see the [`dpi`](crate::dpi) module.
343    ScaleFactorChanged {
344        scale_factor: f64,
345        new_inner_size: &'a mut PhysicalSize<u32>,
346    },
347
348    /// The system window theme has changed.
349    ///
350    /// Applications might wish to react to this to change the theme of the content of the window
351    /// when the system changes the window theme.
352    ///
353    /// At the moment this is only supported on Windows.
354    ThemeChanged(Theme),
355}
356
357impl Clone for WindowEvent<'static> {
358    fn clone(&self) -> Self {
359        use self::WindowEvent::*;
360        return match self {
361            Resized(size) => Resized(size.clone()),
362            Moved(pos) => Moved(pos.clone()),
363            CloseRequested => CloseRequested,
364            Destroyed => Destroyed,
365            DroppedFile(file) => DroppedFile(file.clone()),
366            HoveredFile(file) => HoveredFile(file.clone()),
367            HoveredFileCancelled => HoveredFileCancelled,
368            ReceivedCharacter(c) => ReceivedCharacter(*c),
369            Focused(f) => Focused(*f),
370            KeyboardInput {
371                device_id,
372                input,
373                is_synthetic,
374            } => KeyboardInput {
375                device_id: *device_id,
376                input: *input,
377                is_synthetic: *is_synthetic,
378            },
379
380            ModifiersChanged(modifiers) => ModifiersChanged(modifiers.clone()),
381            #[allow(deprecated)]
382            CursorMoved {
383                device_id,
384                position,
385                modifiers,
386            } => CursorMoved {
387                device_id: *device_id,
388                position: *position,
389                modifiers: *modifiers,
390            },
391            CursorEntered { device_id } => CursorEntered {
392                device_id: *device_id,
393            },
394            CursorLeft { device_id } => CursorLeft {
395                device_id: *device_id,
396            },
397            #[allow(deprecated)]
398            MouseWheel {
399                device_id,
400                delta,
401                phase,
402                modifiers,
403            } => MouseWheel {
404                device_id: *device_id,
405                delta: *delta,
406                phase: *phase,
407                modifiers: *modifiers,
408            },
409            #[allow(deprecated)]
410            MouseInput {
411                device_id,
412                state,
413                button,
414                modifiers,
415            } => MouseInput {
416                device_id: *device_id,
417                state: *state,
418                button: *button,
419                modifiers: *modifiers,
420            },
421            TouchpadPressure {
422                device_id,
423                pressure,
424                stage,
425            } => TouchpadPressure {
426                device_id: *device_id,
427                pressure: *pressure,
428                stage: *stage,
429            },
430            AxisMotion {
431                device_id,
432                axis,
433                value,
434            } => AxisMotion {
435                device_id: *device_id,
436                axis: *axis,
437                value: *value,
438            },
439            Touch(touch) => Touch(*touch),
440            ThemeChanged(theme) => ThemeChanged(theme.clone()),
441            ScaleFactorChanged { .. } => {
442                unreachable!("Static event can't be about scale factor changing")
443            }
444        };
445    }
446}
447
448impl<'a> WindowEvent<'a> {
449    pub fn to_static(self) -> Option<WindowEvent<'static>> {
450        use self::WindowEvent::*;
451        match self {
452            Resized(size) => Some(Resized(size)),
453            Moved(position) => Some(Moved(position)),
454            CloseRequested => Some(CloseRequested),
455            Destroyed => Some(Destroyed),
456            DroppedFile(file) => Some(DroppedFile(file)),
457            HoveredFile(file) => Some(HoveredFile(file)),
458            HoveredFileCancelled => Some(HoveredFileCancelled),
459            ReceivedCharacter(c) => Some(ReceivedCharacter(c)),
460            Focused(focused) => Some(Focused(focused)),
461            KeyboardInput {
462                device_id,
463                input,
464                is_synthetic,
465            } => Some(KeyboardInput {
466                device_id,
467                input,
468                is_synthetic,
469            }),
470            ModifiersChanged(modifiers) => Some(ModifiersChanged(modifiers)),
471            #[allow(deprecated)]
472            CursorMoved {
473                device_id,
474                position,
475                modifiers,
476            } => Some(CursorMoved {
477                device_id,
478                position,
479                modifiers,
480            }),
481            CursorEntered { device_id } => Some(CursorEntered { device_id }),
482            CursorLeft { device_id } => Some(CursorLeft { device_id }),
483            #[allow(deprecated)]
484            MouseWheel {
485                device_id,
486                delta,
487                phase,
488                modifiers,
489            } => Some(MouseWheel {
490                device_id,
491                delta,
492                phase,
493                modifiers,
494            }),
495            #[allow(deprecated)]
496            MouseInput {
497                device_id,
498                state,
499                button,
500                modifiers,
501            } => Some(MouseInput {
502                device_id,
503                state,
504                button,
505                modifiers,
506            }),
507            TouchpadPressure {
508                device_id,
509                pressure,
510                stage,
511            } => Some(TouchpadPressure {
512                device_id,
513                pressure,
514                stage,
515            }),
516            AxisMotion {
517                device_id,
518                axis,
519                value,
520            } => Some(AxisMotion {
521                device_id,
522                axis,
523                value,
524            }),
525            Touch(touch) => Some(Touch(touch)),
526            ThemeChanged(theme) => Some(ThemeChanged(theme)),
527            ScaleFactorChanged { .. } => None,
528        }
529    }
530}
531
532/// Identifier of an input device.
533///
534/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which
535/// identifies its origin. Note that devices may be virtual (representing an on-screen cursor and keyboard focus) or
536/// physical. Virtual devices typically aggregate inputs from multiple physical devices.
537#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
538pub struct DeviceId(pub(crate) platform_impl::DeviceId);
539
540impl DeviceId {
541    /// Returns a dummy `DeviceId`, useful for unit testing. The only guarantee made about the return
542    /// value of this function is that it will always be equal to itself and to future values returned
543    /// by this function.  No other guarantees are made. This may be equal to a real `DeviceId`.
544    ///
545    /// **Passing this into a winit function will result in undefined behavior.**
546    pub unsafe fn dummy() -> Self {
547        DeviceId(platform_impl::DeviceId::dummy())
548    }
549}
550
551/// Represents raw hardware events that are not associated with any particular window.
552///
553/// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera or first-person
554/// game controls. Many physical actions, such as mouse movement, can produce both device and window events. Because
555/// window events typically arise from virtual devices (corresponding to GUI cursors and keyboard focus) the device IDs
556/// may not match.
557///
558/// Note that these events are delivered regardless of input focus.
559#[derive(Clone, Debug, PartialEq)]
560pub enum DeviceEvent {
561    Added,
562    Removed,
563
564    /// Change in physical position of a pointing device.
565    ///
566    /// This represents raw, unfiltered physical motion. Not to be confused with `WindowEvent::CursorMoved`.
567    MouseMotion {
568        /// (x, y) change in position in unspecified units.
569        ///
570        /// Different devices may use different units.
571        delta: (f64, f64),
572    },
573
574    /// Physical scroll event
575    MouseWheel {
576        delta: MouseScrollDelta,
577    },
578
579    /// Motion on some analog axis.  This event will be reported for all arbitrary input devices
580    /// that winit supports on this platform, including mouse devices.  If the device is a mouse
581    /// device then this will be reported alongside the MouseMotion event.
582    Motion {
583        axis: AxisId,
584        value: f64,
585    },
586
587    Button {
588        button: ButtonId,
589        state: ElementState,
590    },
591
592    Key(KeyboardInput),
593
594    Text {
595        codepoint: char,
596    },
597}
598
599/// Describes a keyboard input event.
600#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
601#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
602pub struct KeyboardInput {
603    /// Identifies the physical key pressed
604    ///
605    /// This should not change if the user adjusts the host's keyboard map. Use when the physical location of the
606    /// key is more important than the key's host GUI semantics, such as for movement controls in a first-person
607    /// game.
608    pub scancode: ScanCode,
609
610    pub state: ElementState,
611
612    /// Identifies the semantic meaning of the key
613    ///
614    /// Use when the semantics of the key are more important than the physical location of the key, such as when
615    /// implementing appropriate behavior for "page up."
616    pub virtual_keycode: Option<VirtualKeyCode>,
617
618    /// Modifier keys active at the time of this input.
619    ///
620    /// This is tracked internally to avoid tracking errors arising from modifier key state changes when events from
621    /// this device are not being delivered to the application, e.g. due to keyboard focus being elsewhere.
622    #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
623    pub modifiers: ModifiersState,
624}
625
626/// Describes touch-screen input state.
627#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
628#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
629pub enum TouchPhase {
630    Started,
631    Moved,
632    Ended,
633    Cancelled,
634}
635
636/// Represents a touch event
637///
638/// Every time the user touches the screen, a new `Start` event with an unique
639/// identifier for the finger is generated. When the finger is lifted, an `End`
640/// event is generated with the same finger id.
641///
642/// After a `Start` event has been emitted, there may be zero or more `Move`
643/// events when the finger is moved or the touch pressure changes.
644///
645/// The finger id may be reused by the system after an `End` event. The user
646/// should assume that a new `Start` event received with the same id has nothing
647/// to do with the old finger and is a new finger.
648///
649/// A `Cancelled` event is emitted when the system has canceled tracking this
650/// touch, such as when the window loses focus, or on iOS if the user moves the
651/// device against their face.
652#[derive(Debug, Clone, Copy, PartialEq)]
653pub struct Touch {
654    pub device_id: DeviceId,
655    pub phase: TouchPhase,
656    pub location: PhysicalPosition<f64>,
657    /// Describes how hard the screen was pressed. May be `None` if the platform
658    /// does not support pressure sensitivity.
659    ///
660    /// ## Platform-specific
661    ///
662    /// - Only available on **iOS** 9.0+ and **Windows** 8+.
663    pub force: Option<Force>,
664    /// Unique identifier of a finger.
665    pub id: u64,
666}
667
668/// Describes the force of a touch event
669#[derive(Debug, Clone, Copy, PartialEq)]
670pub enum Force {
671    /// On iOS, the force is calibrated so that the same number corresponds to
672    /// roughly the same amount of pressure on the screen regardless of the
673    /// device.
674    Calibrated {
675        /// The force of the touch, where a value of 1.0 represents the force of
676        /// an average touch (predetermined by the system, not user-specific).
677        ///
678        /// The force reported by Apple Pencil is measured along the axis of the
679        /// pencil. If you want a force perpendicular to the device, you need to
680        /// calculate this value using the `altitude_angle` value.
681        force: f64,
682        /// The maximum possible force for a touch.
683        ///
684        /// The value of this field is sufficiently high to provide a wide
685        /// dynamic range for values of the `force` field.
686        max_possible_force: f64,
687        /// The altitude (in radians) of the stylus.
688        ///
689        /// A value of 0 radians indicates that the stylus is parallel to the
690        /// surface. The value of this property is Pi/2 when the stylus is
691        /// perpendicular to the surface.
692        altitude_angle: Option<f64>,
693    },
694    /// If the platform reports the force as normalized, we have no way of
695    /// knowing how much pressure 1.0 corresponds to – we know it's the maximum
696    /// amount of force, but as to how much force, you might either have to
697    /// press really really hard, or not hard at all, depending on the device.
698    Normalized(f64),
699}
700
701impl Force {
702    /// Returns the force normalized to the range between 0.0 and 1.0 inclusive.
703    /// Instead of normalizing the force, you should prefer to handle
704    /// `Force::Calibrated` so that the amount of force the user has to apply is
705    /// consistent across devices.
706    pub fn normalized(&self) -> f64 {
707        match self {
708            Force::Calibrated {
709                force,
710                max_possible_force,
711                altitude_angle,
712            } => {
713                let force = match altitude_angle {
714                    Some(altitude_angle) => force / altitude_angle.sin(),
715                    None => *force,
716                };
717                force / max_possible_force
718            }
719            Force::Normalized(force) => *force,
720        }
721    }
722}
723
724/// Hardware-dependent keyboard scan code.
725pub type ScanCode = u32;
726
727/// Identifier for a specific analog axis on some device.
728pub type AxisId = u32;
729
730/// Identifier for a specific button on some device.
731pub type ButtonId = u32;
732
733/// Describes the input state of a key.
734#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
735#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
736pub enum ElementState {
737    Pressed,
738    Released,
739}
740
741/// Describes a button of a mouse controller.
742#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
743#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
744pub enum MouseButton {
745    Left,
746    Right,
747    Middle,
748    Other(u16),
749}
750
751/// Describes a difference in the mouse scroll wheel state.
752#[derive(Debug, Clone, Copy, PartialEq)]
753#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
754pub enum MouseScrollDelta {
755    /// Amount in lines or rows to scroll in the horizontal
756    /// and vertical directions.
757    ///
758    /// Positive values indicate movement forward
759    /// (away from the user) or rightwards.
760    LineDelta(f32, f32),
761    /// Amount in pixels to scroll in the horizontal and
762    /// vertical direction.
763    ///
764    /// Scroll events are expressed as a PixelDelta if
765    /// supported by the device (eg. a touchpad) and
766    /// platform.
767    PixelDelta(PhysicalPosition<f64>),
768}
769
770/// Symbolic name for a keyboard key.
771#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
772#[repr(u32)]
773#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
774pub enum VirtualKeyCode {
775    /// The '1' key over the letters.
776    Key1,
777    /// The '2' key over the letters.
778    Key2,
779    /// The '3' key over the letters.
780    Key3,
781    /// The '4' key over the letters.
782    Key4,
783    /// The '5' key over the letters.
784    Key5,
785    /// The '6' key over the letters.
786    Key6,
787    /// The '7' key over the letters.
788    Key7,
789    /// The '8' key over the letters.
790    Key8,
791    /// The '9' key over the letters.
792    Key9,
793    /// The '0' key over the 'O' and 'P' keys.
794    Key0,
795
796    A,
797    B,
798    C,
799    D,
800    E,
801    F,
802    G,
803    H,
804    I,
805    J,
806    K,
807    L,
808    M,
809    N,
810    O,
811    P,
812    Q,
813    R,
814    S,
815    T,
816    U,
817    V,
818    W,
819    X,
820    Y,
821    Z,
822
823    /// The Escape key, next to F1.
824    Escape,
825
826    F1,
827    F2,
828    F3,
829    F4,
830    F5,
831    F6,
832    F7,
833    F8,
834    F9,
835    F10,
836    F11,
837    F12,
838    F13,
839    F14,
840    F15,
841    F16,
842    F17,
843    F18,
844    F19,
845    F20,
846    F21,
847    F22,
848    F23,
849    F24,
850
851    /// Print Screen/SysRq.
852    Snapshot,
853    /// Scroll Lock.
854    Scroll,
855    /// Pause/Break key, next to Scroll lock.
856    Pause,
857
858    /// `Insert`, next to Backspace.
859    Insert,
860    Home,
861    Delete,
862    End,
863    PageDown,
864    PageUp,
865
866    Left,
867    Up,
868    Right,
869    Down,
870
871    /// The Backspace key, right over Enter.
872    // TODO: rename
873    Back,
874    /// The Enter key.
875    Return,
876    /// The space bar.
877    Space,
878
879    /// The "Compose" key on Linux.
880    Compose,
881
882    Caret,
883
884    Numlock,
885    Numpad0,
886    Numpad1,
887    Numpad2,
888    Numpad3,
889    Numpad4,
890    Numpad5,
891    Numpad6,
892    Numpad7,
893    Numpad8,
894    Numpad9,
895    NumpadAdd,
896    NumpadDivide,
897    NumpadDecimal,
898    NumpadComma,
899    NumpadEnter,
900    NumpadEquals,
901    NumpadMultiply,
902    NumpadSubtract,
903
904    AbntC1,
905    AbntC2,
906    Apostrophe,
907    Apps,
908    Asterisk,
909    At,
910    Ax,
911    Backslash,
912    Calculator,
913    Capital,
914    Colon,
915    Comma,
916    Convert,
917    Equals,
918    Grave,
919    Kana,
920    Kanji,
921    LAlt,
922    LBracket,
923    LControl,
924    LShift,
925    LWin,
926    Mail,
927    MediaSelect,
928    MediaStop,
929    Minus,
930    Mute,
931    MyComputer,
932    // also called "Next"
933    NavigateForward,
934    // also called "Prior"
935    NavigateBackward,
936    NextTrack,
937    NoConvert,
938    OEM102,
939    Period,
940    PlayPause,
941    Plus,
942    Power,
943    PrevTrack,
944    RAlt,
945    RBracket,
946    RControl,
947    RShift,
948    RWin,
949    Semicolon,
950    Slash,
951    Sleep,
952    Stop,
953    Sysrq,
954    Tab,
955    Underline,
956    Unlabeled,
957    VolumeDown,
958    VolumeUp,
959    Wake,
960    WebBack,
961    WebFavorites,
962    WebForward,
963    WebHome,
964    WebRefresh,
965    WebSearch,
966    WebStop,
967    Yen,
968    Copy,
969    Paste,
970    Cut,
971}
972
973impl ModifiersState {
974    /// Returns `true` if the shift key is pressed.
975    pub fn shift(&self) -> bool {
976        self.intersects(Self::SHIFT)
977    }
978    /// Returns `true` if the control key is pressed.
979    pub fn ctrl(&self) -> bool {
980        self.intersects(Self::CTRL)
981    }
982    /// Returns `true` if the alt key is pressed.
983    pub fn alt(&self) -> bool {
984        self.intersects(Self::ALT)
985    }
986    /// Returns `true` if the logo key is pressed.
987    pub fn logo(&self) -> bool {
988        self.intersects(Self::LOGO)
989    }
990}
991
992bitflags! {
993    /// Represents the current state of the keyboard modifiers
994    ///
995    /// Each flag represents a modifier and is set if this modifier is active.
996    #[derive(Default)]
997    pub struct ModifiersState: u32 {
998        // left and right modifiers are currently commented out, but we should be able to support
999        // them in a future release
1000        /// The "shift" key.
1001        const SHIFT = 0b100 << 0;
1002        // const LSHIFT = 0b010 << 0;
1003        // const RSHIFT = 0b001 << 0;
1004        /// The "control" key.
1005        const CTRL = 0b100 << 3;
1006        // const LCTRL = 0b010 << 3;
1007        // const RCTRL = 0b001 << 3;
1008        /// The "alt" key.
1009        const ALT = 0b100 << 6;
1010        // const LALT = 0b010 << 6;
1011        // const RALT = 0b001 << 6;
1012        /// This is the "windows" key on PC and "command" key on Mac.
1013        const LOGO = 0b100 << 9;
1014        // const LLOGO = 0b010 << 9;
1015        // const RLOGO = 0b001 << 9;
1016    }
1017}
1018
1019#[cfg(feature = "serde")]
1020mod modifiers_serde {
1021    use super::ModifiersState;
1022    use serde::{Deserialize, Deserializer, Serialize, Serializer};
1023
1024    #[derive(Default, Serialize, Deserialize)]
1025    #[serde(default)]
1026    #[serde(rename = "ModifiersState")]
1027    pub struct ModifiersStateSerialize {
1028        pub shift: bool,
1029        pub ctrl: bool,
1030        pub alt: bool,
1031        pub logo: bool,
1032    }
1033
1034    impl Serialize for ModifiersState {
1035        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1036        where
1037            S: Serializer,
1038        {
1039            let s = ModifiersStateSerialize {
1040                shift: self.shift(),
1041                ctrl: self.ctrl(),
1042                alt: self.alt(),
1043                logo: self.logo(),
1044            };
1045            s.serialize(serializer)
1046        }
1047    }
1048
1049    impl<'de> Deserialize<'de> for ModifiersState {
1050        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1051        where
1052            D: Deserializer<'de>,
1053        {
1054            let ModifiersStateSerialize {
1055                shift,
1056                ctrl,
1057                alt,
1058                logo,
1059            } = ModifiersStateSerialize::deserialize(deserializer)?;
1060            let mut m = ModifiersState::empty();
1061            m.set(ModifiersState::SHIFT, shift);
1062            m.set(ModifiersState::CTRL, ctrl);
1063            m.set(ModifiersState::ALT, alt);
1064            m.set(ModifiersState::LOGO, logo);
1065            Ok(m)
1066        }
1067    }
1068}