aboutsummaryrefslogtreecommitdiff
path: root/quantum/action_tapping.h
blob: 0cf4aa12003d9693f3f08b4e0a405abaeeddd470 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/*
Copyright 2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

/* period of tapping(ms) */
#ifndef TAPPING_TERM
#    define TAPPING_TERM 200
#endif

/* period of quick tap(ms) */
#if !defined(QUICK_TAP_TERM) || QUICK_TAP_TERM > TAPPING_TERM
#    define QUICK_TAP_TERM TAPPING_TERM
#endif

/* tap count needed for toggling a feature */
#ifndef TAPPING_TOGGLE
#    define TAPPING_TOGGLE 5
#endif

#define WAITING_BUFFER_SIZE 8

#ifndef NO_ACTION_TAPPING
uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache);
uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache);
void     action_tapping_process(keyrecord_t record);
#endif

uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record);
uint16_t get_quick_tap_term(uint16_t keycode, keyrecord_t *record);
bool     get_permissive_hold(uint16_t keycode, keyrecord_t *record);
bool     get_retro_tapping(uint16_t keycode, keyrecord_t *record);
bool     get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record);

#ifdef CHORDAL_HOLD
/**
 * Callback to say when a key chord before the tapping term may be held.
 *
 * In keymap.c, define the callback
 *
 *     bool get_chordal_hold(uint16_t tap_hold_keycode,
 *                           keyrecord_t* tap_hold_record,
 *                           uint16_t other_keycode,
 *                           keyrecord_t* other_record) {
 *        // Conditions...
 *     }
 *
 * This callback is called when:
 *
 * 1. `tap_hold_keycode` is pressed.
 * 2. `other_keycode` is pressed while `tap_hold_keycode` is still held,
 *     provided `other_keycode` is *not* also a tap-hold key and it is pressed
 *     before the tapping term.
 *
 * If false is returned, this has the effect of immediately settling the
 * tap-hold key as tapped. If true is returned, the tap-hold key is still
 * unsettled, and may be settled as held depending on configuration and
 * subsequent events.
 *
 * @param tap_hold_keycode   Keycode of the tap-hold key.
 * @param tap_hold_record    Record from the tap-hold press event.
 * @param other_keycode      Keycode of the other key.
 * @param other_record       Record from the other key's press event.
 * @return True if the tap-hold key may be considered held; false if tapped.
 */
bool get_chordal_hold(uint16_t tap_hold_keycode, keyrecord_t *tap_hold_record, uint16_t other_keycode, keyrecord_t *other_record);

/**
 * Default "opposite hands rule" for whether a key chord may settle as held.
 *
 * This function returns true when the tap-hold key and other key are on
 * "opposite hands." In detail, handedness of the two keys are compared. If
 * handedness values differ, or if either handedness is '*', the function
 * returns true, indicating that it may be held. Otherwise, it returns false,
 * in which case the tap-hold key is immediately settled at tapped.
 *
 * @param tap_hold_record  Record of the active tap-hold key press.
 * @param other_record     Record of the other, interrupting key press.
 * @return True if the tap-hold key may be considered held; false if tapped.
 */
bool get_chordal_hold_default(keyrecord_t *tap_hold_record, keyrecord_t *other_record);

/**
 * Gets the handedness of a key.
 *
 * This function returns:
 *   'L' for keys pressed by the left hand,
 *   'R' for keys on the right hand,
 *   '*' for keys exempt from the "opposite hands rule." This could be used
 *       perhaps on thumb keys or keys that might be pressed by either hand.
 *
 * @param key   A key matrix position.
 * @return Handedness value.
 */
char chordal_hold_handedness(keypos_t key);

extern const char chordal_hold_layout[MATRIX_ROWS][MATRIX_COLS] PROGMEM;
#endif

#ifdef FLOW_TAP_TERM
/**
 * Callback to specify the keys where Flow Tap is enabled.
 *
 * Flow Tap is constrained to certain keys by the following rule: this callback
 * is called for both the tap-hold key *and* the key press immediately preceding
 * it. If the callback returns true for both keycodes, Flow Tap is enabled.
 *
 * The default implementation of this callback corresponds to
 *
 *     bool is_flow_tap_key(uint16_t keycode) {
 *       switch (get_tap_keycode(keycode)) {
 *         case KC_SPC:
 *         case KC_A ... KC_Z:
 *         case KC_DOT:
 *         case KC_COMM:
 *         case KC_SCLN:
 *         case KC_SLSH:
 *           return true;
 *       }
 *       return false;
 *     }
 *
 * @param keycode Keycode of the key.
 * @return Whether to enable Flow Tap for this key.
 */
bool is_flow_tap_key(uint16_t keycode);

/**
 * Callback to customize Flow Tap filtering.
 *
 * Flow Tap acts only when key events are closer together than this time.
 *
 * Return a time of 0 to disable filtering. In this way, Flow Tap may be
 * disabled for certain tap-hold keys, or when following certain previous keys.
 *
 * The default implementation of this callback is
 *
 *     uint16_t get_flow_tap_term(uint16_t keycode, keyrecord_t* record,
 *                                uint16_t prev_keycode) {
 *       if (is_flow_tap_key(keycode) && is_flow_tap_key(prev_keycode)) {
 *         return g_flow_tap_term;
 *       }
 *       return 0;
 *     }
 *
 * NOTE: If both `is_flow_tap_key()` and `get_flow_tap_term()` are defined, then
 * `get_flow_tap_term()` takes precedence.
 *
 * @param keycode Keycode of the tap-hold key.
 * @param record keyrecord_t of the tap-hold event.
 * @param prev_keycode Keycode of the previously pressed key.
 * @return Time in milliseconds.
 */
uint16_t get_flow_tap_term(uint16_t keycode, keyrecord_t *record, uint16_t prev_keycode);

/** Updates the Flow Tap last key and timer. */
void flow_tap_update_last_event(keyrecord_t *record);
#endif // FLOW_TAP_TERM

#ifdef DYNAMIC_TAPPING_TERM_ENABLE
extern uint16_t g_tapping_term;
#endif

#if defined(TAPPING_TERM_PER_KEY) && !defined(NO_ACTION_TAPPING)
#    define GET_TAPPING_TERM(keycode, record) get_tapping_term(keycode, record)
#elif defined(DYNAMIC_TAPPING_TERM_ENABLE) && !defined(NO_ACTION_TAPPING)
#    define GET_TAPPING_TERM(keycode, record) g_tapping_term
#else
#    define GET_TAPPING_TERM(keycode, record) (TAPPING_TERM)
#endif

#ifdef QUICK_TAP_TERM_PER_KEY
#    define GET_QUICK_TAP_TERM(keycode, record) get_quick_tap_term(keycode, record)
#else
#    define GET_QUICK_TAP_TERM(keycode, record) (QUICK_TAP_TERM)
#endif