zng_view_api/
raw_input.rs

1//! Types for "input" devices.
2//!
3//! This represents the more basic subset of HIDs, keyboard, mouse, game controllers, it does not include media devices.
4
5use bitflags::bitflags;
6use serde::{Deserialize, Serialize};
7use zng_txt::Txt;
8
9use crate::{
10    AxisId,
11    keyboard::{KeyCode, KeyState},
12    mouse::{ButtonId, ButtonState, MouseScrollDelta},
13};
14
15crate::declare_id! {
16    /// Input device ID in channel.
17    ///
18    /// In the View Process this is mapped to a system id.
19    ///
20    /// In the App Process this is mapped to an unique id, but does not survived View crashes.
21    ///
22    /// The View Process defines the ID.
23    pub struct InputDeviceId(_);
24}
25
26/// Info about an human input device.
27#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
28#[non_exhaustive]
29pub struct InputDeviceInfo {
30    /// Display name.
31    pub name: Txt,
32    /// Device capabilities.
33    pub capabilities: InputDeviceCapability,
34}
35
36impl InputDeviceInfo {
37    /// New info.
38    pub fn new(name: impl Into<Txt>, capabilities: InputDeviceCapability) -> Self {
39        Self {
40            name: name.into(),
41            capabilities,
42        }
43    }
44}
45
46bitflags! {
47    /// Capabilities of an input device.
48    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
49    pub struct InputDeviceCapability: u8 {
50        /// Device can produce keyboard key presses.
51        const KEY = 0b0000_0001;
52        /// Device can produce button presses.
53        const BUTTON = 0b0000_0010;
54        /// Device provides scrolling wheel deltas, vertical or horizontal.
55        const SCROLL_MOTION = 0b0001_0000;
56        /// Device provides axis aligned 1D motion.
57        const AXIS_MOTION = 0b0010_0000;
58        /// Device provides 2D pointer motion.
59        const POINTER_MOTION = 0b0100_0000;
60    }
61}
62
63/// Raw input device event.
64#[derive(Debug, Clone, Serialize, Deserialize)]
65#[non_exhaustive]
66pub enum InputDeviceEvent {
67    /// 2D pointer motion.
68    ///
69    /// The values if the delta of movement (x, y), not position.
70    PointerMotion {
71        /// Delta of change in the cursor position.
72        delta: euclid::Vector2D<f64, ()>,
73    },
74    /// Scroll wheel motion.
75    ScrollMotion {
76        /// Delta of change in the mouse scroll wheel state.
77        delta: MouseScrollDelta,
78    },
79    /// Motion on some analog axis.
80    ///
81    /// This includes the mouse device and any other that fits.
82    AxisMotion {
83        /// Device dependent axis of the motion.
84        axis: AxisId,
85        /// Device dependent value.
86        value: f64,
87    },
88    /// Device button press or release.
89    Button {
90        /// Device dependent button that was used.
91        button: ButtonId,
92        /// If the button was pressed or released.
93        state: ButtonState,
94    },
95    /// Device key press or release.
96    Key {
97        /// Physical key.
98        key_code: KeyCode,
99        /// If the key was pressed or released.
100        state: KeyState,
101    },
102}
103impl InputDeviceEvent {
104    /// Change `self` to incorporate `other` or returns `other` if both events cannot be coalesced.
105    pub fn coalesce(&mut self, other: Self) -> Result<(), Self> {
106        use InputDeviceEvent::*;
107        match (self, other) {
108            (PointerMotion { delta }, PointerMotion { delta: n_delta }) => {
109                *delta += n_delta;
110            }
111            (
112                ScrollMotion {
113                    delta: MouseScrollDelta::LineDelta(delta_x, delta_y),
114                },
115                ScrollMotion {
116                    delta: MouseScrollDelta::LineDelta(n_delta_x, n_delta_y),
117                },
118            ) => {
119                *delta_x += n_delta_x;
120                *delta_y += n_delta_y;
121            }
122
123            (
124                ScrollMotion {
125                    delta: MouseScrollDelta::PixelDelta(delta_x, delta_y),
126                },
127                ScrollMotion {
128                    delta: MouseScrollDelta::PixelDelta(n_delta_x, n_delta_y),
129                },
130            ) => {
131                *delta_x += n_delta_x;
132                *delta_y += n_delta_y;
133            }
134            (_, e) => return Err(e),
135        }
136        Ok(())
137    }
138}