Skip to content

Commit

Permalink
Fix inconsistent macro state when double tapping (#1002)
Browse files Browse the repository at this point in the history
  • Loading branch information
xs5871 authored Jul 6, 2024
1 parent b20efb9 commit 35f2a69
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 14 deletions.
26 changes: 16 additions & 10 deletions kmk/modules/macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,9 @@ def after_matrix_scan(self, keyboard):
return

def process_key(self, keyboard, key, is_pressed, int_coord):
if not self._active or key in self._active:
# Passthrough if there are no active macros, or the key belongs to an
# active macro, or all active macros or non-blocking.
if not self._active or key in self._active or not self._active[-1].blocking:
return key

self.key_buffer.append((int_coord, key, is_pressed))
Expand All @@ -221,22 +223,27 @@ def on_press_unicode_mode(self, key, keyboard, *args, **kwargs):
self.unicode_mode = key.mode

def on_press_macro(self, key, keyboard, *args, **kwargs):
key.state = _ON_PRESS
self.process_macro_async(keyboard, key)
if key.state == _IDLE:
key.state = _ON_PRESS
self.process_macro_async(keyboard, key)
else:
self.key_buffer.append((args[1], key, True))

def on_release_macro(self, key, keyboard, *args, **kwargs):
key.state = _RELEASE
if key._task is None:
self.process_macro_async(keyboard, key)
if key.state == _ON_PRESS or key.state == _ON_HOLD:
key.state = _RELEASE
if key._task is None:
self.process_macro_async(keyboard, key)
else:
self.key_buffer.append((args[1], key, False))

def process_macro_async(self, keyboard, key, _iter=None):
# There's no active macro iterator: select the next one.
if _iter is None:
key._task = None

if key.state == _ON_PRESS:
if key.blocking:
self._active.append(key)
self._active.append(key)
if (macro := key.on_press_macro) is None:
key.state = _ON_HOLD
elif debug.enabled:
Expand Down Expand Up @@ -281,8 +288,7 @@ def process_macro_async(self, keyboard, key, _iter=None):
if debug.enabled:
debug('deactivate')
key.state = _IDLE
if key.blocking:
self._active.remove(key)
self._active.remove(key)
self.send_key_buffer(keyboard)
return

Expand Down
102 changes: 98 additions & 4 deletions tests/test_macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ def setUp(self):
KC.MACRO(on_release='r'),
KC.MACRO(on_press='p', on_hold='h', on_release='r'),
KC.MACRO('bar', blocking=False),
KC.MACRO(on_press='q', on_hold='i', on_release='s', blocking=False),
]
],
debug_enabled=False,
)
self.hold = self.kb.loop_delay_ms * 15

def test_0(self):
self.kb.test(
Expand Down Expand Up @@ -206,7 +208,7 @@ def test_8(self):
def test_9(self):
self.kb.test(
'',
[(9, True), 15 * self.kb.loop_delay_ms, (9, False)],
[(9, True), self.hold, (9, False)],
[{KC.H}, {}, {KC.H}, {}],
)

Expand All @@ -217,20 +219,112 @@ def test_10(self):
[{KC.R}, {}],
)

def test_11(self):
def test_11_0(self):
self.kb.test(
'',
[(11, True), 30 * self.kb.loop_delay_ms, (11, False)],
[(11, True), 2 * self.hold, (11, False)],
[{KC.P}, {}, {KC.H}, {}, {KC.H}, {}, {KC.R}, {}],
)

def test_12(self):
def test_11_1(self):
self.kb.test(
'',
[(11, True), self.hold, (11, False), (11, True), (11, False)],
[{KC.P}, {}, {KC.H}, {}, {KC.R}, {}, {KC.P}, {}, {KC.R}, {}],
)

def test_11_2(self):
self.kb.test(
'',
[(11, True), (11, False), (11, True), (11, False)],
[{KC.P}, {}, {KC.R}, {}, {KC.P}, {}, {KC.R}, {}],
)

def test_11_3(self):
self.kb.test(
'',
[(4, True), (11, True), (4, False), self.hold, (11, False)],
[
{KC.Y},
{KC.P, KC.Y},
{KC.Y},
{KC.H, KC.Y},
{KC.Y},
{KC.R, KC.Y},
{KC.Y},
{},
],
)

def test_12_0(self):
self.kb.test(
'',
[(12, True), (12, False), (4, True), (4, False)],
[{KC.B}, {KC.B, KC.Y}, {KC.B}, {}, {KC.A}, {}, {KC.R}, {}],
)

def test_12_1(self):
self.kb.test(
'',
[(12, True), (12, False), (12, True), (12, False)],
[{KC.B}, {}, {KC.A}, {}, {KC.R}, {}, {KC.B}, {}, {KC.A}, {}, {KC.R}, {}],
)

def test_13_0(self):
self.kb.test(
'',
[(13, True), (13, False), (11, True), (11, False)],
[{KC.Q}, {KC.P, KC.Q}, {KC.P}, {}, {KC.S}, {KC.S, KC.R}, {KC.R}, {}],
)

def test_13_1(self):
self.kb.test(
'',
[(13, True), (11, True), (13, False), (11, False)],
[{KC.Q}, {KC.P, KC.Q}, {KC.P}, {}, {KC.S}, {KC.S, KC.R}, {KC.R}, {}],
)

def test_13_2(self):
self.kb.test(
'',
[(13, True), (11, True), self.hold, (11, False), (13, False)],
[
{KC.Q},
{KC.P, KC.Q},
{KC.P},
{},
{KC.I},
{KC.I, KC.H},
{KC.H},
{},
{KC.S},
{KC.S, KC.R},
{KC.R},
{},
],
)

def test_13_3(self):
self.kb.test(
'',
[(11, True), (11, False), (13, True), (13, False)],
[{KC.P}, {}, {KC.R}, {}, {KC.Q}, {}, {KC.S}, {}],
)

def test_13_4(self):
self.kb.test(
'',
[(11, True), (13, True), (11, False), (13, False)],
[{KC.P}, {}, {KC.R}, {}, {KC.Q}, {}, {KC.S}, {}],
)

def test_13_5(self):
self.kb.test(
'',
[(4, True), (13, True), (4, False), (13, False)],
[{KC.Y}, {KC.Q, KC.Y}, {KC.Q}, {}, {KC.S}, {}],
)


class TestUnicodeModeKeys(unittest.TestCase):
def setUp(self):
Expand Down

0 comments on commit 35f2a69

Please sign in to comment.