Skip to content

Commit b56de4f

Browse files
committed
Added support for Sequence Actions (aka macros) whereby multiple key events are executed in succession.
1 parent c1fd84f commit b56de4f

2 files changed

Lines changed: 110 additions & 3 deletions

File tree

src/action.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
1-
//! The different actions that can be done.
1+
//! The different actions that can be executed via any given key.
22
33
use crate::key_code::KeyCode;
44

5+
/// The different types of actions we support for key macros
6+
#[non_exhaustive]
7+
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
8+
pub enum SequenceEvent {
9+
/// A keypress/keydown
10+
Press(KeyCode),
11+
/// Key release/keyup
12+
Release(KeyCode),
13+
/// Combination quick keydown followed by keyrelease
14+
Tap(KeyCode),
15+
/// Release all (currently) pressed keys
16+
ReleaseAll(),
17+
}
18+
519
/// The different actions that can be done.
620
#[non_exhaustive]
721
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
@@ -41,6 +55,13 @@ pub enum Action {
4155
/// The tap action.
4256
tap: &'static Action,
4357
},
58+
/// A sequence of KeyEvents
59+
Sequence {
60+
/// How long to delay between events
61+
delay: u16, // NOTE: Currently unused
62+
/// The sequence of KeyEvents that will be triggered
63+
actions: &'static [SequenceEvent],
64+
},
4465
}
4566
impl Action {
4667
/// Gets the layer number if the action is the `Layer` action.
@@ -55,6 +76,7 @@ impl Action {
5576
match self {
5677
Action::KeyCode(kc) => core::slice::from_ref(kc).iter().cloned(),
5778
Action::MultipleKeyCodes(kcs) => kcs.iter().cloned(),
79+
// Action::Sequence { delay, actions } => actions.iter().cloned(), // TODO (maybe unnecessary)
5880
_ => [].iter().cloned(),
5981
}
6082
}
@@ -78,8 +100,33 @@ pub const fn d(layer: usize) -> Action {
78100
Action::DefaultLayer(layer)
79101
}
80102

81-
/// A shortcut to create a `Action::KeyCode`, useful to create compact
103+
/// A shortcut to create `Action::MultipleKeyCodes`, useful to create compact
82104
/// layout.
83105
pub const fn m(kcs: &'static [KeyCode]) -> Action {
84106
Action::MultipleKeyCodes(kcs)
85107
}
108+
109+
/// A shortcut to create `KeyEvent::Tap`, useful to create compact
110+
/// layout.
111+
pub const fn tap(kc: KeyCode) -> SequenceEvent {
112+
SequenceEvent::Tap(kc)
113+
}
114+
115+
/// A shortcut to create `KeyEvent::Press`, useful to create compact
116+
/// layout.
117+
pub const fn kp(kc: KeyCode) -> SequenceEvent {
118+
SequenceEvent::Press(kc)
119+
}
120+
121+
/// A shortcut to create `KeyEvent::Release`, useful to create compact
122+
/// layout.
123+
pub const fn kr(kc: KeyCode) -> SequenceEvent {
124+
SequenceEvent::Release(kc)
125+
}
126+
127+
// NOTE: This doesn't work yet:
128+
/// A shortcut to create `KeyEvent::Release`, useful to create compact
129+
/// layout.
130+
pub const fn ra() -> SequenceEvent {
131+
SequenceEvent::ReleaseAll()
132+
}

src/layout.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Layout management.
22
3-
use crate::action::Action;
3+
use crate::action::{Action, SequenceEvent};
44
use crate::key_code::KeyCode;
55
use arraydeque::ArrayDeque;
66
use heapless::consts::U64;
@@ -32,13 +32,18 @@ pub enum Event {
3232
Press(u8, u8),
3333
/// Release event with coordinates (i, j).
3434
Release(u8, u8),
35+
/// Press event with just a keycode (for sequences)
36+
SequencePress(KeyCode),
37+
/// Release event with just a keycode (for sequences)
38+
SequenceRelease(KeyCode),
3539
}
3640
impl Event {
3741
/// Returns the coordinates (i, j) of the event.
3842
pub fn coord(self) -> (u8, u8) {
3943
match self {
4044
Event::Press(i, j) => (i, j),
4145
Event::Release(i, j) => (i, j),
46+
_ => (0, 0), // Need a NaN version of this or something
4247
}
4348
}
4449

@@ -63,6 +68,13 @@ impl Event {
6368
let (i, j) = f(i, j);
6469
Event::Release(i, j)
6570
}
71+
// Not really sure what (if anything) this needs to be. Just returning as-is
72+
Event::SequencePress(k) => {
73+
Event::SequencePress(k)
74+
}
75+
Event::SequenceRelease(k) => {
76+
Event::SequenceRelease(k)
77+
}
6678
}
6779
}
6880
}
@@ -71,11 +83,13 @@ impl Event {
7183
enum State {
7284
NormalKey { keycode: KeyCode, coord: (u8, u8) },
7385
LayerModifier { value: usize, coord: (u8, u8) },
86+
SequenceKey { keycode: KeyCode },
7487
}
7588
impl State {
7689
fn keycode(&self) -> Option<KeyCode> {
7790
match self {
7891
NormalKey { keycode, .. } => Some(*keycode),
92+
SequenceKey { keycode } => Some(*keycode),
7993
_ => None,
8094
}
8195
}
@@ -90,6 +104,12 @@ impl State {
90104
_ => Some(*self),
91105
}
92106
}
107+
fn seq_release(&self, k: KeyCode) -> Option<Self> {
108+
match *self {
109+
SequenceKey { keycode, .. } if keycode == k => None,
110+
_ => Some(*self),
111+
}
112+
}
93113
fn get_layer(&self) -> Option<usize> {
94114
match self {
95115
LayerModifier { value, .. } => Some(*value),
@@ -201,6 +221,16 @@ impl Layout {
201221
let action = self.press_as_action((i, j), self.current_layer());
202222
self.do_action(action, (i, j), stacked.since);
203223
}
224+
SequenceRelease(k) => {
225+
self.states = self
226+
.states
227+
.iter()
228+
.filter_map(|s| s.seq_release(k))
229+
.collect()
230+
}
231+
SequencePress(k) => {
232+
let _ = self.states.push(SequenceKey { keycode: k });
233+
}
204234
}
205235
}
206236
/// A key event.
@@ -278,6 +308,36 @@ impl Layout {
278308
self.do_action(action, coord, delay);
279309
}
280310
}
311+
Sequence { delay, actions } => {
312+
for key_event in actions {
313+
match *key_event {
314+
SequenceEvent::Press(keycode) => {
315+
self.stacked.push_back(Event::SequencePress(keycode).into());
316+
}
317+
SequenceEvent::Release(keycode) => {
318+
self.stacked.push_back(Event::SequenceRelease(keycode).into());
319+
}
320+
SequenceEvent::Tap(keycode) => {
321+
self.stacked.push_back(Event::SequencePress(keycode).into());
322+
self.stacked.push_back(Event::SequenceRelease(keycode).into());
323+
}
324+
SequenceEvent::ReleaseAll() => {
325+
// Can't figure out a good way to handle iterating over self.stacked
326+
// ...without running into borrow checker problems.
327+
// I basically don't know what I'm doing (yet) hehe
328+
// TODO:
329+
// for s in self.stacked.into_iter().collect() {
330+
// match s.event {
331+
// Event::SequencePress(keycode) => {
332+
// self.stacked.push_back(Event::SequenceRelease(keycode.clone()).into());
333+
// }
334+
// _ => { () }
335+
// }
336+
// }
337+
}
338+
}
339+
}
340+
}
281341
Layer(value) => {
282342
let _ = self.states.push(LayerModifier { value, coord });
283343
}

0 commit comments

Comments
 (0)