1use core::fmt::Debug;
2use core::marker::Copy;
3use core::marker::PhantomData;
4use core::ops::Index;
5
6use serde::Deserialize;
7
8use crate::input;
9use crate::key;
10use crate::keymap;
11
12#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
14pub struct Ref(pub u8);
15
16#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
18pub enum StickyKeyActivation {
19 OnStickyKeyRelease,
21 }
25
26#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
28pub enum StickyKeyRelease {
29 OnModifiedKeyRelease,
31 OnNextKeyPress,
33}
34
35#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
37pub struct Config {
38 #[serde(default = "default_activation")]
40 pub activation: StickyKeyActivation,
41 #[serde(default = "default_release")]
43 pub release: StickyKeyRelease,
44}
45
46pub const DEFAULT_ACTIVATION: StickyKeyActivation = StickyKeyActivation::OnStickyKeyRelease;
48
49pub const DEFAULT_RELEASE: StickyKeyRelease = StickyKeyRelease::OnModifiedKeyRelease;
51
52fn default_activation() -> StickyKeyActivation {
53 DEFAULT_ACTIVATION
54}
55
56fn default_release() -> StickyKeyRelease {
57 DEFAULT_RELEASE
58}
59
60pub const DEFAULT_CONFIG: Config = Config {
62 activation: DEFAULT_ACTIVATION,
63 release: DEFAULT_RELEASE,
64};
65
66impl Config {
67 pub const fn new() -> Self {
69 DEFAULT_CONFIG
70 }
71}
72
73impl Default for Config {
74 fn default() -> Self {
76 Self::new()
77 }
78}
79
80const MAX_STICKY_MODIFIERS: u8 = 4;
81
82struct ActiveModifiersDebugHelper<'a> {
83 active_modifiers: &'a [key::KeyboardModifiers; MAX_STICKY_MODIFIERS as usize],
84}
85
86impl core::fmt::Debug for ActiveModifiersDebugHelper<'_> {
87 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
88 let last_active_pos = self
90 .active_modifiers
91 .iter()
92 .rposition(|&pc| pc != key::KeyboardModifiers::NONE)
93 .map_or(0, |pos| pos + 1);
94 if last_active_pos < MAX_STICKY_MODIFIERS as usize {
95 f.debug_list()
96 .entries(&self.active_modifiers[..last_active_pos])
97 .finish_non_exhaustive()
98 } else {
99 f.debug_list().entries(&self.active_modifiers[..]).finish()
100 }
101 }
102}
103
104#[derive(Clone, Copy)]
106pub struct Context {
107 pub config: Config,
109 pub active_modifiers: [key::KeyboardModifiers; MAX_STICKY_MODIFIERS as usize],
111 pub active_modifier_count: u8,
113 pub pressed_keymap_index: Option<u16>,
115}
116
117impl core::fmt::Debug for Context {
118 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
119 f.debug_struct("Context")
120 .field("config", &self.config)
121 .field(
122 "active_modifiers",
123 &ActiveModifiersDebugHelper {
124 active_modifiers: &self.active_modifiers,
125 },
126 )
127 .field("active_modifier_count", &self.active_modifier_count)
128 .field("pressed_keymap_index", &self.pressed_keymap_index)
129 .finish()
130 }
131}
132
133impl Context {
134 pub const fn from_config(config: Config) -> Context {
136 Context {
137 config,
138 active_modifiers: [key::KeyboardModifiers::NONE; MAX_STICKY_MODIFIERS as usize],
139 active_modifier_count: 0,
140 pressed_keymap_index: None,
141 }
142 }
143
144 pub fn reset(&mut self) {
146 *self = Self::from_config(self.config);
147 }
148
149 fn handle_event(&mut self, event: key::Event<Event>) -> key::KeyEvents<Event> {
151 match (self.active_modifier_count, event) {
178 (
181 0,
182 key::Event::Key {
183 key_event: Event::ActivateModifiers(mods),
184 ..
185 },
186 ) => {
187 self.active_modifiers[0] = mods;
188 self.active_modifier_count = 1;
189
190 key::KeyEvents::no_events()
191 }
192 (
195 active_modifier_count,
196 key::Event::Key {
197 key_event: Event::ActivateModifiers(mods),
198 ..
199 },
200 ) => {
201 if active_modifier_count < MAX_STICKY_MODIFIERS {
202 self.active_modifiers[active_modifier_count as usize] = mods;
203 self.active_modifier_count += 1;
204 }
205
206 key::KeyEvents::no_events()
207 }
208 (
212 active_modifier_count,
213 key::Event::Keymap(keymap::KeymapEvent::ResolvedKeyOutput { keymap_index, .. }),
214 ) if active_modifier_count > 0 => {
215 let pke = key::KeyEvents::no_events();
216
217 self.pressed_keymap_index = Some(keymap_index);
222
223 pke
228 }
229 (
232 active_modifier_count,
233 key::Event::Input(input::Event::Release {
234 keymap_index: ev_kmi,
235 }),
236 ) if Some(ev_kmi) == self.pressed_keymap_index && active_modifier_count > 0 => {
237 let mut pke = key::KeyEvents::no_events();
239
240 self.active_modifiers[..active_modifier_count as usize]
241 .iter()
242 .for_each(|&m| {
243 let sticky_key_output = key::KeyOutput::from_key_modifiers(m);
244 let vk_ev = key::Event::Input(input::Event::VirtualKeyRelease {
245 key_output: sticky_key_output,
246 });
247 pke.add_event(key::ScheduledEvent::immediate(vk_ev));
248 });
249
250 self.active_modifier_count = 0;
251 self.pressed_keymap_index = None;
252
253 pke
254 }
255 (active_modifier_count, key::Event::Input(input::Event::Press { .. }))
260 if self.pressed_keymap_index.is_some()
261 && self.config.release == StickyKeyRelease::OnNextKeyPress =>
262 {
263 let mut pke = key::KeyEvents::no_events();
266
267 self.active_modifiers[..active_modifier_count as usize]
268 .iter()
269 .for_each(|&m| {
270 let sticky_key_output = key::KeyOutput::from_key_modifiers(m);
271 let vk_ev = key::Event::Input(input::Event::VirtualKeyRelease {
272 key_output: sticky_key_output,
273 });
274 pke.add_event(key::ScheduledEvent::immediate(vk_ev));
275 });
276
277 self.active_modifier_count = 0;
278 self.pressed_keymap_index = None;
279
280 pke
281 }
282 _ => key::KeyEvents::no_events(),
283 }
284 }
285}
286
287impl key::Context for Context {
288 type Event = Event;
289
290 fn handle_event(&mut self, event: key::Event<Self::Event>) -> key::KeyEvents<Self::Event> {
291 self.handle_event(event)
292 }
293
294 fn reset(&mut self) {
295 Context::reset(self);
296 }
297}
298
299#[derive(Debug, Clone, Copy, PartialEq)]
301pub enum Event {
302 ActivateModifiers(key::KeyboardModifiers),
304}
305
306#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
308pub struct Key {
309 pub sticky_modifiers: key::KeyboardModifiers,
311}
312
313impl Key {
314 pub const fn new(sticky_modifiers: key::KeyboardModifiers) -> Self {
316 Key { sticky_modifiers }
317 }
318
319 pub fn new_pressed_key(&self) -> KeyState {
321 KeyState::new()
322 }
323}
324
325#[derive(Debug, Clone, Copy, PartialEq)]
327pub struct PendingKeyState;
328
329#[derive(Debug, Clone, Copy, Eq, PartialEq)]
331pub enum Behavior {
332 Sticky,
334 Regular,
336}
337
338#[derive(Debug, Clone, Copy, PartialEq)]
340pub struct KeyState {
341 behavior: Behavior,
342}
343
344impl KeyState {
345 pub fn new() -> Self {
347 KeyState {
348 behavior: Behavior::Sticky,
349 }
350 }
351}
352
353impl Default for KeyState {
354 fn default() -> Self {
356 Self::new()
357 }
358}
359
360impl KeyState {
361 pub fn update_state(
363 &mut self,
364 key: &Key,
365 context: &Context,
366 keymap_index: u16,
367 event: key::Event<Event>,
368 ) -> key::KeyEvents<Event> {
369 match self.behavior {
374 Behavior::Sticky => match event {
375 key::Event::Keymap(keymap::KeymapEvent::ResolvedKeyOutput { .. }) => {
376 self.behavior = Behavior::Regular;
379
380 key::KeyEvents::no_events()
381 }
382 key::Event::Input(input::Event::Release {
383 keymap_index: released_index,
384 }) if released_index == keymap_index => {
385 match context.config.activation {
387 StickyKeyActivation::OnStickyKeyRelease => {
388 let sticky_ev = Event::ActivateModifiers(key.sticky_modifiers);
389 let k_ev = key::Event::key_event(keymap_index, sticky_ev);
390
391 let sticky_key_output =
392 key::KeyOutput::from_key_modifiers(key.sticky_modifiers);
393 let vk_ev = key::Event::Input(input::Event::VirtualKeyPress {
394 key_output: sticky_key_output,
395 });
396
397 let mut pke = key::KeyEvents::event(k_ev);
398 pke.add_event(key::ScheduledEvent::immediate(vk_ev));
399 pke
400 }
401 }
402 }
403 _ => key::KeyEvents::no_events(),
404 },
405 Behavior::Regular => key::KeyEvents::no_events(),
406 }
407 }
408
409 pub fn key_output(&self, key: &Key) -> Option<key::KeyOutput> {
411 match self.behavior {
412 Behavior::Sticky => None,
413 Behavior::Regular => Some(key::KeyOutput::from_key_modifiers(key.sticky_modifiers)),
414 }
415 }
416}
417
418#[derive(Debug, Clone, Copy, PartialEq)]
420pub struct System<R, Keys: Index<usize, Output = Key>> {
421 keys: Keys,
422 marker: PhantomData<R>,
423}
424
425impl<R, Keys: Index<usize, Output = Key>> System<R, Keys> {
426 pub const fn new(keys: Keys) -> Self {
428 Self {
429 keys,
430 marker: PhantomData,
431 }
432 }
433}
434
435impl<R: Debug, Keys: Debug + Index<usize, Output = Key>> key::System<R> for System<R, Keys> {
436 type Ref = Ref;
437 type Context = Context;
438 type Event = Event;
439 type PendingKeyState = PendingKeyState;
440 type KeyState = KeyState;
441
442 fn new_pressed_key(
443 &self,
444 _keymap_index: u16,
445 _context: &Self::Context,
446 Ref(key_index): Ref,
447 ) -> (
448 key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
449 key::KeyEvents<Self::Event>,
450 ) {
451 let key = &self.keys[key_index as usize];
452 let ks = key.new_pressed_key();
453 let pks = key::PressedKeyResult::Resolved(ks);
454 let pke = key::KeyEvents::no_events();
455 (pks, pke)
456 }
457
458 fn update_pending_state(
459 &self,
460 _pending_state: &mut Self::PendingKeyState,
461 _keymap_index: u16,
462 _context: &Self::Context,
463 _key_ref: Ref,
464 _event: key::Event<Self::Event>,
465 ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
466 panic!()
467 }
468
469 fn update_state(
470 &self,
471 key_state: &mut Self::KeyState,
472 Ref(key_index): &Self::Ref,
473 context: &Self::Context,
474 keymap_index: u16,
475 event: key::Event<Self::Event>,
476 ) -> key::KeyEvents<Self::Event> {
477 let key = &self.keys[*key_index as usize];
478 key_state.update_state(key, context, keymap_index, event)
479 }
480
481 fn key_output(
482 &self,
483 Ref(key_index): &Self::Ref,
484 key_state: &Self::KeyState,
485 ) -> Option<key::KeyOutput> {
486 let key = &self.keys[*key_index as usize];
487 key_state.key_output(key)
488 }
489}
490
491#[cfg(test)]
492mod tests {
493 use super::*;
494
495 #[test]
496 fn test_sizeof_ref() {
497 assert_eq!(1, core::mem::size_of::<Ref>());
498 }
499
500 #[test]
501 fn test_sizeof_event() {
502 assert_eq!(1, core::mem::size_of::<Event>());
503 }
504}