1use core::fmt::Debug;
15use core::ops::Index;
16
17use serde::Deserialize;
18
19use crate::input;
20use crate::key;
21use crate::keymap;
22
23const MAX_ACTIVE_SUPPRESS: usize = 4;
25
26#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
28pub struct Ref(pub u8);
29
30#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
32pub struct Key<R> {
33 pub base: R,
35 pub morphed: R,
37 #[serde(rename = "mods")]
39 pub trigger_mods: key::KeyboardModifiers,
40 #[serde(default = "default_keep_mods")]
42 pub keep_mods: key::KeyboardModifiers,
43}
44
45fn default_keep_mods() -> key::KeyboardModifiers {
46 key::KeyboardModifiers::NONE
47}
48
49impl<R> Key<R> {
50 pub const fn new(
52 base: R,
53 morphed: R,
54 trigger_mods: key::KeyboardModifiers,
55 keep_mods: key::KeyboardModifiers,
56 ) -> Self {
57 Self {
58 base,
59 morphed,
60 trigger_mods,
61 keep_mods,
62 }
63 }
64
65 pub const fn suppress_mods(&self) -> key::KeyboardModifiers {
67 self.trigger_mods.difference(&self.keep_mods)
68 }
69}
70
71#[derive(Debug, Clone, Copy, PartialEq)]
73pub enum Event {
74 ActivateSuppress {
76 keymap_index: u16,
78 mask: key::KeyboardModifiers,
80 },
81}
82
83#[derive(Debug, Clone, Copy, PartialEq)]
85struct ActiveSuppress {
86 keymap_index: u16,
87 mask: key::KeyboardModifiers,
88}
89
90#[derive(Debug, Clone, Copy, PartialEq)]
92pub struct Context {
93 pressed_modifiers: key::KeyboardModifiers,
94 active: [ActiveSuppress; MAX_ACTIVE_SUPPRESS],
95 active_count: u8,
96}
97
98impl Default for Context {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104impl Context {
105 pub const fn new() -> Self {
107 Context {
108 pressed_modifiers: key::KeyboardModifiers::NONE,
109 active: [ActiveSuppress {
110 keymap_index: 0,
111 mask: key::KeyboardModifiers::NONE,
112 }; MAX_ACTIVE_SUPPRESS],
113 active_count: 0,
114 }
115 }
116
117 pub fn reset(&mut self) {
119 *self = Self::new();
120 }
121
122 pub const fn pressed_modifiers(&self) -> key::KeyboardModifiers {
124 self.pressed_modifiers
125 }
126
127 pub fn suppressed_modifiers(&self) -> key::KeyboardModifiers {
129 self.active[..self.active_count as usize]
130 .iter()
131 .fold(key::KeyboardModifiers::NONE, |acc, e| acc.union(&e.mask))
132 }
133
134 pub fn update_keymap_context(
136 &mut self,
137 keymap::KeymapContext {
138 pressed_modifiers, ..
139 }: &keymap::KeymapContext,
140 ) {
141 self.pressed_modifiers = *pressed_modifiers;
142 }
143
144 fn push_suppress(&mut self, keymap_index: u16, mask: key::KeyboardModifiers) {
145 if mask == key::KeyboardModifiers::NONE {
146 return;
147 }
148 if let Some(slot) = self.active[..self.active_count as usize]
150 .iter_mut()
151 .find(|e| e.keymap_index == keymap_index)
152 {
153 slot.mask = mask;
154 return;
155 }
156 if (self.active_count as usize) < MAX_ACTIVE_SUPPRESS {
157 self.active[self.active_count as usize] = ActiveSuppress { keymap_index, mask };
158 self.active_count += 1;
159 }
160 }
161
162 fn clear_suppress(&mut self, keymap_index: u16) {
163 let count = self.active_count as usize;
164 if let Some(i) = self.active[..count]
165 .iter()
166 .position(|e| e.keymap_index == keymap_index)
167 {
168 for j in i..(count - 1) {
169 self.active[j] = self.active[j + 1];
170 }
171 self.active_count -= 1;
172 }
173 }
174
175 fn handle_event(&mut self, event: key::Event<Event>) -> key::KeyEvents<Event> {
176 match event {
177 key::Event::Key {
178 key_event: Event::ActivateSuppress { keymap_index, mask },
179 ..
180 } => {
181 self.push_suppress(keymap_index, mask);
182 key::KeyEvents::no_events()
183 }
184 key::Event::Input(input::Event::Release { keymap_index }) => {
185 self.clear_suppress(keymap_index);
186 key::KeyEvents::no_events()
187 }
188 _ => key::KeyEvents::no_events(),
189 }
190 }
191}
192
193impl key::Context for Context {
194 type Event = Event;
195
196 fn handle_event(&mut self, event: key::Event<Self::Event>) -> key::KeyEvents<Self::Event> {
197 self.handle_event(event)
198 }
199
200 fn reset(&mut self) {
201 Context::reset(self);
202 }
203}
204
205#[derive(Debug, Clone, Copy, PartialEq)]
207pub struct PendingKeyState;
208
209#[derive(Debug, Clone, Copy, PartialEq)]
211pub struct KeyState;
212
213#[derive(Debug, Clone, Copy, PartialEq)]
215pub struct System<R, Keys: Index<usize, Output = Key<R>>> {
216 keys: Keys,
217}
218
219impl<R, Keys: Index<usize, Output = Key<R>>> System<R, Keys> {
220 pub const fn new(keys: Keys) -> Self {
222 Self { keys }
223 }
224}
225
226impl<R: Copy + Debug, Keys: Debug + Index<usize, Output = Key<R>>> key::System<R>
227 for System<R, Keys>
228{
229 type Ref = Ref;
230 type Context = Context;
231 type Event = Event;
232 type PendingKeyState = PendingKeyState;
233 type KeyState = KeyState;
234
235 fn new_pressed_key(
236 &self,
237 keymap_index: u16,
238 context: &Self::Context,
239 Ref(key_index): Ref,
240 ) -> (
241 key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
242 key::KeyEvents<Self::Event>,
243 ) {
244 let key = &self.keys[key_index as usize];
245 let morph = context.pressed_modifiers().has_modifiers(&key.trigger_mods);
246
247 if morph {
248 let suppress = key.suppress_mods();
249 let pke = if suppress != key::KeyboardModifiers::NONE {
250 key::KeyEvents::event(key::Event::key_event(
251 keymap_index,
252 Event::ActivateSuppress {
253 keymap_index,
254 mask: suppress,
255 },
256 ))
257 } else {
258 key::KeyEvents::no_events()
259 };
260 (
261 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key(key.morphed)),
262 pke,
263 )
264 } else {
265 (
266 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key(key.base)),
267 key::KeyEvents::no_events(),
268 )
269 }
270 }
271
272 fn update_pending_state(
273 &self,
274 _pending_state: &mut Self::PendingKeyState,
275 _keymap_index: u16,
276 _context: &Self::Context,
277 _key_ref: Ref,
278 _event: key::Event<Self::Event>,
279 ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
280 panic!()
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use super::*;
287 use crate::key::System as _;
288
289 #[test]
290 fn test_sizeof_ref() {
291 assert_eq!(1, core::mem::size_of::<Ref>());
292 }
293
294 #[test]
295 fn morph_when_trigger_mod_held() {
296 let keys = [Key::new(
298 0u8, 1u8, key::KeyboardModifiers::LEFT_SHIFT,
301 key::KeyboardModifiers::NONE,
302 )];
303 let system = System::new(keys);
304 let mut ctx = Context::new();
305 ctx.pressed_modifiers = key::KeyboardModifiers::LEFT_SHIFT;
306
307 let (pkr, pke) = system.new_pressed_key(0, &ctx, Ref(0));
309
310 assert_eq!(
312 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key(1u8)),
313 pkr
314 );
315 assert_eq!(
316 key::KeyEvents::event(key::Event::key_event(
317 0,
318 Event::ActivateSuppress {
319 keymap_index: 0,
320 mask: key::KeyboardModifiers::LEFT_SHIFT,
321 },
322 )),
323 pke
324 );
325 }
326
327 #[test]
328 fn base_when_no_trigger_mod() {
329 let keys = [Key::new(
331 0u8,
332 1u8,
333 key::KeyboardModifiers::LEFT_SHIFT,
334 key::KeyboardModifiers::NONE,
335 )];
336 let system = System::new(keys);
337 let ctx = Context::new();
338
339 let (pkr, pke) = system.new_pressed_key(0, &ctx, Ref(0));
341
342 assert_eq!(
344 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key(0u8)),
345 pkr
346 );
347 assert_eq!(key::KeyEvents::no_events(), pke);
348 }
349
350 #[test]
351 fn keep_mods_reduces_suppress_mask() {
352 let key = Key::new(
353 0u8,
354 1u8,
355 key::KeyboardModifiers::LEFT_SHIFT.union(&key::KeyboardModifiers::RIGHT_SHIFT),
356 key::KeyboardModifiers::RIGHT_SHIFT,
357 );
358 assert_eq!(key::KeyboardModifiers::LEFT_SHIFT, key.suppress_mods());
359 }
360
361 #[test]
362 fn morph_with_keep_mods_emits_reduced_suppress() {
363 let keys = [Key::new(
365 0u8,
366 1u8,
367 key::KeyboardModifiers::LEFT_SHIFT.union(&key::KeyboardModifiers::RIGHT_SHIFT),
368 key::KeyboardModifiers::RIGHT_SHIFT,
369 )];
370 let system = System::new(keys);
371 let mut ctx = Context::new();
372 ctx.pressed_modifiers = key::KeyboardModifiers::LEFT_SHIFT;
374
375 let (pkr, pke) = system.new_pressed_key(0, &ctx, Ref(0));
377
378 assert_eq!(
380 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key(1u8)),
381 pkr
382 );
383 assert_eq!(
384 key::KeyEvents::event(key::Event::key_event(
385 0,
386 Event::ActivateSuppress {
387 keymap_index: 0,
388 mask: key::KeyboardModifiers::LEFT_SHIFT,
389 },
390 )),
391 pke
392 );
393 }
394
395 #[test]
396 fn morph_with_all_keep_mods_emits_no_suppress() {
397 let keys = [Key::new(
399 0u8,
400 1u8,
401 key::KeyboardModifiers::LEFT_SHIFT,
402 key::KeyboardModifiers::LEFT_SHIFT,
403 )];
404 let system = System::new(keys);
405 let mut ctx = Context::new();
406 ctx.pressed_modifiers = key::KeyboardModifiers::LEFT_SHIFT;
407
408 let (pkr, pke) = system.new_pressed_key(0, &ctx, Ref(0));
410
411 assert_eq!(
413 key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key(1u8)),
414 pkr
415 );
416 assert_eq!(key::KeyEvents::no_events(), pke);
417 }
418
419 #[test]
420 fn context_suppress_clears_on_release() {
421 let mut ctx = Context::new();
423
424 let _ = key::Context::handle_event(
426 &mut ctx,
427 key::Event::key_event(
428 3,
429 Event::ActivateSuppress {
430 keymap_index: 3,
431 mask: key::KeyboardModifiers::LEFT_SHIFT,
432 },
433 ),
434 );
435
436 assert_eq!(
438 key::KeyboardModifiers::LEFT_SHIFT,
439 ctx.suppressed_modifiers()
440 );
441
442 let _ = key::Context::handle_event(
444 &mut ctx,
445 key::Event::Input(input::Event::Release { keymap_index: 3 }),
446 );
447
448 assert_eq!(key::KeyboardModifiers::NONE, ctx.suppressed_modifiers());
450 }
451}