summaryrefslogtreecommitdiff
path: root/tmk_core/common/action.c
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/common/action.c')
-rw-r--r--tmk_core/common/action.c143
1 files changed, 116 insertions, 27 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index 0162fbd632..be6dea2b79 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -27,11 +27,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action_util.h"
#include "action.h"
-//#ifdef DEBUG_ACTION
+#ifdef DEBUG_ACTION
#include "debug.h"
-//#else
-//#include "nodebug.h"
-//#endif
+#else
+#include "nodebug.h"
+#endif
void action_exec(keyevent_t event)
@@ -46,7 +46,7 @@ void action_exec(keyevent_t event)
#ifndef NO_ACTION_TAPPING
action_tapping_process(record);
#else
- process_action(&record);
+ process_record(&record);
if (!IS_NOEVENT(record.event)) {
dprint("processed: "); debug_record(record); dprintln();
}
@@ -56,34 +56,32 @@ void action_exec(keyevent_t event)
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
bool disable_action_cache = false;
-void process_action_nocache(keyrecord_t *record)
+void process_record_nocache(keyrecord_t *record)
{
disable_action_cache = true;
- process_action(record);
+ process_record(record);
disable_action_cache = false;
}
#else
-void process_action_nocache(keyrecord_t *record)
+void process_record_nocache(keyrecord_t *record)
{
- process_action(record);
+ process_record(record);
}
#endif
__attribute__ ((weak))
-void process_action_kb(keyrecord_t *record) {}
+bool process_record_quantum(keyrecord_t *record) {
+ return true;
+}
-void process_action(keyrecord_t *record)
+void process_record(keyrecord_t *record)
{
- keyevent_t event = record->event;
-#ifndef NO_ACTION_TAPPING
- uint8_t tap_count = record->tap.count;
-#endif
+ if (IS_NOEVENT(record->event)) { return; }
- if (IS_NOEVENT(event)) { return; }
-
- process_action_kb(record);
+ if(!process_record_quantum(record))
+ return;
- action_t action = store_or_get_action(event.pressed, event.key);
+ action_t action = store_or_get_action(record->event.pressed, record->event.key);
dprint("ACTION: "); debug_action(action);
#ifndef NO_ACTION_LAYER
dprint(" layer_state: "); layer_debug();
@@ -91,10 +89,37 @@ void process_action(keyrecord_t *record)
#endif
dprintln();
+ process_action(record, action);
+}
+
+void process_action(keyrecord_t *record, action_t action)
+{
+ bool do_release_oneshot = false;
+ keyevent_t event = record->event;
+#ifndef NO_ACTION_TAPPING
+ uint8_t tap_count = record->tap.count;
+#endif
+
+#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
+
if (event.pressed) {
// 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 +164,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 +347,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 +448,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_record(record);
+ layer_off(get_oneshot_layer());
+ }
+#endif
}
@@ -560,6 +648,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;