summaryrefslogtreecommitdiff
path: root/tmk_core/common/action.c
diff options
context:
space:
mode:
authorThiago Alves <talk@thiagoalves.com.br>2016-05-05 18:41:37 -0700
committerJack Humbert <jack.humb@gmail.com>2016-05-05 21:41:37 -0400
commit74e97eefd7ae76f9ddcb76890a30aa9038804cdb (patch)
tree9bdf7ce6ffb97a024c8230e5e960d53503262ced /tmk_core/common/action.c
parentd4520cd3ac7550fc7243e9a76824d9ba674875c6 (diff)
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.c97
1 files changed, 89 insertions, 8 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index f9e6c17dc3..081e90b2db 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -74,6 +74,7 @@ void process_action_kb(keyrecord_t *record) {}
void process_action(keyrecord_t *record)
{
+ bool do_release_oneshot = false;
keyevent_t event = record->event;
#ifndef NO_ACTION_TAPPING
uint8_t tap_count = record->tap.count;
@@ -81,6 +82,13 @@ void process_action(keyrecord_t *record)
if (IS_NOEVENT(event)) { return; }
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ if (has_oneshot_layer_timed_out()) {
+ dprintf("Oneshot layer: timeout\n");
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ }
+#endif
+
process_action_kb(record);
action_t action = store_or_get_action(event.pressed, event.key);
@@ -95,6 +103,15 @@ void process_action(keyrecord_t *record)
// clear the potential weak mods left by previously pressed keys
clear_weak_mods();
}
+
+#ifndef NO_ACTION_ONESHOT
+ // notice we only clear the one shot layer if the pressed key is not a modifier.
+ if (is_oneshot_layer_active() && event.pressed && !IS_MOD(action.key.code)) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ do_release_oneshot = !is_oneshot_layer_active();
+ }
+#endif
+
switch (action.kind.id) {
/* Key and Mods */
case ACT_LMODS:
@@ -139,24 +156,37 @@ void process_action(keyrecord_t *record)
// Oneshot modifier
if (event.pressed) {
if (tap_count == 0) {
+ dprint("MODS_TAP: Oneshot: 0\n");
register_mods(mods);
- }
- else if (tap_count == 1) {
+ } else if (tap_count == 1) {
dprint("MODS_TAP: Oneshot: start\n");
set_oneshot_mods(mods);
- }
- else {
+ #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ } else if (tap_count == ONESHOT_TAP_TOGGLE) {
+ dprint("MODS_TAP: Toggling oneshot");
+ clear_oneshot_mods();
+ set_oneshot_locked_mods(mods);
+ register_mods(mods);
+ #endif
+ } else {
register_mods(mods);
}
} else {
if (tap_count == 0) {
clear_oneshot_mods();
unregister_mods(mods);
- }
- else if (tap_count == 1) {
+ } else if (tap_count == 1) {
// Retain Oneshot mods
- }
- else {
+ #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ if (mods & get_mods()) {
+ clear_oneshot_locked_mods();
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ }
+ } else if (tap_count == ONESHOT_TAP_TOGGLE) {
+ // Toggle Oneshot Layer
+ #endif
+ } else {
clear_oneshot_mods();
unregister_mods(mods);
}
@@ -309,6 +339,44 @@ void process_action(keyrecord_t *record)
event.pressed ? layer_move(action.layer_tap.val) :
layer_clear();
break;
+ #ifndef NO_ACTION_ONESHOT
+ case OP_ONESHOT:
+ // Oneshot modifier
+ #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ do_release_oneshot = false;
+ if (event.pressed) {
+ del_mods(get_oneshot_locked_mods());
+ if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
+ reset_oneshot_layer();
+ layer_off(action.layer_tap.val);
+ break;
+ } else if (tap_count < ONESHOT_TAP_TOGGLE) {
+ layer_on(action.layer_tap.val);
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ }
+ } else {
+ add_mods(get_oneshot_locked_mods());
+ if (tap_count >= ONESHOT_TAP_TOGGLE) {
+ reset_oneshot_layer();
+ clear_oneshot_locked_mods();
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
+ } else {
+ clear_oneshot_layer_state(ONESHOT_PRESSED);
+ }
+ }
+ #else
+ if (event.pressed) {
+ layer_on(action.layer_tap.val);
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ } else {
+ clear_oneshot_layer_state(ONESHOT_PRESSED);
+ if (tap_count > 1) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ }
+ }
+ #endif
+ break;
+ #endif
default:
/* tap key */
if (event.pressed) {
@@ -372,6 +440,18 @@ void process_action(keyrecord_t *record)
default:
break;
}
+
+#ifndef NO_ACTION_ONESHOT
+ /* Because we switch layers after a oneshot event, we need to release the
+ * key before we leave the layer or no key up event will be generated.
+ */
+ if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED ) ) {
+ record->event.pressed = false;
+ layer_on(get_oneshot_layer());
+ process_action(record);
+ layer_off(get_oneshot_layer());
+ }
+#endif
}
@@ -560,6 +640,7 @@ bool is_tap_key(keypos_t key)
switch (action.layer_tap.code) {
case 0x00 ... 0xdf:
case OP_TAP_TOGGLE:
+ case OP_ONESHOT:
return true;
}
return false;