Skip to content

Commit ba2883f

Browse files
committed
core: Fix for stuck key problem #441
- Idea form qmk/qmk_firmware#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
1 parent cf9f157 commit ba2883f

File tree

6 files changed

+48
-16
lines changed

6 files changed

+48
-16
lines changed

tmk_core/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ Source code is available here: <https://github.com/tmk/tmk_keyboard/tree/core>
77

88
Updates
99
-------
10+
#### 2017/05/30
11+
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`.
12+
13+
This is virtually equivalent to QMK `PREVENT_STUCK_MODIFIERS`. <https://github.com/qmk/qmk_firmware/pull/182>
14+
15+
#### 2017/01/11
16+
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.
17+
1018
#### 2016/06/26
1119
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[]`.
1220

tmk_core/common/action.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ void process_action(keyrecord_t *record)
6565

6666
if (IS_NOEVENT(event)) { return; }
6767

68-
action_t action = layer_switch_get_action(event.key);
68+
action_t action = layer_switch_get_action(event);
6969
dprint("ACTION: "); debug_action(action);
7070
#ifndef NO_ACTION_LAYER
7171
dprint(" layer_state: "); layer_debug();
@@ -529,9 +529,9 @@ void clear_keyboard_but_mods(void)
529529
#endif
530530
}
531531

532-
bool is_tap_key(keypos_t key)
532+
bool is_tap_key(keyevent_t event)
533533
{
534-
action_t action = layer_switch_get_action(key);
534+
action_t action = layer_switch_get_action(event);
535535

536536
switch (action.kind.id) {
537537
case ACT_LMODS_TAP:

tmk_core/common/action.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ void unregister_mods(uint8_t mods);
6868
void clear_keyboard(void);
6969
void clear_keyboard_but_mods(void);
7070
void layer_switch(uint8_t new_layer);
71-
bool is_tap_key(keypos_t key);
71+
bool is_tap_key(keyevent_t event);
7272

7373
/* debug */
7474
void debug_event(keyevent_t event);

tmk_core/common/action_layer.c

+30-6
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ static void default_layer_state_set(uint32_t state)
2424
default_layer_state = state;
2525
hook_default_layer_change(default_layer_state);
2626
default_layer_debug(); debug("\n");
27+
#ifdef NO_TRACK_KEY_PRESS
2728
clear_keyboard_but_mods(); // To avoid stuck keys
29+
#endif
2830
}
2931

3032
void default_layer_debug(void)
@@ -66,7 +68,9 @@ static void layer_state_set(uint32_t state)
6668
layer_state = state;
6769
hook_layer_change(layer_state);
6870
layer_debug(); dprintln();
71+
#ifdef NO_TRACK_KEY_PRESS
6972
clear_keyboard_but_mods(); // To avoid stuck keys
73+
#endif
7074
}
7175

7276
void layer_clear(void)
@@ -115,7 +119,8 @@ void layer_debug(void)
115119

116120

117121

118-
action_t layer_switch_get_action(keypos_t key)
122+
/* return layer effective for key at this time */
123+
static uint8_t current_layer_for_key(keypos_t key)
119124
{
120125
action_t action = ACTION_TRANSPARENT;
121126

@@ -126,15 +131,34 @@ action_t layer_switch_get_action(keypos_t key)
126131
if (layers & (1UL<<i)) {
127132
action = action_for_key(i, key);
128133
if (action.code != (action_t)ACTION_TRANSPARENT.code) {
129-
return action;
134+
return i;
130135
}
131136
}
132137
}
133138
/* fall back to layer 0 */
134-
action = action_for_key(0, key);
135-
return action;
139+
return 0;
140+
#else
141+
return biton32(default_layer_state);
142+
#endif
143+
}
144+
145+
146+
#ifndef NO_TRACK_KEY_PRESS
147+
/* record layer on where key is pressed */
148+
static uint8_t layer_pressed[MATRIX_ROWS][MATRIX_COLS] = {};
149+
#endif
150+
action_t layer_switch_get_action(keyevent_t event)
151+
{
152+
uint8_t layer = 0;
153+
#ifndef NO_TRACK_KEY_PRESS
154+
if (event.pressed) {
155+
layer = current_layer_for_key(event.key);
156+
layer_pressed[event.key.row][event.key.col] = layer;
157+
} else {
158+
layer = layer_pressed[event.key.row][event.key.col];
159+
}
136160
#else
137-
action = action_for_key(biton32(default_layer_state), key);
138-
return action;
161+
layer = current_layer_for_key(event.key);
139162
#endif
163+
return action_for_key(layer, event.key);
140164
}

tmk_core/common/action_layer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,6 @@ void layer_xor(uint32_t state);
7272

7373

7474
/* return action depending on current layer status */
75-
action_t layer_switch_get_action(keypos_t key);
75+
action_t layer_switch_get_action(keyevent_t key);
7676

7777
#endif

tmk_core/common/action_tapping.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ bool process_tapping(keyrecord_t *keyp)
115115
*/
116116
else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) {
117117
// Modifier should be retained till end of this tapping.
118-
action_t action = layer_switch_get_action(event.key);
118+
action_t action = layer_switch_get_action(event);
119119
switch (action.kind.id) {
120120
case ACT_LMODS:
121121
case ACT_RMODS:
@@ -152,7 +152,7 @@ bool process_tapping(keyrecord_t *keyp)
152152
debug_tapping_key();
153153
return true;
154154
}
155-
else if (is_tap_key(event.key) && event.pressed) {
155+
else if (is_tap_key(event) && event.pressed) {
156156
if (tapping_key.tap.count > 1) {
157157
debug("Tapping: Start new tap with releasing last tap(>1).\n");
158158
// unregister key
@@ -196,7 +196,7 @@ bool process_tapping(keyrecord_t *keyp)
196196
tapping_key = (keyrecord_t){};
197197
return true;
198198
}
199-
else if (is_tap_key(event.key) && event.pressed) {
199+
else if (is_tap_key(event) && event.pressed) {
200200
if (tapping_key.tap.count > 1) {
201201
debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
202202
// unregister key
@@ -241,7 +241,7 @@ bool process_tapping(keyrecord_t *keyp)
241241
tapping_key = *keyp;
242242
return true;
243243
}
244-
} else if (is_tap_key(event.key)) {
244+
} else if (is_tap_key(event)) {
245245
// Sequential tap can be interfered with other tap key.
246246
debug("Tapping: Start with interfering other tap.\n");
247247
tapping_key = *keyp;
@@ -272,7 +272,7 @@ bool process_tapping(keyrecord_t *keyp)
272272
}
273273
// not tapping state
274274
else {
275-
if (event.pressed && is_tap_key(event.key)) {
275+
if (event.pressed && is_tap_key(event)) {
276276
debug("Tapping: Start(Press tap key).\n");
277277
tapping_key = *keyp;
278278
waiting_buffer_scan_tap();

0 commit comments

Comments
 (0)