diff options
Diffstat (limited to 'tmk_core/common')
| -rw-r--r-- | tmk_core/common/action.c | 32 | ||||
| -rw-r--r-- | tmk_core/common/action.h | 4 | ||||
| -rw-r--r-- | tmk_core/common/action_layer.c | 77 | ||||
| -rw-r--r-- | tmk_core/common/action_layer.h | 11 |
4 files changed, 115 insertions, 9 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index 2ccc0e0b9..f9e6c17dc 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c | |||
| @@ -53,6 +53,22 @@ void action_exec(keyevent_t event) | |||
| 53 | #endif | 53 | #endif |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) | ||
| 57 | bool disable_action_cache = false; | ||
| 58 | |||
| 59 | void process_action_nocache(keyrecord_t *record) | ||
| 60 | { | ||
| 61 | disable_action_cache = true; | ||
| 62 | process_action(record); | ||
| 63 | disable_action_cache = false; | ||
| 64 | } | ||
| 65 | #else | ||
| 66 | void process_action_nocache(keyrecord_t *record) | ||
| 67 | { | ||
| 68 | process_action(record); | ||
| 69 | } | ||
| 70 | #endif | ||
| 71 | |||
| 56 | __attribute__ ((weak)) | 72 | __attribute__ ((weak)) |
| 57 | void process_action_kb(keyrecord_t *record) {} | 73 | void process_action_kb(keyrecord_t *record) {} |
| 58 | 74 | ||
| @@ -67,7 +83,7 @@ void process_action(keyrecord_t *record) | |||
| 67 | 83 | ||
| 68 | process_action_kb(record); | 84 | process_action_kb(record); |
| 69 | 85 | ||
| 70 | action_t action = layer_switch_get_action(event.key); | 86 | action_t action = store_or_get_action(event.pressed, event.key); |
| 71 | dprint("ACTION: "); debug_action(action); | 87 | dprint("ACTION: "); debug_action(action); |
| 72 | #ifndef NO_ACTION_LAYER | 88 | #ifndef NO_ACTION_LAYER |
| 73 | dprint(" layer_state: "); layer_debug(); | 89 | dprint(" layer_state: "); layer_debug(); |
| @@ -88,14 +104,24 @@ void process_action(keyrecord_t *record) | |||
| 88 | action.key.mods<<4; | 104 | action.key.mods<<4; |
| 89 | if (event.pressed) { | 105 | if (event.pressed) { |
| 90 | if (mods) { | 106 | if (mods) { |
| 91 | add_weak_mods(mods); | 107 | if (IS_MOD(action.key.code)) { |
| 108 | // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless. | ||
| 109 | // this also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT) | ||
| 110 | add_mods(mods); | ||
| 111 | } else { | ||
| 112 | add_weak_mods(mods); | ||
| 113 | } | ||
| 92 | send_keyboard_report(); | 114 | send_keyboard_report(); |
| 93 | } | 115 | } |
| 94 | register_code(action.key.code); | 116 | register_code(action.key.code); |
| 95 | } else { | 117 | } else { |
| 96 | unregister_code(action.key.code); | 118 | unregister_code(action.key.code); |
| 97 | if (mods) { | 119 | if (mods) { |
| 98 | del_weak_mods(mods); | 120 | if (IS_MOD(action.key.code)) { |
| 121 | del_mods(mods); | ||
| 122 | } else { | ||
| 123 | del_weak_mods(mods); | ||
| 124 | } | ||
| 99 | send_keyboard_report(); | 125 | send_keyboard_report(); |
| 100 | } | 126 | } |
| 101 | } | 127 | } |
diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index 9f528af4b..44ec3047b 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h | |||
| @@ -62,6 +62,10 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt); | |||
| 62 | void process_action_kb(keyrecord_t *record); | 62 | void process_action_kb(keyrecord_t *record); |
| 63 | 63 | ||
| 64 | /* Utilities for actions. */ | 64 | /* Utilities for actions. */ |
| 65 | #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) | ||
| 66 | extern bool disable_action_cache; | ||
| 67 | #endif | ||
| 68 | void process_action_nocache(keyrecord_t *record); | ||
| 65 | void process_action(keyrecord_t *record); | 69 | void process_action(keyrecord_t *record); |
| 66 | void register_code(uint8_t code); | 70 | void register_code(uint8_t code); |
| 67 | void unregister_code(uint8_t code); | 71 | void unregister_code(uint8_t code); |
diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index c535615f4..fc721a732 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c | |||
| @@ -110,9 +110,71 @@ void layer_debug(void) | |||
| 110 | } | 110 | } |
| 111 | #endif | 111 | #endif |
| 112 | 112 | ||
| 113 | #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) | ||
| 114 | uint8_t source_layers_cache[MAX_LAYER_BITS][(MATRIX_ROWS * MATRIX_COLS + 7) / 8] = {0}; | ||
| 113 | 115 | ||
| 116 | void update_source_layers_cache(keypos_t key, uint8_t layer) | ||
| 117 | { | ||
| 118 | const uint8_t key_number = key.col + (key.row * MATRIX_COLS); | ||
| 119 | const uint8_t storage_row = key_number / 8; | ||
| 120 | const uint8_t storage_bit = key_number % 8; | ||
| 114 | 121 | ||
| 115 | action_t layer_switch_get_action(keypos_t key) | 122 | for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { |
| 123 | source_layers_cache[bit_number][storage_row] ^= | ||
| 124 | (-((layer & (1U << bit_number)) != 0) | ||
| 125 | ^ source_layers_cache[bit_number][storage_row]) | ||
| 126 | & (1U << storage_bit); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | uint8_t read_source_layers_cache(keypos_t key) | ||
| 131 | { | ||
| 132 | const uint8_t key_number = key.col + (key.row * MATRIX_COLS); | ||
| 133 | const uint8_t storage_row = key_number / 8; | ||
| 134 | const uint8_t storage_bit = key_number % 8; | ||
| 135 | uint8_t layer = 0; | ||
| 136 | |||
| 137 | for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { | ||
| 138 | layer |= | ||
| 139 | ((source_layers_cache[bit_number][storage_row] | ||
| 140 | & (1U << storage_bit)) != 0) | ||
| 141 | << bit_number; | ||
| 142 | } | ||
| 143 | |||
| 144 | return layer; | ||
| 145 | } | ||
| 146 | #endif | ||
| 147 | |||
| 148 | /* | ||
| 149 | * Make sure the action triggered when the key is released is the same | ||
| 150 | * one as the one triggered on press. It's important for the mod keys | ||
| 151 | * when the layer is switched after the down event but before the up | ||
| 152 | * event as they may get stuck otherwise. | ||
| 153 | */ | ||
| 154 | action_t store_or_get_action(bool pressed, keypos_t key) | ||
| 155 | { | ||
| 156 | #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) | ||
| 157 | if (disable_action_cache) { | ||
| 158 | return layer_switch_get_action(key); | ||
| 159 | } | ||
| 160 | |||
| 161 | uint8_t layer; | ||
| 162 | |||
| 163 | if (pressed) { | ||
| 164 | layer = layer_switch_get_layer(key); | ||
| 165 | update_source_layers_cache(key, layer); | ||
| 166 | } | ||
| 167 | else { | ||
| 168 | layer = read_source_layers_cache(key); | ||
| 169 | } | ||
| 170 | return action_for_key(layer, key); | ||
| 171 | #else | ||
| 172 | return layer_switch_get_action(key); | ||
| 173 | #endif | ||
| 174 | } | ||
| 175 | |||
| 176 | |||
| 177 | int8_t layer_switch_get_layer(keypos_t key) | ||
| 116 | { | 178 | { |
| 117 | action_t action; | 179 | action_t action; |
| 118 | action.code = ACTION_TRANSPARENT; | 180 | action.code = ACTION_TRANSPARENT; |
| @@ -124,15 +186,18 @@ action_t layer_switch_get_action(keypos_t key) | |||
| 124 | if (layers & (1UL<<i)) { | 186 | if (layers & (1UL<<i)) { |
| 125 | action = action_for_key(i, key); | 187 | action = action_for_key(i, key); |
| 126 | if (action.code != ACTION_TRANSPARENT) { | 188 | if (action.code != ACTION_TRANSPARENT) { |
| 127 | return action; | 189 | return i; |
| 128 | } | 190 | } |
| 129 | } | 191 | } |
| 130 | } | 192 | } |
| 131 | /* fall back to layer 0 */ | 193 | /* fall back to layer 0 */ |
| 132 | action = action_for_key(0, key); | 194 | return 0; |
| 133 | return action; | ||
| 134 | #else | 195 | #else |
| 135 | action = action_for_key(biton32(default_layer_state), key); | 196 | return biton32(default_layer_state); |
| 136 | return action; | ||
| 137 | #endif | 197 | #endif |
| 138 | } | 198 | } |
| 199 | |||
| 200 | action_t layer_switch_get_action(keypos_t key) | ||
| 201 | { | ||
| 202 | return action_for_key(layer_switch_get_layer(key), key); | ||
| 203 | } | ||
diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h index b6da353cf..3a4b1e334 100644 --- a/tmk_core/common/action_layer.h +++ b/tmk_core/common/action_layer.h | |||
| @@ -70,6 +70,17 @@ void layer_xor(uint32_t state); | |||
| 70 | #define layer_debug() | 70 | #define layer_debug() |
| 71 | #endif | 71 | #endif |
| 72 | 72 | ||
| 73 | /* pressed actions cache */ | ||
| 74 | #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) | ||
| 75 | /* The number of bits needed to represent the layer number: log2(32). */ | ||
| 76 | #define MAX_LAYER_BITS 5 | ||
| 77 | void update_source_layers_cache(keypos_t key, uint8_t layer); | ||
| 78 | uint8_t read_source_layers_cache(keypos_t key); | ||
| 79 | #endif | ||
| 80 | action_t store_or_get_action(bool pressed, keypos_t key); | ||
| 81 | |||
| 82 | /* return the topmost non-transparent layer currently associated with key */ | ||
| 83 | int8_t layer_switch_get_layer(keypos_t key); | ||
| 73 | 84 | ||
| 74 | /* return action depending on current layer status */ | 85 | /* return action depending on current layer status */ |
| 75 | action_t layer_switch_get_action(keypos_t key); | 86 | action_t layer_switch_get_action(keypos_t key); |
