summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorStephen Ostermiller <stephenostermiller@users.noreply.github.com>2025-11-23 06:32:36 -0500
committerGitHub <noreply@github.com>2025-11-23 22:32:36 +1100
commit1a954e8da5dcbd81eeccb9d6ac41b6eda64d7b85 (patch)
tree4f09599d467a9c9bbb1dde722511139fa965ff03 /docs
parentc7e17538eea98540dbee71de5d024db99f7786fe (diff)
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>
Diffstat (limited to 'docs')
-rw-r--r--docs/ChangeLog/20250831/pr25415.md47
-rw-r--r--docs/features/tap_dance.md12
2 files changed, 56 insertions, 3 deletions
diff --git a/docs/ChangeLog/20250831/pr25415.md b/docs/ChangeLog/20250831/pr25415.md
new file mode 100644
index 0000000000..54eb8c737e
--- /dev/null
+++ b/docs/ChangeLog/20250831/pr25415.md
@@ -0,0 +1,47 @@
1# Tap dance state removed from `tap_dance_action_t`
2
3The tap dance state has been separated from the action structure. Custom tap dance functions now receive the state as a separate parameter instead of accessing it through `action->state`.
4
5## User Action Required
6
7If your keymap uses custom tap dance functions that access the tap dance state, you need to update your code.
8
9 - You can't use `action->state`. Instead you need to call `tap_dance_state_t *tap_dance_get_state(uint8_t tap_dance_idx)` to get the state.
10 - You now get a pointer to the state, so use `->` notation rather than `.` notation to get fields from it.
11
12### Before:
13```c
14bool process_record_user(uint16_t keycode, keyrecord_t *record) {
15 tap_dance_action_t *action;
16
17 switch (keycode) {
18 case TD(CT_CLN):
19 action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(keycode));
20 if (!record->event.pressed && action->state.count && !action->state.finished) {
21 tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
22 tap_code16(tap_hold->tap);
23 }
24
25 }
26 return true;
27}
28```
29
30### After:
31```c
32bool process_record_user(uint16_t keycode, keyrecord_t *record) {
33 tap_dance_action_t *action;
34 tap_dance_state_t* state;
35
36 switch (keycode) {
37 case TD(CT_CLN):
38 action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(keycode));
39 state = tap_dance_get_state(QK_TAP_DANCE_GET_INDEX(keycode));
40 if (!record->event.pressed && state != NULL && state->count && !state->finished) {
41 tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
42 tap_code16(tap_hold->tap);
43 }
44 }
45 return true;
46}
47```
diff --git a/docs/features/tap_dance.md b/docs/features/tap_dance.md
index d533e41aaa..688241a16b 100644
--- a/docs/features/tap_dance.md
+++ b/docs/features/tap_dance.md
@@ -40,6 +40,10 @@ Similar to the first option, the second and third option are good for simple lay
40 40
41For 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. 41For 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.
42 42
43::: tip
44If 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.
45:::
46
43## Implementation Details {#implementation} 47## Implementation Details {#implementation}
44 48
45Well, 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! 49Well, 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[] = {
209 213
210bool process_record_user(uint16_t keycode, keyrecord_t *record) { 214bool process_record_user(uint16_t keycode, keyrecord_t *record) {
211 tap_dance_action_t *action; 215 tap_dance_action_t *action;
216 tap_dance_state_t* state;
212 217
213 switch (keycode) { 218 switch (keycode) {
214 case TD(CT_CLN): // list all tap dance keycodes with tap-hold configurations 219 case TD(CT_CLN):
215 action = &tap_dance_actions[QK_TAP_DANCE_GET_INDEX(keycode)]; 220 action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(keycode));
216 if (!record->event.pressed && action->state.count && !action->state.finished) { 221 state = tap_dance_get_state(QK_TAP_DANCE_GET_INDEX(keycode));
222 if (!record->event.pressed && state != NULL && state->count && !state->finished) {
217 tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data; 223 tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data;
218 tap_code16(tap_hold->tap); 224 tap_code16(tap_hold->tap);
219 } 225 }