qsk_types/
layer_composer.rs

1use std::collections::HashMap;
2use std::time::{Duration, SystemTime};
3
4use crate::control_code::{ControlCode, LayerRef};
5use crate::errors::Result;
6use crate::events::{InputEvent, EventCode, KeyCode, KeyCode::*, KeyState::*};
7use crate::layers::{Layer, Layers};
8
9/// An `InputTransformer` that passes through all input events it receives save for `KC_PAUSE`,
10/// which it translates to `ControlCode::Exit`.
11pub struct Passthrough {}
12
13impl InputTransformer for Passthrough {
14    fn transform(&mut self, e: InputEvent) -> Option<Vec<ControlCode>> {
15        match e.code {
16            EventCode::KeyCode(KC_PAUSE) => Some(vec![ControlCode::Exit]),
17            _ => Some(vec![ControlCode::InputEvent(e)]),
18        }
19    }
20}
21
22pub trait InputTransformer {
23    fn transform(&mut self, e: InputEvent) -> Option<Vec<ControlCode>>;
24}
25
26trait Nower {
27    fn now(&self) -> SystemTime;
28}
29
30struct RealNower {}
31
32impl Nower for RealNower {
33    fn now(&self) -> SystemTime {
34        SystemTime::now()
35    }
36}
37
38/// LayerComposer is the "top-level" type involved in `qsk`'s layered approach to keyboard
39/// remapping. It works by iterating over the `Layer`s that it composes and applying the
40/// transformation from the first active layer it finds to the given `InputEvent`.
41pub struct LayerComposer {
42    base: Box<dyn InputTransformer + Send>,
43    layers: Layers,
44    timers: HashMap<KeyCode, SystemTime>,
45
46    nower: Box<dyn Nower + Send>,
47}
48
49impl LayerComposer {
50    pub fn from_layers(layers: Vec<Layer>) -> Result<LayerComposer> {
51        let composer = LayerComposer {
52            base: Box::new(Passthrough {}),
53            layers: layers.into(),
54            timers: HashMap::new(),
55            nower: Box::new(RealNower {}),
56        };
57
58        Ok(composer)
59    }
60
61    fn now(&self) -> SystemTime {
62        self.nower.now()
63    }
64
65    fn duration_since(&self, t: SystemTime) -> Duration {
66        match self.now().duration_since(t) {
67            Ok(d) => d,
68            Err(_) => Duration::new(0, 0),
69        }
70    }
71
72    fn key_up_and_down(&self, k: KeyCode) -> Vec<ControlCode> {
73        let now = self.now();
74        let now_plus = now + Duration::from_micros(1);
75        vec![
76            ControlCode::InputEvent(InputEvent {
77                time: now,
78                code: EventCode::KeyCode(k),
79                state: Down,
80            }),
81            ControlCode::InputEvent(InputEvent {
82                time: now_plus,
83                code: EventCode::KeyCode(k),
84                state: Up,
85            }),
86        ]
87    }
88
89    fn handle_control_codes(
90        &mut self,
91        e: &InputEvent,
92        ccs: Vec<ControlCode>,
93    ) -> Option<Vec<ControlCode>> {
94        let mut output: Vec<ControlCode> = Vec::new();
95        for cc in ccs {
96            match cc {
97                ControlCode::TapToggle(ref layer_ref, key) => match (e.state, self.timers.get(&key)) {
98                    (Down, None) => {
99                        self.timers.insert(key, self.now());
100                    }
101                    (Held, Some(t)) => {
102                        if self.duration_since(*t) > Duration::from_millis(180) {
103                            self.activate_layer(layer_ref);
104                            self.timers.remove(&key);
105                        }
106                    }
107                    (Up, None) => {
108                        if self.is_layer_active(layer_ref) {
109                            self.deactivate_layer(layer_ref);
110                            self.timers.remove(&key);
111                        } else {
112                            self.key_up_and_down(key)
113                                .iter()
114                                .for_each(|cc| output.push(cc.clone()));
115                        }
116                    }
117                    (Up, Some(t)) => {
118                        if self.duration_since(*t) < Duration::from_millis(180) {
119                            self.key_up_and_down(key)
120                                .iter()
121                                .for_each(|cc| output.push(cc.clone()));
122                        }
123                        self.deactivate_layer(layer_ref);
124                        self.timers.remove(&key);
125                    }
126                    (_, _) => output.push(cc),
127                },
128                _ => output.push(cc),
129            }
130        }
131        match output[..] {
132            [] => None,
133            _ => Some(output),
134        }
135    }
136
137    fn is_layer_active(&mut self, lr: &LayerRef) -> bool {
138        match lr {
139            LayerRef::ByIndex(index) => {
140                self.layers[*index].active
141            },
142            LayerRef::ByName(name) => {
143                self.layers.get_mut(name).unwrap().active
144            },
145        }
146    }
147
148    fn activate_layer(&mut self, lr: &LayerRef) {
149        self.set_layer_active(lr, true)
150    }
151
152    fn deactivate_layer(&mut self, lr: &LayerRef) {
153        self.set_layer_active(lr, false)
154    }
155
156    fn set_layer_active(&mut self, lr: &LayerRef, to: bool) {
157        match lr {
158            LayerRef::ByIndex(index) => {
159                self.layers[*index].active = to
160            },
161            LayerRef::ByName(name) => {
162                self.layers.get_mut(name).unwrap().active = to
163            },
164        };
165    }
166
167    pub fn iter(&self) -> impl Iterator<Item = &Layer> {
168        self.layers.iter()
169    }
170}
171
172impl InputTransformer for LayerComposer {
173    fn transform(&mut self, e: InputEvent) -> Option<Vec<ControlCode>> {
174        for l in &mut self.layers.iter_mut().rev() {
175            match l.transform(e) {
176                Some(ccs) => return self.handle_control_codes(&e, ccs),
177                None => continue,
178            }
179        }
180        self.base.transform(e)
181    }
182}
183
184#[cfg(test)]
185mod layer_composer {
186    use std::sync::{Arc, Mutex};
187    use std::time::SystemTime;
188
189    use galvanic_assert::matchers::collection::*;
190    use galvanic_assert::matchers::*;
191    use galvanic_assert::*;
192    use maplit::hashmap;
193
194    use super::*;
195    use crate::KeyState;
196
197    impl LayerComposer {
198        fn key(&self, kc: KeyCode, ks: KeyState) -> InputEvent {
199            InputEvent {
200                time: self.nower.now(),
201                code: EventCode::KeyCode(kc),
202                state: ks,
203            }
204        }
205
206        fn validate_single(&mut self, input: InputEvent, output: Option<InputEvent>) {
207            let result = self.transform(input);
208            match output {
209                None => assert_that!(&result, eq(None)),
210                Some(e) => {
211                    let expect = vec![ControlCode::InputEvent(e)];
212                    assert_that!(&result.unwrap(), contains_in_order(expect));
213                }
214            };
215        }
216
217        fn validate_multiple(&mut self, input: InputEvent, output: Vec<ControlCode>) {
218            assert_that!(&self.transform(input).unwrap(), contains_in_order(output));
219        }
220    }
221
222    pub fn key(k: KeyCode) -> Vec<ControlCode> { vec![ControlCode::KeyMap(k)] }
223
224    pub fn tap_toggle(layer: usize, kc: KeyCode) -> Vec<ControlCode> {
225        vec![ControlCode::TapToggle(LayerRef::ByIndex(layer), kc)]
226    }
227
228    pub fn tap_toggle_by_name(name: String, kc: KeyCode) -> Vec<ControlCode> {
229        vec![ControlCode::TapToggle(LayerRef::ByName(name), kc)]
230    }
231
232
233    #[derive(Clone)]
234    struct FakeNow {
235        t: Arc<Mutex<SystemTime>>,
236    }
237
238    impl FakeNow {
239        fn new() -> Self {
240            FakeNow {
241                t: Arc::new(Mutex::new(SystemTime::now())),
242            }
243        }
244        fn adjust_now(&self, by: Duration) {
245            let mut mut_ref = self.t.lock().unwrap();
246            *mut_ref += by;
247        }
248    }
249
250    impl Nower for FakeNow {
251        fn now(&self) -> SystemTime {
252            self.t.lock().unwrap().clone()
253        }
254    }
255
256    #[derive(Clone, Debug, PartialEq, Copy)]
257    enum LAYERS {
258        HomerowCodeRight = 0,
259        Navigation = 1,
260    }
261
262    impl From<LAYERS> for usize {
263        fn from(layer: LAYERS) -> usize {
264            layer as usize
265        }
266    }
267
268    fn test_layer_composer() -> (LayerComposer, FakeNow) {
269        let mut layers = Vec::with_capacity(8);
270
271        layers.insert(
272            LAYERS::HomerowCodeRight.into(),
273            Layer::from_hashmap(
274                "control".to_string(),
275                hashmap!(
276                    KC_F => tap_toggle(LAYERS::Navigation.into(), KC_F),
277                    KC_D => tap_toggle_by_name("navigation".to_string(), KC_D),
278                ),
279                true,
280            ),
281        );
282
283        layers.insert(
284            LAYERS::Navigation.into(),
285            Layer::from_hashmap(
286                "navigation".to_string(),
287                hashmap!(
288                    KC_Y => key(KC_HOME),
289                    KC_U => key(KC_PAGEDOWN),
290                    KC_I => key(KC_PAGEUP),
291                    KC_O => key(KC_END),
292                    KC_H => key(KC_LEFT),
293                    KC_J => key(KC_DOWN),
294                    KC_K => key(KC_UP),
295                    KC_SEMICOLON => key(KC_RIGHT),
296                ),
297                false,
298            ),
299        );
300
301        let fake_now = FakeNow::new();
302        (
303            LayerComposer {
304                base: Box::new(Passthrough {}),
305                layers: layers.into(),
306                timers: HashMap::new(),
307                nower: Box::new(fake_now.clone()),
308            },
309            fake_now,
310        )
311    }
312
313    #[test]
314    fn fake_now() {
315        let fake_now = Box::new(FakeNow::new());
316        let c_fake_now = fake_now.clone();
317
318        let t1 = fake_now.now();
319        fake_now.adjust_now(Duration::from_millis(1000));
320        let mut t2 = fake_now.now();
321        assert_eq!(t2, t1 + Duration::from_millis(1000));
322
323        t2 = c_fake_now.now();
324        assert_eq!(t2, t1 + Duration::from_millis(1000));
325    }
326
327    #[test]
328    fn passthrough_no_active_layers() {
329        let (mut th, _) = test_layer_composer();
330        assert_that!(&th.layers[0].active, eq(true));
331        assert_that!(&th.layers[1].active, eq(false));
332
333        th.validate_single(th.key(KC_E, Down), Some(th.key(KC_E, Down)));
334        th.validate_single(th.key(KC_E, Up), Some(th.key(KC_E, Up)));
335
336        th.validate_single(th.key(KC_K, Down), Some(th.key(KC_K, Down)));
337        th.validate_single(th.key(KC_K, Up), Some(th.key(KC_K, Up)));
338
339        th.validate_single(th.key(KC_J, Down), Some(th.key(KC_J, Down)));
340        th.validate_single(th.key(KC_J, Up), Some(th.key(KC_J, Up)));
341    }
342
343    #[test]
344    fn tap_toggle_toggle_by_layer_name() {
345        let (mut th, fake_now) = test_layer_composer();
346        assert_that!(&th.layers[0].active, eq(true));
347        assert_that!(&th.layers[1].active, eq(false));
348
349        // initial button down of a tap toggle key should not produce any characters and should not
350        // set the toggle layer to active
351        th.validate_single(th.key(KC_D, Down), None);
352        assert_that!(&th.layers[1].active, eq(false));
353
354        // layer doesn't get set to active until both after the next Held key fter the tap
355        // toggle timeout
356        fake_now.adjust_now(Duration::from_millis(1000));
357        assert_that!(&th.layers[1].active, eq(false));
358        th.validate_single(th.key(KC_D, Held), None);
359        assert_that!(&th.layers[1].active, eq(true));
360
361        // once layer is active, key transformation should take place based on definitions in the
362        // activated layer
363        th.validate_single(th.key(KC_J, Down), Some(th.key(KC_DOWN, Down)));
364        th.validate_single(th.key(KC_J, Up), Some(th.key(KC_DOWN, Up)));
365
366        // if layer is toggled, releasing tap toggle key after tap toggle timeout should result in
367        // no keyboard events and should result in the layer being disabled once again
368        th.validate_single(th.key(KC_D, Up), None);
369        assert_that!(&th.layers[1].active, eq(false));
370        th.validate_single(th.key(KC_J, Down), Some(th.key(KC_J, Down)));
371        th.validate_single(th.key(KC_J, Up), Some(th.key(KC_J, Up)));
372    }
373
374    #[test]
375    fn tap_toggle_toggle() {
376        let (mut th, fake_now) = test_layer_composer();
377        assert_that!(&th.layers[0].active, eq(true));
378        assert_that!(&th.layers[1].active, eq(false));
379
380        // initial button down of a tap toggle key should not produce any characters and should not
381        // set the toggle layer to active
382        th.validate_single(th.key(KC_F, Down), None);
383        assert_that!(&th.layers[1].active, eq(false));
384
385        // layer doesn't get set to active until both after the next Held key fter the tap
386        // toggle timeout
387        fake_now.adjust_now(Duration::from_millis(1000));
388        assert_that!(&th.layers[1].active, eq(false));
389        th.validate_single(th.key(KC_F, Held), None);
390        assert_that!(&th.layers[1].active, eq(true));
391
392        // once layer is active, key transformation should take place based on definitions in the
393        // activated layer
394        th.validate_single(th.key(KC_J, Down), Some(th.key(KC_DOWN, Down)));
395        th.validate_single(th.key(KC_J, Up), Some(th.key(KC_DOWN, Up)));
396
397        // if layer is toggled, releasing tap toggle key after tap toggle timeout should result in
398        // no keyboard events and should result in the layer being disabled once again
399        th.validate_single(th.key(KC_F, Up), None);
400        assert_that!(&th.layers[1].active, eq(false));
401        th.validate_single(th.key(KC_J, Down), Some(th.key(KC_J, Down)));
402        th.validate_single(th.key(KC_J, Up), Some(th.key(KC_J, Up)));
403    }
404
405    #[test]
406    #[ignore]
407    // TODO: try to remember what i was going to test here over a year ago...
408    fn tap_toggle_regression_() {
409        assert!(false);
410        let (mut th, _) = test_layer_composer();
411        assert_that!(&th.layers[0].active, eq(true));
412        assert_that!(&th.layers[1].active, eq(false));
413
414        // initial button down of a tap toggle key should not produce any characters and should not
415        // set the toggle layer to active
416        th.validate_single(th.key(KC_F, Down), None);
417        assert_that!(&th.layers[0].active, eq(true));
418        assert_that!(&th.layers[1].active, eq(false));
419    }
420
421    #[test]
422    #[ignore]
423    // TODO: try to remember what i was going to test here over a year ago...
424    fn tap_toggle_tap_short_circuits_timeout() {
425        assert!(false);
426        let (mut th, fake_now) = test_layer_composer();
427        assert_that!(&th.layers[0].active, eq(true));
428        assert_that!(&th.layers[1].active, eq(false));
429
430        // if we type from the layer in question within the timeout the layer is activated
431        th.validate_single(th.key(KC_F, Down), None);
432        fake_now.adjust_now(Duration::from_millis(10));
433        th.validate_multiple(
434            th.key(KC_F, Up),
435            vec![
436                ControlCode::InputEvent(th.key(KC_F, Down)),
437                ControlCode::InputEvent(th.key(KC_F, Up)),
438            ],
439        );
440    }
441
442    #[test]
443    fn tap_toggle_tap() {
444        let (mut th, _) = test_layer_composer();
445        let mut expected: Vec<ControlCode> = Vec::new();
446        assert_that!(&th.layers[0].active, eq(true));
447        assert_that!(&th.layers[1].active, eq(false));
448
449        // if we release the key within the tap toggle timeout, then we should get the tapped key's
450        // usual output in sequence
451        th.validate_single(th.key(KC_F, Down), None);
452
453        let down = th.key(KC_F, Down);
454        let mut up = th.key(KC_F, Up);
455        up.time = down.time + Duration::from_micros(1);
456        expected.push(ControlCode::InputEvent(down));
457        expected.push(ControlCode::InputEvent(up));
458        th.validate_multiple(th.key(KC_F, Up), expected);
459    }
460
461    #[test]
462    fn key_up_and_down() {
463        let (th, _) = test_layer_composer();
464        let mut expected: Vec<ControlCode> = Vec::new();
465
466        let down = th.key(KC_F, Down);
467        let mut up = th.key(KC_F, Up);
468        up.time = down.time + Duration::from_micros(1);
469        expected.push(ControlCode::InputEvent(down));
470        expected.push(ControlCode::InputEvent(up));
471
472        let actual = th.key_up_and_down(KC_F);
473        assert_that!(&actual, contains_in_order(expected));
474    }
475}