diff --git a/src/action.rs b/src/action.rs index 97f94f6..df222be 100644 --- a/src/action.rs +++ b/src/action.rs @@ -184,6 +184,21 @@ where Trans, /// A key code, i.e. a classic key. KeyCode(K), + /// TOOD document + ModifiedKeyCode( + &'static ( + // The modifiers to be applied to the key code. Unlike with + // MultipleKeyCodes, these modifiers will be released right after + // pressing and re-pressed before releasing the key. This ensures + // modifiers are not incorrectly applied to other keys that might be + // pressed while a modified key is still being held down, e.g. when + // rolling "&[". With MultipleKeyCodes, that would result in "&{", + // because the shift modifier is applied to "[" as well. + &'static [K], + // A key code, i.e. a classic key. + K, + ), + ), /// Multiple key codes sent at the same time, as if these keys /// were pressed at the same time. Useful to send a shifted key, /// or complex shortcuts like Ctrl+Alt+Del in a single key press. diff --git a/src/layout.rs b/src/layout.rs index 69d474e..8903659 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -179,9 +179,23 @@ impl CustomEvent { #[derive(Debug, Eq, PartialEq)] enum State { - NormalKey { keycode: K, coord: (u8, u8) }, - LayerModifier { value: usize, coord: (u8, u8) }, - Custom { value: &'static T, coord: (u8, u8) }, + NormalKey { + keycode: K, + coord: (u8, u8), + }, + ModifiedKey { + modifiers: &'static [K], + keycode: K, + coord: (u8, u8), + }, + LayerModifier { + value: usize, + coord: (u8, u8), + }, + Custom { + value: &'static T, + coord: (u8, u8), + }, } impl Copy for State {} impl Clone for State { @@ -194,6 +208,7 @@ impl State { fn keycode(&self) -> Option { match self { NormalKey { keycode, .. } => Some(*keycode), + ModifiedKey { keycode, .. } => Some(*keycode), _ => None, } } @@ -202,7 +217,11 @@ impl State { } fn release(&self, c: (u8, u8), custom: &mut CustomEvent) -> Option { match *self { - NormalKey { coord, .. } | LayerModifier { coord, .. } if coord == c => None, + NormalKey { coord, .. } | ModifiedKey { coord, .. } | LayerModifier { coord, .. } + if coord == c => + { + None + } Custom { value, coord } if coord == c => { custom.update(CustomEvent::Release(value)); None @@ -351,7 +370,14 @@ impl impl Iterator + '_ { - self.states.iter().filter_map(State::keycode) + let additional_modifiers = match self.states.last() { + Some(ModifiedKey { modifiers, .. }) => *modifiers, + _ => &[], + }; + self.states + .iter() + .filter_map(State::keycode) + .chain(additional_modifiers.iter().copied()) } fn waiting_into_hold(&mut self) -> CustomEvent { if let Some(w) = &self.waiting { @@ -489,6 +515,14 @@ impl { + self.tap_hold_tracker.coord = coord; + let _ = self.states.push(ModifiedKey { + coord, + modifiers, + keycode, + }); + } &MultipleKeyCodes(v) => { self.tap_hold_tracker.coord = coord; for &keycode in *v {