hidg_core/
mouse.rs

1use bitflags::bitflags;
2use core::mem::{size_of, transmute};
3use static_assertions::const_assert_eq;
4
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8use crate::{Class, StateChange, ValueChange};
9
10/// Mouse HID class
11#[derive(Clone, Copy, Debug)]
12pub struct Mouse;
13
14impl Class for Mouse {
15    type Input = MouseInput;
16    type Output = MouseOutput;
17
18    fn input(&self) -> Self::Input {
19        Self::Input::default()
20    }
21
22    fn output(&self) -> Self::Output {
23        Self::Output::default()
24    }
25}
26
27impl AsRef<str> for Mouse {
28    fn as_ref(&self) -> &str {
29        "mouse"
30    }
31}
32
33impl core::fmt::Display for Mouse {
34    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
35        f.write_str(self.as_ref())
36    }
37}
38
39bitflags! {
40    /// Button mask
41    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
42    pub struct Buttons: u8 {
43        /// Primary button
44        ///
45        /// Usually left for right hand.
46        const Primary = 0x01;
47
48        /// Secondary button
49        ///
50        /// Usually right for right hand.
51        const Secondary = 0x02;
52
53        /// Tertiary button
54        ///
55        /// Usually middle.
56        const Tertiary = 0x04;
57    }
58}
59
60const_assert_eq!(size_of::<Buttons>(), 1);
61
62impl Default for Buttons {
63    fn default() -> Self {
64        Self::empty()
65    }
66}
67
68impl Buttons {
69    /// Converts from raw value safely
70    pub fn safe_from(raw: u8) -> Option<Self> {
71        Self::from_bits(raw)
72    }
73}
74
75impl From<Buttons> for u8 {
76    fn from(btns: Buttons) -> Self {
77        btns.bits()
78    }
79}
80
81code_enum! {
82    /// Button code
83    Button: u8 {
84        /// No button
85        None = 0x00 => "none" | "0",
86
87        /// Primary button
88        ///
89        /// Usually left for right hand.
90        Primary = 0x01 => "primary" | "first" | "1",
91
92        /// Secondary button
93        ///
94        /// Usually right for right hand.
95        Secondary = 0x02 => "secondary" | "second" | "2",
96
97        /// Tertiary button
98        ///
99        /// Usually middle.
100        Tertiary = 0x03 => "tertiary" | "third" | "3",
101    }
102}
103
104impl From<Buttons> for Button {
105    fn from(mods: Buttons) -> Self {
106        let off = mods.bits().trailing_zeros() as u8;
107        if off < 3 {
108            Button::from(off + 1)
109        } else {
110            Button::None
111        }
112    }
113}
114
115impl From<Button> for Buttons {
116    fn from(key: Button) -> Self {
117        let code = key as u8;
118        Buttons::from_bits_retain(if code != 0 { 1 << (code - 1) } else { 0 })
119    }
120}
121
122impl Button {
123    /// Converts from raw value safely
124    pub fn safe_from(raw: u8) -> Option<Self> {
125        if raw <= 3 {
126            Some(From::from(raw))
127        } else {
128            None
129        }
130    }
131}
132
133impl Default for Button {
134    fn default() -> Self {
135        Self::None
136    }
137}
138
139serde_num! {
140    Buttons: u8, "a button mask";
141    Button: u8, "a numeric button code";
142}
143
144/// Mouse input report
145#[derive(Clone, Copy, Debug, Default)]
146#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
147#[repr(C, packed)]
148pub struct MouseInput {
149    /// Pressed buttons
150    #[cfg_attr(feature = "serde", serde(rename = "b"))]
151    button: Buttons,
152    /// Pointer coordinates
153    #[cfg_attr(feature = "serde", serde(rename = "p"))]
154    pointer: (i16, i16),
155    /// Mouse wheel coordinate
156    #[cfg_attr(feature = "serde", serde(rename = "w"))]
157    wheel: i8,
158}
159
160const_assert_eq!(size_of::<MouseInput>(), 6);
161
162impl MouseInput {
163    /// Get button mask
164    pub fn mods(&self) -> Buttons {
165        self.button
166    }
167
168    /// Get number of pressed buttons
169    pub fn count_pressed(&self) -> usize {
170        self.button.bits().count_ones() as _
171    }
172
173    /// Get iterator over pressed buttons
174    pub fn pressed(&self) -> PressedButtons<'_> {
175        PressedButtons {
176            report: self,
177            element: 0,
178        }
179    }
180
181    /// Press or release buttons
182    pub fn change_buttons(&mut self, mask: Buttons, state: bool) {
183        if state {
184            self.button |= mask;
185        } else {
186            self.button &= !mask;
187        }
188    }
189
190    /// Press buttons
191    pub fn press_buttons(&mut self, mask: Buttons) {
192        self.change_buttons(mask, true);
193    }
194
195    /// Release buttons
196    pub fn release_buttons(&mut self, mask: Buttons) {
197        self.change_buttons(mask, false);
198    }
199
200    /// Press or release button
201    pub fn change_button(&mut self, code: Button, state: bool) {
202        self.change_buttons(code.into(), state);
203    }
204
205    /// Press button
206    pub fn press_button(&mut self, code: Button) {
207        self.change_button(code, true);
208    }
209
210    /// Release button
211    pub fn release_button(&mut self, code: Button) {
212        self.change_button(code, false);
213    }
214
215    /// Get XY coordinates
216    pub fn pointer(&self) -> (i16, i16) {
217        self.pointer
218    }
219
220    /// Set XY coordinates
221    pub fn set_pointer(&mut self, pointer: (i16, i16)) {
222        self.pointer = pointer;
223    }
224
225    /// Change XY coordinates
226    pub fn change_pointer(&mut self, pointer: (i16, i16), relative: bool) {
227        if relative {
228            self.pointer = (self.pointer.0 + pointer.0, self.pointer.1 + pointer.1);
229        } else {
230            self.pointer = pointer;
231        }
232    }
233
234    /// Get wheel value
235    pub fn wheel(&self) -> i8 {
236        self.wheel
237    }
238
239    /// Set wheel value
240    pub fn set_wheel(&mut self, wheel: i8) {
241        self.wheel = wheel;
242    }
243
244    /// Change wheel value
245    pub fn change_wheel(&mut self, wheel: i8, relative: bool) {
246        if relative {
247            self.wheel += wheel;
248        } else {
249            self.wheel = wheel;
250        }
251    }
252
253    /// Change mouse input
254    pub fn change(&mut self, change: &MouseInputChange) {
255        match change {
256            MouseInputChange::Button(change) => self.change_button(**change, change.state()),
257            MouseInputChange::Pointer(change) => {
258                self.change_pointer(**change, change.is_relative())
259            }
260            MouseInputChange::Wheel(change) => self.change_wheel(**change, change.is_relative()),
261        }
262    }
263
264    /// Get changes between two reports
265    ///
266    /// Difference of two reports
267    pub fn diff<'i>(
268        &'i self,
269        other: &'i Self,
270        relative_pointer: bool,
271        relative_wheel: bool,
272    ) -> MouseInputChanges<'i> {
273        MouseInputChanges {
274            new: self,
275            old: other,
276            element: 0,
277            relative_pointer,
278            relative_wheel,
279        }
280    }
281}
282
283impl<'i> core::ops::Sub<&'i MouseInput> for &'i MouseInput {
284    type Output = MouseInputChanges<'i>;
285
286    fn sub(self, other: Self) -> Self::Output {
287        self.diff(other, false, false)
288    }
289}
290
291/// Change between mouse input reports
292#[derive(Clone, Copy, Debug, PartialEq, Eq)]
293pub enum MouseInputChange {
294    /// Button state change
295    Button(StateChange<Button>),
296    /// Pointer coordinates change
297    Pointer(ValueChange<(i16, i16)>),
298    /// Wheel value change
299    Wheel(ValueChange<i8>),
300}
301
302/// Changes between mouse input reports
303pub struct MouseInputChanges<'i> {
304    new: &'i MouseInput,
305    old: &'i MouseInput,
306    element: u8,
307    relative_pointer: bool,
308    relative_wheel: bool,
309}
310
311impl<'i> Iterator for MouseInputChanges<'i> {
312    type Item = MouseInputChange;
313
314    fn next(&mut self) -> Option<Self::Item> {
315        loop {
316            if self.element < 8 {
317                // find changed buttons
318                let buttons = Buttons::from_bits_retain(1 << self.element);
319                self.element += 1;
320                if Buttons::empty() != ((self.new.button ^ self.old.button) & buttons) {
321                    let button = Button::from(buttons);
322                    let old_button = Button::from(self.old.button & buttons);
323                    return Some(MouseInputChange::Button(StateChange::new(
324                        button,
325                        matches!(old_button, Button::None),
326                    )));
327                }
328            } else if self.element < 9 {
329                // changed pointer coords
330                self.element += 1;
331                if self.new.pointer.0 != self.old.pointer.0
332                    || self.new.pointer.1 != self.old.pointer.1
333                {
334                    return Some(MouseInputChange::Pointer(ValueChange::new(
335                        if self.relative_pointer {
336                            (
337                                self.new.pointer.0 - self.old.pointer.0,
338                                self.new.pointer.1 - self.old.pointer.1,
339                            )
340                        } else {
341                            (self.new.pointer.0, self.new.pointer.1)
342                        },
343                        self.relative_pointer,
344                    )));
345                }
346            } else if self.element < 10 {
347                self.element += 1;
348                if self.new.wheel != self.old.wheel {
349                    return Some(MouseInputChange::Wheel(ValueChange::new(
350                        if self.relative_wheel {
351                            self.new.wheel - self.old.wheel
352                        } else {
353                            self.new.wheel
354                        },
355                        self.relative_wheel,
356                    )));
357                }
358            } else {
359                return None;
360            }
361        }
362    }
363}
364
365impl Extend<StateChange<Buttons>> for MouseInput {
366    fn extend<T>(&mut self, iter: T)
367    where
368        T: IntoIterator<Item = StateChange<Buttons>>,
369    {
370        for StateChange { data, state } in iter {
371            self.change_buttons(data, state);
372        }
373    }
374}
375
376impl Extend<StateChange<Button>> for MouseInput {
377    fn extend<T>(&mut self, iter: T)
378    where
379        T: IntoIterator<Item = StateChange<Button>>,
380    {
381        for StateChange { data, state } in iter {
382            self.change_button(data, state);
383        }
384    }
385}
386
387impl Extend<ValueChange<(i16, i16)>> for MouseInput {
388    fn extend<T>(&mut self, iter: T)
389    where
390        T: IntoIterator<Item = ValueChange<(i16, i16)>>,
391    {
392        for ValueChange { data, relative } in iter {
393            self.change_pointer(data, relative);
394        }
395    }
396}
397
398impl Extend<(i16, i16)> for MouseInput {
399    fn extend<T>(&mut self, iter: T)
400    where
401        T: IntoIterator<Item = (i16, i16)>,
402    {
403        for data in iter {
404            self.set_pointer(data);
405        }
406    }
407}
408
409impl Extend<ValueChange<i8>> for MouseInput {
410    fn extend<T>(&mut self, iter: T)
411    where
412        T: IntoIterator<Item = ValueChange<i8>>,
413    {
414        for ValueChange { data, relative } in iter {
415            self.change_wheel(data, relative)
416        }
417    }
418}
419
420impl Extend<MouseInput> for MouseInput {
421    fn extend<T>(&mut self, iter: T)
422    where
423        T: IntoIterator<Item = MouseInput>,
424    {
425        for item in iter {
426            *self = item;
427        }
428    }
429}
430
431/// An iterator over pressed buttons
432pub struct PressedButtons<'i> {
433    report: &'i MouseInput,
434    element: u8,
435}
436
437impl<'i> Iterator for PressedButtons<'i> {
438    type Item = Button;
439
440    fn next(&mut self) -> Option<Self::Item> {
441        while self.element < 8 {
442            let mask = Buttons::from_bits_retain(1u8 << self.element);
443            self.element += 1;
444            if self.report.button.contains(mask) {
445                return Some(mask.into());
446            }
447        }
448        None
449    }
450}
451
452/// Keyboard output report
453#[derive(Clone, Copy, Debug, Default)]
454#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
455#[repr(C, packed)]
456pub struct MouseOutput {}
457
458const_assert_eq!(size_of::<MouseOutput>(), 0);
459
460raw_ref! {
461    Buttons;
462    Button;
463    MouseInput;
464    MouseOutput;
465}
466
467#[cfg(test)]
468mod test {
469    use super::*;
470
471    #[test]
472    fn button_mask_to_code() {
473        assert_eq!(Button::from(Buttons::default()), Button::None);
474        assert_eq!(Button::from(Buttons::empty()), Button::None);
475        assert_eq!(Button::from(Buttons::Primary), Button::Primary);
476        assert_eq!(Button::from(Buttons::Secondary), Button::Secondary);
477        assert_eq!(Button::from(Buttons::Tertiary), Button::Tertiary);
478    }
479
480    #[test]
481    fn button_code_to_mask() {
482        assert_eq!(Buttons::from(Button::None), Buttons::default());
483        assert_eq!(Buttons::from(Button::Primary), Buttons::Primary);
484        assert_eq!(Buttons::from(Button::Secondary), Buttons::Secondary);
485        assert_eq!(Buttons::from(Button::Tertiary), Buttons::Tertiary);
486    }
487
488    #[test]
489    fn mouse_input_diff() {
490        let mut old = MouseInput::default();
491
492        old.press_button(Button::Primary);
493        old.press_button(Button::Tertiary);
494        old.set_pointer((120, 450));
495        old.set_wheel(7);
496
497        let mut new = MouseInput::default();
498
499        new.press_button(Button::Tertiary);
500        new.press_button(Button::Secondary);
501        new.set_pointer((120, 150));
502        new.set_wheel(-1);
503
504        let mut changes = &new - &old;
505
506        assert_eq!(
507            changes.next(),
508            Some(MouseInputChange::Button(StateChange::release(
509                Button::Primary
510            )))
511        );
512        assert_eq!(
513            changes.next(),
514            Some(MouseInputChange::Button(StateChange::press(
515                Button::Secondary
516            )))
517        );
518        assert_eq!(
519            changes.next(),
520            Some(MouseInputChange::Pointer(ValueChange::new(
521                (120, 150),
522                false
523            )))
524        );
525        assert_eq!(
526            changes.next(),
527            Some(MouseInputChange::Wheel(ValueChange::new(-1, false)))
528        );
529        assert_eq!(changes.next(), None);
530
531        new.release_button(Button::Secondary);
532        new.set_wheel(7);
533
534        let mut changes = new.diff(&old, true, true);
535
536        assert_eq!(
537            changes.next(),
538            Some(MouseInputChange::Button(StateChange::release(
539                Button::Primary
540            )))
541        );
542        assert_eq!(
543            changes.next(),
544            Some(MouseInputChange::Pointer(ValueChange::new((0, -300), true)))
545        );
546        assert_eq!(changes.next(), None);
547    }
548}