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