summaryrefslogtreecommitdiffstats
path: root/tmk_core/common/action_layer.c
diff options
context:
space:
mode:
authorDidier Loiseau <didierloiseau+git@gmail.com>2016-09-11 01:26:47 +0200
committerDidier Loiseau <didierloiseau+git@gmail.com>2016-09-11 01:26:47 +0200
commitb9014c757599ca288be07629ad1d00ef66c033f1 (patch)
treeba056e704e76327c597e25d1be200c4c991efeb8 /tmk_core/common/action_layer.c
parent60a826923d5a6b0dbe416b0837608149ab82e470 (diff)
parent5010df3d8b68a53c382b853c7c2e45922975b631 (diff)
downloadqmk_firmware-b9014c757599ca288be07629ad1d00ef66c033f1.tar.gz
qmk_firmware-b9014c757599ca288be07629ad1d00ef66c033f1.tar.xz
Merge remote-tracking branch 'remotes/jackhumbert/master' into bépo
Diffstat (limited to 'tmk_core/common/action_layer.c')
-rw-r--r--tmk_core/common/action_layer.c81
1 files changed, 73 insertions, 8 deletions
diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c
index c535615f4..a3c757964 100644
--- a/tmk_core/common/action_layer.c
+++ b/tmk_core/common/action_layer.c
@@ -11,7 +11,7 @@
#endif
-/*
+/*
* Default Layer State
*/
uint32_t default_layer_state = 0;
@@ -52,7 +52,7 @@ void default_layer_xor(uint32_t state)
#ifndef NO_ACTION_LAYER
-/*
+/*
* Keymap Layer State
*/
uint32_t layer_state = 0;
@@ -110,9 +110,71 @@ void layer_debug(void)
}
#endif
+#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{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;
-action_t layer_switch_get_action(keypos_t key)
+ for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
+ source_layers_cache[storage_row][bit_number] ^=
+ (-((layer & (1U << bit_number)) != 0)
+ ^ source_layers_cache[storage_row][bit_number])
+ & (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[storage_row][bit_number]
+ & (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)
{
action_t action;
action.code = ACTION_TRANSPARENT;
@@ -124,15 +186,18 @@ action_t layer_switch_get_action(keypos_t key)
if (layers & (1UL<<i)) {
action = action_for_key(i, key);
if (action.code != ACTION_TRANSPARENT) {
- return action;
+ return i;
}
}
}
/* fall back to layer 0 */
- action = action_for_key(0, key);
- return action;
+ return 0;
#else
- action = action_for_key(biton32(default_layer_state), key);
- return action;
+ return biton32(default_layer_state);
#endif
}
+
+action_t layer_switch_get_action(keypos_t key)
+{
+ return action_for_key(layer_switch_get_layer(key), key);
+}