core: Fix for stuck key problem #441
authortmk <hasu@tmk-kbd.com>
Fri, 26 May 2017 03:03:30 +0000 (12:03 +0900)
committertmk <hasu@tmk-kbd.com>
Tue, 30 May 2017 06:25:26 +0000 (15:25 +0900)
- Idea form https://github.com/qmk/qmk_firmware/pull/182
- Define NO_TRACK_KEY_PRESS to get old behaviour
- This should resolve #105, #248, #397, #441 and FAQ entry: https://github.com/tmk/tmk_keyboard/wiki/FAQ-Keymap#modifierlayer-stuck

tmk_core/README.md
tmk_core/common/action.c
tmk_core/common/action.h
tmk_core/common/action_layer.c
tmk_core/common/action_layer.h
tmk_core/common/action_tapping.c

index c9c2eda4c1d2dd5fc4c3dbbf7686d96dfb7baf0a..50456880b2216639d4ea97afc538b9f05c6316d2 100644 (file)
@@ -7,6 +7,14 @@ Source code is available here: <https://github.com/tmk/tmk_keyboard/tree/core>
 
 Updates
 -------
+#### 2017/05/30
+Fixed **Modifier/Layer key stuck** problem. See this wiki entry. <https://github.com/tmk/tmk_keyboard/wiki/FAQ-Keymap#modifierlayer-stuck> If you need old keymap behaviour for some reason define `NO_TRACK_KEY_PRESS` in your `config.h`.
+
+This is virtually equivalent to QMK `PREVENT_STUCK_MODIFIERS`. <https://github.com/qmk/qmk_firmware/pull/182>
+
+#### 2017/01/11
+Changed action code for `ACTION_LAYER_MODS` and this may cause incompatibility with existent shared URL and downloaded firmwware of keymap editor. If you are using the action you just have to redefine it on keymap editor. Existent keymap code should not suffer.
+
 #### 2016/06/26
 Keymap framework was updated. `fn_actions[]` should be defined as `action_t` instead of `uint16_t`. And default code for keymap handling is now included in core you just need define `uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS]` and `action_t fn_actions[]`.
 
index ab6e9d895807898fde8b7112eadfb0eb8053b9e1..05aa12eee87af2631f6da268e1df0d253b390fec 100644 (file)
@@ -65,7 +65,7 @@ void process_action(keyrecord_t *record)
 
     if (IS_NOEVENT(event)) { return; }
 
-    action_t action = layer_switch_get_action(event.key);
+    action_t action = layer_switch_get_action(event);
     dprint("ACTION: "); debug_action(action);
 #ifndef NO_ACTION_LAYER
     dprint(" layer_state: "); layer_debug();
@@ -529,9 +529,9 @@ void clear_keyboard_but_mods(void)
 #endif
 }
 
-bool is_tap_key(keypos_t key)
+bool is_tap_key(keyevent_t event)
 {
-    action_t action = layer_switch_get_action(key);
+    action_t action = layer_switch_get_action(event);
 
     switch (action.kind.id) {
         case ACT_LMODS_TAP:
index 8a4736d7bc19cbb833481649b467cc4da109e1ac..993fc463ff6de196f0ee2412740012d78710850d 100644 (file)
@@ -68,7 +68,7 @@ void unregister_mods(uint8_t mods);
 void clear_keyboard(void);
 void clear_keyboard_but_mods(void);
 void layer_switch(uint8_t new_layer);
-bool is_tap_key(keypos_t key);
+bool is_tap_key(keyevent_t event);
 
 /* debug */
 void debug_event(keyevent_t event);
index 6b5a7fd2b83e9216939601cb5439ec65da459e86..46401eba6248483bbf75e48408da12b3acc9da27 100644 (file)
@@ -24,7 +24,9 @@ static void default_layer_state_set(uint32_t state)
     default_layer_state = state;
     hook_default_layer_change(default_layer_state);
     default_layer_debug(); debug("\n");
+#ifdef NO_TRACK_KEY_PRESS
     clear_keyboard_but_mods(); // To avoid stuck keys
+#endif
 }
 
 void default_layer_debug(void)
@@ -66,7 +68,9 @@ static void layer_state_set(uint32_t state)
     layer_state = state;
     hook_layer_change(layer_state);
     layer_debug(); dprintln();
+#ifdef NO_TRACK_KEY_PRESS
     clear_keyboard_but_mods(); // To avoid stuck keys
+#endif
 }
 
 void layer_clear(void)
@@ -115,7 +119,8 @@ void layer_debug(void)
 
 
 
-action_t layer_switch_get_action(keypos_t key)
+/* return layer effective for key at this time */
+static uint8_t current_layer_for_key(keypos_t key)
 {
     action_t action = ACTION_TRANSPARENT;
 
@@ -126,15 +131,34 @@ action_t layer_switch_get_action(keypos_t key)
         if (layers & (1UL<<i)) {
             action = action_for_key(i, key);
             if (action.code != (action_t)ACTION_TRANSPARENT.code) {
-                return action;
+                return i;
             }
         }
     }
     /* fall back to layer 0 */
-    action = action_for_key(0, key);
-    return action;
+    return 0;
+#else
+    return biton32(default_layer_state);
+#endif
+}
+
+
+#ifndef NO_TRACK_KEY_PRESS
+/* record layer on where key is pressed */
+static uint8_t layer_pressed[MATRIX_ROWS][MATRIX_COLS] = {};
+#endif
+action_t layer_switch_get_action(keyevent_t event)
+{
+    uint8_t layer = 0;
+#ifndef NO_TRACK_KEY_PRESS
+    if (event.pressed) {
+        layer = current_layer_for_key(event.key);
+        layer_pressed[event.key.row][event.key.col] = layer;
+    } else {
+        layer = layer_pressed[event.key.row][event.key.col];
+    }
 #else
-    action = action_for_key(biton32(default_layer_state), key);
-    return action;
+    layer = current_layer_for_key(event.key);
 #endif
+    return action_for_key(layer, event.key);
 }
index b6da353cfdbe851d6bfb5689b6173135b8697d84..ba8b06384ccb3cba067108f1f617cb65f1d96d9b 100644 (file)
@@ -72,6 +72,6 @@ void layer_xor(uint32_t state);
 
 
 /* return action depending on current layer status */
-action_t layer_switch_get_action(keypos_t key);
+action_t layer_switch_get_action(keyevent_t key);
 
 #endif
index a74eb1061d5371c88d4e43ed97ed875b34f07c6a..45cb2fcfbb62cb6b96fe87b963c6072de76080f6 100644 (file)
@@ -115,7 +115,7 @@ bool process_tapping(keyrecord_t *keyp)
                  */
                 else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) {
                     // Modifier should be retained till end of this tapping.
-                    action_t action = layer_switch_get_action(event.key);
+                    action_t action = layer_switch_get_action(event);
                     switch (action.kind.id) {
                         case ACT_LMODS:
                         case ACT_RMODS:
@@ -152,7 +152,7 @@ bool process_tapping(keyrecord_t *keyp)
                     debug_tapping_key();
                     return true;
                 }
-                else if (is_tap_key(event.key) && event.pressed) {
+                else if (is_tap_key(event) && event.pressed) {
                     if (tapping_key.tap.count > 1) {
                         debug("Tapping: Start new tap with releasing last tap(>1).\n");
                         // unregister key
@@ -196,7 +196,7 @@ bool process_tapping(keyrecord_t *keyp)
                     tapping_key = (keyrecord_t){};
                     return true;
                 }
-                else if (is_tap_key(event.key) && event.pressed) {
+                else if (is_tap_key(event) && event.pressed) {
                     if (tapping_key.tap.count > 1) {
                         debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
                         // unregister key
@@ -241,7 +241,7 @@ bool process_tapping(keyrecord_t *keyp)
                         tapping_key = *keyp;
                         return true;
                     }
-                } else if (is_tap_key(event.key)) {
+                } else if (is_tap_key(event)) {
                     // Sequential tap can be interfered with other tap key.
                     debug("Tapping: Start with interfering other tap.\n");
                     tapping_key = *keyp;
@@ -272,7 +272,7 @@ bool process_tapping(keyrecord_t *keyp)
     }
     // not tapping state
     else {
-        if (event.pressed && is_tap_key(event.key)) {
+        if (event.pressed && is_tap_key(event)) {
             debug("Tapping: Start(Press tap key).\n");
             tapping_key = *keyp;
             waiting_buffer_scan_tap();
Imprint / Impressum