#include <stdint.h>
#include <stdbool.h>
#include "action.h"
+#include "action_layer.h"
#include "action_tapping.h"
+#include "keycode.h"
#include "timer.h"
-#include "debug.h"
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
#ifndef NO_ACTION_TAPPING
static bool process_tapping(keyrecord_t *record);
static bool waiting_buffer_enq(keyrecord_t record);
static void waiting_buffer_clear(void);
-#if TAPPING_TERM >= 500
static bool waiting_buffer_typed(keyevent_t event);
-#endif
static bool waiting_buffer_has_anykey_pressed(void);
static void waiting_buffer_scan_tap(void);
static void debug_tapping_key(void);
// first tap!
debug("Tapping: First tap(0->1).\n");
tapping_key.tap.count = 1;
- tapping_key.tap.interrupted = (waiting_buffer_has_anykey_pressed() ? true : false);
debug_tapping_key();
process_action(&tapping_key);
- // enqueue
+ // copy tapping state
keyp->tap = tapping_key.tap;
+ // enqueue
return false;
}
#if TAPPING_TERM >= 500
- /* This can prevent from typing some tap keys in a row at a time. */
- else if (!event.pressed && waiting_buffer_typed(event)) {
- // other key typed. not tap.
+ /* Process a key typed within TAPPING_TERM
+ * This can register the key before settlement of tapping,
+ * useful for long TAPPING_TERM but may prevent fast typing.
+ */
+ else if (IS_RELEASED(event) && waiting_buffer_typed(event)) {
debug("Tapping: End. No tap. Interfered by typing key\n");
process_action(&tapping_key);
tapping_key = (keyrecord_t){};
debug_tapping_key();
-
// enqueue
return false;
}
#endif
+ /* Process release event of a key pressed before tapping starts
+ * Without this unexpected repeating will occur with having fast repeating setting
+ * https://github.com/tmk/tmk_keyboard/issues/60
+ */
+ else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) {
+ // Modifier should be retained till end of this tapping.
+ action_t action = layer_switch_get_action(event.key);
+ switch (action.kind.id) {
+ case ACT_LMODS:
+ case ACT_RMODS:
+ if (action.key.mods && !action.key.code) return false;
+ if (IS_MOD(action.key.code)) return false;
+ break;
+ case ACT_LMODS_TAP:
+ case ACT_RMODS_TAP:
+ if (action.key.mods && keyp->tap.count == 0) return false;
+ if (IS_MOD(action.key.code)) return false;
+ break;
+ }
+ // Release of key should be process immediately.
+ debug("Tapping: release event of a key pressed before tapping\n");
+ process_action(keyp);
+ return true;
+ }
else {
- // other key events shall be enq'd till tapping state settles.
+ // set interrupted flag when other key preesed during tapping
+ if (event.pressed) {
+ tapping_key.tap.interrupted = true;
+ }
+ // enqueue
return false;
}
}
debug_tapping_key();
return true;
}
- else if (is_tap_key(keyp->event.key) && event.pressed) {
+ else if (is_tap_key(event.key) && event.pressed) {
if (tapping_key.tap.count > 1) {
debug("Tapping: Start new tap with releasing last tap(>1).\n");
// unregister key
return true;
}
else {
- if (!IS_NOEVENT(keyp->event)) {
+ if (!IS_NOEVENT(event)) {
debug("Tapping: key event while last tap(>0).\n");
}
process_action(keyp);
tapping_key = (keyrecord_t){};
return true;
}
- else if (is_tap_key(keyp->event.key) && event.pressed) {
+ else if (is_tap_key(event.key) && event.pressed) {
if (tapping_key.tap.count > 1) {
debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
// unregister key
return true;
}
else {
- if (!IS_NOEVENT(keyp->event)) {
+ if (!IS_NOEVENT(event)) {
debug("Tapping: key event while last timeout tap(>0).\n");
}
process_action(keyp);
}
} else if (IS_TAPPING_RELEASED()) {
if (WITHIN_TAPPING_TERM(event)) {
- if (tapping_key.tap.count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) {
- // sequential tap.
- keyp->tap = tapping_key.tap;
- keyp->tap.count += 1;
- debug("Tapping: Tap press("); debug_dec(keyp->tap.count); debug(")\n");
- process_action(keyp);
- tapping_key = *keyp;
- debug_tapping_key();
- return true;
- } else if (event.pressed && is_tap_key(event.key)) {
- // Sequential tap can be interfered with other tap key.
- debug("Tapping: Start with interfering other tap.\n");
- tapping_key = *keyp;
- waiting_buffer_scan_tap();
- debug_tapping_key();
- return true;
+ if (event.pressed) {
+ if (IS_TAPPING_KEY(event.key)) {
+ if (!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
+ // sequential tap.
+ keyp->tap = tapping_key.tap;
+ if (keyp->tap.count < 15) keyp->tap.count += 1;
+ debug("Tapping: Tap press("); debug_dec(keyp->tap.count); debug(")\n");
+ process_action(keyp);
+ tapping_key = *keyp;
+ debug_tapping_key();
+ return true;
+ } else {
+ // FIX: start new tap again
+ tapping_key = *keyp;
+ return true;
+ }
+ } else if (is_tap_key(event.key)) {
+ // Sequential tap can be interfered with other tap key.
+ debug("Tapping: Start with interfering other tap.\n");
+ tapping_key = *keyp;
+ waiting_buffer_scan_tap();
+ debug_tapping_key();
+ return true;
+ } else {
+ // should none in buffer
+ // FIX: interrupted when other key is pressed
+ tapping_key.tap.interrupted = true;
+ process_action(keyp);
+ return true;
+ }
} else {
- if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n");
+ if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
process_action(keyp);
return true;
}
} else {
+ // FIX: process_aciton here?
// timeout. no sequential tap.
debug("Tapping: End(Timeout after releasing last tap): ");
debug_event(event); debug("\n");
return false;
}
}
- // not tapping satate
+ // not tapping state
else {
if (event.pressed && is_tap_key(event.key)) {
debug("Tapping: Start(Press tap key).\n");
waiting_buffer_tail = 0;
}
-#if TAPPING_TERM >= 500
bool waiting_buffer_typed(keyevent_t event)
{
for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
}
return false;
}
-#endif
bool waiting_buffer_has_anykey_pressed(void)
{