dioxus_html/
input_data.rs

1//! Data structures representing user input, such as modifier keys and mouse buttons
2use enumset::{EnumSet, EnumSetType};
3
4/// A re-export of keyboard_types
5pub use keyboard_types;
6use keyboard_types::Location;
7
8/// A mouse button type (such as Primary/Secondary)
9// note: EnumSetType also derives Copy and Clone for some reason
10#[allow(clippy::unused_unit)]
11#[derive(EnumSetType, Debug, Default)]
12#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
13pub enum MouseButton {
14    #[default]
15    /// Primary button (typically the left button)
16    Primary,
17    /// Secondary button (typically the right button)
18    Secondary,
19    /// Auxiliary button (typically the middle button)
20    Auxiliary,
21    /// Fourth button (typically the "Browser Back" button)
22    Fourth,
23    /// Fifth button (typically the "Browser Forward" button)
24    Fifth,
25    /// A button with an unknown code
26    Unknown,
27}
28
29impl MouseButton {
30    /// Constructs a MouseButton for the specified button code
31    ///
32    /// E.g. 0 => Primary; 1 => Auxiliary
33    ///
34    /// Unknown codes get mapped to MouseButton::Unknown.
35    pub fn from_web_code(code: i16) -> Self {
36        match code {
37            0 => MouseButton::Primary,
38            // not a typo; auxiliary and secondary are swapped unlike in the `buttons` field.
39            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
40            1 => MouseButton::Auxiliary,
41            2 => MouseButton::Secondary,
42            3 => MouseButton::Fourth,
43            4 => MouseButton::Fifth,
44            _ => MouseButton::Unknown,
45        }
46    }
47
48    /// Converts MouseButton into the corresponding button code
49    ///
50    /// MouseButton::Unknown will get mapped to -1
51    pub fn into_web_code(self) -> i16 {
52        match self {
53            MouseButton::Primary => 0,
54            // not a typo; auxiliary and secondary are swapped unlike in the `buttons` field.
55            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
56            MouseButton::Auxiliary => 1,
57            MouseButton::Secondary => 2,
58            MouseButton::Fourth => 3,
59            MouseButton::Fifth => 4,
60            MouseButton::Unknown => -1,
61        }
62    }
63}
64
65/// A set of mouse buttons
66pub type MouseButtonSet = EnumSet<MouseButton>;
67
68pub fn decode_mouse_button_set(code: u16) -> MouseButtonSet {
69    let mut set = EnumSet::empty();
70
71    // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
72    #[allow(deprecated)]
73    {
74        if code & 0b1 != 0 {
75            set |= MouseButton::Primary;
76        }
77        if code & 0b10 != 0 {
78            set |= MouseButton::Secondary;
79        }
80        if code & 0b100 != 0 {
81            set |= MouseButton::Auxiliary;
82        }
83        if code & 0b1000 != 0 {
84            set |= MouseButton::Fourth;
85        }
86        if code & 0b10000 != 0 {
87            set |= MouseButton::Fifth;
88        }
89        if code & (!0b11111) != 0 {
90            set |= MouseButton::Unknown;
91        }
92    }
93
94    set
95}
96
97pub fn encode_mouse_button_set(set: MouseButtonSet) -> u16 {
98    let mut code = 0;
99
100    // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
101    {
102        if set.contains(MouseButton::Primary) {
103            code |= 0b1;
104        }
105        if set.contains(MouseButton::Secondary) {
106            code |= 0b10;
107        }
108        if set.contains(MouseButton::Auxiliary) {
109            code |= 0b100;
110        }
111        if set.contains(MouseButton::Fourth) {
112            code |= 0b1000;
113        }
114        if set.contains(MouseButton::Fifth) {
115            code |= 0b10000;
116        }
117        if set.contains(MouseButton::Unknown) {
118            code |= 0b100000;
119        }
120    }
121
122    code
123}
124
125pub fn decode_key_location(code: usize) -> Location {
126    match code {
127        0 => Location::Standard,
128        1 => Location::Left,
129        2 => Location::Right,
130        3 => Location::Numpad,
131        // keyboard_types doesn't yet support mobile/joystick locations
132        4 | 5 => Location::Standard,
133        // unknown location; Standard seems better than panicking
134        _ => Location::Standard,
135    }
136}
137
138pub fn encode_key_location(location: Location) -> usize {
139    match location {
140        Location::Standard => 0,
141        Location::Left => 1,
142        Location::Right => 2,
143        Location::Numpad => 3,
144    }
145}