mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-07-18 13:42:00 +00:00
new approach
This commit is contained in:
parent
423e0881cf
commit
2809c68d03
@ -1,23 +0,0 @@
|
|||||||
# QMK Breaking Changes - 2025 August 24 Changelog
|
|
||||||
|
|
||||||
## Notable Features
|
|
||||||
|
|
||||||
### Tap Dance ([#25415](https://github.com/qmk/qmk_firmware/pull/25415))
|
|
||||||
|
|
||||||
Tap dance state has been removed from `tap_dance_action_t`. Instead, tap dance
|
|
||||||
state can now be obtained from a method `tap_dance_get_state(int tap_dance_idx)`.
|
|
||||||
|
|
||||||
`action.state->xxxxx` should generally be replaced with:
|
|
||||||
|
|
||||||
```c
|
|
||||||
tap_dance_state_t* state;
|
|
||||||
...
|
|
||||||
state = tap_dance_get_state(QK_TAP_DANCE_GET_INDEX(keycode));
|
|
||||||
...
|
|
||||||
state->xxxxx
|
|
||||||
```
|
|
||||||
|
|
||||||
Eg. [Example 3 in the tap dance documentation](../tap_dance#example-3).
|
|
||||||
|
|
||||||
Tap dance functions that obtain the state as a parameter to one of the callback
|
|
||||||
methods are unaffected. They will continue to work without changes.
|
|
3
docs/ChangeLog/20250831/pr25415.md
Normal file
3
docs/ChangeLog/20250831/pr25415.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Tap dance state removed from `tap_dance_action_t`
|
||||||
|
|
||||||
|
Code that accessed the tap dance state as a field in the tap dance action should now call `tap_dance_get_state(int tap_dance_idx)` instead.
|
@ -25,30 +25,40 @@
|
|||||||
|
|
||||||
static uint16_t active_td;
|
static uint16_t active_td;
|
||||||
|
|
||||||
// Pointer to array of state pointers. Because the size of the
|
#ifndef TAP_DANCE_MAX_SIMULTANEOUS
|
||||||
// array depends on the number of tap dances, it is discovered
|
# define TAP_DANCE_MAX_SIMULTANEOUS 3
|
||||||
// via introspection and is unknown at compile time. It will
|
#endif
|
||||||
// be allocated when first used.
|
|
||||||
static tap_dance_state_t **tap_dance_states = NULL;
|
static tap_dance_state_t tap_dance_states[TAP_DANCE_MAX_SIMULTANEOUS];
|
||||||
|
|
||||||
static uint16_t last_tap_time;
|
static uint16_t last_tap_time;
|
||||||
|
|
||||||
tap_dance_state_t *tap_dance_get_state(int tap_dance_idx) {
|
tap_dance_state_t *tap_dance_get_state(uint8_t tap_dance_idx) {
|
||||||
|
uint8_t i;
|
||||||
|
uint16_t keycode = QK_TAP_DANCE + tap_dance_idx;
|
||||||
if (tap_dance_idx >= tap_dance_count()) {
|
if (tap_dance_idx >= tap_dance_count()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (tap_dance_states == NULL) {
|
// Search for a state already used for this case
|
||||||
// Dynamic allocation of array of NULL pointers to tap dance states
|
for (i = 0; i < TAP_DANCE_MAX_SIMULTANEOUS; i++) {
|
||||||
// This is never freed, this array is initialized once and used forever
|
if (tap_dance_states[i].keycode == keycode) {
|
||||||
tap_dance_states = calloc(tap_dance_count(), sizeof(tap_dance_state_t *));
|
return &tap_dance_states[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (tap_dance_states[tap_dance_idx] == NULL) {
|
// Search for the first free state
|
||||||
// Dynamic allocation of struct for the tap dance state.
|
for (i = 0; i < TAP_DANCE_MAX_SIMULTANEOUS; i++) {
|
||||||
// This memory will be freed when the tap dance is complete
|
if (tap_dance_states[i].keycode == 0) {
|
||||||
tap_dance_states[tap_dance_idx] = calloc(1, sizeof(tap_dance_state_t));
|
tap_dance_states[i].keycode = keycode;
|
||||||
tap_dance_states[tap_dance_idx]->index = tap_dance_idx;
|
return &tap_dance_states[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return tap_dance_states[tap_dance_idx];
|
// No states are free, reuse the last state.
|
||||||
|
// The undefined behavior that causes is
|
||||||
|
// better than returning null. All the tap dances
|
||||||
|
// don't get processed correctly, but the keyboard
|
||||||
|
// doesn't crash when more than the max tap dance
|
||||||
|
// keys are held at the same time.
|
||||||
|
return &tap_dance_states[TAP_DANCE_MAX_SIMULTANEOUS - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void tap_dance_pair_on_each_tap(tap_dance_state_t *state, void *user_data) {
|
void tap_dance_pair_on_each_tap(tap_dance_state_t *state, void *user_data) {
|
||||||
@ -132,9 +142,8 @@ static inline void process_tap_dance_action_on_reset(tap_dance_action_t *action,
|
|||||||
del_mods(state->oneshot_mods);
|
del_mods(state->oneshot_mods);
|
||||||
#endif
|
#endif
|
||||||
send_keyboard_report();
|
send_keyboard_report();
|
||||||
uint8_t tap_dance_idx = state->index;
|
// Clear the tap dance state and mark it as unused
|
||||||
free(tap_dance_states[tap_dance_idx]);
|
memset(state, 0, sizeof(tap_dance_state_t));
|
||||||
tap_dance_states[tap_dance_idx] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void process_tap_dance_action_on_dance_finished(tap_dance_action_t *action, tap_dance_state_t *state) {
|
static inline void process_tap_dance_action_on_dance_finished(tap_dance_action_t *action, tap_dance_state_t *state) {
|
||||||
@ -180,7 +189,7 @@ bool preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
|
||||||
int td_index;
|
uint8_t td_index;
|
||||||
tap_dance_action_t *action;
|
tap_dance_action_t *action;
|
||||||
tap_dance_state_t *state;
|
tap_dance_state_t *state;
|
||||||
|
|
||||||
@ -229,5 +238,5 @@ void tap_dance_task(void) {
|
|||||||
|
|
||||||
void reset_tap_dance(tap_dance_state_t *state) {
|
void reset_tap_dance(tap_dance_state_t *state) {
|
||||||
active_td = 0;
|
active_td = 0;
|
||||||
process_tap_dance_action_on_reset(tap_dance_get(state->index), state);
|
process_tap_dance_action_on_reset(tap_dance_get(QK_TAP_DANCE_GET_INDEX(state->keycode)), state);
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,10 @@ typedef struct {
|
|||||||
#ifndef NO_ACTION_ONESHOT
|
#ifndef NO_ACTION_ONESHOT
|
||||||
uint8_t oneshot_mods;
|
uint8_t oneshot_mods;
|
||||||
#endif
|
#endif
|
||||||
bool pressed : 1;
|
bool pressed : 1;
|
||||||
bool finished : 1;
|
bool finished : 1;
|
||||||
bool interrupted : 1;
|
bool interrupted : 1;
|
||||||
uint8_t index;
|
uint16_t keycode;
|
||||||
} tap_dance_state_t;
|
} tap_dance_state_t;
|
||||||
|
|
||||||
typedef void (*tap_dance_user_fn_t)(tap_dance_state_t *state, void *user_data);
|
typedef void (*tap_dance_user_fn_t)(tap_dance_state_t *state, void *user_data);
|
||||||
@ -80,7 +80,7 @@ typedef struct {
|
|||||||
|
|
||||||
void reset_tap_dance(tap_dance_state_t *state);
|
void reset_tap_dance(tap_dance_state_t *state);
|
||||||
|
|
||||||
tap_dance_state_t *tap_dance_get_state(int tap_dance_idx);
|
tap_dance_state_t *tap_dance_get_state(uint8_t tap_dance_idx);
|
||||||
|
|
||||||
/* To be used internally */
|
/* To be used internally */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user