From b763dd9c4baa43feb7e98aea505e010cb3251e12 Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Thu, 11 Oct 2018 18:20:42 -0700 Subject: [PATCH 1/2] Resolves #53 by removing InternalState.update and moving its still-unused functionality up the stack a bit --- kmk/internal_state.py | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/kmk/internal_state.py b/kmk/internal_state.py index 5f7f90f..d66c658 100644 --- a/kmk/internal_state.py +++ b/kmk/internal_state.py @@ -32,6 +32,9 @@ class Store: self.callbacks = [] def dispatch(self, action): + if self.state.preserve_intermediate_states: + self.state._oldstates.append(repr(self.state.to_dict(verbose=True))) + if callable(action): self.logger.debug('Received thunk') action(self.dispatch, self.get_state) @@ -124,15 +127,6 @@ class InternalState: def __repr__(self): return 'InternalState({})'.format(self.to_dict()) - def update(self, **kwargs): - if self.preserve_intermediate_states: - self._oldstates.append(repr(self.to_dict(verbose=True))) - - for k, v in kwargs.items(): - setattr(self, k, v) - - return self - def find_key_in_map(state, row, col): # Later-added layers have priority. Sift through the layers @@ -178,10 +172,12 @@ def kmk_reducer(state=None, action=None, logger=None): if not changed_key: continue elif changed_key.code >= FIRST_KMK_INTERNAL_KEYCODE: - state = process_internal_key_event(state, - KEY_UP_EVENT, - changed_key, - logger=logger) + state = process_internal_key_event( + state, + KEY_UP_EVENT, + changed_key, + logger=logger, + ) for changed_key in pressed: if not changed_key: @@ -213,12 +209,11 @@ def kmk_reducer(state=None, action=None, logger=None): return state if action.type == INIT_FIRMWARE_EVENT: - return state.update( - keymap=action.keymap, - row_pins=action.row_pins, - col_pins=action.col_pins, - diode_orientation=action.diode_orientation, - ) + state.keymap = action.keymap + state.row_pins = action.row_pins + state.col_pins = action.col_pins + state.diode_orientation = action.diode_orientation + return state # HID events are non-mutating, used exclusively for listeners to know # they should be doing things. This could/should arguably be folded back @@ -228,7 +223,8 @@ def kmk_reducer(state=None, action=None, logger=None): return state if action.type == MACRO_COMPLETE_EVENT: - return state.update(macro_pending=None) + state.macro_pending = None + return state if action.type == PENDING_KEYCODE_POP_EVENT: state.pending_keys.pop() From 98dfb53a83f355a757994d4796df63b59e3b9775 Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Thu, 11 Oct 2018 18:56:46 -0700 Subject: [PATCH 2/2] Resolve #59, adds MEH and HYPER modifiers This also cleans up some weird potentially-buggy logic paths within the ModifierKeycode creation and handling. I can now press a free-floating HYPER in my keymap and see the appropriate codes in `xev` for press and release events. --- kmk/abstract/hid.py | 12 +++++-- kmk/keycodes.py | 34 +++++++++++++++---- .../itsybitsy_m4_express/threethree.py | 2 +- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/kmk/abstract/hid.py b/kmk/abstract/hid.py index e6d8507..3c92136 100644 --- a/kmk/abstract/hid.py +++ b/kmk/abstract/hid.py @@ -102,7 +102,11 @@ class AbstractHidHelper: def add_modifier(self, modifier): if isinstance(modifier, ModifierKeycode): - self.report_mods[0] |= modifier.code + if modifier.code == ModifierKeycode.FAKE_CODE: + for mod in modifier.has_modifiers: + self.report_mods[0] |= mod + else: + self.report_mods[0] |= modifier.code else: self.report_mods[0] |= modifier @@ -110,7 +114,11 @@ class AbstractHidHelper: def remove_modifier(self, modifier): if isinstance(modifier, ModifierKeycode): - self.report_mods[0] ^= modifier.code + if modifier.code == ModifierKeycode.FAKE_CODE: + for mod in modifier.has_modifiers: + self.report_mods[0] ^= mod + else: + self.report_mods[0] ^= modifier.code else: self.report_mods[0] ^= modifier diff --git a/kmk/keycodes.py b/kmk/keycodes.py index 2341c30..6f558f3 100644 --- a/kmk/keycodes.py +++ b/kmk/keycodes.py @@ -81,17 +81,33 @@ class Keycode: class ModifierKeycode(Keycode): + FAKE_CODE = -1 + def __call__(self, modified_code=None, no_press=None, no_release=None): if modified_code is None and no_press is None and no_release is None: return self if modified_code is not None: - new_keycode = Keycode( - modified_code.code, - {self.code}, - no_press=no_press, - no_release=no_release, - ) + if isinstance(modified_code, ModifierKeycode): + new_keycode = ModifierKeycode( + ModifierKeycode.FAKE_CODE, + set() if self.has_modifiers is None else self.has_modifiers, + no_press=no_press, + no_release=no_release, + ) + + if self.code != ModifierKeycode.FAKE_CODE: + new_keycode.has_modifiers.add(self.code) + + if modified_code.code != ModifierKeycode.FAKE_CODE: + new_keycode.has_modifiers.add(modified_code.code) + else: + new_keycode = Keycode( + modified_code.code, + {self.code}, + no_press=no_press, + no_release=no_release, + ) if modified_code.has_modifiers: new_keycode.has_modifiers |= modified_code.has_modifiers @@ -104,6 +120,9 @@ class ModifierKeycode(Keycode): return new_keycode + def __repr__(self): + return 'ModifierKeycode(code={}, has_modifiers={})'.format(self.code, self.has_modifiers) + class ConsumerKeycode(Keycode): pass @@ -220,6 +239,9 @@ class Modifiers(KeycodeCategory): KC_RALT = ModifierKeycode(RawKeycodes.RALT) KC_RGUI = KC_RCMD = KC_RWIN = ModifierKeycode(RawKeycodes.RGUI) + KC_MEH = KC_LSHIFT(KC_LALT(KC_LCTRL)) + KC_HYPR = KC_HYPER = KC_MEH(KC_LGUI) + class Common(KeycodeCategory): KC_A = Keycode(4) diff --git a/user_keymaps/klardotsh/itsybitsy_m4_express/threethree.py b/user_keymaps/klardotsh/itsybitsy_m4_express/threethree.py index 752679b..f84c01a 100644 --- a/user_keymaps/klardotsh/itsybitsy_m4_express/threethree.py +++ b/user_keymaps/klardotsh/itsybitsy_m4_express/threethree.py @@ -72,7 +72,7 @@ MACRO_HELLO_WORLD = simple_key_sequence([ keymap = [ [ - [KC.GESC, KC.A, KC.RESET], + [KC.GESC, KC.HYPR, KC.RESET], [KC.MO(1), KC.B, KC.MUTE], [KC.LT(2, KC.EXCLAIM), KC.HASH, KC.ENTER], ],