1use core::fmt::Debug;
21use core::marker::PhantomData;
22use core::ops::Index;
23
24use serde::Deserialize;
25
26use crate::input;
27use crate::key;
28use crate::keymap;
29
30#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
32pub struct Ref(pub u8);
33
34#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
36pub struct Key {
37 pub hold: key::KeyOutput,
39 pub tap: key::KeyOutput,
41}
42
43impl Key {
44 pub const fn new(hold: key::KeyOutput, tap: key::KeyOutput) -> Self {
46 Self { hold, tap }
47 }
48}
49
50#[derive(Debug, Clone, Copy, PartialEq)]
52struct Session {
53 keymap_index: u16,
54 hold: key::KeyOutput,
55 tap: key::KeyOutput,
56 tap_held: bool,
57}
58
59#[derive(Debug, Clone, Copy, PartialEq)]
61pub struct Context {
62 session: Option<Session>,
63}
64
65impl Default for Context {
66 fn default() -> Self {
67 Self::new()
68 }
69}
70
71impl Context {
72 pub const fn new() -> Self {
74 Context { session: None }
75 }
76
77 pub fn reset(&mut self) {
79 *self = Self::new();
80 }
81
82 pub fn is_active(&self) -> bool {
84 self.session.is_some()
85 }
86
87 pub fn is_session_for(&self, keymap_index: u16) -> bool {
89 matches!(self.session, Some(s) if s.keymap_index == keymap_index)
90 }
91
92 fn end_session(&mut self) -> key::KeyEvents<Event> {
93 match self.session.take() {
94 None => key::KeyEvents::no_events(),
95 Some(session) => {
96 let mut pke = key::KeyEvents::no_events();
97 if session.tap_held {
98 pke.add_event(key::Event::Input(input::Event::VirtualKeyRelease {
99 key_output: session.tap,
100 }));
101 }
102 pke.add_event(key::Event::Input(input::Event::VirtualKeyRelease {
103 key_output: session.hold,
104 }));
105 pke
106 }
107 }
108 }
109
110 fn handle_event(&mut self, event: key::Event<Event>) -> key::KeyEvents<Event> {
111 match event {
112 key::Event::Key {
113 keymap_index,
114 key_event: Event::Start { hold, tap },
115 } => {
116 let mut pke = self.end_session();
117 self.session = Some(Session {
118 keymap_index,
119 hold,
120 tap,
121 tap_held: true,
122 });
123 pke.add_event(key::Event::Input(input::Event::VirtualKeyPress {
124 key_output: hold,
125 }));
126 pke.add_event(key::Event::Input(input::Event::VirtualKeyPress {
127 key_output: tap,
128 }));
129 pke
130 }
131 key::Event::Key {
132 keymap_index,
133 key_event: Event::Continue,
134 } => match self.session.as_mut() {
135 Some(session) if session.keymap_index == keymap_index => {
136 session.tap_held = true;
137 key::KeyEvents::event(key::Event::Input(input::Event::VirtualKeyPress {
138 key_output: session.tap,
139 }))
140 }
141 _ => key::KeyEvents::no_events(),
142 },
143 key::Event::Input(input::Event::Release { keymap_index }) => {
144 match self.session.as_mut() {
145 Some(session) if session.keymap_index == keymap_index && session.tap_held => {
146 session.tap_held = false;
147 key::KeyEvents::event(key::Event::Input(input::Event::VirtualKeyRelease {
148 key_output: session.tap,
149 }))
150 }
151 _ => key::KeyEvents::no_events(),
152 }
153 }
154 key::Event::Keymap(keymap::KeymapEvent::ResolvedKeyOutput { keymap_index, .. }) => {
155 match self.session {
156 Some(session) if session.keymap_index != keymap_index => self.end_session(),
157 _ => key::KeyEvents::no_events(),
158 }
159 }
160 _ => key::KeyEvents::no_events(),
161 }
162 }
163}
164
165impl key::Context for Context {
166 type Event = Event;
167
168 fn handle_event(&mut self, event: key::Event<Self::Event>) -> key::KeyEvents<Self::Event> {
169 self.handle_event(event)
170 }
171
172 fn reset(&mut self) {
173 Context::reset(self);
174 }
175}
176
177#[derive(Debug, Clone, Copy, PartialEq)]
179pub enum Event {
180 Start {
182 hold: key::KeyOutput,
184 tap: key::KeyOutput,
186 },
187 Continue,
189}
190
191#[derive(Debug, Clone, Copy, PartialEq)]
193pub struct PendingKeyState;
194
195#[derive(Debug, Clone, Copy, PartialEq)]
197pub struct KeyState;
198
199#[derive(Debug, Clone, Copy, PartialEq)]
201pub struct System<R, Keys: Index<usize, Output = Key>> {
202 keys: Keys,
203 marker: PhantomData<R>,
204}
205
206impl<R, Keys: Index<usize, Output = Key>> System<R, Keys> {
207 pub const fn new(keys: Keys) -> Self {
209 Self {
210 keys,
211 marker: PhantomData,
212 }
213 }
214}
215
216impl<R: Debug, Keys: Debug + Index<usize, Output = Key>> key::System<R> for System<R, Keys> {
217 type Ref = Ref;
218 type Context = Context;
219 type Event = Event;
220 type PendingKeyState = PendingKeyState;
221 type KeyState = KeyState;
222
223 fn new_pressed_key(
224 &self,
225 keymap_index: u16,
226 context: &Self::Context,
227 Ref(key_index): Ref,
228 ) -> (
229 key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
230 key::KeyEvents<Self::Event>,
231 ) {
232 let Key { hold, tap } = self.keys[key_index as usize];
233 let key_event = if context.is_session_for(keymap_index) {
234 Event::Continue
235 } else {
236 Event::Start { hold, tap }
237 };
238 let pkr = key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp);
239 let pke = key::KeyEvents::event(key::Event::key_event(keymap_index, key_event));
240 (pkr, pke)
241 }
242
243 fn update_pending_state(
244 &self,
245 _pending_state: &mut Self::PendingKeyState,
246 _keymap_index: u16,
247 _context: &Self::Context,
248 _key_ref: Ref,
249 _event: key::Event<Self::Event>,
250 ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
251 panic!()
252 }
253
254 fn update_state(
255 &self,
256 _key_state: &mut Self::KeyState,
257 _ref: &Self::Ref,
258 _context: &Self::Context,
259 _keymap_index: u16,
260 _event: key::Event<Self::Event>,
261 ) -> key::KeyEvents<Self::Event> {
262 panic!()
263 }
264
265 fn key_output(
266 &self,
267 _key_ref: &Self::Ref,
268 _key_state: &Self::KeyState,
269 ) -> Option<key::KeyOutput> {
270 panic!()
271 }
272}
273
274#[cfg(test)]
275mod tests {
276 use super::*;
277
278 #[test]
279 fn test_sizeof_ref() {
280 assert_eq!(1, core::mem::size_of::<Ref>());
281 }
282
283 #[test]
284 fn test_sizeof_event() {
285 assert_eq!(14, core::mem::size_of::<Event>());
286 }
287
288 #[test]
289 fn start_arms_session() {
290 let mut ctx = Context::new();
291 let hold = key::KeyOutput::from_key_code(0xE2);
292 let tap = key::KeyOutput::from_key_code(0x2B);
293 let _ = key::Context::handle_event(
294 &mut ctx,
295 key::Event::key_event(0, Event::Start { hold, tap }),
296 );
297 assert!(ctx.is_active());
298 assert!(ctx.is_session_for(0));
299 }
300
301 #[test]
302 fn other_resolved_output_ends_session() {
303 let mut ctx = Context::new();
304 let hold = key::KeyOutput::from_key_code(0xE2);
305 let tap = key::KeyOutput::from_key_code(0x2B);
306 let _ = key::Context::handle_event(
307 &mut ctx,
308 key::Event::key_event(0, Event::Start { hold, tap }),
309 );
310 let _ = key::Context::handle_event(
311 &mut ctx,
312 key::Event::Keymap(keymap::KeymapEvent::ResolvedKeyOutput {
313 keymap_index: 1,
314 key_output: key::KeyOutput::from_key_code(0x04),
315 }),
316 );
317 assert!(!ctx.is_active());
318 }
319
320 #[test]
321 fn own_resolved_output_does_not_end_session() {
322 let mut ctx = Context::new();
323 let hold = key::KeyOutput::from_key_code(0xE2);
324 let tap = key::KeyOutput::from_key_code(0x2B);
325 let _ = key::Context::handle_event(
326 &mut ctx,
327 key::Event::key_event(0, Event::Start { hold, tap }),
328 );
329 let _ = key::Context::handle_event(
330 &mut ctx,
331 key::Event::Keymap(keymap::KeymapEvent::ResolvedKeyOutput {
332 keymap_index: 0,
333 key_output: tap,
334 }),
335 );
336 assert!(ctx.is_active());
337 }
338}