aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/common/action_layer.c
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/common/action_layer.c')
-rw-r--r--tmk_core/common/action_layer.c77
1 files changed, 71 insertions, 6 deletions
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)
114uint8_t source_layers_cache[MAX_LAYER_BITS][(MATRIX_ROWS * MATRIX_COLS + 7) / 8] = {0};
113 115
116void 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
115action_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
130uint8_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 */
154action_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
177int8_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
200action_t layer_switch_get_action(keypos_t key)
201{
202 return action_for_key(layer_switch_get_layer(key), key);
203}