diff options
Diffstat (limited to 'quantum/process_keycode')
| -rw-r--r-- | quantum/process_keycode/process_combo.c | 4 | ||||
| -rw-r--r-- | quantum/process_keycode/process_dynamic_macro.c | 23 | ||||
| -rw-r--r-- | quantum/process_keycode/process_led_matrix.c | 6 | ||||
| -rw-r--r-- | quantum/process_keycode/process_rgb_matrix.c | 14 | ||||
| -rw-r--r-- | quantum/process_keycode/process_tap_dance.c | 122 | ||||
| -rw-r--r-- | quantum/process_keycode/process_tap_dance.h | 11 |
6 files changed, 139 insertions, 41 deletions
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c index 3fdb732c41..dfab42e70d 100644 --- a/quantum/process_keycode/process_combo.c +++ b/quantum/process_keycode/process_combo.c @@ -347,6 +347,10 @@ void apply_combo(uint16_t combo_index, combo_t *combo) { qrecord->combo_index = combo_index; ACTIVATE_COMBO(combo); + if (key_count == 1) { + release_combo(combo_index, combo); + } + break; } else { // key was part of the combo but not the last one, "disable" it diff --git a/quantum/process_keycode/process_dynamic_macro.c b/quantum/process_keycode/process_dynamic_macro.c index f8e8256ac8..20e90c6e14 100644 --- a/quantum/process_keycode/process_dynamic_macro.c +++ b/quantum/process_keycode/process_dynamic_macro.c @@ -89,6 +89,11 @@ __attribute__((weak)) bool dynamic_macro_valid_key_user(uint16_t keycode, keyrec #define DYNAMIC_MACRO_CURRENT_LENGTH(BEGIN, POINTER) ((int)(direction * ((POINTER) - (BEGIN)))) #define DYNAMIC_MACRO_CURRENT_CAPACITY(BEGIN, END2) ((int)(direction * ((END2) - (BEGIN)) + 1)) +#ifdef DYNAMIC_MACRO_KEEP_ORIGINAL_LAYER_STATE +static layer_state_t dm1_layer_state; +static layer_state_t dm2_layer_state; +#endif + /** * Start recording of the dynamic macro. * @@ -100,8 +105,16 @@ void dynamic_macro_record_start(keyrecord_t **macro_pointer, keyrecord_t *macro_ dynamic_macro_record_start_kb(direction); - clear_keyboard(); +#ifdef DYNAMIC_MACRO_KEEP_ORIGINAL_LAYER_STATE + if (direction == 1) { + dm1_layer_state = layer_state; + } else if (direction == -1) { + dm2_layer_state = layer_state; + } +#else layer_clear(); +#endif + clear_keyboard(); *macro_pointer = macro_buffer; } @@ -118,7 +131,15 @@ void dynamic_macro_play(keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_ layer_state_t saved_layer_state = layer_state; clear_keyboard(); +#ifdef DYNAMIC_MACRO_KEEP_ORIGINAL_LAYER_STATE + if (direction == 1) { + layer_state_set(dm1_layer_state); + } else if (direction == -1) { + layer_state_set(dm2_layer_state); + } +#else layer_clear(); +#endif while (macro_buffer != macro_end) { process_record(macro_buffer); diff --git a/quantum/process_keycode/process_led_matrix.c b/quantum/process_keycode/process_led_matrix.c index 7f95bf1011..3342b33b92 100644 --- a/quantum/process_keycode/process_led_matrix.c +++ b/quantum/process_keycode/process_led_matrix.c @@ -40,6 +40,12 @@ bool process_led_matrix(uint16_t keycode, keyrecord_t *record) { case QK_LED_MATRIX_SPEED_DOWN: led_matrix_decrease_speed(); return false; + case QK_LED_MATRIX_FLAG_NEXT: + led_matrix_flags_step(); + return false; + case QK_LED_MATRIX_FLAG_PREVIOUS: + led_matrix_flags_step_reverse(); + return false; } } diff --git a/quantum/process_keycode/process_rgb_matrix.c b/quantum/process_keycode/process_rgb_matrix.c index fd2aa1a0c7..c18212294d 100644 --- a/quantum/process_keycode/process_rgb_matrix.c +++ b/quantum/process_keycode/process_rgb_matrix.c @@ -94,6 +94,20 @@ bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record) { rgb_matrix_decrease_speed(); } return false; + case QK_RGB_MATRIX_FLAG_NEXT: + if (shifted) { + rgb_matrix_flags_step_reverse(); + } else { + rgb_matrix_flags_step(); + } + return false; + case QK_RGB_MATRIX_FLAG_PREVIOUS: + if (shifted) { + rgb_matrix_flags_step(); + } else { + rgb_matrix_flags_step_reverse(); + } + return false; } } diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c index 11df62763d..399f71a827 100644 --- a/quantum/process_keycode/process_tap_dance.c +++ b/quantum/process_keycode/process_tap_dance.c @@ -24,8 +24,46 @@ #include "keymap_introspection.h" static uint16_t active_td; + +#ifndef TAP_DANCE_MAX_SIMULTANEOUS +# define TAP_DANCE_MAX_SIMULTANEOUS 3 +#endif + +static tap_dance_state_t tap_dance_states[TAP_DANCE_MAX_SIMULTANEOUS]; + static uint16_t last_tap_time; +static tap_dance_state_t *tap_dance_get_or_allocate_state(uint8_t tap_dance_idx, bool allocate) { + uint8_t i; + if (tap_dance_idx >= tap_dance_count()) { + return NULL; + } + // Search for a state already used for this keycode + for (i = 0; i < TAP_DANCE_MAX_SIMULTANEOUS; i++) { + if (tap_dance_states[i].in_use && tap_dance_states[i].index == tap_dance_idx) { + return &tap_dance_states[i]; + } + } + // No existing state found; bail out if new state allocation is not allowed + if (!allocate) { + return NULL; + } + // Search for the first available state + for (i = 0; i < TAP_DANCE_MAX_SIMULTANEOUS; i++) { + if (!tap_dance_states[i].in_use) { + tap_dance_states[i].index = tap_dance_idx; + tap_dance_states[i].in_use = true; + return &tap_dance_states[i]; + } + } + // No states are available, tap dance won't happen + return NULL; +} + +tap_dance_state_t *tap_dance_get_state(uint8_t tap_dance_idx) { + return tap_dance_get_or_allocate_state(tap_dance_idx, false); +} + void tap_dance_pair_on_each_tap(tap_dance_state_t *state, void *user_data) { tap_dance_pair_t *pair = (tap_dance_pair_t *)user_data; @@ -86,58 +124,64 @@ static inline void _process_tap_dance_action_fn(tap_dance_state_t *state, void * } } -static inline void process_tap_dance_action_on_each_tap(tap_dance_action_t *action) { - action->state.count++; - action->state.weak_mods = get_mods(); - action->state.weak_mods |= get_weak_mods(); +static inline void process_tap_dance_action_on_each_tap(tap_dance_action_t *action, tap_dance_state_t *state) { + state->count++; + state->weak_mods = get_mods(); + state->weak_mods |= get_weak_mods(); #ifndef NO_ACTION_ONESHOT - action->state.oneshot_mods = get_oneshot_mods(); + state->oneshot_mods = get_oneshot_mods(); #endif - _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_each_tap); + _process_tap_dance_action_fn(state, action->user_data, action->fn.on_each_tap); } -static inline void process_tap_dance_action_on_each_release(tap_dance_action_t *action) { - _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_each_release); +static inline void process_tap_dance_action_on_each_release(tap_dance_action_t *action, tap_dance_state_t *state) { + _process_tap_dance_action_fn(state, action->user_data, action->fn.on_each_release); } -static inline void process_tap_dance_action_on_reset(tap_dance_action_t *action) { - _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_reset); - del_weak_mods(action->state.weak_mods); +static inline void process_tap_dance_action_on_reset(tap_dance_action_t *action, tap_dance_state_t *state) { + _process_tap_dance_action_fn(state, action->user_data, action->fn.on_reset); + del_weak_mods(state->weak_mods); #ifndef NO_ACTION_ONESHOT - del_mods(action->state.oneshot_mods); + del_mods(state->oneshot_mods); #endif send_keyboard_report(); - action->state = (const tap_dance_state_t){0}; + // Clear the tap dance state and mark it as unused + memset(state, 0, sizeof(tap_dance_state_t)); } -static inline void process_tap_dance_action_on_dance_finished(tap_dance_action_t *action) { - if (!action->state.finished) { - action->state.finished = true; - add_weak_mods(action->state.weak_mods); +static inline void process_tap_dance_action_on_dance_finished(tap_dance_action_t *action, tap_dance_state_t *state) { + if (!state->finished) { + state->finished = true; + add_weak_mods(state->weak_mods); #ifndef NO_ACTION_ONESHOT - add_mods(action->state.oneshot_mods); + add_mods(state->oneshot_mods); #endif send_keyboard_report(); - _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_dance_finished); + _process_tap_dance_action_fn(state, action->user_data, action->fn.on_dance_finished); } active_td = 0; - if (!action->state.pressed) { + if (!state->pressed) { // There will not be a key release event, so reset now. - process_tap_dance_action_on_reset(action); + process_tap_dance_action_on_reset(action, state); } } bool preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) { tap_dance_action_t *action; + tap_dance_state_t *state; if (!record->event.pressed) return false; if (!active_td || keycode == active_td) return false; - action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(active_td)); - action->state.interrupted = true; - action->state.interrupting_keycode = keycode; - process_tap_dance_action_on_dance_finished(action); + action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(active_td)); + state = tap_dance_get_state(QK_TAP_DANCE_GET_INDEX(active_td)); + if (state == NULL) { + return false; + } + state->interrupted = true; + state->interrupting_keycode = keycode; + process_tap_dance_action_on_dance_finished(action, state); // Tap dance actions can leave some weak mods active (e.g., if the tap dance is mapped to a keycode with // modifiers), but these weak mods should not affect the keypress which interrupted the tap dance. @@ -151,8 +195,9 @@ bool preprocess_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_state_t *state; switch (keycode) { case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: @@ -161,16 +206,19 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { return false; } action = tap_dance_get(td_index); - - action->state.pressed = record->event.pressed; + state = tap_dance_get_or_allocate_state(td_index, record->event.pressed); + if (state == NULL) { + return false; + } + state->pressed = record->event.pressed; if (record->event.pressed) { last_tap_time = timer_read(); - process_tap_dance_action_on_each_tap(action); - active_td = action->state.finished ? 0 : keycode; + process_tap_dance_action_on_each_tap(action, state); + active_td = state->finished ? 0 : keycode; } else { - process_tap_dance_action_on_each_release(action); - if (action->state.finished) { - process_tap_dance_action_on_reset(action); + process_tap_dance_action_on_each_release(action, state); + if (state->finished) { + process_tap_dance_action_on_reset(action, state); if (active_td == keycode) { active_td = 0; } @@ -185,16 +233,18 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { void tap_dance_task(void) { tap_dance_action_t *action; + tap_dance_state_t *state; if (!active_td || timer_elapsed(last_tap_time) <= GET_TAPPING_TERM(active_td, &(keyrecord_t){})) return; action = tap_dance_get(QK_TAP_DANCE_GET_INDEX(active_td)); - if (!action->state.interrupted) { - process_tap_dance_action_on_dance_finished(action); + state = tap_dance_get_state(QK_TAP_DANCE_GET_INDEX(active_td)); + if (state != NULL && !state->interrupted) { + process_tap_dance_action_on_dance_finished(action, state); } } void reset_tap_dance(tap_dance_state_t *state) { active_td = 0; - process_tap_dance_action_on_reset((tap_dance_action_t *)state); + process_tap_dance_action_on_reset(tap_dance_get(state->index), state); } diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h index b64321da0c..bce93d611b 100644 --- a/quantum/process_keycode/process_tap_dance.h +++ b/quantum/process_keycode/process_tap_dance.h @@ -28,15 +28,16 @@ typedef struct { #ifndef NO_ACTION_ONESHOT uint8_t oneshot_mods; #endif - bool pressed : 1; - bool finished : 1; - bool interrupted : 1; + bool pressed : 1; + bool finished : 1; + bool interrupted : 1; + bool in_use : 1; + uint8_t index; } tap_dance_state_t; typedef void (*tap_dance_user_fn_t)(tap_dance_state_t *state, void *user_data); typedef struct tap_dance_action_t { - tap_dance_state_t state; struct { tap_dance_user_fn_t on_each_tap; tap_dance_user_fn_t on_dance_finished; @@ -98,6 +99,8 @@ typedef struct { void reset_tap_dance(tap_dance_state_t *state); +tap_dance_state_t *tap_dance_get_state(uint8_t tap_dance_idx); + /* To be used internally */ bool preprocess_tap_dance(uint16_t keycode, keyrecord_t *record); |