implement hold-tap interrupt on other key tap (i.e. release)
This commit is contained in:
parent
5cae17c9f3
commit
a685618480
@ -11,7 +11,7 @@ def key_seq_sleep_validator(ms):
|
||||
return KeySeqSleepMeta(ms)
|
||||
|
||||
|
||||
def layer_key_validator(layer, kc=None):
|
||||
def layer_key_validator(layer, kc=None, tap_time=None):
|
||||
'''
|
||||
Validates the syntax (but not semantics) of a layer key call. We won't
|
||||
have access to the keymap here, so we can't verify much of anything useful
|
||||
@ -19,14 +19,24 @@ def layer_key_validator(layer, kc=None):
|
||||
existing is mostly that Python will catch extraneous args/kwargs and error
|
||||
out.
|
||||
'''
|
||||
return LayerKeyMeta(layer=layer, kc=kc)
|
||||
return LayerKeyMeta(
|
||||
layer=layer, kc=kc, prefer_hold=False, tap_interrupted=False, tap_time=tap_time
|
||||
)
|
||||
|
||||
|
||||
def mod_tap_validator(kc, mods=None, prefer_hold=True, tap_time=None):
|
||||
def mod_tap_validator(
|
||||
kc, mods=None, prefer_hold=True, tap_interrupted=False, tap_time=None
|
||||
):
|
||||
'''
|
||||
Validates that mod tap keys are correctly used
|
||||
'''
|
||||
return ModTapKeyMeta(kc=kc, mods=mods, prefer_hold=prefer_hold, tap_time=tap_time)
|
||||
return ModTapKeyMeta(
|
||||
kc=kc,
|
||||
mods=mods,
|
||||
prefer_hold=prefer_hold,
|
||||
tap_interrupted=tap_interrupted,
|
||||
tap_time=tap_time,
|
||||
)
|
||||
|
||||
|
||||
def tap_dance_key_validator(*codes):
|
||||
|
@ -21,6 +21,7 @@ class HoldTap(Module):
|
||||
tap_time = 300
|
||||
|
||||
def __init__(self):
|
||||
self.key_buffer = set()
|
||||
self.key_states = {}
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
@ -33,19 +34,36 @@ class HoldTap(Module):
|
||||
return
|
||||
|
||||
def process_key(self, keyboard, key, is_pressed):
|
||||
'''Before other key down decide to send tap kc down.'''
|
||||
'''Handle holdtap being interrupted by another key press/release.'''
|
||||
current_key = key
|
||||
for key, state in self.key_states.items():
|
||||
if key == current_key:
|
||||
continue
|
||||
if is_pressed:
|
||||
if state.activated == ActivationType.NOT_ACTIVATED:
|
||||
# press tap because interrupted by other key
|
||||
self.key_states[key].activated = ActivationType.INTERRUPTED
|
||||
self.ht_activate_on_interrupt(
|
||||
key, keyboard, *state.args, **state.kwargs
|
||||
)
|
||||
if state.activated != ActivationType.NOT_ACTIVATED:
|
||||
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
|
||||
):
|
||||
|
||||
keyboard.cancel_timeout(state.timeout_key)
|
||||
self.key_states[key].activated = ActivationType.INTERRUPTED
|
||||
self.ht_activate_on_interrupt(
|
||||
key, keyboard, *state.args, **state.kwargs
|
||||
)
|
||||
|
||||
keyboard._send_hid()
|
||||
|
||||
self.send_key_buffer(keyboard)
|
||||
|
||||
# if interrupt on release: store interrupting keys until one of them
|
||||
# is released.
|
||||
if key.meta.tap_interrupted:
|
||||
if is_pressed:
|
||||
self.key_buffer.add(current_key)
|
||||
current_key = None
|
||||
|
||||
return current_key
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
@ -91,6 +109,7 @@ class HoldTap(Module):
|
||||
False,
|
||||
lambda: self.ht_deactivate_tap(key, keyboard, *args, **kwargs),
|
||||
)
|
||||
self.send_key_buffer(keyboard)
|
||||
del self.key_states[key]
|
||||
return keyboard
|
||||
|
||||
@ -103,6 +122,13 @@ class HoldTap(Module):
|
||||
# press hold because timer expired after tap time
|
||||
self.key_states[key].activated = ActivationType.HOLD_TIMEOUT
|
||||
self.ht_activate_hold(key, keyboard, *args, **kwargs)
|
||||
self.send_key_buffer(keyboard)
|
||||
|
||||
def send_key_buffer(self, keyboard):
|
||||
for key in self.key_buffer:
|
||||
key.on_press(keyboard)
|
||||
keyboard._send_hid()
|
||||
self.key_buffer.clear()
|
||||
|
||||
def ht_activate_hold(self, key, keyboard, *args, **kwargs):
|
||||
pass
|
||||
|
25
kmk/types.py
25
kmk/types.py
@ -11,21 +11,26 @@ class AttrDict(dict):
|
||||
return self[key]
|
||||
|
||||
|
||||
class LayerKeyMeta:
|
||||
def __init__(self, layer, kc=None, tap_time=None):
|
||||
self.layer = layer
|
||||
class HoldTapKeyMeta:
|
||||
def __init__(self, kc=None, prefer_hold=True, tap_interrupted=False, tap_time=None):
|
||||
self.kc = kc
|
||||
self.tap_time = tap_time
|
||||
|
||||
|
||||
class ModTapKeyMeta:
|
||||
def __init__(self, kc=None, mods=None, prefer_hold=True, tap_time=None):
|
||||
self.prefer_hold = prefer_hold
|
||||
self.kc = kc
|
||||
self.mods = mods
|
||||
self.tap_interrupted = tap_interrupted
|
||||
self.tap_time = tap_time
|
||||
|
||||
|
||||
class LayerKeyMeta(HoldTapKeyMeta):
|
||||
def __init__(self, layer, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.layer = layer
|
||||
|
||||
|
||||
class ModTapKeyMeta(HoldTapKeyMeta):
|
||||
def __init__(self, kc=None, mods=None, **kwargs):
|
||||
super().__init__(kc=kc, **kwargs)
|
||||
self.mods = mods
|
||||
|
||||
|
||||
class KeySequenceMeta:
|
||||
def __init__(self, seq):
|
||||
self.seq = seq
|
||||
|
Loading…
x
Reference in New Issue
Block a user