Fix key pressed before combo making combo wait for timeout
This commit is contained in:
parent
3f3bd93109
commit
74563368c5
@ -1,5 +1,9 @@
|
|||||||
|
try:
|
||||||
|
from typing import Optional, Tuple
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
import kmk.handlers.stock as handlers
|
import kmk.handlers.stock as handlers
|
||||||
from kmk.keys import make_key
|
from kmk.keys import Key, make_key
|
||||||
from kmk.modules import Module
|
from kmk.modules import Module
|
||||||
|
|
||||||
|
|
||||||
@ -12,8 +16,8 @@ class Combo:
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
match,
|
match: Tuple[Key, ...],
|
||||||
result,
|
result: Key,
|
||||||
fast_reset=None,
|
fast_reset=None,
|
||||||
per_key_timeout=None,
|
per_key_timeout=None,
|
||||||
timeout=None,
|
timeout=None,
|
||||||
@ -69,7 +73,11 @@ class Combos(Module):
|
|||||||
self._matching = []
|
self._matching = []
|
||||||
self._reset = set()
|
self._reset = set()
|
||||||
self._key_buffer = []
|
self._key_buffer = []
|
||||||
|
self._combo_keys = []
|
||||||
|
for combo in self.combos:
|
||||||
|
for k in combo.match:
|
||||||
|
if not k in self._combo_keys:
|
||||||
|
self._combo_keys.append(k)
|
||||||
make_key(
|
make_key(
|
||||||
names=('LEADER', 'LDR'),
|
names=('LEADER', 'LDR'),
|
||||||
on_press=handlers.passthrough,
|
on_press=handlers.passthrough,
|
||||||
@ -97,13 +105,13 @@ class Combos(Module):
|
|||||||
def on_powersave_disable(self, keyboard):
|
def on_powersave_disable(self, keyboard):
|
||||||
return
|
return
|
||||||
|
|
||||||
def process_key(self, keyboard, key, is_pressed, int_coord):
|
def process_key(self, keyboard, key: Key, is_pressed, int_coord):
|
||||||
if is_pressed:
|
if is_pressed:
|
||||||
return self.on_press(keyboard, key, int_coord)
|
return self.on_press(keyboard, key, int_coord)
|
||||||
else:
|
else:
|
||||||
return self.on_release(keyboard, key, int_coord)
|
return self.on_release(keyboard, key, int_coord)
|
||||||
|
|
||||||
def on_press(self, keyboard, key, int_coord):
|
def on_press(self, keyboard, key: Optional[Key], int_coord):
|
||||||
# refill potential matches from timed-out matches
|
# refill potential matches from timed-out matches
|
||||||
if not self._matching:
|
if not self._matching:
|
||||||
self._matching = list(self._reset)
|
self._matching = list(self._reset)
|
||||||
@ -156,7 +164,7 @@ class Combos(Module):
|
|||||||
|
|
||||||
return key
|
return key
|
||||||
|
|
||||||
def on_release(self, keyboard, key, int_coord):
|
def on_release(self, keyboard, key: Optional[Key], int_coord):
|
||||||
for combo in self._active:
|
for combo in self._active:
|
||||||
if key in combo.match:
|
if key in combo.match:
|
||||||
# Deactivate combo if it matches current key.
|
# Deactivate combo if it matches current key.
|
||||||
@ -171,7 +179,6 @@ class Combos(Module):
|
|||||||
|
|
||||||
key = combo.result
|
key = combo.result
|
||||||
break
|
break
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Non-active but matching combos can either activate on key release
|
# Non-active but matching combos can either activate on key release
|
||||||
# if they're the only match, or "un-match" the released key but stay
|
# if they're the only match, or "un-match" the released key but stay
|
||||||
@ -223,6 +230,10 @@ class Combos(Module):
|
|||||||
self._key_buffer.append((int_coord, key, False))
|
self._key_buffer.append((int_coord, key, False))
|
||||||
key = None
|
key = None
|
||||||
|
|
||||||
|
# Reset on non-combo key up
|
||||||
|
if key is not None and key not in self._combo_keys:
|
||||||
|
if not self._matching:
|
||||||
|
self.reset(keyboard)
|
||||||
return key
|
return key
|
||||||
|
|
||||||
def on_timeout(self, keyboard, combo):
|
def on_timeout(self, keyboard, combo):
|
||||||
|
@ -16,6 +16,7 @@ class TestCombo(unittest.TestCase):
|
|||||||
Chord((KC.A, KC.B), KC.X),
|
Chord((KC.A, KC.B), KC.X),
|
||||||
Chord((KC.C, KC.D), KC.Z, timeout=80),
|
Chord((KC.C, KC.D), KC.Z, timeout=80),
|
||||||
Chord((KC.C, KCMO), KC.Z),
|
Chord((KC.C, KCMO), KC.Z),
|
||||||
|
Chord((KC.F, KC.G), KC.Z, timeout=130),
|
||||||
Sequence((KC.N1, KC.N2, KC.N3), KC.Y, timeout=50),
|
Sequence((KC.N1, KC.N2, KC.N3), KC.Y, timeout=50),
|
||||||
Sequence((KC.N1, KC.N2), KC.X, timeout=50),
|
Sequence((KC.N1, KC.N2), KC.X, timeout=50),
|
||||||
Sequence((KC.N3, KC.N4), KC.Z, timeout=100),
|
Sequence((KC.N3, KC.N4), KC.Z, timeout=100),
|
||||||
@ -26,7 +27,7 @@ class TestCombo(unittest.TestCase):
|
|||||||
self.keyboard = KeyboardTest(
|
self.keyboard = KeyboardTest(
|
||||||
[combos, layers],
|
[combos, layers],
|
||||||
[
|
[
|
||||||
[KC.A, KC.B, KC.C, KC.D, KC.E, KCMO],
|
[KC.A, KC.B, KC.C, KC.D, KC.E, KCMO, KC.F, KC.G],
|
||||||
[KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.LEADER],
|
[KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.LEADER],
|
||||||
],
|
],
|
||||||
debug_enabled=False,
|
debug_enabled=False,
|
||||||
@ -368,6 +369,68 @@ class TestCombo(unittest.TestCase):
|
|||||||
[{KC.N1}, {}],
|
[{KC.N1}, {}],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
keyboard.test(
|
||||||
|
'match: Other pressed and released before combo, delay after other press but within the combo timeout',
|
||||||
|
[
|
||||||
|
(1, True),
|
||||||
|
t_within,
|
||||||
|
t_within,
|
||||||
|
(1, False),
|
||||||
|
(7, True),
|
||||||
|
(6, True),
|
||||||
|
(6, False),
|
||||||
|
(7, False),
|
||||||
|
t_after,
|
||||||
|
],
|
||||||
|
[{KC.B}, {}, {KC.Z}, {}],
|
||||||
|
)
|
||||||
|
|
||||||
|
keyboard.test(
|
||||||
|
'match: Other pressed and released before combo, delay after other release but within the combo timeout',
|
||||||
|
[
|
||||||
|
(1, True),
|
||||||
|
(1, False),
|
||||||
|
t_within,
|
||||||
|
t_within,
|
||||||
|
(7, True),
|
||||||
|
(6, True),
|
||||||
|
(6, False),
|
||||||
|
(7, False),
|
||||||
|
t_after,
|
||||||
|
],
|
||||||
|
[{KC.B}, {}, {KC.Z}, {}],
|
||||||
|
)
|
||||||
|
keyboard.test(
|
||||||
|
'match: Other pressed and released before combo, delay after other pressed but within the combo timeout, other is part of another combo',
|
||||||
|
[
|
||||||
|
(0, True),
|
||||||
|
t_within,
|
||||||
|
t_within,
|
||||||
|
(0, False),
|
||||||
|
(7, True),
|
||||||
|
(6, True),
|
||||||
|
(6, False),
|
||||||
|
(7, False),
|
||||||
|
t_after,
|
||||||
|
],
|
||||||
|
[{KC.A}, {}, {KC.Z}, {}],
|
||||||
|
)
|
||||||
|
keyboard.test(
|
||||||
|
'match: Other pressed and released before combo, delay after other release but within the combo timeout, other is part of another combo',
|
||||||
|
[
|
||||||
|
(0, True),
|
||||||
|
(0, False),
|
||||||
|
t_within,
|
||||||
|
t_within,
|
||||||
|
(7, True),
|
||||||
|
(6, True),
|
||||||
|
(6, False),
|
||||||
|
(7, False),
|
||||||
|
t_after,
|
||||||
|
],
|
||||||
|
[{KC.A}, {}, {KC.Z}, {}],
|
||||||
|
)
|
||||||
|
|
||||||
def test_sequence(self):
|
def test_sequence(self):
|
||||||
keyboard = self.keyboard
|
keyboard = self.keyboard
|
||||||
t_within = self.t_within
|
t_within = self.t_within
|
||||||
|
Loading…
x
Reference in New Issue
Block a user