azul_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 /// Custom command (currently only emitted on Windows). Win32 allows the user to
357 /// register custom command IDs for app menus, context menus and so on
358 /// (see the `WM_COMMAND` message in the Windows API). This event allows
359 /// you to, for example, react to when a user has clicked an item in an application menu.
360 ///
361 /// The ID contained in the `Command` has to be registered by the user of the library,
362 /// usually by using the `WindowBuilder::with_create_callback` function.
363 /// For an example of how to use it, see the `menu_bar_win32` example.
364 Command(u16),
365}
366
367impl Clone for WindowEvent<'static> {
368 fn clone(&self) -> Self {
369 use self::WindowEvent::*;
370 return match self {
371 Resized(size) => Resized(size.clone()),
372 Moved(pos) => Moved(pos.clone()),
373 CloseRequested => CloseRequested,
374 Destroyed => Destroyed,
375 DroppedFile(file) => DroppedFile(file.clone()),
376 HoveredFile(file) => HoveredFile(file.clone()),
377 HoveredFileCancelled => HoveredFileCancelled,
378 ReceivedCharacter(c) => ReceivedCharacter(*c),
379 Focused(f) => Focused(*f),
380 KeyboardInput {
381 device_id,
382 input,
383 is_synthetic,
384 } => KeyboardInput {
385 device_id: *device_id,
386 input: *input,
387 is_synthetic: *is_synthetic,
388 },
389
390 ModifiersChanged(modifiers) => ModifiersChanged(modifiers.clone()),
391 #[allow(deprecated)]
392 CursorMoved {
393 device_id,
394 position,
395 modifiers,
396 } => CursorMoved {
397 device_id: *device_id,
398 position: *position,
399 modifiers: *modifiers,
400 },
401 CursorEntered { device_id } => CursorEntered {
402 device_id: *device_id,
403 },
404 CursorLeft { device_id } => CursorLeft {
405 device_id: *device_id,
406 },
407 #[allow(deprecated)]
408 MouseWheel {
409 device_id,
410 delta,
411 phase,
412 modifiers,
413 } => MouseWheel {
414 device_id: *device_id,
415 delta: *delta,
416 phase: *phase,
417 modifiers: *modifiers,
418 },
419 #[allow(deprecated)]
420 MouseInput {
421 device_id,
422 state,
423 button,
424 modifiers,
425 } => MouseInput {
426 device_id: *device_id,
427 state: *state,
428 button: *button,
429 modifiers: *modifiers,
430 },
431 TouchpadPressure {
432 device_id,
433 pressure,
434 stage,
435 } => TouchpadPressure {
436 device_id: *device_id,
437 pressure: *pressure,
438 stage: *stage,
439 },
440 AxisMotion {
441 device_id,
442 axis,
443 value,
444 } => AxisMotion {
445 device_id: *device_id,
446 axis: *axis,
447 value: *value,
448 },
449 Touch(touch) => Touch(*touch),
450 ThemeChanged(theme) => ThemeChanged(theme.clone()),
451 ScaleFactorChanged { .. } => {
452 unreachable!("Static event can't be about scale factor changing")
453 },
454 Command(c) => Command(*c),
455 };
456 }
457}
458
459impl<'a> WindowEvent<'a> {
460 pub fn to_static(self) -> Option<WindowEvent<'static>> {
461 use self::WindowEvent::*;
462 match self {
463 Resized(size) => Some(Resized(size)),
464 Moved(position) => Some(Moved(position)),
465 CloseRequested => Some(CloseRequested),
466 Destroyed => Some(Destroyed),
467 DroppedFile(file) => Some(DroppedFile(file)),
468 HoveredFile(file) => Some(HoveredFile(file)),
469 HoveredFileCancelled => Some(HoveredFileCancelled),
470 ReceivedCharacter(c) => Some(ReceivedCharacter(c)),
471 Focused(focused) => Some(Focused(focused)),
472 KeyboardInput {
473 device_id,
474 input,
475 is_synthetic,
476 } => Some(KeyboardInput {
477 device_id,
478 input,
479 is_synthetic,
480 }),
481 ModifiersChanged(modifiers) => Some(ModifiersChanged(modifiers)),
482 #[allow(deprecated)]
483 CursorMoved {
484 device_id,
485 position,
486 modifiers,
487 } => Some(CursorMoved {
488 device_id,
489 position,
490 modifiers,
491 }),
492 CursorEntered { device_id } => Some(CursorEntered { device_id }),
493 CursorLeft { device_id } => Some(CursorLeft { device_id }),
494 #[allow(deprecated)]
495 MouseWheel {
496 device_id,
497 delta,
498 phase,
499 modifiers,
500 } => Some(MouseWheel {
501 device_id,
502 delta,
503 phase,
504 modifiers,
505 }),
506 #[allow(deprecated)]
507 MouseInput {
508 device_id,
509 state,
510 button,
511 modifiers,
512 } => Some(MouseInput {
513 device_id,
514 state,
515 button,
516 modifiers,
517 }),
518 TouchpadPressure {
519 device_id,
520 pressure,
521 stage,
522 } => Some(TouchpadPressure {
523 device_id,
524 pressure,
525 stage,
526 }),
527 AxisMotion {
528 device_id,
529 axis,
530 value,
531 } => Some(AxisMotion {
532 device_id,
533 axis,
534 value,
535 }),
536 Touch(touch) => Some(Touch(touch)),
537 ThemeChanged(theme) => Some(ThemeChanged(theme)),
538 ScaleFactorChanged { .. } => None,
539 Command(c) => Some(Command(c)),
540 }
541 }
542}
543
544/// Identifier of an input device.
545///
546/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which
547/// identifies its origin. Note that devices may be virtual (representing an on-screen cursor and keyboard focus) or
548/// physical. Virtual devices typically aggregate inputs from multiple physical devices.
549#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
550pub struct DeviceId(pub(crate) platform_impl::DeviceId);
551
552impl DeviceId {
553 /// Returns a dummy `DeviceId`, useful for unit testing. The only guarantee made about the return
554 /// value of this function is that it will always be equal to itself and to future values returned
555 /// by this function. No other guarantees are made. This may be equal to a real `DeviceId`.
556 ///
557 /// **Passing this into a winit function will result in undefined behavior.**
558 pub unsafe fn dummy() -> Self {
559 DeviceId(platform_impl::DeviceId::dummy())
560 }
561}
562
563/// Represents raw hardware events that are not associated with any particular window.
564///
565/// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera or first-person
566/// game controls. Many physical actions, such as mouse movement, can produce both device and window events. Because
567/// window events typically arise from virtual devices (corresponding to GUI cursors and keyboard focus) the device IDs
568/// may not match.
569///
570/// Note that these events are delivered regardless of input focus.
571#[derive(Clone, Debug, PartialEq)]
572pub enum DeviceEvent {
573 Added,
574 Removed,
575
576 /// Change in physical position of a pointing device.
577 ///
578 /// This represents raw, unfiltered physical motion. Not to be confused with `WindowEvent::CursorMoved`.
579 MouseMotion {
580 /// (x, y) change in position in unspecified units.
581 ///
582 /// Different devices may use different units.
583 delta: (f64, f64),
584 },
585
586 /// Physical scroll event
587 MouseWheel {
588 delta: MouseScrollDelta,
589 },
590
591 /// Motion on some analog axis. This event will be reported for all arbitrary input devices
592 /// that winit supports on this platform, including mouse devices. If the device is a mouse
593 /// device then this will be reported alongside the MouseMotion event.
594 Motion {
595 axis: AxisId,
596 value: f64,
597 },
598
599 Button {
600 button: ButtonId,
601 state: ElementState,
602 },
603
604 Key(KeyboardInput),
605
606 Text {
607 codepoint: char,
608 },
609}
610
611/// Describes a keyboard input event.
612#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
613#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
614pub struct KeyboardInput {
615 /// Identifies the physical key pressed
616 ///
617 /// This should not change if the user adjusts the host's keyboard map. Use when the physical location of the
618 /// key is more important than the key's host GUI semantics, such as for movement controls in a first-person
619 /// game.
620 pub scancode: ScanCode,
621
622 pub state: ElementState,
623
624 /// Identifies the semantic meaning of the key
625 ///
626 /// Use when the semantics of the key are more important than the physical location of the key, such as when
627 /// implementing appropriate behavior for "page up."
628 pub virtual_keycode: Option<VirtualKeyCode>,
629
630 /// Modifier keys active at the time of this input.
631 ///
632 /// This is tracked internally to avoid tracking errors arising from modifier key state changes when events from
633 /// this device are not being delivered to the application, e.g. due to keyboard focus being elsewhere.
634 #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
635 pub modifiers: ModifiersState,
636}
637
638/// Describes touch-screen input state.
639#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
640#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
641pub enum TouchPhase {
642 Started,
643 Moved,
644 Ended,
645 Cancelled,
646}
647
648/// Represents a touch event
649///
650/// Every time the user touches the screen, a new `Start` event with an unique
651/// identifier for the finger is generated. When the finger is lifted, an `End`
652/// event is generated with the same finger id.
653///
654/// After a `Start` event has been emitted, there may be zero or more `Move`
655/// events when the finger is moved or the touch pressure changes.
656///
657/// The finger id may be reused by the system after an `End` event. The user
658/// should assume that a new `Start` event received with the same id has nothing
659/// to do with the old finger and is a new finger.
660///
661/// A `Cancelled` event is emitted when the system has canceled tracking this
662/// touch, such as when the window loses focus, or on iOS if the user moves the
663/// device against their face.
664#[derive(Debug, Clone, Copy, PartialEq)]
665pub struct Touch {
666 pub device_id: DeviceId,
667 pub phase: TouchPhase,
668 pub location: PhysicalPosition<f64>,
669 /// Describes how hard the screen was pressed. May be `None` if the platform
670 /// does not support pressure sensitivity.
671 ///
672 /// ## Platform-specific
673 ///
674 /// - Only available on **iOS** 9.0+ and **Windows** 8+.
675 pub force: Option<Force>,
676 /// Unique identifier of a finger.
677 pub id: u64,
678}
679
680/// Describes the force of a touch event
681#[derive(Debug, Clone, Copy, PartialEq)]
682pub enum Force {
683 /// On iOS, the force is calibrated so that the same number corresponds to
684 /// roughly the same amount of pressure on the screen regardless of the
685 /// device.
686 Calibrated {
687 /// The force of the touch, where a value of 1.0 represents the force of
688 /// an average touch (predetermined by the system, not user-specific).
689 ///
690 /// The force reported by Apple Pencil is measured along the axis of the
691 /// pencil. If you want a force perpendicular to the device, you need to
692 /// calculate this value using the `altitude_angle` value.
693 force: f64,
694 /// The maximum possible force for a touch.
695 ///
696 /// The value of this field is sufficiently high to provide a wide
697 /// dynamic range for values of the `force` field.
698 max_possible_force: f64,
699 /// The altitude (in radians) of the stylus.
700 ///
701 /// A value of 0 radians indicates that the stylus is parallel to the
702 /// surface. The value of this property is Pi/2 when the stylus is
703 /// perpendicular to the surface.
704 altitude_angle: Option<f64>,
705 },
706 /// If the platform reports the force as normalized, we have no way of
707 /// knowing how much pressure 1.0 corresponds to – we know it's the maximum
708 /// amount of force, but as to how much force, you might either have to
709 /// press really really hard, or not hard at all, depending on the device.
710 Normalized(f64),
711}
712
713impl Force {
714 /// Returns the force normalized to the range between 0.0 and 1.0 inclusive.
715 /// Instead of normalizing the force, you should prefer to handle
716 /// `Force::Calibrated` so that the amount of force the user has to apply is
717 /// consistent across devices.
718 pub fn normalized(&self) -> f64 {
719 match self {
720 Force::Calibrated {
721 force,
722 max_possible_force,
723 altitude_angle,
724 } => {
725 let force = match altitude_angle {
726 Some(altitude_angle) => force / altitude_angle.sin(),
727 None => *force,
728 };
729 force / max_possible_force
730 }
731 Force::Normalized(force) => *force,
732 }
733 }
734}
735
736/// Hardware-dependent keyboard scan code.
737pub type ScanCode = u32;
738
739/// Identifier for a specific analog axis on some device.
740pub type AxisId = u32;
741
742/// Identifier for a specific button on some device.
743pub type ButtonId = u32;
744
745/// Describes the input state of a key.
746#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
747#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
748pub enum ElementState {
749 Pressed,
750 Released,
751}
752
753/// Describes a button of a mouse controller.
754#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
755#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
756pub enum MouseButton {
757 Left,
758 Right,
759 Middle,
760 Other(u16),
761}
762
763/// Describes a difference in the mouse scroll wheel state.
764#[derive(Debug, Clone, Copy, PartialEq)]
765#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
766pub enum MouseScrollDelta {
767 /// Amount in lines or rows to scroll in the horizontal
768 /// and vertical directions.
769 ///
770 /// Positive values indicate movement forward
771 /// (away from the user) or rightwards.
772 LineDelta(f32, f32),
773 /// Amount in pixels to scroll in the horizontal and
774 /// vertical direction.
775 ///
776 /// Scroll events are expressed as a PixelDelta if
777 /// supported by the device (eg. a touchpad) and
778 /// platform.
779 PixelDelta(PhysicalPosition<f64>),
780}
781
782/// Symbolic name for a keyboard key.
783#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
784#[repr(u32)]
785#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
786pub enum VirtualKeyCode {
787 /// The '1' key over the letters.
788 Key1,
789 /// The '2' key over the letters.
790 Key2,
791 /// The '3' key over the letters.
792 Key3,
793 /// The '4' key over the letters.
794 Key4,
795 /// The '5' key over the letters.
796 Key5,
797 /// The '6' key over the letters.
798 Key6,
799 /// The '7' key over the letters.
800 Key7,
801 /// The '8' key over the letters.
802 Key8,
803 /// The '9' key over the letters.
804 Key9,
805 /// The '0' key over the 'O' and 'P' keys.
806 Key0,
807
808 A,
809 B,
810 C,
811 D,
812 E,
813 F,
814 G,
815 H,
816 I,
817 J,
818 K,
819 L,
820 M,
821 N,
822 O,
823 P,
824 Q,
825 R,
826 S,
827 T,
828 U,
829 V,
830 W,
831 X,
832 Y,
833 Z,
834
835 /// The Escape key, next to F1.
836 Escape,
837
838 F1,
839 F2,
840 F3,
841 F4,
842 F5,
843 F6,
844 F7,
845 F8,
846 F9,
847 F10,
848 F11,
849 F12,
850 F13,
851 F14,
852 F15,
853 F16,
854 F17,
855 F18,
856 F19,
857 F20,
858 F21,
859 F22,
860 F23,
861 F24,
862
863 /// Print Screen/SysRq.
864 Snapshot,
865 /// Scroll Lock.
866 Scroll,
867 /// Pause/Break key, next to Scroll lock.
868 Pause,
869
870 /// `Insert`, next to Backspace.
871 Insert,
872 Home,
873 Delete,
874 End,
875 PageDown,
876 PageUp,
877
878 Left,
879 Up,
880 Right,
881 Down,
882
883 /// The Backspace key, right over Enter.
884 // TODO: rename
885 Back,
886 /// The Enter key.
887 Return,
888 /// The space bar.
889 Space,
890
891 /// The "Compose" key on Linux.
892 Compose,
893
894 Caret,
895
896 Numlock,
897 Numpad0,
898 Numpad1,
899 Numpad2,
900 Numpad3,
901 Numpad4,
902 Numpad5,
903 Numpad6,
904 Numpad7,
905 Numpad8,
906 Numpad9,
907 NumpadAdd,
908 NumpadDivide,
909 NumpadDecimal,
910 NumpadComma,
911 NumpadEnter,
912 NumpadEquals,
913 NumpadMultiply,
914 NumpadSubtract,
915
916 AbntC1,
917 AbntC2,
918 Apostrophe,
919 Apps,
920 Asterisk,
921 At,
922 Ax,
923 Backslash,
924 Calculator,
925 Capital,
926 Colon,
927 Comma,
928 Convert,
929 Equals,
930 Grave,
931 Kana,
932 Kanji,
933 LAlt,
934 LBracket,
935 LControl,
936 LShift,
937 LWin,
938 Mail,
939 MediaSelect,
940 MediaStop,
941 Minus,
942 Mute,
943 MyComputer,
944 // also called "Next"
945 NavigateForward,
946 // also called "Prior"
947 NavigateBackward,
948 NextTrack,
949 NoConvert,
950 OEM102,
951 Period,
952 PlayPause,
953 Plus,
954 Power,
955 PrevTrack,
956 RAlt,
957 RBracket,
958 RControl,
959 RShift,
960 RWin,
961 Semicolon,
962 Slash,
963 Sleep,
964 Stop,
965 Sysrq,
966 Tab,
967 Underline,
968 Unlabeled,
969 VolumeDown,
970 VolumeUp,
971 Wake,
972 WebBack,
973 WebFavorites,
974 WebForward,
975 WebHome,
976 WebRefresh,
977 WebSearch,
978 WebStop,
979 Yen,
980 Copy,
981 Paste,
982 Cut,
983}
984
985impl ModifiersState {
986 /// Returns `true` if the shift key is pressed.
987 pub fn shift(&self) -> bool {
988 self.intersects(Self::SHIFT)
989 }
990 /// Returns `true` if the control key is pressed.
991 pub fn ctrl(&self) -> bool {
992 self.intersects(Self::CTRL)
993 }
994 /// Returns `true` if the alt key is pressed.
995 pub fn alt(&self) -> bool {
996 self.intersects(Self::ALT)
997 }
998 /// Returns `true` if the logo key is pressed.
999 pub fn logo(&self) -> bool {
1000 self.intersects(Self::LOGO)
1001 }
1002}
1003
1004bitflags! {
1005 /// Represents the current state of the keyboard modifiers
1006 ///
1007 /// Each flag represents a modifier and is set if this modifier is active.
1008 #[derive(Default)]
1009 pub struct ModifiersState: u32 {
1010 // left and right modifiers are currently commented out, but we should be able to support
1011 // them in a future release
1012 /// The "shift" key.
1013 const SHIFT = 0b100 << 0;
1014 // const LSHIFT = 0b010 << 0;
1015 // const RSHIFT = 0b001 << 0;
1016 /// The "control" key.
1017 const CTRL = 0b100 << 3;
1018 // const LCTRL = 0b010 << 3;
1019 // const RCTRL = 0b001 << 3;
1020 /// The "alt" key.
1021 const ALT = 0b100 << 6;
1022 // const LALT = 0b010 << 6;
1023 // const RALT = 0b001 << 6;
1024 /// This is the "windows" key on PC and "command" key on Mac.
1025 const LOGO = 0b100 << 9;
1026 // const LLOGO = 0b010 << 9;
1027 // const RLOGO = 0b001 << 9;
1028 }
1029}
1030
1031#[cfg(feature = "serde")]
1032mod modifiers_serde {
1033 use super::ModifiersState;
1034 use serde::{Deserialize, Deserializer, Serialize, Serializer};
1035
1036 #[derive(Default, Serialize, Deserialize)]
1037 #[serde(default)]
1038 #[serde(rename = "ModifiersState")]
1039 pub struct ModifiersStateSerialize {
1040 pub shift: bool,
1041 pub ctrl: bool,
1042 pub alt: bool,
1043 pub logo: bool,
1044 }
1045
1046 impl Serialize for ModifiersState {
1047 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1048 where
1049 S: Serializer,
1050 {
1051 let s = ModifiersStateSerialize {
1052 shift: self.shift(),
1053 ctrl: self.ctrl(),
1054 alt: self.alt(),
1055 logo: self.logo(),
1056 };
1057 s.serialize(serializer)
1058 }
1059 }
1060
1061 impl<'de> Deserialize<'de> for ModifiersState {
1062 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1063 where
1064 D: Deserializer<'de>,
1065 {
1066 let ModifiersStateSerialize {
1067 shift,
1068 ctrl,
1069 alt,
1070 logo,
1071 } = ModifiersStateSerialize::deserialize(deserializer)?;
1072 let mut m = ModifiersState::empty();
1073 m.set(ModifiersState::SHIFT, shift);
1074 m.set(ModifiersState::CTRL, ctrl);
1075 m.set(ModifiersState::ALT, alt);
1076 m.set(ModifiersState::LOGO, logo);
1077 Ok(m)
1078 }
1079 }
1080}