Reduce tap dance memory usage, move state out of data (#25415)

* Use less tap dance memory.

Use dynamically allocated sparse array for tap dance state, dynamically allocate tap dance state when needed and free it when the tap dance is done.

* new approach

* Use null, check for null

* Reformat with docker

* Use uint8 with idx rather than uint16 with keycode in state

* fix accidental change

* reformat

* Add null check

* add documentation tip suggested by tzarc

* Only allow tap dance state allocation on key down, not on key up

Co-authored-by: Sergey Vlasov <sigprof@gmail.com>

* Only allow tap dance allocation on key down, not on key up

Co-authored-by: Sergey Vlasov <sigprof@gmail.com>

* add user action required section

---------

Co-authored-by: Sergey Vlasov <sigprof@gmail.com>
This commit is contained in:
Stephen Ostermiller 2025-11-23 06:32:36 -05:00 committed by GitHub
parent c7e17538ee
commit 1a954e8da5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 152 additions and 44 deletions

View file

@ -40,6 +40,10 @@ Similar to the first option, the second and third option are good for simple lay
For more complicated cases, like blink the LEDs, fiddle with the backlighting, and so on, use the fourth or fifth option. Examples of each are listed below.
::: tip
If too many tap dances are active at the same time, later ones won't have any effect. You need to increase `TAP_DANCE_MAX_SIMULTANEOUS` by adding `#define TAP_DANCE_MAX_SIMULTANEOUS 5` (or higher) to your keymap's `config.h` file if you expect that users may hold down many tap dance keys simultaneously. By default, only 3 tap dance keys can be used together at the same time.
:::
## Implementation Details {#implementation}
Well, that's the bulk of it! You should now be able to work through the examples below, and to develop your own Tap Dance functionality. But if you want a deeper understanding of what's going on behind the scenes, then read on for the explanation of how it all works!
@ -209,11 +213,13 @@ tap_dance_action_t tap_dance_actions[] = {
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
tap_dance_action_t *action;
tap_dance_state_t* state;
switch (keycode) {
case TD(CT_CLN): // list all tap dance keycodes with tap-hold configurations
action = &tap_dance_actions[QK_TAP_DANCE_GET_INDEX(keycode)];
if (!record->event.pressed && action->state.count && !action->state.finished) {
case TD(CT_CLN):
action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(keycode));
state = tap_dance_get_state(QK_TAP_DANCE_GET_INDEX(keycode));
if (!record->event.pressed && state != NULL && state->count && !state->finished) {
tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
tap_code16(tap_hold->tap);
}