From da999fa9dec75f27d9b4645eb624e26e9107ceff Mon Sep 17 00:00:00 2001 From: xs5871 Date: Mon, 13 Mar 2023 22:14:49 +0000 Subject: [PATCH] Fix layer tap interrupted --- kmk/kmk_keyboard.py | 2 +- kmk/modules/holdtap.py | 5 +++++ kmk/modules/oneshot.py | 2 +- kmk/modules/tapdance.py | 2 +- tests/test_holdtap.py | 8 ++++---- tests/test_layers.py | 28 ++++++++++++++++++++++++++-- 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/kmk/kmk_keyboard.py b/kmk/kmk_keyboard.py index 44646acea..5b5224e73 100644 --- a/kmk/kmk_keyboard.py +++ b/kmk/kmk_keyboard.py @@ -197,7 +197,7 @@ def _process_resume_buffer(self): key = ksf.key # Handle any unaccounted-for layer shifts by looking up the key resolution again. - if ksf.int_coord in self._coordkeys_pressed.keys(): + if ksf.int_coord is not None: key = self._find_key_in_map(ksf.int_coord) # Resume the processing of the key event and update the HID report diff --git a/kmk/modules/holdtap.py b/kmk/modules/holdtap.py index e79fa9f58..4f47b397d 100644 --- a/kmk/modules/holdtap.py +++ b/kmk/modules/holdtap.py @@ -83,6 +83,11 @@ def process_key(self, keyboard, key, is_pressed, int_coord): if state.activated != ActivationType.PRESSED: continue + # holdtap isn't interruptable, resolves on ht_release or timeout. + if not key.meta.tap_interrupted and not key.meta.prefer_hold: + append_buffer = True + continue + # holdtap is interrupted by another key event. if (is_pressed and not key.meta.tap_interrupted) or ( not is_pressed and key.meta.tap_interrupted and self.key_buffer diff --git a/kmk/modules/oneshot.py b/kmk/modules/oneshot.py index c86a095e7..d7dcf317e 100644 --- a/kmk/modules/oneshot.py +++ b/kmk/modules/oneshot.py @@ -53,7 +53,7 @@ def process_key(self, keyboard, current_key, is_pressed, int_coord): elif state.activated == ActivationType.INTERRUPTED: if is_pressed: send_buffer = True - self.key_buffer.insert(0, (0, key, False)) + self.key_buffer.insert(0, (None, key, False)) if send_buffer: self.key_buffer.append((int_coord, current_key, is_pressed)) diff --git a/kmk/modules/tapdance.py b/kmk/modules/tapdance.py index 0320fa9a8..b78d35d69 100644 --- a/kmk/modules/tapdance.py +++ b/kmk/modules/tapdance.py @@ -17,7 +17,7 @@ def __init__(self, *keys, tap_time=None): ht_key = KC.HT( tap=key, hold=key, - prefer_hold=False, + prefer_hold=True, tap_interrupted=False, tap_time=self.tap_time, ) diff --git a/tests/test_holdtap.py b/tests/test_holdtap.py index 52595dca3..b7e56fc2a 100644 --- a/tests/test_holdtap.py +++ b/tests/test_holdtap.py @@ -11,8 +11,8 @@ def setUp(self): KC.clear() self.t_within = 2 * KeyboardTest.loop_delay_ms - self.t_after = 5 * KeyboardTest.loop_delay_ms - tap_time = (self.t_after + self.t_within) // 2 + self.t_after = 6 * KeyboardTest.loop_delay_ms + tap_time = 5 * KeyboardTest.loop_delay_ms # overide default timeouts HoldTap.tap_time = tap_time @@ -91,13 +91,13 @@ def test_holdtap(self): keyboard.test( 'LT within tap time rolling -> tap behavior', - [(1, True), t_within, (3, True), t_after, (1, False), (3, False)], + [(1, True), t_within, (3, True), (1, False), (3, False)], [{KC.B}, {KC.B, KC.D}, {KC.D}, {}], ) keyboard.test( 'LT within tap time nested -> tap behavior', - [(1, True), t_within, (3, True), (3, False), t_after, (1, False)], + [(1, True), t_within, (3, True), (3, False), (1, False)], [{KC.B}, {KC.B, KC.D}, {KC.B}, {}], ) diff --git a/tests/test_layers.py b/tests/test_layers.py index 2a830d677..ae26acfd1 100644 --- a/tests/test_layers.py +++ b/tests/test_layers.py @@ -10,8 +10,13 @@ def setUp(self): self.kb = KeyboardTest( [Layers()], [ - [KC.N0, KC.LM(1, KC.LCTL)], - [KC.A, KC.B], + [ + KC.N0, + KC.LM(1, KC.LCTL), + KC.LT(1, KC.N2, tap_interrupted=True, prefer_hold=True), + KC.LT(1, KC.N3, tap_interrupted=False, prefer_hold=True), + ], + [KC.A, KC.B, KC.C, KC.D], ], debug_enabled=False, ) @@ -23,6 +28,25 @@ def test_layermod(self): [{KC.LCTL}, {KC.LCTL, KC.A}, {KC.A}, {}], ) + def test_layertap(self): + self.kb.test( + 'Layertap roll', + [(2, True), (0, True), (2, False), (0, False)], + [{KC.N2}, {KC.N0, KC.N2}, {KC.N0}, {}], + ) + + self.kb.test( + 'Layertap tap interrupted', + [(2, True), (0, True), 200, (0, False), (2, False)], + [{KC.A}, {}], + ) + + self.kb.test( + 'Layertap tap interrupted by holdtap', + [(3, True), (2, True), (2, False), (3, False)], + [{KC.C}, {}], + ) + if __name__ == '__main__': unittest.main()