summaryrefslogtreecommitdiffstats
path: root/tmk_core
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core')
-rw-r--r--tmk_core/common/action.c59
-rw-r--r--tmk_core/common/action.h4
-rw-r--r--tmk_core/common/action_layer.c16
-rw-r--r--tmk_core/common/action_layer.h3
4 files changed, 74 insertions, 8 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index 2ccc0e0b9..20e1fc614 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -53,6 +53,63 @@ void action_exec(keyevent_t event)
#endif
}
+#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+bool disable_action_cache = false;
+uint8_t source_layers_cache[5][(MATRIX_ROWS * MATRIX_COLS + 7) / 8] = {0};
+
+void process_action_nocache(keyrecord_t *record)
+{
+ disable_action_cache = true;
+ process_action(record);
+ disable_action_cache = false;
+}
+#else
+void process_action_nocache(keyrecord_t *record)
+{
+ process_action(record);
+}
+#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);
+ }
+ 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;
+ if (pressed) {
+ layer = layer_switch_get_layer(key);
+ for (uint8_t bit_number = 0; bit_number < 5; bit_number++) {
+ source_layers_cache[bit_number][storage_row] ^=
+ (-((layer & (1U << bit_number)) != 0)
+ ^ source_layers_cache[bit_number][storage_row])
+ & (1U << storage_bit);
+ }
+ }
+ else {
+ layer = 0;
+ for (uint8_t bit_number = 0; bit_number < 5; bit_number++) {
+ layer |=
+ ((source_layers_cache[bit_number][storage_row]
+ & (1U << storage_bit)) != 0)
+ << bit_number;
+ }
+ }
+ return action_for_key(layer, key);
+#else
+ return layer_switch_get_action(key);
+#endif
+}
+
__attribute__ ((weak))
void process_action_kb(keyrecord_t *record) {}
@@ -67,7 +124,7 @@ void process_action(keyrecord_t *record)
process_action_kb(record);
- action_t action = layer_switch_get_action(event.key);
+ action_t action = store_or_get_action(event.pressed, event.key);
dprint("ACTION: "); debug_action(action);
#ifndef NO_ACTION_LAYER
dprint(" layer_state: "); layer_debug();
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);
void process_action_kb(keyrecord_t *record);
/* Utilities for actions. */
+#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+extern bool disable_action_cache;
+#endif
+void process_action_nocache(keyrecord_t *record);
void process_action(keyrecord_t *record);
void register_code(uint8_t code);
void unregister_code(uint8_t code);
diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c
index c535615f4..76164adb5 100644
--- a/tmk_core/common/action_layer.c
+++ b/tmk_core/common/action_layer.c
@@ -111,8 +111,7 @@ void layer_debug(void)
#endif
-
-action_t layer_switch_get_action(keypos_t key)
+int8_t layer_switch_get_layer(keypos_t key)
{
action_t action;
action.code = ACTION_TRANSPARENT;
@@ -124,15 +123,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);
+}
diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h
index b6da353cf..1a313a259 100644
--- a/tmk_core/common/action_layer.h
+++ b/tmk_core/common/action_layer.h
@@ -71,6 +71,9 @@ void layer_xor(uint32_t state);
#endif
+/* return the topmost non-transparent layer currently associated with key */
+int8_t layer_switch_get_layer(keypos_t key);
+
/* return action depending on current layer status */
action_t layer_switch_get_action(keypos_t key);