diff options
| author | Thiago Alves <talk@thiagoalves.com.br> | 2016-05-05 18:41:37 -0700 |
|---|---|---|
| committer | Jack Humbert <jack.humb@gmail.com> | 2016-05-05 21:41:37 -0400 |
| commit | 74e97eefd7ae76f9ddcb76890a30aa9038804cdb (patch) | |
| tree | 9bdf7ce6ffb97a024c8230e5e960d53503262ced /tmk_core/common/action.c | |
| parent | d4520cd3ac7550fc7243e9a76824d9ba674875c6 (diff) | |
| download | qmk_firmware-74e97eefd7ae76f9ddcb76890a30aa9038804cdb.tar.gz qmk_firmware-74e97eefd7ae76f9ddcb76890a30aa9038804cdb.zip | |
Adds oneshot layer and oneshot tap toggling (#308)
This commit is mostly a cherry-pick from `ahtn` at
https://github.com/tmk/tmk_keyboard/pull/255.
These are the changes:
* Adds ACTION_LAYER_ONESHOT
* Adds ONESHOT_TAP_TOGGLE
* Mentions sticky keys in the docs on oneshot.
Diffstat (limited to 'tmk_core/common/action.c')
| -rw-r--r-- | tmk_core/common/action.c | 97 |
1 files changed, 89 insertions, 8 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index f9e6c17dc..081e90b2d 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c | |||
| @@ -74,6 +74,7 @@ void process_action_kb(keyrecord_t *record) {} | |||
| 74 | 74 | ||
| 75 | void process_action(keyrecord_t *record) | 75 | void process_action(keyrecord_t *record) |
| 76 | { | 76 | { |
| 77 | bool do_release_oneshot = false; | ||
| 77 | keyevent_t event = record->event; | 78 | keyevent_t event = record->event; |
| 78 | #ifndef NO_ACTION_TAPPING | 79 | #ifndef NO_ACTION_TAPPING |
| 79 | uint8_t tap_count = record->tap.count; | 80 | uint8_t tap_count = record->tap.count; |
| @@ -81,6 +82,13 @@ void process_action(keyrecord_t *record) | |||
| 81 | 82 | ||
| 82 | if (IS_NOEVENT(event)) { return; } | 83 | if (IS_NOEVENT(event)) { return; } |
| 83 | 84 | ||
| 85 | #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) | ||
| 86 | if (has_oneshot_layer_timed_out()) { | ||
| 87 | dprintf("Oneshot layer: timeout\n"); | ||
| 88 | clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); | ||
| 89 | } | ||
| 90 | #endif | ||
| 91 | |||
| 84 | process_action_kb(record); | 92 | process_action_kb(record); |
| 85 | 93 | ||
| 86 | action_t action = store_or_get_action(event.pressed, event.key); | 94 | action_t action = store_or_get_action(event.pressed, event.key); |
| @@ -95,6 +103,15 @@ void process_action(keyrecord_t *record) | |||
| 95 | // clear the potential weak mods left by previously pressed keys | 103 | // clear the potential weak mods left by previously pressed keys |
| 96 | clear_weak_mods(); | 104 | clear_weak_mods(); |
| 97 | } | 105 | } |
| 106 | |||
| 107 | #ifndef NO_ACTION_ONESHOT | ||
| 108 | // notice we only clear the one shot layer if the pressed key is not a modifier. | ||
| 109 | if (is_oneshot_layer_active() && event.pressed && !IS_MOD(action.key.code)) { | ||
| 110 | clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); | ||
| 111 | do_release_oneshot = !is_oneshot_layer_active(); | ||
| 112 | } | ||
| 113 | #endif | ||
| 114 | |||
| 98 | switch (action.kind.id) { | 115 | switch (action.kind.id) { |
| 99 | /* Key and Mods */ | 116 | /* Key and Mods */ |
| 100 | case ACT_LMODS: | 117 | case ACT_LMODS: |
| @@ -139,24 +156,37 @@ void process_action(keyrecord_t *record) | |||
| 139 | // Oneshot modifier | 156 | // Oneshot modifier |
| 140 | if (event.pressed) { | 157 | if (event.pressed) { |
| 141 | if (tap_count == 0) { | 158 | if (tap_count == 0) { |
| 159 | dprint("MODS_TAP: Oneshot: 0\n"); | ||
| 142 | register_mods(mods); | 160 | register_mods(mods); |
| 143 | } | 161 | } else if (tap_count == 1) { |
| 144 | else if (tap_count == 1) { | ||
| 145 | dprint("MODS_TAP: Oneshot: start\n"); | 162 | dprint("MODS_TAP: Oneshot: start\n"); |
| 146 | set_oneshot_mods(mods); | 163 | set_oneshot_mods(mods); |
| 147 | } | 164 | #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 |
| 148 | else { | 165 | } else if (tap_count == ONESHOT_TAP_TOGGLE) { |
| 166 | dprint("MODS_TAP: Toggling oneshot"); | ||
| 167 | clear_oneshot_mods(); | ||
| 168 | set_oneshot_locked_mods(mods); | ||
| 169 | register_mods(mods); | ||
| 170 | #endif | ||
| 171 | } else { | ||
| 149 | register_mods(mods); | 172 | register_mods(mods); |
| 150 | } | 173 | } |
| 151 | } else { | 174 | } else { |
| 152 | if (tap_count == 0) { | 175 | if (tap_count == 0) { |
| 153 | clear_oneshot_mods(); | 176 | clear_oneshot_mods(); |
| 154 | unregister_mods(mods); | 177 | unregister_mods(mods); |
| 155 | } | 178 | } else if (tap_count == 1) { |
| 156 | else if (tap_count == 1) { | ||
| 157 | // Retain Oneshot mods | 179 | // Retain Oneshot mods |
| 158 | } | 180 | #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 |
| 159 | else { | 181 | if (mods & get_mods()) { |
| 182 | clear_oneshot_locked_mods(); | ||
| 183 | clear_oneshot_mods(); | ||
| 184 | unregister_mods(mods); | ||
| 185 | } | ||
| 186 | } else if (tap_count == ONESHOT_TAP_TOGGLE) { | ||
| 187 | // Toggle Oneshot Layer | ||
| 188 | #endif | ||
| 189 | } else { | ||
| 160 | clear_oneshot_mods(); | 190 | clear_oneshot_mods(); |
| 161 | unregister_mods(mods); | 191 | unregister_mods(mods); |
| 162 | } | 192 | } |
| @@ -309,6 +339,44 @@ void process_action(keyrecord_t *record) | |||
| 309 | event.pressed ? layer_move(action.layer_tap.val) : | 339 | event.pressed ? layer_move(action.layer_tap.val) : |
| 310 | layer_clear(); | 340 | layer_clear(); |
| 311 | break; | 341 | break; |
| 342 | #ifndef NO_ACTION_ONESHOT | ||
| 343 | case OP_ONESHOT: | ||
| 344 | // Oneshot modifier | ||
| 345 | #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1 | ||
| 346 | do_release_oneshot = false; | ||
| 347 | if (event.pressed) { | ||
| 348 | del_mods(get_oneshot_locked_mods()); | ||
| 349 | if (get_oneshot_layer_state() == ONESHOT_TOGGLED) { | ||
| 350 | reset_oneshot_layer(); | ||
| 351 | layer_off(action.layer_tap.val); | ||
| 352 | break; | ||
| 353 | } else if (tap_count < ONESHOT_TAP_TOGGLE) { | ||
| 354 | layer_on(action.layer_tap.val); | ||
| 355 | set_oneshot_layer(action.layer_tap.val, ONESHOT_START); | ||
| 356 | } | ||
| 357 | } else { | ||
| 358 | add_mods(get_oneshot_locked_mods()); | ||
| 359 | if (tap_count >= ONESHOT_TAP_TOGGLE) { | ||
| 360 | reset_oneshot_layer(); | ||
| 361 | clear_oneshot_locked_mods(); | ||
| 362 | set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED); | ||
| 363 | } else { | ||
| 364 | clear_oneshot_layer_state(ONESHOT_PRESSED); | ||
| 365 | } | ||
| 366 | } | ||
| 367 | #else | ||
| 368 | if (event.pressed) { | ||
| 369 | layer_on(action.layer_tap.val); | ||
| 370 | set_oneshot_layer(action.layer_tap.val, ONESHOT_START); | ||
| 371 | } else { | ||
| 372 | clear_oneshot_layer_state(ONESHOT_PRESSED); | ||
| 373 | if (tap_count > 1) { | ||
| 374 | clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); | ||
| 375 | } | ||
| 376 | } | ||
| 377 | #endif | ||
| 378 | break; | ||
| 379 | #endif | ||
| 312 | default: | 380 | default: |
| 313 | /* tap key */ | 381 | /* tap key */ |
| 314 | if (event.pressed) { | 382 | if (event.pressed) { |
| @@ -372,6 +440,18 @@ void process_action(keyrecord_t *record) | |||
| 372 | default: | 440 | default: |
| 373 | break; | 441 | break; |
| 374 | } | 442 | } |
| 443 | |||
| 444 | #ifndef NO_ACTION_ONESHOT | ||
| 445 | /* Because we switch layers after a oneshot event, we need to release the | ||
| 446 | * key before we leave the layer or no key up event will be generated. | ||
| 447 | */ | ||
| 448 | if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED ) ) { | ||
| 449 | record->event.pressed = false; | ||
| 450 | layer_on(get_oneshot_layer()); | ||
| 451 | process_action(record); | ||
| 452 | layer_off(get_oneshot_layer()); | ||
| 453 | } | ||
| 454 | #endif | ||
| 375 | } | 455 | } |
| 376 | 456 | ||
| 377 | 457 | ||
| @@ -560,6 +640,7 @@ bool is_tap_key(keypos_t key) | |||
| 560 | switch (action.layer_tap.code) { | 640 | switch (action.layer_tap.code) { |
| 561 | case 0x00 ... 0xdf: | 641 | case 0x00 ... 0xdf: |
| 562 | case OP_TAP_TOGGLE: | 642 | case OP_TAP_TOGGLE: |
| 643 | case OP_ONESHOT: | ||
| 563 | return true; | 644 | return true; |
| 564 | } | 645 | } |
| 565 | return false; | 646 | return false; |
