1#![doc = include_str!("doc_de_composite.md")]
5
6use core::fmt::Debug;
7
8#[cfg(feature = "std")]
9use serde::Deserialize;
10
11use crate::{key, keymap};
12
13mod base;
14mod chorded;
15mod layered;
16mod tap_hold;
17
18pub use base::BaseKey;
19pub use chorded::{Chorded, ChordedKey, ChordedNestable};
20pub use layered::{Layered, LayeredKey, LayeredNestable};
21pub use tap_hold::{TapHold, TapHoldKey, TapHoldNestable};
22
23pub type Key = ChordedKey<LayeredKey<TapHoldKey<BaseKey>>>;
37
38pub type PressedKeyResult = key::PressedKeyResult<PendingKeyState, KeyState>;
40
41#[derive(Debug, Clone, Copy, PartialEq)]
43#[cfg_attr(feature = "std", derive(Deserialize))]
44pub struct Config {
45 #[cfg_attr(feature = "std", serde(default))]
47 pub chorded: key::chorded::Config,
48 #[cfg_attr(feature = "std", serde(default))]
50 pub sticky: key::sticky::Config,
51 #[cfg_attr(feature = "std", serde(default))]
53 pub tap_dance: key::tap_dance::Config,
54 #[cfg_attr(feature = "std", serde(default))]
56 pub tap_hold: key::tap_hold::Config,
57}
58
59pub const DEFAULT_CONFIG: Config = Config {
61 chorded: key::chorded::DEFAULT_CONFIG,
62 sticky: key::sticky::DEFAULT_CONFIG,
63 tap_dance: key::tap_dance::DEFAULT_CONFIG,
64 tap_hold: key::tap_hold::DEFAULT_CONFIG,
65};
66
67#[derive(Debug, Clone, Copy)]
69pub struct Context {
70 keymap_context: keymap::KeymapContext,
71 caps_word_context: key::caps_word::Context,
72 chorded_context: key::chorded::Context,
73 layer_context: key::layered::Context,
74 tap_dance_context: key::tap_dance::Context,
75 tap_hold_context: key::tap_hold::Context,
76 sticky_context: key::sticky::Context,
77}
78
79pub const DEFAULT_CONTEXT: Context = Context {
81 keymap_context: keymap::DEFAULT_KEYMAP_CONTEXT,
82 caps_word_context: key::caps_word::DEFAULT_CONTEXT,
83 chorded_context: key::chorded::DEFAULT_CONTEXT,
84 layer_context: key::layered::DEFAULT_CONTEXT,
85 sticky_context: key::sticky::DEFAULT_CONTEXT,
86 tap_dance_context: key::tap_dance::DEFAULT_CONTEXT,
87 tap_hold_context: key::tap_hold::DEFAULT_CONTEXT,
88};
89
90impl Context {
91 pub const fn from_config(config: Config) -> Self {
93 Self {
94 chorded_context: key::chorded::Context::from_config(config.chorded),
95 sticky_context: key::sticky::Context::from_config(config.sticky),
96 tap_dance_context: key::tap_dance::Context::from_config(config.tap_dance),
97 tap_hold_context: key::tap_hold::Context::from_config(config.tap_hold),
98 ..DEFAULT_CONTEXT
99 }
100 }
101}
102
103impl Default for Context {
104 fn default() -> Self {
106 DEFAULT_CONTEXT
107 }
108}
109
110impl key::Context for Context {
111 type Event = Event;
112 fn handle_event(&mut self, event: key::Event<Self::Event>) -> key::KeyEvents<Self::Event> {
113 let mut pke = key::KeyEvents::no_events();
114
115 let caps_word_ev = self.caps_word_context.handle_event(event);
116 pke.extend(caps_word_ev);
117
118 if let Ok(e) = event.try_into_key_event(|e| e.try_into()) {
119 let sticky_ev = self.sticky_context.handle_event(e);
120 pke.extend(sticky_ev.into_events());
121 }
122
123 if let Ok(e) = event.try_into_key_event(|e| e.try_into()) {
124 self.chorded_context.handle_event(e);
125 }
126
127 if let key::Event::Key {
128 key_event: Event::LayerModification(ev),
129 ..
130 } = event
131 {
132 self.layer_context.handle_event(ev);
133 }
134
135 pke
136 }
137}
138
139impl keymap::SetKeymapContext for Context {
140 fn set_keymap_context(&mut self, context: keymap::KeymapContext) {
141 self.keymap_context = context;
142 }
143}
144
145impl<'c> From<&'c Context> for &'c keymap::KeymapContext {
146 fn from(ctx: &'c Context) -> Self {
147 &ctx.keymap_context
148 }
149}
150
151impl<'c> From<&'c Context> for &'c key::caps_word::Context {
152 fn from(ctx: &'c Context) -> Self {
153 &ctx.caps_word_context
154 }
155}
156
157impl<'c> From<&'c Context> for &'c key::chorded::Context {
158 fn from(ctx: &'c Context) -> Self {
159 &ctx.chorded_context
160 }
161}
162
163impl<'c> From<&'c Context> for &'c key::layered::Context {
164 fn from(ctx: &'c Context) -> Self {
165 &ctx.layer_context
166 }
167}
168
169impl<'c> From<&'c Context> for &'c key::sticky::Context {
170 fn from(ctx: &'c Context) -> Self {
171 &ctx.sticky_context
172 }
173}
174
175impl<'c> From<&'c Context> for &'c key::tap_dance::Context {
176 fn from(ctx: &'c Context) -> Self {
177 &ctx.tap_dance_context
178 }
179}
180
181impl<'c> From<&'c Context> for &'c key::tap_hold::Context {
182 fn from(ctx: &'c Context) -> Self {
183 &ctx.tap_hold_context
184 }
185}
186
187#[derive(Debug, Clone, Copy, PartialEq)]
189pub enum Event {
190 CapsWord(key::caps_word::Event),
192 Chorded(key::chorded::Event),
194 Sticky(key::sticky::Event),
196 TapDance(key::tap_dance::Event),
198 TapHold(key::tap_hold::Event),
200 LayerModification(key::layered::LayerEvent),
202}
203
204impl From<key::caps_word::Event> for Event {
205 fn from(ev: key::caps_word::Event) -> Self {
206 Event::CapsWord(ev)
207 }
208}
209
210impl From<key::chorded::Event> for Event {
211 fn from(ev: key::chorded::Event) -> Self {
212 Event::Chorded(ev)
213 }
214}
215
216impl From<key::layered::LayerEvent> for Event {
217 fn from(ev: key::layered::LayerEvent) -> Self {
218 Event::LayerModification(ev)
219 }
220}
221
222impl From<key::sticky::Event> for Event {
223 fn from(ev: key::sticky::Event) -> Self {
224 Event::Sticky(ev)
225 }
226}
227
228impl From<key::tap_dance::Event> for Event {
229 fn from(ev: key::tap_dance::Event) -> Self {
230 Event::TapDance(ev)
231 }
232}
233
234impl From<key::tap_hold::Event> for Event {
235 fn from(ev: key::tap_hold::Event) -> Self {
236 Event::TapHold(ev)
237 }
238}
239
240impl TryFrom<Event> for key::caps_word::Event {
241 type Error = key::EventError;
242
243 fn try_from(ev: Event) -> Result<Self, Self::Error> {
244 match ev {
245 Event::CapsWord(ev) => Ok(ev),
246 _ => Err(key::EventError::UnmappableEvent),
247 }
248 }
249}
250
251impl TryFrom<Event> for key::chorded::Event {
252 type Error = key::EventError;
253
254 fn try_from(ev: Event) -> Result<Self, Self::Error> {
255 match ev {
256 Event::Chorded(ev) => Ok(ev),
257 _ => Err(key::EventError::UnmappableEvent),
258 }
259 }
260}
261
262impl TryFrom<Event> for key::layered::LayerEvent {
263 type Error = key::EventError;
264
265 fn try_from(ev: Event) -> Result<Self, Self::Error> {
266 match ev {
267 Event::LayerModification(ev) => Ok(ev),
268 _ => Err(key::EventError::UnmappableEvent),
269 }
270 }
271}
272
273impl TryFrom<Event> for key::sticky::Event {
274 type Error = key::EventError;
275
276 fn try_from(ev: Event) -> Result<Self, Self::Error> {
277 match ev {
278 Event::Sticky(ev) => Ok(ev),
279 _ => Err(key::EventError::UnmappableEvent),
280 }
281 }
282}
283
284impl TryFrom<Event> for key::tap_dance::Event {
285 type Error = key::EventError;
286
287 fn try_from(ev: Event) -> Result<Self, Self::Error> {
288 match ev {
289 Event::TapDance(ev) => Ok(ev),
290 _ => Err(key::EventError::UnmappableEvent),
291 }
292 }
293}
294
295impl TryFrom<Event> for key::tap_hold::Event {
296 type Error = key::EventError;
297
298 fn try_from(ev: Event) -> Result<Self, Self::Error> {
299 match ev {
300 Event::TapHold(ev) => Ok(ev),
301 _ => Err(key::EventError::UnmappableEvent),
302 }
303 }
304}
305
306#[derive(Debug, Clone, PartialEq)]
308pub enum PendingKeyState {
309 TapDance(key::tap_dance::PendingKeyState),
311 TapHold(key::tap_hold::PendingKeyState),
313 Chorded(key::chorded::PendingKeyState),
315}
316
317impl From<key::tap_dance::PendingKeyState> for PendingKeyState {
318 fn from(pks: key::tap_dance::PendingKeyState) -> Self {
319 PendingKeyState::TapDance(pks)
320 }
321}
322
323impl From<key::tap_hold::PendingKeyState> for PendingKeyState {
324 fn from(pks: key::tap_hold::PendingKeyState) -> Self {
325 PendingKeyState::TapHold(pks)
326 }
327}
328
329impl From<key::chorded::PendingKeyState> for PendingKeyState {
330 fn from(pks: key::chorded::PendingKeyState) -> Self {
331 PendingKeyState::Chorded(pks)
332 }
333}
334
335impl<'pks> TryFrom<&'pks mut PendingKeyState> for &'pks mut key::tap_dance::PendingKeyState {
336 type Error = ();
337
338 fn try_from(pks: &'pks mut PendingKeyState) -> Result<Self, Self::Error> {
339 match pks {
340 PendingKeyState::TapDance(pks) => Ok(pks),
341 _ => Err(()),
342 }
343 }
344}
345
346impl<'pks> TryFrom<&'pks mut PendingKeyState> for &'pks mut key::tap_hold::PendingKeyState {
347 type Error = ();
348
349 fn try_from(pks: &'pks mut PendingKeyState) -> Result<Self, Self::Error> {
350 match pks {
351 PendingKeyState::TapHold(pks) => Ok(pks),
352 _ => Err(()),
353 }
354 }
355}
356
357impl<'pks> TryFrom<&'pks mut PendingKeyState> for &'pks mut key::chorded::PendingKeyState {
358 type Error = ();
359
360 fn try_from(pks: &'pks mut PendingKeyState) -> Result<Self, Self::Error> {
361 match pks {
362 PendingKeyState::Chorded(pks) => Ok(pks),
363 _ => Err(()),
364 }
365 }
366}
367
368#[derive(Debug, Clone, Copy, PartialEq)]
370pub enum KeyState {
371 NoOp, Keyboard(key::keyboard::KeyState),
375 LayerModifier(key::layered::ModifierKeyState),
377 Sticky(key::sticky::KeyState),
379 Custom(key::custom::KeyState),
381}
382
383impl From<key::NoOpKeyState<Context, Event>> for KeyState {
384 fn from(_: key::NoOpKeyState<Context, Event>) -> Self {
385 KeyState::NoOp
386 }
387}
388
389impl From<key::keyboard::KeyState> for KeyState {
390 fn from(ks: key::keyboard::KeyState) -> Self {
391 KeyState::Keyboard(ks)
392 }
393}
394
395impl From<key::layered::ModifierKeyState> for KeyState {
396 fn from(ks: key::layered::ModifierKeyState) -> Self {
397 KeyState::LayerModifier(ks)
398 }
399}
400
401impl From<key::sticky::KeyState> for KeyState {
402 fn from(ks: key::sticky::KeyState) -> Self {
403 KeyState::Sticky(ks)
404 }
405}
406
407impl From<key::custom::KeyState> for KeyState {
408 fn from(ks: key::custom::KeyState) -> Self {
409 KeyState::Custom(ks)
410 }
411}
412
413impl key::KeyState for KeyState {
414 type Context = Context;
415 type Event = Event;
416
417 fn handle_event(
418 &mut self,
419 context: &Self::Context,
420 keymap_index: u16,
421 event: key::Event<Self::Event>,
422 ) -> key::KeyEvents<Self::Event> {
423 match self {
424 KeyState::Keyboard(_) => key::KeyEvents::no_events(),
425 KeyState::LayerModifier(ks) => {
426 if let Ok(ev) = event.try_into_key_event(|e| e.try_into()) {
427 let l_ev = ks.handle_event(keymap_index, ev);
428 if let Some(l_ev) = l_ev {
429 let c_ev = Event::LayerModification(l_ev);
430 key::KeyEvents::event(key::Event::key_event(keymap_index, c_ev))
431 } else {
432 key::KeyEvents::no_events()
433 }
434 } else {
435 key::KeyEvents::no_events()
436 }
437 }
438 KeyState::Sticky(ks) => {
439 if let Ok(ev) = event.try_into_key_event(|e| e.try_into()) {
440 let ctx = context.into();
441 let ke = ks.handle_event(ctx, keymap_index, ev);
442 ke.into_events()
443 } else {
444 key::KeyEvents::no_events()
445 }
446 }
447 KeyState::NoOp => key::KeyEvents::no_events(),
448 KeyState::Custom(_) => key::KeyEvents::no_events(),
449 }
450 }
451
452 fn key_output(&self) -> Option<key::KeyOutput> {
453 match self {
454 KeyState::Keyboard(ks) => Some(ks.key_output()),
455 KeyState::LayerModifier(_) => None,
456 KeyState::Sticky(ks) => ks.key_output(),
457 KeyState::NoOp => None,
458 KeyState::Custom(ks) => Some(ks.key_output()),
459 }
460 }
461}
462
463#[cfg(test)]
464mod tests {
465 use super::*;
466
467 #[test]
468 fn test_composite_pressedkey_layerpressedmodifier_handles_release_event() {
469 use crate::input;
470 use key::{composite, Key, KeyState};
471
472 type Ctx = composite::Context;
474 type K = composite::Key;
475 let keymap_index: u16 = 0;
476 let key_path = key::key_path(keymap_index);
477 let key = K::layer_modifier(key::layered::ModifierKey::Hold(1));
478 let context: Ctx = DEFAULT_CONTEXT;
479 let (pressed_lmod_key, _) = key.new_pressed_key(&context, key_path);
480
481 let events = pressed_lmod_key.unwrap_resolved().handle_event(
483 &context,
484 keymap_index,
485 key::Event::Input(input::Event::Release { keymap_index }),
486 );
487
488 let _key_ev = match events.into_iter().next().map(|sch_ev| sch_ev.event) {
490 Some(key::Event::Key {
491 key_event:
492 Event::LayerModification(key::layered::LayerEvent::LayerDeactivated(layer_index)),
493 ..
494 }) => {
495 assert_eq!(1, layer_index);
496 }
497 _ => panic!("Expected an Event::Key(LayerModification(LayerDeactivated(layer)))"),
498 };
499 }
500
501 #[test]
502 fn test_composite_context_updates_with_composite_layermodifier_press_event() {
503 use key::{composite, Context, Key};
504
505 type Ctx = composite::Context;
507 type K = composite::Key;
508 let keys: [K; 2] = [
509 K::layer_modifier(key::layered::ModifierKey::Hold(1)),
510 K::layered(key::layered::LayeredKey::new(
511 key::keyboard::Key::new(0x04).into(),
512 [Some(key::keyboard::Key::new(0x05).into())],
513 )),
514 ];
515 let mut context: Ctx = DEFAULT_CONTEXT;
516 let keymap_index: u16 = 0;
517 let key_path = key::key_path(keymap_index);
518 let (_pressed_key, pressed_key_events) =
519 keys[keymap_index as usize].new_pressed_key(&context, key_path);
520 let maybe_ev = pressed_key_events.into_iter().next();
521
522 let event = match maybe_ev {
524 Some(key::ScheduledEvent { event, .. }) => event,
525 _ => panic!("Expected Some(ScheduledEvent(Event::Key(_)))"),
526 };
527 context.handle_event(event);
528 let actual_active_layers = context.layer_context.layer_state();
529
530 let expected_active_layers = &[true];
532 assert_eq!(expected_active_layers[0..1], actual_active_layers[0..1]);
533 }
534
535 #[test]
536 fn test_composite_context_updates_with_composite_layerpressedmodifier_release_event() {
537 use crate::input;
538 use key::{composite, Context, Key, KeyState};
539
540 type Ctx = composite::Context;
542 type K = composite::Key;
543 let keys: [K; 2] = [
544 K::layer_modifier(key::layered::ModifierKey::Hold(1)),
545 K::layered(key::layered::LayeredKey::new(
546 key::keyboard::Key::new(0x04).into(),
547 [Some(key::keyboard::Key::new(0x05).into())],
548 )),
549 ];
550 let mut context: Ctx = DEFAULT_CONTEXT;
551 let keymap_index: u16 = 0;
552 let key_path = key::key_path(keymap_index);
553 let (pressed_lmod_key, _) = keys[keymap_index as usize].new_pressed_key(&context, key_path);
554 context.layer_context.activate_layer(1);
555 let events = pressed_lmod_key.unwrap_resolved().handle_event(
556 &context,
557 0,
558 key::Event::Input(input::Event::Release { keymap_index: 0 }),
559 );
560 let key_ev = match events.into_iter().next().map(|sch_ev| sch_ev.event) {
561 Some(key_event) => key_event,
562 _ => panic!("Expected an Event::Key(_)"),
563 };
564
565 context.handle_event(key_ev);
567 let actual_active_layers = context.layer_context.layer_state();
568
569 let expected_active_layers = &[false];
571 assert_eq!(expected_active_layers[0..1], actual_active_layers[0..1]);
572 }
573
574 #[test]
575 fn test_composite_keyboard_pressed_key_has_key_code_for_composite_keyboard_key_def() {
576 use key::{composite, Key, KeyState};
577
578 type Ctx = composite::Context;
580 type K = composite::Key;
581 let keys: [K; 3] = [
582 K::layer_modifier(key::layered::ModifierKey::Hold(1)),
583 K::layered(key::layered::LayeredKey::new(
584 key::keyboard::Key::new(0x04).into(),
585 [Some(key::keyboard::Key::new(0x05).into())],
586 )),
587 K::keyboard(key::keyboard::Key::new(0x06)),
588 ];
589 let context: Ctx = DEFAULT_CONTEXT;
590
591 let keymap_index: u16 = 2;
593 let key_path = key::key_path(keymap_index);
594 let (pressed_key, _) = keys[keymap_index as usize].new_pressed_key(&context, key_path);
595 let actual_keycode = pressed_key.unwrap_resolved().key_output();
596
597 let expected_keycode = Some(key::KeyOutput::from_key_code(0x06));
599 assert_eq!(expected_keycode, actual_keycode);
600 }
601
602 #[test]
603 fn test_composite_keyboard_pressed_key_has_key_code_for_composite_layered_key_def() {
604 use key::{composite, Key, KeyState};
605
606 type Ctx = composite::Context;
608 type K = composite::Key;
609 let keys: [K; 3] = [
610 K::layer_modifier(key::layered::ModifierKey::Hold(1)),
611 K::layered(key::layered::LayeredKey::new(
612 key::keyboard::Key::new(0x04).into(),
613 [Some(key::keyboard::Key::new(0x05).into())],
614 )),
615 K::keyboard(key::keyboard::Key::new(0x06)),
616 ];
617 let context: Ctx = DEFAULT_CONTEXT;
618
619 let keymap_index: u16 = 1;
621 let key_path = key::key_path(keymap_index);
622 let (pressed_key, _) = keys[keymap_index as usize].new_pressed_key(&context, key_path);
623 let actual_keycode = pressed_key.unwrap_resolved().key_output();
624
625 let expected_keycode = Some(key::KeyOutput::from_key_code(0x04));
627 assert_eq!(expected_keycode, actual_keycode);
628 }
629}