Merge pull request #74 from KMKfw/topic-leader-timer

Add LeaderMode.TIMEOUT (QMK default Leader mode)
This commit is contained in:
Josh Klar 2018-10-19 01:55:26 -07:00 committed by GitHub
commit 3cb9b762e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 50 deletions

View File

@ -150,7 +150,7 @@ class UnicodeModes:
class LeaderMode:
DEFAULT = 0
DEFAULT_ACTIVE = 1
TIMEOUT = 0
TIMEOUT_ACTIVE = 1
ENTER = 2
ENTER_ACTIVE = 3

View File

@ -55,6 +55,7 @@ class Firmware:
tap_time = 300
leader_mode = LeaderMode.ENTER
leader_dictionary = {}
leader_timeout = 1000
hid_helper = USB_HID
@ -94,28 +95,30 @@ class Firmware:
print("Firin' lazers. Keyboard is booted.")
while True:
for update in self.matrix.scan_for_changes():
if update is not None:
self._state.matrix_changed(
update[0],
update[1],
update[2],
)
update = self.matrix.scan_for_changes()
if update is not None:
self._state.matrix_changed(
update[0],
update[1],
update[2],
)
if self._state.hid_pending:
self._send_hid()
if self._state.hid_pending:
self._send_hid()
for key in self._state.pending_keys:
self._send_key(key)
self._state.pending_key_handled()
if self.debug_enabled:
print('New State: {}'.format(self._state._to_dict()))
if self._state.macro_pending:
for key in self._state.macro_pending(self):
self._send_key(key)
self._state.process_timeouts()
self._state.resolve_macro()
for key in self._state.pending_keys:
self._send_key(key)
self._state.pending_key_handled()
if self.debug_enabled:
print('New State: {}'.format(self._state._to_dict()))
if self._state.macro_pending:
for key in self._state.macro_pending(self):
self._send_key(key)
self._state.resolve_macro()
gc.collect()

View File

@ -1,3 +1,4 @@
from kmk.consts import LeaderMode
from kmk.keycodes import FIRST_KMK_INTERNAL_KEYCODE, Keycodes, RawKeycodes
from kmk.kmktime import sleep_ms, ticks_diff, ticks_ms
from kmk.util import intify_coordinate
@ -26,12 +27,10 @@ class InternalState:
'lm': None,
'leader': None,
}
timeouts = {}
def __init__(self, config):
self.config = config
self.leader_mode = config.leader_mode
self.internal_key_handlers = {
RawKeycodes.KC_DF: self._layer_df,
RawKeycodes.KC_MO: self._layer_mo,
@ -56,6 +55,7 @@ class InternalState:
'keys_pressed': self.keys_pressed,
'active_layers': self.active_layers,
'leader_mode_history': self.leader_mode_history,
'leader_mode': self.config.leader_mode,
'start_time': self.start_time,
}
@ -75,6 +75,21 @@ class InternalState:
return layer_key
def set_timeout(self, after_ticks, callback):
timeout_key = ticks_ms() + after_ticks
self.timeouts[timeout_key] = callback
return self
def process_timeouts(self):
current_time = ticks_ms()
for k, v in self.timeouts.items():
if k <= current_time:
v()
del self.timeouts[k]
return self
def matrix_changed(self, row, col, is_pressed):
if self.config.debug_enabled:
print('Matrix changed (col, row, pressed?): {}, {}, {}'.format(
@ -88,24 +103,24 @@ class InternalState:
print('No key accessible for col, row: {}, {}'.format(row, col))
return self
if is_pressed:
self.keys_pressed.add(kc_changed)
self.coord_keys_pressed[int_coord] = kc_changed
else:
self.keys_pressed.discard(kc_changed)
self.keys_pressed.discard(self.coord_keys_pressed[int_coord])
self.coord_keys_pressed[int_coord] = None
if kc_changed.code >= FIRST_KMK_INTERNAL_KEYCODE:
self._process_internal_key_event(
kc_changed,
is_pressed,
)
else:
if is_pressed:
self.keys_pressed.add(kc_changed)
self.coord_keys_pressed[int_coord] = kc_changed
else:
self.keys_pressed.discard(kc_changed)
self.keys_pressed.discard(self.coord_keys_pressed[int_coord])
self.coord_keys_pressed[int_coord] = None
self.hid_pending = True
if self.leader_mode % 2 == 1:
self._process_leader_mode()
if self.config.leader_mode % 2 == 1:
self._process_leader_mode()
return self
@ -304,13 +319,24 @@ class InternalState:
return self
def _begin_leader_mode(self):
if self.leader_mode % 2 == 0:
if self.config.leader_mode % 2 == 0:
self.keys_pressed.discard(Keycodes.KMK.KC_LEAD)
# All leader modes are one number higher when activating
self.leader_mode += 1
self.config.leader_mode += 1
if self.config.leader_mode == LeaderMode.TIMEOUT_ACTIVE:
self.set_timeout(self.config.leader_timeout, self._handle_leader_sequence)
return self
def _handle_leader_sequence(self):
lmh = tuple(self.leader_mode_history)
if lmh in self.config.leader_dictionary:
self.macro_pending = self.config.leader_dictionary[lmh].keydown
return self._exit_leader_mode()
def _process_leader_mode(self):
keys_pressed = self.keys_pressed
@ -322,15 +348,11 @@ class InternalState:
self.leader_last_len = len(self.keys_pressed)
for key in keys_pressed:
if key == Keycodes.Common.KC_ENT:
# Process the action and remove the extra KC.ENT that was added to get here
lmh = tuple(self.leader_mode_history)
if lmh in self.config.leader_dictionary:
self.macro_pending = self.config.leader_dictionary[lmh].keydown
self._exit_leader_mode()
if (
self.config.leader_mode == LeaderMode.ENTER_ACTIVE and
key == Keycodes.Common.KC_ENT
):
self._handle_leader_sequence()
break
elif key == Keycodes.Common.KC_ESC or key == Keycodes.KMK.KC_GESC:
# Clean self and turn leader mode off.
@ -348,7 +370,7 @@ class InternalState:
def _exit_leader_mode(self):
self.leader_mode_history.clear()
self.leader_mode -= 1
self.config.leader_mode -= 1
self.leader_last_len = 0
self.keys_pressed.clear()
return self

View File

@ -98,12 +98,13 @@ class MatrixScanner:
self.report[2] = new_val
self.state[ba_idx] = new_val
any_changed = True
yield self.report
break
ba_idx += 1
opin.value(False)
if any_changed:
break
if not any_changed:
yield None
if any_changed:
return self.report

View File

@ -1,5 +1,5 @@
from kmk.boards.klarank import Firmware
from kmk.consts import UnicodeModes
from kmk.consts import LeaderMode, UnicodeModes
from kmk.keycodes import KC
from kmk.keycodes import generate_leader_dictionary_seq as glds
from kmk.macros.simple import send_string
@ -45,6 +45,7 @@ emoticons = cuss({
WPM = send_string("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.")
keyboard.leader_mode = LeaderMode.TIMEOUT
keyboard.leader_dictionary = {
glds('hello'): send_string('hello world from kmk macros'),
glds('wpm'): WPM,