diff --git a/src/key.rs b/src/key.rs index 1ed4f89b2..c4628c846 100644 --- a/src/key.rs +++ b/src/key.rs @@ -44,8 +44,10 @@ impl KeyPath { } /// Adds an item to the KeyPath. - pub fn add_path_item(&mut self, item: u16) { - self.0.insert(1, item).unwrap(); + pub fn append_path_item(&self, item: u16) -> KeyPath { + let mut kp = self.clone(); + kp.0.push(item).unwrap(); + kp } } @@ -127,11 +129,34 @@ impl IntoIterator for KeyEvents { } } +/// Newtype for invoking new_pressed_key on the key at the given [KeyPath]. +#[derive(Debug)] +pub enum NewPressedKey { + /// Invoke new_pressed_key on the key at the given [KeyPath]. + Key(KeyPath), + /// For keys which do nothing when pressed. + NoOp, +} + +impl NewPressedKey { + /// Constructs a NewPressedKey value. + pub fn key_path(key_path: KeyPath) -> Self { + NewPressedKey::Key(key_path) + } + + /// Constructs a NoOp NewPressedKey value. + pub fn no_op() -> Self { + NewPressedKey::NoOp + } +} + /// Pressed Key which may be pending, or a resolved key state. #[derive(Debug)] pub enum PressedKeyResult { /// Unresolved key state. (e.g. tap-hold or chorded keys when first pressed). Pending(KeyPath, PKS), + /// Resolved as a new pressed key. + NewPressedKey(NewPressedKey), /// Resolved key state. Resolved(KS), } @@ -154,11 +179,10 @@ impl PressedKeyResult { } /// Adds an item to the KeyPath if the pressed key result is pending. - pub fn add_path_item(self, item: u16) -> Self { + pub fn append_path_item(self, item: u16) -> Self { match self { - PressedKeyResult::Pending(mut key_path, pks) => { - key_path.add_path_item(item); - PressedKeyResult::Pending(key_path, pks) + PressedKeyResult::Pending(key_path, pks) => { + PressedKeyResult::Pending(key_path.append_path_item(item), pks) } pkr => pkr, } @@ -210,10 +234,7 @@ pub trait Key: Debug { context: &Self::Context, key_path: KeyPath, event: Event, - ) -> ( - Option>, - KeyEvents, - ); + ) -> (Option, KeyEvents); /// Return a reference to the key for the given path. fn lookup( diff --git a/src/key/callback.rs b/src/key/callback.rs index e70abe116..e131aed75 100644 --- a/src/key/callback.rs +++ b/src/key/callback.rs @@ -35,10 +35,10 @@ impl key::Key for Key { key::KeyEvents, ) { let &Key { keymap_callback } = self; - let pks = key::PressedKeyResult::Resolved(key::NoOpKeyState::new().into()); + let pkr = key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp); let km_ev = crate::keymap::KeymapEvent::Callback(keymap_callback); let pke = key::KeyEvents::event(key::Event::Keymap(km_ev)); - (pks, pke) + (pkr, pke) } fn handle_event( @@ -47,10 +47,7 @@ impl key::Key for Key { _context: &Self::Context, _key_path: key::KeyPath, _event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { panic!() } diff --git a/src/key/caps_word.rs b/src/key/caps_word.rs index 0af2a7a51..56c1d568f 100644 --- a/src/key/caps_word.rs +++ b/src/key/caps_word.rs @@ -148,8 +148,8 @@ impl key::Key for Key { let caps_word_context = context.into(); let keymap_index: u16 = key_path.keymap_index(); let pke = self.new_pressed_key(caps_word_context, keymap_index); - let pks = key::PressedKeyResult::Resolved(key::NoOpKeyState::new().into()); - (pks, pke.into_events()) + let pkr = key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp); + (pkr, pke.into_events()) } fn handle_event( @@ -158,10 +158,7 @@ impl key::Key for Key { _context: &Self::Context, _key_path: key::KeyPath, _event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { panic!() } diff --git a/src/key/chorded.rs b/src/key/chorded.rs index f0c6d100b..6cd817235 100644 --- a/src/key/chorded.rs +++ b/src/key/chorded.rs @@ -293,7 +293,6 @@ where K::Event: TryInto, K::Event: From, K::PendingKeyState: From, - K::KeyState: From>, { /// Constructs new pressed key. pub fn new_pressed_key( @@ -320,12 +319,12 @@ where chorded_ctx.config.chords.get(resolved_chord_id as usize) { if resolved_chord_indices.as_slice()[0] == keymap_index { - if let Some((_, k)) = self + if let Some((_, _k)) = self .chords .iter() .find(|(ch_id, _)| *ch_id == resolved_chord_id) { - Some((1 + resolved_chord_id, k)) + Some(1 + resolved_chord_id) } else { panic!("check_resolution has invalid chord id") } @@ -336,15 +335,20 @@ where panic!("check_resolution has invalid chord id") } } - ChordResolution::Passthrough => Some((0, &self.passthrough)), + ChordResolution::Passthrough => Some(0), }; - if let Some((i, k)) = maybe_pathel_key { - let (pkr, pke) = k.new_pressed_key(context, key_path); + if let Some(i) = maybe_pathel_key { // PRESSED KEY PATH: add Chord (0 = passthrough, 1 = 1+chord_id) - (pkr.add_path_item(i as u16), pke) + let new_key_path = key_path.append_path_item(i as u16); + let pkr = key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key_path( + new_key_path, + )); + let pke = key::KeyEvents::no_events(); + + (pkr, pke) } else { - let pkr = key::PressedKeyResult::Resolved(key::NoOpKeyState::new().into()); + let pkr = key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp); let pke = key::KeyEvents::no_events(); (pkr, pke) } @@ -407,10 +411,7 @@ impl< context: &Self::Context, key_path: key::KeyPath, event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { let keymap_index = key_path.keymap_index(); let ch_pks_res: Result<&mut PendingKeyState, _> = pending_state.try_into(); if let Ok(ch_pks) = ch_pks_res { @@ -428,12 +429,12 @@ impl< chorded_ctx.config.chords.get(resolved_chord_id as usize) { if resolved_chord_indices.as_slice()[0] == keymap_index { - if let Some((_, k)) = self + if let Some((_, _k)) = self .chords .iter() .find(|(ch_id, _)| *ch_id == resolved_chord_id) { - Some((1 + resolved_chord_id, k)) + Some(1 + resolved_chord_id) } else { panic!("event's chord resolution has invalid chord id") } @@ -444,7 +445,7 @@ impl< panic!("event's chord resolution has invalid chord id") } } - ChordResolution::Passthrough => Some((0, &self.passthrough)), + ChordResolution::Passthrough => Some(0), }; let ch_r_ev = Event::ChordResolved(ch_state); @@ -453,18 +454,16 @@ impl< ch_r_ev.into(), )); - if let Some((i, nk)) = maybe_pathel_and_key { - let (pkr, mut pke) = nk.new_pressed_key(context, key_path); + if let Some(i) = maybe_pathel_and_key { // PRESSED KEY PATH: add Chord (0 = passthrough, 1 = 1+chord_id) - let pkr = pkr.add_path_item(i as u16); + let new_key_path = key_path.append_path_item(i as u16); - pke.add_event(sch_ev); + let pke = key::KeyEvents::scheduled_event(sch_ev); - (Some(pkr), pke) + (Some(key::NewPressedKey::key_path(new_key_path)), pke) } else { - let pkr = key::PressedKeyResult::Resolved(key::NoOpKeyState::new().into()); let pke = key::KeyEvents::scheduled_event(sch_ev); - (Some(pkr), pke) + (Some(key::NewPressedKey::no_op()), pke) } } else { (None, key::KeyEvents::no_events()) @@ -520,7 +519,6 @@ where K::Event: TryInto, K::Event: From, K::PendingKeyState: From, - K::KeyState: From>, { /// Constructs new pressed key. pub fn new_pressed_key( @@ -539,14 +537,17 @@ where if let PendingChordState::Resolved(resolution) = chord_resolution { match resolution { ChordResolution::Chord(_resolved_chord_id) => { - let pkr = key::PressedKeyResult::Resolved(key::NoOpKeyState::new().into()); + let pkr = key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp); let pke = key::KeyEvents::no_events(); (pkr, pke) } ChordResolution::Passthrough => { - let (pkr, pke) = self.passthrough.new_pressed_key(context, key_path); - let pkr = pkr.add_path_item(0); // 0 = passthrough key + let new_key_path = key_path.append_path_item(0); // 0 = passthrough key + let pkr = key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key_path( + new_key_path, + )); + let pke = key::KeyEvents::no_events(); (pkr, pke) } } @@ -601,42 +602,32 @@ impl< fn handle_event( &self, pending_state: &mut Self::PendingKeyState, - context: &Self::Context, + _context: &Self::Context, key_path: key::KeyPath, event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { let keymap_index = key_path.keymap_index(); let ch_pks_res: Result<&mut PendingKeyState, _> = pending_state.try_into(); if let Ok(ch_pks) = ch_pks_res { if let Ok(ch_ev) = event.try_into_key_event(|e| e.try_into()) { let ch_state = ch_pks.handle_event(keymap_index, ch_ev); if let Some(ChordResolution::Passthrough) = ch_state { - let nk = &self.passthrough; - let (pkr, mut pke) = nk.new_pressed_key(context, key_path); - let pkr = pkr.add_path_item(0); // 0 = passthrough key + let new_key_path = key_path.append_path_item(0); // 0 = passthrough key let ch_r_ev = Event::ChordResolved(ChordResolution::Passthrough); let sch_ev = key::ScheduledEvent::immediate(key::Event::key_event( keymap_index, ch_r_ev.into(), )); - pke.add_event(sch_ev); + let pke = key::KeyEvents::scheduled_event(sch_ev); - (Some(pkr), pke) + (Some(key::NewPressedKey::key_path(new_key_path)), pke) } else if let Some(ChordResolution::Chord(resolved_chord_id)) = ch_state { let ch_r_ev = Event::ChordResolved(ChordResolution::Chord(resolved_chord_id)); let pke = key::KeyEvents::event(key::Event::key_event(keymap_index, ch_r_ev.into())); - ( - Some(key::PressedKeyResult::Resolved( - key::NoOpKeyState::new().into(), - )), - pke, - ) + (Some(key::NewPressedKey::no_op()), pke) } else { (None, key::KeyEvents::no_events()) } diff --git a/src/key/composite/base.rs b/src/key/composite/base.rs index ccfba5c96..5611593f3 100644 --- a/src/key/composite/base.rs +++ b/src/key/composite/base.rs @@ -60,10 +60,7 @@ impl key::Key for BaseKey { _context: &Self::Context, _key_path: key::KeyPath, _event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { panic!() } diff --git a/src/key/composite/chorded.rs b/src/key/composite/chorded.rs index 470c889bb..eb31849ab 100644 --- a/src/key/composite/chorded.rs +++ b/src/key/composite/chorded.rs @@ -66,10 +66,7 @@ impl key::Key for ChordedKey { context: &Self::Context, key_path: key::KeyPath, event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { match self { ChordedKey::Chorded(key) => key.handle_event(pending_state, context, key_path, event), ChordedKey::Auxiliary(key) => key.handle_event(pending_state, context, key_path, event), @@ -115,10 +112,7 @@ impl key::Key for Chorded { context: &Self::Context, key_path: key::KeyPath, event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { let Chorded(key) = self; key.handle_event(pending_state, context, key_path, event) } diff --git a/src/key/composite/layered.rs b/src/key/composite/layered.rs index 5ee8beee9..5b4cf1bf3 100644 --- a/src/key/composite/layered.rs +++ b/src/key/composite/layered.rs @@ -62,10 +62,7 @@ impl key::Key for LayeredKey { context: &Self::Context, key_path: key::KeyPath, event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { match self { LayeredKey::Layered(key) => key.handle_event(pending_state, context, key_path, event), LayeredKey::Pass(key) => key.handle_event(pending_state, context, key_path, event), @@ -109,10 +106,7 @@ impl key::Key for Layered { context: &Self::Context, key_path: key::KeyPath, event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { let Layered(key) = self; key.handle_event(pending_state, context, key_path, event) } diff --git a/src/key/composite/tap_hold.rs b/src/key/composite/tap_hold.rs index b26fb24b6..1d75dfd19 100644 --- a/src/key/composite/tap_hold.rs +++ b/src/key/composite/tap_hold.rs @@ -69,10 +69,7 @@ impl key::Key for TapHoldKey { context: &Self::Context, key_path: key::KeyPath, event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { match self { TapHoldKey::TapDance(key) => key.handle_event(pending_state, context, key_path, event), TapHoldKey::TapHold(key) => key.handle_event(pending_state, context, key_path, event), @@ -118,10 +115,7 @@ impl key::Key for TapHold { context: &Self::Context, key_path: key::KeyPath, event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { let TapHold(key) = self; key.handle_event(pending_state, context, key_path, event) } diff --git a/src/key/custom.rs b/src/key/custom.rs index f78fccc30..feaf28117 100644 --- a/src/key/custom.rs +++ b/src/key/custom.rs @@ -46,10 +46,7 @@ impl key::Key for Key { _context: &Self::Context, _key_path: key::KeyPath, _event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { panic!() } diff --git a/src/key/keyboard.rs b/src/key/keyboard.rs index 3abdf5215..15df0b7ff 100644 --- a/src/key/keyboard.rs +++ b/src/key/keyboard.rs @@ -99,10 +99,7 @@ impl key::Key for Key { _context: &Self::Context, _key_path: key::KeyPath, _event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { panic!() } diff --git a/src/key/layered.rs b/src/key/layered.rs index af441722d..7a9035cbb 100644 --- a/src/key/layered.rs +++ b/src/key/layered.rs @@ -118,10 +118,7 @@ impl key::Key for ModifierKey { _context: &Self::Context, _key_path: key::KeyPath, _event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { panic!() } @@ -373,7 +370,7 @@ where // PRESSED KEY PATH: add Layer (0 = base, n = layer_index) let (pkr, pke) = passthrough_key.new_pressed_key(context, key_path); - (pkr.add_path_item(layer as u16), pke) + (pkr.append_path_item(layer as u16), pke) } } @@ -409,10 +406,7 @@ impl< _context: &Self::Context, _key_path: key::KeyPath, _event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { panic!() } @@ -426,7 +420,7 @@ impl< KeyState = Self::KeyState, > { match path { - [] => panic!(), + [] => self, [0, path @ ..] => self.base.lookup(path), [layer_index, path @ ..] => self.layered[(layer_index - 1) as usize] .as_ref() diff --git a/src/key/sticky.rs b/src/key/sticky.rs index 87e30cd6b..53b50b2ec 100644 --- a/src/key/sticky.rs +++ b/src/key/sticky.rs @@ -280,10 +280,7 @@ impl key::Key for Key { _context: &Self::Context, _key_path: key::KeyPath, _event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { panic!() } diff --git a/src/key/tap_dance.rs b/src/key/tap_dance.rs index fa5cced90..d67064dc6 100644 --- a/src/key/tap_dance.rs +++ b/src/key/tap_dance.rs @@ -120,10 +120,7 @@ impl< context: &Self::Context, key_path: key::KeyPath, event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { let keymap_index = key_path.keymap_index(); let td_pks_res: Result<&mut PendingKeyState, _> = pending_state.try_into(); if let Ok(td_pks) = td_pks_res { @@ -132,24 +129,25 @@ impl< td_pks.handle_event(context.into(), keymap_index, td_ev); if let Some(TapDanceResolution(idx)) = maybe_resolution { - let nk = self.definitions[idx as usize].as_ref().unwrap(); - - let (pkr, pke) = nk.new_pressed_key(context, key_path); // PRESSED KEY PATH: add Tap Dance item (index for the tap-dance definition) - let pkr = pkr.add_path_item(idx as u16); + let new_key_path = key_path.append_path_item(idx as u16); - (Some(pkr), pke) + ( + Some(key::NewPressedKey::key_path(new_key_path)), + pke.into_events(), + ) } else { // check td_pks press_count against key definitions let definition_count = self.definitions.iter().filter(|o| o.is_some()).count(); if td_pks.press_count as usize >= definition_count - 1 { let idx = definition_count - 1; - let nk = self.definitions[idx].as_ref().unwrap(); - let (pkr, pke) = nk.new_pressed_key(context, key_path); // PRESSED KEY PATH: add Tap Dance item (index for the tap-dance definition) - let pkr = pkr.add_path_item(idx as u16); + let new_key_path = key_path.append_path_item(idx as u16); - (Some(pkr), pke) + ( + Some(key::NewPressedKey::key_path(new_key_path)), + pke.into_events(), + ) } else { (None, pke.into_events()) } diff --git a/src/key/tap_hold.rs b/src/key/tap_hold.rs index 8b738f1db..ac4fea44a 100644 --- a/src/key/tap_hold.rs +++ b/src/key/tap_hold.rs @@ -106,7 +106,14 @@ impl Key { } else { // Keymap has not been idle for long enough; // immediately resolve as tap. - self.tap.new_pressed_key(context, key_path) + // PRESSED KEY PATH: add Tap Hold item (0 = tap, 1 = hold) + let tap_key_path = key_path.append_path_item(0); + ( + key::PressedKeyResult::NewPressedKey(key::NewPressedKey::key_path( + tap_key_path, + )), + key::KeyEvents::no_events(), + ) } } None => { @@ -167,25 +174,24 @@ impl< context: &Self::Context, key_path: key::KeyPath, event: key::Event, - ) -> ( - Option>, - key::KeyEvents, - ) { + ) -> (Option, key::KeyEvents) { let keymap_index = key_path.keymap_index(); let th_pks_res: Result<&mut PendingKeyState, _> = pending_state.try_into(); if let Ok(th_pks) = th_pks_res { if let Ok(th_ev) = event.try_into_key_event(|e| e.try_into()) { let th_state = th_pks.handle_event(context.into(), keymap_index, th_ev); if let Some(th_state) = th_state { - let (i, nk) = match th_state { - key::tap_hold::TapHoldState::Tap => (0, &self.tap), - key::tap_hold::TapHoldState::Hold => (1, &self.hold), + let i = match th_state { + key::tap_hold::TapHoldState::Tap => 0, + key::tap_hold::TapHoldState::Hold => 1, }; - let (pkr, pke) = nk.new_pressed_key(context, key_path); // PRESSED KEY PATH: add Tap Hold item (0 = tap, 1 = hold) - let pkr = pkr.add_path_item(i); + let new_key_path = key_path.append_path_item(i); - (Some(pkr), pke) + ( + Some(key::NewPressedKey::key_path(new_key_path)), + key::KeyEvents::no_events(), + ) } else { (None, key::KeyEvents::no_events()) } diff --git a/src/keymap.rs b/src/keymap.rs index 703494425..e4bc2b1da 100644 --- a/src/keymap.rs +++ b/src/keymap.rs @@ -224,6 +224,8 @@ impl< K: key::Key + ?Sized, I: Index, > Keymap +where + KS: From>, { /// Constructs a new keymap with the given key definitions and context. pub const fn new(key_definitions: I, context: Ctx) -> Self { @@ -396,7 +398,7 @@ impl< let pending_key = &self.key_definitions[key_path.keymap_index() as usize]; let pending_key = pending_key.lookup(&key_path[1..]); - let (ks, pke) = pending_key.handle_event( + let (mut maybe_npk, pke) = pending_key.handle_event( pending_key_state, &self.context, key_path.clone(), @@ -406,30 +408,55 @@ impl< pke.into_iter() .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev)); - match ks { - Some(key::PressedKeyResult::Resolved(ks)) => { - self.resolve_pending_key_state(ks); - } - Some(key::PressedKeyResult::Pending(kp, pks)) => { - *key_path = kp; - *pending_key_state = pks; - - // Since the pending key state resolved into another pending key state, - // we re-queue all the input events that had been received. - let orig_input_queue = core::mem::take(&mut self.input_queue); - while let Some(ev) = queued_events.pop() { - match ev { - key::Event::Input(input_ev) => { - self.input_queue.enqueue(input_ev).unwrap(); + while let Some(npk) = maybe_npk.take() { + let pkr = match npk { + key::NewPressedKey::Key(new_key_path) => { + let new_key = &self.key_definitions[new_key_path.keymap_index() as usize]; + let new_key = new_key.lookup(&new_key_path[1..]); + let (pkr, pke) = + new_key.new_pressed_key(&self.context, new_key_path.clone()); + pke.into_iter() + .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev)); + pkr + } + key::NewPressedKey::NoOp => { + let no_op_ks: KS = key::NoOpKeyState::new().into(); + key::PressedKeyResult::Resolved(no_op_ks) + } + }; + + match pkr { + key::PressedKeyResult::Resolved(ks) => { + self.resolve_pending_key_state(ks); + break; + } + key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(new_key_path)) => { + maybe_npk = Some(key::NewPressedKey::Key(new_key_path)); + } + key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => { + self.resolve_pending_key_state(key::NoOpKeyState::new().into()); + break; + } + key::PressedKeyResult::Pending(kp, pks) => { + *key_path = kp; + *pending_key_state = pks; + + // Since the pending key state resolved into another pending key state, + // we re-queue all the input events that had been received. + let orig_input_queue = core::mem::take(&mut self.input_queue); + while let Some(ev) = queued_events.pop() { + match ev { + key::Event::Input(input_ev) => { + self.input_queue.enqueue(input_ev).unwrap(); + } + _ => {} } - _ => {} } + orig_input_queue.iter().for_each(|&ev| { + self.input_queue.enqueue(ev).unwrap(); + }); } - orig_input_queue.iter().for_each(|&ev| { - self.input_queue.enqueue(ev).unwrap(); - }); } - None => {} } } else { // Update each of the pressed keys with the event. @@ -451,35 +478,51 @@ impl< input::Event::Press { keymap_index } if !self.has_pressed_input_with_keymap_index(keymap_index) => { - let key = &self.key_definitions[keymap_index as usize]; - - let key_path = key::key_path(keymap_index); - let (pk, pke) = key.new_pressed_key(&self.context, key_path); - - pke.into_iter() - .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev)); + let mut maybe_key_path = Some(key::key_path(keymap_index)); + + while let Some(key_path) = maybe_key_path.take() { + let key = &self.key_definitions[key_path.keymap_index() as usize] + .lookup(&key_path[1..]); + + let (pkr, pke) = key.new_pressed_key(&self.context, key_path); + + pke.into_iter() + .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev)); + + match pkr { + key::PressedKeyResult::Resolved(key_state) => { + self.pressed_inputs + .push(input::PressedInput::pressed_key(key_state, keymap_index)) + .unwrap(); + + // The resolved key state has output. Emit this as an event. + if let Some(key_output) = key_state.key_output() { + let km_ev = KeymapEvent::ResolvedKeyOutput { + keymap_index, + key_output, + }; + self.handle_event(key::Event::Keymap(km_ev)); + } + } + key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key( + new_key_path, + )) => { + maybe_key_path = Some(new_key_path); + } + key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => { + let key_state: KS = key::NoOpKeyState::new().into(); - match pk { - key::PressedKeyResult::Resolved(key_state) => { - self.pressed_inputs - .push(input::PressedInput::pressed_key(key_state, keymap_index)) - .unwrap(); - - // The resolved key state has output. Emit this as an event. - if let Some(key_output) = key_state.key_output() { - let km_ev = KeymapEvent::ResolvedKeyOutput { - keymap_index, - key_output, - }; - self.handle_event(key::Event::Keymap(km_ev)); + self.pressed_inputs + .push(input::PressedInput::pressed_key(key_state, keymap_index)) + .unwrap(); + } + key::PressedKeyResult::Pending(key_path, pending_key_state) => { + self.pending_key_state = Some(PendingState { + key_path, + pending_key_state, + queued_events: heapless::Vec::new(), + }); } - } - key::PressedKeyResult::Pending(key_path, pending_key_state) => { - self.pending_key_state = Some(PendingState { - key_path, - pending_key_state, - queued_events: heapless::Vec::new(), - }); } } } @@ -540,26 +583,67 @@ impl< if let Some(PendingState { key_path, pending_key_state, + queued_events, .. }) = &mut self.pending_key_state { let pending_key = &self.key_definitions[key_path.keymap_index() as usize]; let pending_key = pending_key.lookup(&key_path[1..]); - let (ks, pke) = + let (mut maybe_npk, pke) = pending_key.handle_event(pending_key_state, &self.context, key_path.clone(), ev); pke.into_iter() .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev)); - match ks { - Some(key::PressedKeyResult::Resolved(ks)) => { - self.resolve_pending_key_state(ks); - } - Some(key::PressedKeyResult::Pending(kp, pks)) => { - *key_path = kp; - *pending_key_state = pks; + while let Some(npk) = maybe_npk.take() { + let pkr = match npk { + key::NewPressedKey::Key(new_key_path) => { + let new_key = &self.key_definitions[new_key_path.keymap_index() as usize]; + let new_key = new_key.lookup(&new_key_path[1..]); + let (pkr, pke) = + new_key.new_pressed_key(&self.context, new_key_path.clone()); + pke.into_iter() + .for_each(|sch_ev| self.event_scheduler.schedule_event(sch_ev)); + pkr + } + key::NewPressedKey::NoOp => { + let no_op_ks: KS = key::NoOpKeyState::new().into(); + key::PressedKeyResult::Resolved(no_op_ks) + } + }; + + match pkr { + key::PressedKeyResult::Resolved(ks) => { + self.resolve_pending_key_state(ks); + break; + } + key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(new_key_path)) => { + maybe_npk = Some(key::NewPressedKey::Key(new_key_path)); + } + key::PressedKeyResult::NewPressedKey(key::NewPressedKey::NoOp) => { + self.resolve_pending_key_state(key::NoOpKeyState::new().into()); + break; + } + key::PressedKeyResult::Pending(kp, pks) => { + *key_path = kp; + *pending_key_state = pks; + + // Since the pending key state resolved into another pending key state, + // we re-queue all the input events that had been received. + let orig_input_queue = core::mem::take(&mut self.input_queue); + while let Some(ev) = queued_events.pop() { + match ev { + key::Event::Input(input_ev) => { + self.input_queue.enqueue(input_ev).unwrap(); + } + _ => {} + } + } + orig_input_queue.iter().for_each(|&ev| { + self.input_queue.enqueue(ev).unwrap(); + }); + } } - None => {} } }