Skip to main content

smart_keymap_core/key/
mouse.rs

1use core::fmt::Debug;
2use core::marker::PhantomData;
3use core::ops::Index;
4
5use serde::Deserialize;
6
7use crate::key;
8
9/// Mouse action (button, cursor movement, or wheel).
10#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
11pub enum Action {
12    /// A mouse button. (Value is button number, 1-8).
13    Button(u8),
14    /// Move cursor left.
15    CursorLeft,
16    /// Move cursor right.
17    CursorRight,
18    /// Move cursor up.
19    CursorUp,
20    /// Move cursor down.
21    CursorDown,
22    /// Scroll wheel up.
23    WheelUp,
24    /// Scroll wheel down.
25    WheelDown,
26    /// Scroll wheel left.
27    WheelLeft,
28    /// Scroll wheel right.
29    WheelRight,
30}
31
32/// Reference for a mouse key.
33///
34/// Simple actions without keyboard modifiers
35///  are represented directly as [Ref::Action].
36/// Keys that include keyboard modifiers
37///  are an index into [System] key data.
38#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
39pub enum Ref {
40    /// A mouse action without keyboard modifiers.
41    Action(Action),
42    /// Index into the key data array of [System] for a [Key] (action + modifiers).
43    Key(u8),
44}
45
46/// A mouse key: an [Action] with optional keyboard modifiers.
47///
48/// A modifiers value of zero is equivalent to no modifiers.
49#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
50pub struct Key {
51    /// The mouse action.
52    pub action: Action,
53    /// Keyboard modifiers.
54    #[serde(default)]
55    pub modifiers: key::KeyboardModifiers,
56}
57
58impl Key {
59    /// Constructs a key with the given action and no modifiers.
60    pub const fn new(action: Action) -> Self {
61        Self {
62            action,
63            modifiers: key::KeyboardModifiers::new(),
64        }
65    }
66
67    /// Constructs a key with the given action and modifiers.
68    pub const fn new_with_modifiers(action: Action, modifiers: key::KeyboardModifiers) -> Self {
69        Self { action, modifiers }
70    }
71}
72
73/// Context for mouse keys. (No context).
74#[derive(Debug, Clone, Copy, PartialEq)]
75pub struct Context;
76
77impl Context {
78    /// No runtime state to clear.
79    pub fn reset(&mut self) {}
80}
81
82/// The event type for mouse keys. (No events).
83#[derive(Debug, Clone, Copy, PartialEq)]
84pub struct Event;
85
86/// The pending key state type for mouse keys. (No pending state).
87#[derive(Debug, Clone, Copy, PartialEq)]
88pub struct PendingKeyState;
89
90/// Key state used by [System].
91#[derive(Debug, Clone, Copy, PartialEq)]
92pub struct KeyState;
93
94/// The [key::System] implementation for mouse keys.
95#[derive(Debug, Clone, Copy, PartialEq)]
96pub struct System<R: Debug, Keys: Index<usize, Output = Key>> {
97    keys: Keys,
98    marker: PhantomData<R>,
99}
100
101impl<R: Debug, Keys: Index<usize, Output = Key>> System<R, Keys> {
102    /// Constructs a new [System] with the given key data.
103    ///
104    /// The key data is for mouse keys that include keyboard modifiers.
105    pub const fn new(keys: Keys) -> Self {
106        Self {
107            keys,
108            marker: PhantomData,
109        }
110    }
111}
112
113fn mouse_output_for_action(action: Action) -> key::MouseOutput {
114    const MOVE_AMOUNT: i8 = 5;
115    match action {
116        Action::Button(b) => key::MouseOutput {
117            pressed_buttons: 1 << (b - 1),
118            ..key::MouseOutput::NO_OUTPUT
119        },
120        Action::CursorLeft => key::MouseOutput {
121            x: -MOVE_AMOUNT,
122            ..key::MouseOutput::NO_OUTPUT
123        },
124        Action::CursorRight => key::MouseOutput {
125            x: MOVE_AMOUNT,
126            ..key::MouseOutput::NO_OUTPUT
127        },
128        Action::CursorUp => key::MouseOutput {
129            y: -MOVE_AMOUNT,
130            ..key::MouseOutput::NO_OUTPUT
131        },
132        Action::CursorDown => key::MouseOutput {
133            y: MOVE_AMOUNT,
134            ..key::MouseOutput::NO_OUTPUT
135        },
136        Action::WheelUp => key::MouseOutput {
137            vertical_scroll: 1,
138            ..key::MouseOutput::NO_OUTPUT
139        },
140        Action::WheelDown => key::MouseOutput {
141            vertical_scroll: -1,
142            ..key::MouseOutput::NO_OUTPUT
143        },
144        Action::WheelLeft => key::MouseOutput {
145            horizontal_scroll: -1,
146            ..key::MouseOutput::NO_OUTPUT
147        },
148        Action::WheelRight => key::MouseOutput {
149            horizontal_scroll: 1,
150            ..key::MouseOutput::NO_OUTPUT
151        },
152    }
153}
154
155impl<R: Debug, Keys: Debug + Index<usize, Output = Key>> key::System<R> for System<R, Keys> {
156    type Ref = Ref;
157    type Context = Context;
158    type Event = Event;
159    type PendingKeyState = PendingKeyState;
160    type KeyState = KeyState;
161
162    fn new_pressed_key(
163        &self,
164        _keymap_index: u16,
165        _context: &Self::Context,
166        _key_ref: Ref,
167    ) -> (
168        key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
169        key::KeyEvents<Self::Event>,
170    ) {
171        (
172            key::PressedKeyResult::Resolved(KeyState),
173            key::KeyEvents::no_events(),
174        )
175    }
176
177    fn update_pending_state(
178        &self,
179        _pending_state: &mut Self::PendingKeyState,
180        _keymap_index: u16,
181        _context: &Self::Context,
182        _key_ref: Ref,
183        _event: key::Event<Self::Event>,
184    ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
185        panic!()
186    }
187
188    fn update_state(
189        &self,
190        _key_state: &mut Self::KeyState,
191        _ref: &Self::Ref,
192        _context: &Self::Context,
193        _keymap_index: u16,
194        _event: key::Event<Self::Event>,
195    ) -> key::KeyEvents<Self::Event> {
196        key::KeyEvents::no_events()
197    }
198
199    fn key_output(
200        &self,
201        key_ref: &Self::Ref,
202        _key_state: &Self::KeyState,
203    ) -> Option<key::KeyOutput> {
204        match key_ref {
205            Ref::Action(action) => Some(key::KeyOutput::from_mouse_output(
206                mouse_output_for_action(*action),
207            )),
208            Ref::Key(idx) => {
209                let Key { action, modifiers } = self.keys[*idx as usize];
210                Some(key::KeyOutput::from_usage_with_modifiers(
211                    key::KeyUsage::Mouse(mouse_output_for_action(action)),
212                    modifiers,
213                ))
214            }
215        }
216    }
217}
218
219#[cfg(test)]
220mod tests {
221    use super::*;
222
223    #[test]
224    fn test_sizeof_ref() {
225        // Action(Action) niches with Key(u8): still 2 bytes.
226        assert_eq!(2, core::mem::size_of::<Ref>());
227    }
228
229    #[test]
230    fn test_sizeof_event() {
231        assert_eq!(0, core::mem::size_of::<Event>());
232    }
233}