@ -15,14 +15,10 @@
# error "IGNORE_MOD_TAP_INTERRUPT is no longer necessary as it is now the default behavior of mod-tap keys. Please remove it from your config."
# error "IGNORE_MOD_TAP_INTERRUPT is no longer necessary as it is now the default behavior of mod-tap keys. Please remove it from your config."
# endif
# endif
# define IS_TAPPING() IS_EVENT(tapping_key.event)
# define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
# define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
# define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
# ifndef COMBO_ENABLE
# ifndef COMBO_ENABLE
# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)))
# define IS_TAPPING_RECORD(r) (KEYEQ(tapping_key.event.key, (r->event.key)))
# else
# else
# define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode)
# define IS_TAPPING_RECORD(r) (KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode)
# endif
# endif
# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < GET_TAPPING_TERM(get_record_keycode(&tapping_key, false), &tapping_key))
# define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < GET_TAPPING_TERM(get_record_keycode(&tapping_key, false), &tapping_key))
# define WITHIN_QUICK_TAP_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < GET_QUICK_TAP_TERM(get_record_keycode(&tapping_key, false), &tapping_key))
# define WITHIN_QUICK_TAP_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < GET_QUICK_TAP_TERM(get_record_keycode(&tapping_key, false), &tapping_key))
@ -94,7 +90,7 @@ void action_tapping_process(keyrecord_t record) {
ac_dprintf ( " OVERFLOW: CLEAR ALL STATES \n " ) ;
ac_dprintf ( " OVERFLOW: CLEAR ALL STATES \n " ) ;
clear_keyboard ( ) ;
clear_keyboard ( ) ;
waiting_buffer_clear ( ) ;
waiting_buffer_clear ( ) ;
tapping_key = ( keyrecord_t ) { } ;
tapping_key = ( keyrecord_t ) { 0 } ;
}
}
}
}
@ -121,7 +117,7 @@ void action_tapping_process(keyrecord_t record) {
* conditional uses of it are hidden inside macros named TAP_ . . .
* conditional uses of it are hidden inside macros named TAP_ . . .
*/
*/
# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
# define TAP_DEFINE_KEYCODE uint16_t tapping_keycode = get_record_keycode(&tapping_key, false)
# define TAP_DEFINE_KEYCODE const uint16_t tapping_keycode = get_record_keycode(&tapping_key, false)
# else
# else
# define TAP_DEFINE_KEYCODE
# define TAP_DEFINE_KEYCODE
# endif
# endif
@ -167,12 +163,37 @@ void action_tapping_process(keyrecord_t record) {
*/
*/
/* return true when key event is processed or consumed. */
/* return true when key event is processed or consumed. */
bool process_tapping ( keyrecord_t * keyp ) {
bool process_tapping ( keyrecord_t * keyp ) {
keyevent_t event = keyp - > event ;
const keyevent_t event = keyp - > event ;
// state machine is in the "reset" state, no tapping key is to be
// processed
if ( IS_NOEVENT ( tapping_key . event ) & & IS_EVENT ( event ) ) {
if ( event . pressed & & is_tap_record ( keyp ) ) {
// the currently pressed key is a tapping key, therefore transition
// into the "pressed" tapping key state
ac_dprintf ( " Tapping: Start(Press tap key). \n " ) ;
tapping_key = * keyp ;
process_record_tap_hint ( & tapping_key ) ;
waiting_buffer_scan_tap ( ) ;
debug_tapping_key ( ) ;
return true ;
} else {
// the current key is just a regular key, pass it on for regular
// processing
process_record ( keyp ) ;
return true ;
}
}
TAP_DEFINE_KEYCODE ;
TAP_DEFINE_KEYCODE ;
// if tapping
// process "pressed" tapping key state
if ( IS_TAPPING_PRESSED ( ) ) {
if ( tapping_key . event . pressed ) {
if ( WITHIN_TAPPING_TERM ( event ) | | MAYBE_RETRO_SHIFTING ( event ) ) {
if ( WITHIN_TAPPING_TERM ( event ) | | MAYBE_RETRO_SHIFTING ( event ) ) {
if ( IS_NOEVENT ( event ) ) {
// early return for tick events
return true ;
}
if ( tapping_key . tap . count = = 0 ) {
if ( tapping_key . tap . count = = 0 ) {
if ( IS_TAPPING_RECORD ( keyp ) & & ! event . pressed ) {
if ( IS_TAPPING_RECORD ( keyp ) & & ! event . pressed ) {
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
@ -196,7 +217,7 @@ bool process_tapping(keyrecord_t *keyp) {
// clang-format off
// clang-format off
else if (
else if (
(
(
IS_RELEASED ( event ) & & waiting_buffer_typed ( event ) & &
! event . pressed & & waiting_buffer_typed ( event ) & &
TAP_GET_PERMISSIVE_HOLD
TAP_GET_PERMISSIVE_HOLD
)
)
// Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
// Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
@ -214,7 +235,7 @@ bool process_tapping(keyrecord_t *keyp) {
| | (
| | (
TAP_IS_RETRO
TAP_IS_RETRO
& & ( event . key . col ! = tapping_key . event . key . col | | event . key . row ! = tapping_key . event . key . row )
& & ( event . key . col ! = tapping_key . event . key . col | | event . key . row ! = tapping_key . event . key . row )
& & IS_RELEASED ( event ) & & waiting_buffer_typed ( event )
& & ! event . pressed & & waiting_buffer_typed ( event )
)
)
)
)
)
)
@ -222,7 +243,7 @@ bool process_tapping(keyrecord_t *keyp) {
// clang-format on
// clang-format on
ac_dprintf ( " Tapping: End. No tap. Interfered by typing key \n " ) ;
ac_dprintf ( " Tapping: End. No tap. Interfered by typing key \n " ) ;
process_record ( & tapping_key ) ;
process_record ( & tapping_key ) ;
tapping_key = ( keyrecord_t ) { } ;
tapping_key = ( keyrecord_t ) { 0 } ;
debug_tapping_key ( ) ;
debug_tapping_key ( ) ;
// enqueue
// enqueue
return false ;
return false ;
@ -231,7 +252,7 @@ bool process_tapping(keyrecord_t *keyp) {
* Without this unexpected repeating will occur with having fast repeating setting
* Without this unexpected repeating will occur with having fast repeating setting
* https : //github.com/tmk/tmk_keyboard/issues/60
* https : //github.com/tmk/tmk_keyboard/issues/60
*/
*/
else if ( IS_RELEASED ( event ) & & ! waiting_buffer_typed ( event ) ) {
else if ( ! event . pressed & & ! waiting_buffer_typed ( event ) ) {
// Modifier/Layer should be retained till end of this tapping.
// Modifier/Layer should be retained till end of this tapping.
action_t action = layer_switch_get_action ( event . key ) ;
action_t action = layer_switch_get_action ( event . key ) ;
switch ( action . kind . id ) {
switch ( action . kind . id ) {
@ -267,7 +288,7 @@ bool process_tapping(keyrecord_t *keyp) {
if ( TAP_GET_HOLD_ON_OTHER_KEY_PRESS ) {
if ( TAP_GET_HOLD_ON_OTHER_KEY_PRESS ) {
ac_dprintf ( " Tapping: End. No tap. Interfered by pressed key \n " ) ;
ac_dprintf ( " Tapping: End. No tap. Interfered by pressed key \n " ) ;
process_record ( & tapping_key ) ;
process_record ( & tapping_key ) ;
tapping_key = ( keyrecord_t ) { } ;
tapping_key = ( keyrecord_t ) { 0 } ;
debug_tapping_key ( ) ;
debug_tapping_key ( ) ;
// enqueue
// enqueue
return false ;
return false ;
@ -295,6 +316,7 @@ bool process_tapping(keyrecord_t *keyp) {
. event . key = tapping_key . event . key ,
. event . key = tapping_key . event . key ,
. event . time = event . time ,
. event . time = event . time ,
. event . pressed = false ,
. event . pressed = false ,
. event . type = tapping_key . event . type ,
# ifdef COMBO_ENABLE
# ifdef COMBO_ENABLE
. keycode = tapping_key . keycode ,
. keycode = tapping_key . keycode ,
# endif
# endif
@ -307,9 +329,7 @@ bool process_tapping(keyrecord_t *keyp) {
debug_tapping_key ( ) ;
debug_tapping_key ( ) ;
return true ;
return true ;
} else {
} else {
if ( IS_EVENT ( event ) ) {
ac_dprintf ( " Tapping: key event while last tap(>0). \n " ) ;
ac_dprintf ( " Tapping: key event while last tap(>0). \n " ) ;
}
process_record ( keyp ) ;
process_record ( keyp ) ;
return true ;
return true ;
}
}
@ -322,15 +342,18 @@ bool process_tapping(keyrecord_t *keyp) {
debug_event ( event ) ;
debug_event ( event ) ;
ac_dprintf ( " \n " ) ;
ac_dprintf ( " \n " ) ;
process_record ( & tapping_key ) ;
process_record ( & tapping_key ) ;
tapping_key = ( keyrecord_t ) { } ;
tapping_key = ( keyrecord_t ) { 0 } ;
debug_tapping_key ( ) ;
debug_tapping_key ( ) ;
return false ;
return false ;
} else {
} else {
if ( IS_NOEVENT ( event ) ) {
return true ;
}
if ( IS_TAPPING_RECORD ( keyp ) & & ! event . pressed ) {
if ( IS_TAPPING_RECORD ( keyp ) & & ! event . pressed ) {
ac_dprintf ( " Tapping: End. last timeout tap release(>0). " ) ;
ac_dprintf ( " Tapping: End. last timeout tap release(>0). " ) ;
keyp - > tap = tapping_key . tap ;
keyp - > tap = tapping_key . tap ;
process_record ( keyp ) ;
process_record ( keyp ) ;
tapping_key = ( keyrecord_t ) { } ;
tapping_key = ( keyrecord_t ) { 0 } ;
return true ;
return true ;
} else if ( is_tap_record ( keyp ) & & event . pressed ) {
} else if ( is_tap_record ( keyp ) & & event . pressed ) {
if ( tapping_key . tap . count > 1 ) {
if ( tapping_key . tap . count > 1 ) {
@ -341,6 +364,7 @@ bool process_tapping(keyrecord_t *keyp) {
. event . key = tapping_key . event . key ,
. event . key = tapping_key . event . key ,
. event . time = event . time ,
. event . time = event . time ,
. event . pressed = false ,
. event . pressed = false ,
. event . type = tapping_key . event . type ,
# ifdef COMBO_ENABLE
# ifdef COMBO_ENABLE
. keycode = tapping_key . keycode ,
. keycode = tapping_key . keycode ,
# endif
# endif
@ -353,16 +377,20 @@ bool process_tapping(keyrecord_t *keyp) {
debug_tapping_key ( ) ;
debug_tapping_key ( ) ;
return true ;
return true ;
} else {
} else {
if ( IS_EVENT ( event ) ) {
ac_dprintf ( " Tapping: key event while last timeout tap(>0). \n " ) ;
ac_dprintf ( " Tapping: key event while last timeout tap(>0). \n " ) ;
}
process_record ( keyp ) ;
process_record ( keyp ) ;
return true ;
return true ;
}
}
}
}
}
}
} else if ( IS_TAPPING_RELEASED ( ) ) {
}
// process "released" tapping key state
else {
if ( WITHIN_TAPPING_TERM ( event ) | | MAYBE_RETRO_SHIFTING ( event ) ) {
if ( WITHIN_TAPPING_TERM ( event ) | | MAYBE_RETRO_SHIFTING ( event ) ) {
if ( IS_NOEVENT ( event ) ) {
// early return for tick events
return true ;
}
if ( event . pressed ) {
if ( event . pressed ) {
if ( IS_TAPPING_RECORD ( keyp ) ) {
if ( IS_TAPPING_RECORD ( keyp ) ) {
if ( WITHIN_QUICK_TAP_TERM ( event ) & & ! tapping_key . tap . interrupted & & tapping_key . tap . count > 0 ) {
if ( WITHIN_QUICK_TAP_TERM ( event ) & & ! tapping_key . tap . interrupted & & tapping_key . tap . count > 0 ) {
@ -393,35 +421,20 @@ bool process_tapping(keyrecord_t *keyp) {
return true ;
return true ;
}
}
} else {
} else {
if ( IS_EVENT ( event ) ) ac_dprintf ( " Tapping: other key just after tap. \n " ) ;
ac_dprintf ( " Tapping: other key just after tap. \n " ) ;
process_record ( keyp ) ;
process_record ( keyp ) ;
return true ;
return true ;
}
}
} else {
} else {
// FIX: process_action here?
// Timeout - reset state machine.
// timeout. no sequential tap.
ac_dprintf ( " Tapping: End(Timeout after releasing last tap): " ) ;
ac_dprintf ( " Tapping: End(Timeout after releasing last tap): " ) ;
debug_event ( event ) ;
debug_event ( event ) ;
ac_dprintf ( " \n " ) ;
ac_dprintf ( " \n " ) ;
tapping_key = ( keyrecord_t ) { } ;
tapping_key = ( keyrecord_t ) { 0 } ;
debug_tapping_key ( ) ;
debug_tapping_key ( ) ;
return false ;
return false ;
}
}
}
}
// not tapping state
else {
if ( event . pressed & & is_tap_record ( keyp ) ) {
ac_dprintf ( " Tapping: Start(Press tap key). \n " ) ;
tapping_key = * keyp ;
process_record_tap_hint ( & tapping_key ) ;
waiting_buffer_scan_tap ( ) ;
debug_tapping_key ( ) ;
return true ;
} else {
process_record ( keyp ) ;
return true ;
}
}
}
}
/** \brief Waiting buffer enq
/** \brief Waiting buffer enq
@ -484,15 +497,18 @@ __attribute__((unused)) bool waiting_buffer_has_anykey_pressed(void) {
* FIXME : Needs docs
* FIXME : Needs docs
*/
*/
void waiting_buffer_scan_tap ( void ) {
void waiting_buffer_scan_tap ( void ) {
// tapping already is settled
// early return if:
if ( tapping_key . tap . count > 0 ) return ;
// - tapping already is settled
// invalid state: tapping_key released && tap.count == 0
// - invalid state: tapping_key released && tap.count == 0
if ( ! tapping_key . event . pressed ) return ;
if ( ( tapping_key . tap . count > 0 ) | | ! tapping_key . event . pressed ) {
return ;
}
for ( uint8_t i = waiting_buffer_tail ; i ! = waiting_buffer_head ; i = ( i + 1 ) % WAITING_BUFFER_SIZE ) {
for ( uint8_t i = waiting_buffer_tail ; i ! = waiting_buffer_head ; i = ( i + 1 ) % WAITING_BUFFER_SIZE ) {
if ( IS_TAPPING_KEY ( waiting_buffer [ i ] . event . key ) & & ! waiting_buffer [ i ] . event . pressed & & WITHIN_TAPPING_TERM ( waiting_buffer [ i ] . event ) ) {
keyrecord_t * candidate = & waiting_buffer [ i ] ;
tapping_key . tap . count = 1 ;
if ( IS_EVENT ( candidate - > event ) & & KEYEQ ( candidate - > event . key , tapping_key . event . key ) & & ! candidate - > event . pressed & & WITHIN_TAPPING_TERM ( candidate - > event ) ) {
waiting_buffer [ i ] . tap . count = 1 ;
tapping_key . tap . count = 1 ;
candidate - > tap . count = 1 ;
process_record ( & tapping_key ) ;
process_record ( & tapping_key ) ;
ac_dprintf ( " waiting_buffer_scan_tap: found at [%u] \n " , i ) ;
ac_dprintf ( " waiting_buffer_scan_tap: found at [%u] \n " , i ) ;