kmk_firmware/kmk/modules/oneshot.py
xs5871 17f2961c0b fix pystack exhaust during resume_process_key.
Instead of handling resumed key events in a deep stack, buffer them
until the next main loop iteration. New resume events that may be emitted
during handling of old resumes are prepended to that buffer, i.e. take
precedence over events that happen deeper into the buffer/event stack.
Logical replay order is thus preserved.
2022-10-08 13:36:00 -07:00

64 lines
2.3 KiB
Python

from kmk.keys import make_argumented_key
from kmk.modules.holdtap import ActivationType, HoldTap, HoldTapKeyMeta
def oneshot_validator(kc, tap_time=None):
return HoldTapKeyMeta(tap=kc, hold=kc, prefer_hold=False, tap_time=tap_time)
class OneShot(HoldTap):
tap_time = 1000
def __init__(self):
super().__init__()
make_argumented_key(
validator=oneshot_validator,
names=('OS', 'ONESHOT'),
on_press=self.osk_pressed,
on_release=self.osk_released,
)
def process_key(self, keyboard, current_key, is_pressed, int_coord):
'''Release os key after interrupting keyup.'''
for key, state in self.key_states.items():
if key == current_key:
continue
if state.activated == ActivationType.PRESSED and is_pressed:
state.activated = ActivationType.HOLD_TIMEOUT
elif state.activated == ActivationType.RELEASED and is_pressed:
state.activated = ActivationType.INTERRUPTED
elif state.activated == ActivationType.INTERRUPTED:
if is_pressed:
keyboard.remove_key(key.meta.tap)
self.key_buffer.append((int_coord, current_key, is_pressed))
keyboard.set_timeout(False, lambda: self.send_key_buffer(keyboard))
current_key = None
else:
self.ht_released(key, keyboard)
return current_key
def osk_pressed(self, key, keyboard, *args, **kwargs):
'''Register HoldTap mechanism and activate os key.'''
self.ht_pressed(key, keyboard, *args, **kwargs)
self.ht_activate_tap(key, keyboard, *args, **kwargs)
self.send_key_buffer(keyboard)
return keyboard
def osk_released(self, key, keyboard, *args, **kwargs):
'''On keyup, mark os key as released or handle HoldTap.'''
try:
state = self.key_states[key]
except KeyError:
if keyboard.debug_enabled:
print(f'OneShot.osk_released: no such key {key}')
return keyboard
if state.activated == ActivationType.PRESSED:
state.activated = ActivationType.RELEASED
else:
self.ht_released(key, keyboard, *args, **kwargs)
return keyboard