aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrashna Jaelre <drashna@live.com>2019-04-05 12:47:25 -0700
committerJack Humbert <jack.humb@gmail.com>2019-04-05 15:47:25 -0400
commit5701b75e3c10728d424ec058d26ef2e354aba0c0 (patch)
tree979b01e8226d5fb33789bd1c41853c8412bfa669
parent4c1760883e2e0ed710348f02bc791786ed0c1b04 (diff)
downloadqmk_firmware-5701b75e3c10728d424ec058d26ef2e354aba0c0.tar.gz
qmk_firmware-5701b75e3c10728d424ec058d26ef2e354aba0c0.zip
Custom Tapping Term per key (#5009)
* Add customizable tapping terms * Add Documentation * Fix function * Fixes * It's not a pointer * Add debugging output * Update documentation to be at least vaguely accurate * Use `get_tapping_term(tapping_key.event)` instead `e` doesn't include column and row information, properly. It registers as 255, regardless of the actual keypress. However `tapping_key.event` actually gives the correct column and row information. It appears be the correct structure to use. In fact, it looks like the issue is that `e` is actually the "TICK" structure, as defined in keyboard.h * Use variable tapping term value rather than define * Silly drashna - tapping_key.event, not event * add get_event_keycode() function * Fix typo Co-Authored-By: drashna <drashna@live.com> * Remove post_process_record_quantum since it's the wrong PR * Update quantum/quantum.c Co-Authored-By: drashna <drashna@live.com> * Better handle ifdef statement for permissive hold Since we can't be sure that tapping term is actually 500 * Update quantum.c comments based on feedback * Clean up get_tapping_term function Clean up function so that users don't need to call the event function, and instead only check the keycode * Add ability to run functionality on and off * Make ifdef's more compact
-rw-r--r--docs/config_options.md2
-rw-r--r--docs/custom_quantum_functions.md29
-rw-r--r--quantum/quantum.c32
-rw-r--r--quantum/quantum.h2
-rw-r--r--tmk_core/common/action_tapping.c20
-rw-r--r--tmk_core/common/action_tapping.h2
6 files changed, 74 insertions, 13 deletions
diff --git a/docs/config_options.md b/docs/config_options.md
index ad42e9780..c5131a841 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -126,6 +126,8 @@ If you define these options you will enable the associated feature, which may in
126 126
127* `#define TAPPING_TERM 200` 127* `#define TAPPING_TERM 200`
128 * how long before a tap becomes a hold, if set above 500, a key tapped during the tapping term will turn it into a hold too 128 * how long before a tap becomes a hold, if set above 500, a key tapped during the tapping term will turn it into a hold too
129* `#define TAPPING_TERM_PER_KEY`
130 * enables handling for per key `TAPPING_TERM` settings
129* `#define RETRO_TAPPING` 131* `#define RETRO_TAPPING`
130 * tap anyway, even after TAPPING_TERM, if there was no other key interruption between press and release 132 * tap anyway, even after TAPPING_TERM, if there was no other key interruption between press and release
131 * See [Retro Tapping](feature_advanced_keycodes.md#retro-tapping) for details 133 * See [Retro Tapping](feature_advanced_keycodes.md#retro-tapping) for details
diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md
index 418faf349..6287b9530 100644
--- a/docs/custom_quantum_functions.md
+++ b/docs/custom_quantum_functions.md
@@ -323,6 +323,7 @@ uint32_t layer_state_set_user(uint32_t state) {
323* Keyboard/Revision: `uint32_t layer_state_set_kb(uint32_t state)` 323* Keyboard/Revision: `uint32_t layer_state_set_kb(uint32_t state)`
324* Keymap: `uint32_t layer_state_set_user(uint32_t state)` 324* Keymap: `uint32_t layer_state_set_user(uint32_t state)`
325 325
326
326The `state` is the bitmask of the active layers, as explained in the [Keymap Overview](keymap.md#keymap-layer-status) 327The `state` is the bitmask of the active layers, as explained in the [Keymap Overview](keymap.md#keymap-layer-status)
327 328
328 329
@@ -460,3 +461,31 @@ And you're done. The RGB layer indication will only work if you want it to. And
460* Keymap: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)` and `void eeconfig_update_user(uint32_t val)` 461* Keymap: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)` and `void eeconfig_update_user(uint32_t val)`
461 462
462The `val` is the value of the data that you want to write to EEPROM. And the `eeconfig_read_*` function return a 32 bit (DWORD) value from the EEPROM. 463The `val` is the value of the data that you want to write to EEPROM. And the `eeconfig_read_*` function return a 32 bit (DWORD) value from the EEPROM.
464
465# Custom Tapping Term
466
467By default, the tapping term is defined globally, and is not configurable by key. For most users, this is perfectly fine. But in come cases, dual function keys would be greatly improved by different timeouts than `LT` keys, or because some keys may be easier to hold than others. Instead of using custom key codes for each, this allows for per key configurable `TAPPING_TERM`.
468
469To enable this functionality, you need to add `#define TAPPING_TERM_PER_KEY` to your `config.h`, first.
470
471
472## Example `get_tapping_term` Implementation
473
474To change the `TAPPING TERM` based on the keycode, you'd want to add something like the following to your `keymap.c` file:
475
476```c
477uint16_t get_tapping_term(uint16_t keycode) {
478 switch (keycode) {
479 case SFT_T(KC_SPC):
480 return TAPPING_TERM + 1250;
481 case LT(1, KC_GRV):
482 return 130;
483 default:
484 return TAPPING_TERM;
485 }
486}
487```
488
489### `get_tapping_term` Function Documentation
490
491Unlike many of the other functions here, there isn't a need (or even reason) to have a quantum or keyboard level function. Only a user level function is useful here, so no need to mark it as such.
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 8c928441c..48c338fc8 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -225,27 +225,39 @@ static uint16_t scs_timer[2] = {0, 0};
225 */ 225 */
226static bool grave_esc_was_shifted = false; 226static bool grave_esc_was_shifted = false;
227 227
228bool process_record_quantum(keyrecord_t *record) { 228/* Convert record into usable keycode via the contained event. */
229uint16_t get_record_keycode(keyrecord_t *record) {
230 return get_event_keycode(record->event);
231}
229 232
230 /* This gets the keycode from the key pressed */ 233
231 keypos_t key = record->event.key; 234/* Convert event into usable keycode. Checks the layer cache to ensure that it
232 uint16_t keycode; 235 * retains the correct keycode after a layer change, if the key is still pressed.
236 */
237uint16_t get_event_keycode(keyevent_t event) {
233 238
234 #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) 239 #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
235 /* TODO: Use store_or_get_action() or a similar function. */ 240 /* TODO: Use store_or_get_action() or a similar function. */
236 if (!disable_action_cache) { 241 if (!disable_action_cache) {
237 uint8_t layer; 242 uint8_t layer;
238 243
239 if (record->event.pressed) { 244 if (event.pressed) {
240 layer = layer_switch_get_layer(key); 245 layer = layer_switch_get_layer(event.key);
241 update_source_layers_cache(key, layer); 246 update_source_layers_cache(event.key, layer);
242 } else { 247 } else {
243 layer = read_source_layers_cache(key); 248 layer = read_source_layers_cache(event.key);
244 } 249 }
245 keycode = keymap_key_to_keycode(layer, key); 250 return keymap_key_to_keycode(layer, event.key);
246 } else 251 } else
247 #endif 252 #endif
248 keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key); 253 return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key);
254}
255
256/* Main keycode processing function. Hands off handling to other functions,
257 * then processes internal Quantum keycodes, then processes ACTIONs.
258 */
259bool process_record_quantum(keyrecord_t *record) {
260 uint16_t keycode = get_record_keycode(record);
249 261
250 // This is how you use actions here 262 // This is how you use actions here
251 // if (keycode == KC_LEAD) { 263 // if (keycode == KC_LEAD) {
diff --git a/quantum/quantum.h b/quantum/quantum.h
index c12ac9ab8..d0b2bedb1 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -224,6 +224,8 @@ void matrix_init_kb(void);
224void matrix_scan_kb(void); 224void matrix_scan_kb(void);
225void matrix_init_user(void); 225void matrix_init_user(void);
226void matrix_scan_user(void); 226void matrix_scan_user(void);
227uint16_t get_record_keycode(keyrecord_t *record);
228uint16_t get_event_keycode(keyevent_t event);
227bool process_action_kb(keyrecord_t *record); 229bool process_action_kb(keyrecord_t *record);
228bool process_record_kb(uint16_t keycode, keyrecord_t *record); 230bool process_record_kb(uint16_t keycode, keyrecord_t *record);
229bool process_record_user(uint16_t keycode, keyrecord_t *record); 231bool process_record_user(uint16_t keycode, keyrecord_t *record);
diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c
index 8adf013e1..3b67ed152 100644
--- a/tmk_core/common/action_tapping.c
+++ b/tmk_core/common/action_tapping.c
@@ -18,8 +18,17 @@
18#define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed) 18#define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
19#define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed) 19#define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
20#define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k))) 20#define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
21#define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
22 21
22__attribute__ ((weak))
23uint16_t get_tapping_term(uint16_t keycode) {
24 return TAPPING_TERM;
25}
26
27#ifdef TAPPING_TERM_PER_KEY
28#define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_event_keycode(tapping_key.event)))
29#else
30#define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
31#endif
23 32
24static keyrecord_t tapping_key = {}; 33static keyrecord_t tapping_key = {};
25static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; 34static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
@@ -100,12 +109,17 @@ bool process_tapping(keyrecord_t *keyp)
100 // enqueue 109 // enqueue
101 return false; 110 return false;
102 } 111 }
103#if TAPPING_TERM >= 500 || defined PERMISSIVE_HOLD
104 /* Process a key typed within TAPPING_TERM 112 /* Process a key typed within TAPPING_TERM
105 * This can register the key before settlement of tapping, 113 * This can register the key before settlement of tapping,
106 * useful for long TAPPING_TERM but may prevent fast typing. 114 * useful for long TAPPING_TERM but may prevent fast typing.
107 */ 115 */
108 else if (IS_RELEASED(event) && waiting_buffer_typed(event)) { 116#if defined(TAPPING_TERM_PER_KEY) || (!defined(PER_KEY_TAPPING_TERM) && TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD)
117#ifdef TAPPING_TERM_PER_KEY
118 else if ( ( get_tapping_term(get_event_keycode(tapping_key.event)) >= 500) && IS_RELEASED(event) && waiting_buffer_typed(event))
119#else
120 else if ( IS_RELEASED(event) && waiting_buffer_typed(event))
121#endif
122 {
109 debug("Tapping: End. No tap. Interfered by typing key\n"); 123 debug("Tapping: End. No tap. Interfered by typing key\n");
110 process_record(&tapping_key); 124 process_record(&tapping_key);
111 tapping_key = (keyrecord_t){}; 125 tapping_key = (keyrecord_t){};
diff --git a/tmk_core/common/action_tapping.h b/tmk_core/common/action_tapping.h
index 2f143ae8b..1db43a442 100644
--- a/tmk_core/common/action_tapping.h
+++ b/tmk_core/common/action_tapping.h
@@ -35,6 +35,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
35 35
36 36
37#ifndef NO_ACTION_TAPPING 37#ifndef NO_ACTION_TAPPING
38uint16_t get_event_keycode(keyevent_t event);
39uint16_t get_tapping_term(uint16_t keycode);
38void action_tapping_process(keyrecord_t record); 40void action_tapping_process(keyrecord_t record);
39#endif 41#endif
40 42