diff options
Diffstat (limited to 'tmk_core/common/action_layer.c')
-rw-r--r-- | tmk_core/common/action_layer.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index 76164adb5d..fc721a7323 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -110,6 +110,69 @@ void layer_debug(void) } #endif +#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) +uint8_t source_layers_cache[MAX_LAYER_BITS][(MATRIX_ROWS * MATRIX_COLS + 7) / 8] = {0}; + +void update_source_layers_cache(keypos_t key, uint8_t layer) +{ + const uint8_t key_number = key.col + (key.row * MATRIX_COLS); + const uint8_t storage_row = key_number / 8; + const uint8_t storage_bit = key_number % 8; + + for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { + source_layers_cache[bit_number][storage_row] ^= + (-((layer & (1U << bit_number)) != 0) + ^ source_layers_cache[bit_number][storage_row]) + & (1U << storage_bit); + } +} + +uint8_t read_source_layers_cache(keypos_t key) +{ + const uint8_t key_number = key.col + (key.row * MATRIX_COLS); + const uint8_t storage_row = key_number / 8; + const uint8_t storage_bit = key_number % 8; + uint8_t layer = 0; + + for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { + layer |= + ((source_layers_cache[bit_number][storage_row] + & (1U << storage_bit)) != 0) + << bit_number; + } + + return layer; +} +#endif + +/* + * Make sure the action triggered when the key is released is the same + * one as the one triggered on press. It's important for the mod keys + * when the layer is switched after the down event but before the up + * event as they may get stuck otherwise. + */ +action_t store_or_get_action(bool pressed, keypos_t key) +{ +#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) + if (disable_action_cache) { + return layer_switch_get_action(key); + } + + uint8_t layer; + + if (pressed) { + layer = layer_switch_get_layer(key); + update_source_layers_cache(key, layer); + } + else { + layer = read_source_layers_cache(key); + } + return action_for_key(layer, key); +#else + return layer_switch_get_action(key); +#endif +} + int8_t layer_switch_get_layer(keypos_t key) { |