From e792524b6340049159eaa3424104ce710f80976f Mon Sep 17 00:00:00 2001 From: Kyle Brown Date: Sun, 3 Mar 2019 16:28:13 -0800 Subject: [PATCH 1/3] Added mod tap with docs --- docs/modtap.md | 24 ++++++++++++++++++++++++ kmk/firmware.py | 24 ++++++++++++------------ kmk/handlers/modtap.py | 35 +++++++++++++++++++++++++++++++++++ kmk/keys.py | 19 ++++++++++++++++++- kmk/types.py | 9 +++++++++ 5 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 docs/modtap.md create mode 100644 kmk/handlers/modtap.py diff --git a/docs/modtap.md b/docs/modtap.md new file mode 100644 index 0000000..f7ee5a3 --- /dev/null +++ b/docs/modtap.md @@ -0,0 +1,24 @@ +# ModTap +One key if you tap it, one or more modifiers if you hold it! + + +## Helpful examples +Just copy the example from New Keycode above your keymap and change KC.SOMETHING to the key that you want when tapped. +After that, just use the new keycode anywhere in your keymap. + +|New Keycode | Description | +|------------------------------------------------------------------|-----------------------------------------------------------------| +|LCTL = KC.MT(KC.LCTRL, kc=KC.SOMETHING) |`LCTRL` if held `kc` if tapped | +|LSFT = KC.MT(KC.LSFT, kc=KC.SOMETHING) |`LSHIFT` if held `kc` if tapped | +|LALT = KC.MT(KC.LALT, kc=KC.SOMETHING) |`LALT` if held `kc` if tapped | +|LGUI = KC.MT(KC.LGUI, kc=KC.SOMETHING) |`LGUI` if held `kc` if tapped | +|RCTL = KC.MT(KC.RCTRL, kc=KC.SOMETHING) |`RCTRL` if held `kc` if tapped | +|RSFT = KC.MT(KC.RSFT, kc=KC.SOMETHING) |`RSHIFT` if held `kc` if tapped | +|RALT = KC.MT(KC.RALT, kc=KC.SOMETHING) |`RALT` if held `kc` if tapped | +|RGUI = KC.MT(KC.RGUI, kc=KC.SOMETHING) |`RGUI` if held `kc` if tapped | +|SGUI = KC.MT(KC.LSHFT, KC.LGUI, kc=KC.SOMETHING) |`LSHIFT` and `LGUI` if held `kc` if tapped | +|LCA = KC.MT(KC.LCTRL, KC.LALT, kc=KC.SOMETHING) |`LCTRL` and `LALT` if held `kc` if tapped | +|LCAG = KC.MT(KC.LCTRL, KC.LALT, KC.LGUI, kc=KC.SOMETHING) |`LCTRL` and `LALT` and `LGUI` if held `kc` if tapped | +|MEH = KC.MT(KC.LCTRL, KC.LSFT, KC.LALT, kc=KC.SOMETHING) |`CTRL` and `LSHIFT` and `LALT` if held `kc` if tapped | +|HYPR = KC.MT(KC.LCTRL, KC.LSFT, KC.LALT, KC.LGUI, kc=KC.SOMETHING)|`LCTRL` and `LSHIFT` and `LALT` and `LGUI` if held `kc` if tapped| + diff --git a/kmk/firmware.py b/kmk/firmware.py index 1bfcb54..7bb3c14 100644 --- a/kmk/firmware.py +++ b/kmk/firmware.py @@ -22,9 +22,19 @@ import kmk.kmktime # isort:skip import kmk.types # isort:skip import kmk.util # isort:skip +import busio # isort:skip +import gc # isort:skip + +import supervisor # isort:skip +from kmk.consts import LeaderMode, UnicodeMode # isort:skip +from kmk.hid import USB_HID # isort:skip +from kmk.internal_state import InternalState # isort:skip +from kmk.keys import KC # isort:skip +from kmk.matrix import MatrixScanner # isort:skip + # Now handlers that will be used in keys later -import kmk.handlers.layers -import kmk.handlers.stock +import kmk.handlers.layers # isort:skip +import kmk.handlers.stock # isort:skip # Now stuff that depends on the above (and so on) import kmk.keys # isort:skip @@ -39,16 +49,6 @@ import kmk.internal_state # isort:skip # Thanks for sticking around. Now let's do real work, starting below -import busio -import gc - -import supervisor -from kmk.consts import LeaderMode, UnicodeMode -from kmk.hid import USB_HID -from kmk.internal_state import InternalState -from kmk.keys import KC -from kmk.matrix import MatrixScanner - class Firmware: debug_enabled = False diff --git a/kmk/handlers/modtap.py b/kmk/handlers/modtap.py new file mode 100644 index 0000000..a0a70d5 --- /dev/null +++ b/kmk/handlers/modtap.py @@ -0,0 +1,35 @@ +from kmk.kmktime import ticks_diff, ticks_ms + + +def mt_pressed(key, state, *args, **kwargs): + # Sets the timer start and acts like a modifier otherwise + state.keys_pressed.add(key.meta.mod1) + if key.meta.mod2: + state.keys_pressed.add(key.meta.mod2) + if key.meta.mod3: + state.keys_pressed.add(key.meta.mod3) + if key.meta.mod4: + state.keys_pressed.add(key.meta.mod4) + + state.start_time['mod_tap'] = ticks_ms() + return state + + +def mt_released(key, state, *args, **kwargs): + # On keyup, check timer, and press key if needed. + state.keys_pressed.discard(key.meta.mod1) + if key.meta.mod2: + state.keys_pressed.discard(key.meta.mod2) + if key.meta.mod3: + state.keys_pressed.discard(key.meta.mod3) + if key.meta.mod4: + state.keys_pressed.discard(key.meta.mod4) + timer_name = 'mod_tap' + if state.start_time[timer_name] and ( + ticks_diff(ticks_ms(), state.start_time[timer_name]) < state.config.tap_time + ): + state.hid_pending = True + state.tap_key(key.meta.kc) + + state.start_time[timer_name] = None + return state diff --git a/kmk/keys.py b/kmk/keys.py index 544c5be..3a757ec 100644 --- a/kmk/keys.py +++ b/kmk/keys.py @@ -1,9 +1,10 @@ import gc import kmk.handlers.layers as layers +import kmk.handlers.modtap as modtap import kmk.handlers.stock as handlers from kmk.consts import UnicodeMode -from kmk.types import (AttrDict, KeySeqSleepMeta, LayerKeyMeta, +from kmk.types import (AttrDict, KeySeqSleepMeta, LayerKeyMeta, ModTapKeyMeta, TapDanceKeyMeta, UnicodeModeKeyMeta) FIRST_KMK_INTERNAL_KEY = 1000 @@ -678,6 +679,22 @@ make_argumented_key( ) +def mod_tap_validator(mod1, mod2=None, mod3=None, mod4=None, kc=None): + ''' + Validates that mod tap keys are correctly used + ''' + return ModTapKeyMeta(mod1=mod1, mod2=mod2, mod3=mod3, mod4=mod4, kc=kc) + + +# ModTap +make_argumented_key( + validator=mod_tap_validator, + names=('MT',), + on_press=modtap.mt_pressed, + on_release=modtap.mt_released, +) + + gc.collect() diff --git a/kmk/types.py b/kmk/types.py index 123f806..80a3c3b 100644 --- a/kmk/types.py +++ b/kmk/types.py @@ -32,6 +32,15 @@ class LayerKeyMeta: self.kc = kc +class ModTapKeyMeta: + def __init__(self, mod1=None, mod2=None, mod3=None, mod4=None, kc=None): + self.mod1 = mod1 + self.mod2 = mod2 + self.mod3 = mod3 + self.mod4 = mod4 + self.kc = kc + + class KeySequenceMeta: def __init__(self, seq): self.seq = seq From a2cfa92f2fedd7d874b95e1faf5fcb05874a3498 Mon Sep 17 00:00:00 2001 From: Kyle Brown Date: Mon, 4 Mar 2019 15:28:45 -0800 Subject: [PATCH 2/3] Missed some obvious things --- docs/keycodes.md | 20 -------------------- docs/modtap.md | 36 +++++++++++++++++++++--------------- kmk/keys.py | 4 ++-- kmk/types.py | 2 +- 4 files changed, 24 insertions(+), 38 deletions(-) diff --git a/docs/keycodes.md b/docs/keycodes.md index 0708371..e3de088 100644 --- a/docs/keycodes.md +++ b/docs/keycodes.md @@ -229,23 +229,3 @@ |`KC.RALT(kc)`|Hold Right Alt and press `kc` | |`KC.RGUI(kc)`|Hold Right GUI and press `kc` | - -## [Mod-Tap Keys] NOT IMPLEMENTED AT THIS TIME - -|Key |Aliases |Description | -|------------|---------------------------------------|-------------------------------------------------------| -|`LCTL_T(kc)`|`CTL_T(kc)` |Left Control when held, `kc` when tapped | -|`RCTL_T(kc)`| |Right Control when held, `kc` when tapped | -|`LSFT_T(kc)`|`SFT_T(kc)` |Left Shift when held, `kc` when tapped | -|`RSFT_T(kc)`| |Right Shift when held, `kc` when tapped | -|`LALT_T(kc)`|`ALT_T(kc)` |Left Alt when held, `kc` when tapped | -|`RALT_T(kc)`|`ALGR_T(kc)` |Right Alt when held, `kc` when tapped | -|`LGUI_T(kc)`|`LCMD_T(kc)`, `RWIN_T(kc)`, `GUI_T(kc)`|Left GUI when held, `kc` when tapped | -|`RGUI_T(kc)`|`RCMD_T(kc)`, `RWIN_T(kc)` |Right GUI when held, `kc` when tapped | -|`C_S_T(kc)` | |Left Control and Shift when held, `kc` when tapped | -|`MEH_T(kc)` | |Left Control, Shift and Alt when held, `kc` when tapped| -|`LCAG_T(kc)`| |Left Control, Alt and GUI when held, `kc` when tapped | -|`RCAG_T(kc)`| |Right Control, Alt and GUI when held, `kc` when tapped | -|`ALL_T(kc)` | |Left Control, Shift, Alt and GUI when held, `kc` when tapped - more info [here](http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/)| -|`SGUI_T(kc)`|`SCMD_T(kc)`, `SWIN_T(kc)` |Left Shift and GUI when held, `kc` when tapped | -|`LCA_T(kc)` | |Left Control and Alt when held, `kc` when tapped | diff --git a/docs/modtap.md b/docs/modtap.md index f7ee5a3..1662a48 100644 --- a/docs/modtap.md +++ b/docs/modtap.md @@ -6,19 +6,25 @@ One key if you tap it, one or more modifiers if you hold it! Just copy the example from New Keycode above your keymap and change KC.SOMETHING to the key that you want when tapped. After that, just use the new keycode anywhere in your keymap. -|New Keycode | Description | -|------------------------------------------------------------------|-----------------------------------------------------------------| -|LCTL = KC.MT(KC.LCTRL, kc=KC.SOMETHING) |`LCTRL` if held `kc` if tapped | -|LSFT = KC.MT(KC.LSFT, kc=KC.SOMETHING) |`LSHIFT` if held `kc` if tapped | -|LALT = KC.MT(KC.LALT, kc=KC.SOMETHING) |`LALT` if held `kc` if tapped | -|LGUI = KC.MT(KC.LGUI, kc=KC.SOMETHING) |`LGUI` if held `kc` if tapped | -|RCTL = KC.MT(KC.RCTRL, kc=KC.SOMETHING) |`RCTRL` if held `kc` if tapped | -|RSFT = KC.MT(KC.RSFT, kc=KC.SOMETHING) |`RSHIFT` if held `kc` if tapped | -|RALT = KC.MT(KC.RALT, kc=KC.SOMETHING) |`RALT` if held `kc` if tapped | -|RGUI = KC.MT(KC.RGUI, kc=KC.SOMETHING) |`RGUI` if held `kc` if tapped | -|SGUI = KC.MT(KC.LSHFT, KC.LGUI, kc=KC.SOMETHING) |`LSHIFT` and `LGUI` if held `kc` if tapped | -|LCA = KC.MT(KC.LCTRL, KC.LALT, kc=KC.SOMETHING) |`LCTRL` and `LALT` if held `kc` if tapped | -|LCAG = KC.MT(KC.LCTRL, KC.LALT, KC.LGUI, kc=KC.SOMETHING) |`LCTRL` and `LALT` and `LGUI` if held `kc` if tapped | -|MEH = KC.MT(KC.LCTRL, KC.LSFT, KC.LALT, kc=KC.SOMETHING) |`CTRL` and `LSHIFT` and `LALT` if held `kc` if tapped | -|HYPR = KC.MT(KC.LCTRL, KC.LSFT, KC.LALT, KC.LGUI, kc=KC.SOMETHING)|`LCTRL` and `LSHIFT` and `LALT` and `LGUI` if held `kc` if tapped| +|New Keycode | Description | +|---------------------------------------------------------------|-----------------------------------------------------------------| +|LCTL = KC.MT(KC.SOMETHING, KC.LCTRL) |`LCTRL` if held `kc` if tapped | +|LSFT = KC.MT(KC.SOMETHING, KC.LSFT) |`LSHIFT` if held `kc` if tapped | +|LALT = KC.MT(KC.SOMETHING, KC.LALT) |`LALT` if held `kc` if tapped | +|LGUI = KC.MT(KC.SOMETHING, KC.LGUI) |`LGUI` if held `kc` if tapped | +|RCTL = KC.MT(KC.SOMETHING, KC.RCTRL) |`RCTRL` if held `kc` if tapped | +|RSFT = KC.MT(KC.SOMETHING, KC.RSFT) |`RSHIFT` if held `kc` if tapped | +|RALT = KC.MT(KC.SOMETHING, KC.RALT) |`RALT` if held `kc` if tapped | +|RGUI = KC.MT(KC.SOMETHING, KC.RGUI) |`RGUI` if held `kc` if tapped | +|SGUI = KC.MT(KC.SOMETHING, KC.LSHFT, KC.LGUI) |`LSHIFT` and `LGUI` if held `kc` if tapped | +|LCA = KC.MT(KC.SOMETHING, KC.LCTRL, KC.LALT) |`LCTRL` and `LALT` if held `kc` if tapped | +|LCAG = KC.MT(KC.SOMETHING, KC.LCTRL, KC.LALT, KC.LGUI) |`LCTRL` and `LALT` and `LGUI` if held `kc` if tapped | +|MEH = KC.MT(KC.SOMETHING, KC.LCTRL, KC.LSFT, KC.LALT) |`CTRL` and `LSHIFT` and `LALT` if held `kc` if tapped | +|HYPR = KC.MT(KC.SOMETHING, KC.LCTRL, KC.LSFT, KC.LALT, KC.LGUI)|`LCTRL` and `LSHIFT` and `LALT` and `LGUI` if held `kc` if tapped| + +```python +SHFT_HOME = KC.MT(KC.HOME, KC.LSFT) + +keyboard.keymap = [[ ...., SHFT_HOME, ....], ....] +``` diff --git a/kmk/keys.py b/kmk/keys.py index 3a757ec..bc021ee 100644 --- a/kmk/keys.py +++ b/kmk/keys.py @@ -679,11 +679,11 @@ make_argumented_key( ) -def mod_tap_validator(mod1, mod2=None, mod3=None, mod4=None, kc=None): +def mod_tap_validator(kc, mod1=None, mod2=None, mod3=None, mod4=None): ''' Validates that mod tap keys are correctly used ''' - return ModTapKeyMeta(mod1=mod1, mod2=mod2, mod3=mod3, mod4=mod4, kc=kc) + return ModTapKeyMeta(kc=kc, mod1=mod1, mod2=mod2, mod3=mod3, mod4=mod4) # ModTap diff --git a/kmk/types.py b/kmk/types.py index 80a3c3b..6276cdf 100644 --- a/kmk/types.py +++ b/kmk/types.py @@ -33,7 +33,7 @@ class LayerKeyMeta: class ModTapKeyMeta: - def __init__(self, mod1=None, mod2=None, mod3=None, mod4=None, kc=None): + def __init__(self, kc=None, mod1=None, mod2=None, mod3=None, mod4=None): self.mod1 = mod1 self.mod2 = mod2 self.mod3 = mod3 From 298f9489c2bd25f5ad9768bd0cf093c50e3e73a0 Mon Sep 17 00:00:00 2001 From: Kyle Brown Date: Wed, 6 Mar 2019 18:56:35 -0800 Subject: [PATCH 3/3] Duh, chaining.... --- docs/modtap.md | 30 +++++++++++++++--------------- kmk/handlers/modtap.py | 16 ++-------------- kmk/keys.py | 4 ++-- kmk/types.py | 7 ++----- 4 files changed, 21 insertions(+), 36 deletions(-) diff --git a/docs/modtap.md b/docs/modtap.md index 1662a48..7db2dec 100644 --- a/docs/modtap.md +++ b/docs/modtap.md @@ -6,21 +6,21 @@ One key if you tap it, one or more modifiers if you hold it! Just copy the example from New Keycode above your keymap and change KC.SOMETHING to the key that you want when tapped. After that, just use the new keycode anywhere in your keymap. -|New Keycode | Description | -|---------------------------------------------------------------|-----------------------------------------------------------------| -|LCTL = KC.MT(KC.SOMETHING, KC.LCTRL) |`LCTRL` if held `kc` if tapped | -|LSFT = KC.MT(KC.SOMETHING, KC.LSFT) |`LSHIFT` if held `kc` if tapped | -|LALT = KC.MT(KC.SOMETHING, KC.LALT) |`LALT` if held `kc` if tapped | -|LGUI = KC.MT(KC.SOMETHING, KC.LGUI) |`LGUI` if held `kc` if tapped | -|RCTL = KC.MT(KC.SOMETHING, KC.RCTRL) |`RCTRL` if held `kc` if tapped | -|RSFT = KC.MT(KC.SOMETHING, KC.RSFT) |`RSHIFT` if held `kc` if tapped | -|RALT = KC.MT(KC.SOMETHING, KC.RALT) |`RALT` if held `kc` if tapped | -|RGUI = KC.MT(KC.SOMETHING, KC.RGUI) |`RGUI` if held `kc` if tapped | -|SGUI = KC.MT(KC.SOMETHING, KC.LSHFT, KC.LGUI) |`LSHIFT` and `LGUI` if held `kc` if tapped | -|LCA = KC.MT(KC.SOMETHING, KC.LCTRL, KC.LALT) |`LCTRL` and `LALT` if held `kc` if tapped | -|LCAG = KC.MT(KC.SOMETHING, KC.LCTRL, KC.LALT, KC.LGUI) |`LCTRL` and `LALT` and `LGUI` if held `kc` if tapped | -|MEH = KC.MT(KC.SOMETHING, KC.LCTRL, KC.LSFT, KC.LALT) |`CTRL` and `LSHIFT` and `LALT` if held `kc` if tapped | -|HYPR = KC.MT(KC.SOMETHING, KC.LCTRL, KC.LSFT, KC.LALT, KC.LGUI)|`LCTRL` and `LSHIFT` and `LALT` and `LGUI` if held `kc` if tapped| +|New Keycode | Description | +|-------------------------------------------------------|-----------------------------------------------------------------| +|LCTL = KC.MT(KC.SOMETHING, KC.LCTRL) |`LCTRL` if held `kc` if tapped | +|LSFT = KC.MT(KC.SOMETHING, KC.LSFT) |`LSHIFT` if held `kc` if tapped | +|LALT = KC.MT(KC.SOMETHING, KC.LALT) |`LALT` if held `kc` if tapped | +|LGUI = KC.MT(KC.SOMETHING, KC.LGUI) |`LGUI` if held `kc` if tapped | +|RCTL = KC.MT(KC.SOMETHING, KC.RCTRL) |`RCTRL` if held `kc` if tapped | +|RSFT = KC.MT(KC.SOMETHING, KC.RSFT) |`RSHIFT` if held `kc` if tapped | +|RALT = KC.MT(KC.SOMETHING, KC.RALT) |`RALT` if held `kc` if tapped | +|RGUI = KC.MT(KC.SOMETHING, KC.RGUI) |`RGUI` if held `kc` if tapped | +|SGUI = KC.MT(KC.SOMETHING, KC.LSHFT(KC.LGUI)) |`LSHIFT` and `LGUI` if held `kc` if tapped | +|LCA = KC.MT(KC.SOMETHING, KC.LCTRL(KC.LALT)) |`LCTRL` and `LALT` if held `kc` if tapped | +|LCAG = KC.MT(KC.SOMETHING, KC.LCTRL(KC.LALT(KC.LGUI))) |`LCTRL` and `LALT` and `LGUI` if held `kc` if tapped | +|MEH = KC.MT(KC.SOMETHING, KC.LCTRL(KC.LSFT(KC.LALT))) |`CTRL` and `LSHIFT` and `LALT` if held `kc` if tapped | +|HYPR = KC.MT(KC.SOMETHING, KC.HYPR) |`LCTRL` and `LSHIFT` and `LALT` and `LGUI` if held `kc` if tapped| ```python SHFT_HOME = KC.MT(KC.HOME, KC.LSFT) diff --git a/kmk/handlers/modtap.py b/kmk/handlers/modtap.py index a0a70d5..c88dad4 100644 --- a/kmk/handlers/modtap.py +++ b/kmk/handlers/modtap.py @@ -3,13 +3,7 @@ from kmk.kmktime import ticks_diff, ticks_ms def mt_pressed(key, state, *args, **kwargs): # Sets the timer start and acts like a modifier otherwise - state.keys_pressed.add(key.meta.mod1) - if key.meta.mod2: - state.keys_pressed.add(key.meta.mod2) - if key.meta.mod3: - state.keys_pressed.add(key.meta.mod3) - if key.meta.mod4: - state.keys_pressed.add(key.meta.mod4) + state.keys_pressed.add(key.meta.mods) state.start_time['mod_tap'] = ticks_ms() return state @@ -17,13 +11,7 @@ def mt_pressed(key, state, *args, **kwargs): def mt_released(key, state, *args, **kwargs): # On keyup, check timer, and press key if needed. - state.keys_pressed.discard(key.meta.mod1) - if key.meta.mod2: - state.keys_pressed.discard(key.meta.mod2) - if key.meta.mod3: - state.keys_pressed.discard(key.meta.mod3) - if key.meta.mod4: - state.keys_pressed.discard(key.meta.mod4) + state.keys_pressed.discard(key.meta.mods) timer_name = 'mod_tap' if state.start_time[timer_name] and ( ticks_diff(ticks_ms(), state.start_time[timer_name]) < state.config.tap_time diff --git a/kmk/keys.py b/kmk/keys.py index bc021ee..0272acd 100644 --- a/kmk/keys.py +++ b/kmk/keys.py @@ -679,11 +679,11 @@ make_argumented_key( ) -def mod_tap_validator(kc, mod1=None, mod2=None, mod3=None, mod4=None): +def mod_tap_validator(kc, mods=None): ''' Validates that mod tap keys are correctly used ''' - return ModTapKeyMeta(kc=kc, mod1=mod1, mod2=mod2, mod3=mod3, mod4=mod4) + return ModTapKeyMeta(kc=kc, mods=mods) # ModTap diff --git a/kmk/types.py b/kmk/types.py index 6276cdf..73a6d60 100644 --- a/kmk/types.py +++ b/kmk/types.py @@ -33,11 +33,8 @@ class LayerKeyMeta: class ModTapKeyMeta: - def __init__(self, kc=None, mod1=None, mod2=None, mod3=None, mod4=None): - self.mod1 = mod1 - self.mod2 = mod2 - self.mod3 = mod3 - self.mod4 = mod4 + def __init__(self, kc=None, mods=None): + self.mods = mods self.kc = kc