aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Elenbaas <isaacelenbaas@gmail.com>2021-11-25 07:12:14 -0500
committerGitHub <noreply@github.com>2021-11-25 23:12:14 +1100
commitd9393b86842b7ef143259b5f771ae7969f98cbb4 (patch)
treee0760c20f65c4cac7b6ffb3fedf3f36c6f7c13a2
parent282e916d86a5d353b7cbdfef3afad3c7b011eb14 (diff)
downloadqmk_firmware-d9393b86842b7ef143259b5f771ae7969f98cbb4.tar.gz
qmk_firmware-d9393b86842b7ef143259b5f771ae7969f98cbb4.zip
Add Retro Shift (Auto Shift for Tap Hold via Retro Tapping) and Custom Auto Shifts (#11059)
* Add Retro Shift and Custom Auto Shifts * Fix compilation errors with no RETRO_SHIFT value
-rw-r--r--docs/feature_auto_shift.md176
-rw-r--r--docs/tap_hold.md4
-rw-r--r--quantum/action.c19
-rw-r--r--quantum/action_tapping.c106
-rw-r--r--quantum/process_keycode/process_auto_shift.c419
-rw-r--r--quantum/process_keycode/process_auto_shift.h22
6 files changed, 621 insertions, 125 deletions
diff --git a/docs/feature_auto_shift.md b/docs/feature_auto_shift.md
index a54cd79e4..99b0ca3c8 100644
--- a/docs/feature_auto_shift.md
+++ b/docs/feature_auto_shift.md
@@ -26,20 +26,26 @@ down will repeat the shifted key, though this can be disabled with
26once then immediately (within `TAPPING_TERM`) hold it down again (this works 26once then immediately (within `TAPPING_TERM`) hold it down again (this works
27with the shifted value as well if auto-repeat is disabled). 27with the shifted value as well if auto-repeat is disabled).
28 28
29There are also the `get_auto_shift_repeat` and `get_auto_shift_no_auto_repeat`
30functions for more granular control. Neither will have an effect unless
31`AUTO_SHIFT_REPEAT_PER_KEY` or `AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY` respectively
32are defined.
33
29## Are There Limitations to Auto Shift? 34## Are There Limitations to Auto Shift?
30 35
31Yes, unfortunately. 36Yes, unfortunately.
32 37
33You will have characters that are shifted when you did not intend on shifting, and 381. You will have characters that are shifted when you did not intend on shifting, and
34other characters you wanted shifted, but were not. This simply comes down to 39 other characters you wanted shifted, but were not. This simply comes down to
35practice. As we get in a hurry, we think we have hit the key long enough for a 40 practice. As we get in a hurry, we think we have hit the key long enough for a
36shifted version, but we did not. On the other hand, we may think we are tapping 41 shifted version, but we did not. On the other hand, we may think we are tapping
37the keys, but really we have held it for a little longer than anticipated. 42 the keys, but really we have held it for a little longer than anticipated.
38 432. Additionally, with keyrepeat the desired shift state can get mixed up. It will
39Additionally, with keyrepeat the desired shift state can get mixed up. It will 44 always 'belong' to the last key pressed. For example, keyrepeating a capital
40always 'belong' to the last key pressed. For example, keyrepeating a capital 45 and then tapping something lowercase (whether or not it's an Auto Shift key)
41and then tapping something lowercase (whether or not it's an Auto Shift key) 46 will result in the capital's *key* still being held, but shift not.
42will result in the capital's *key* still being held, but shift not. 473. Auto Shift does not apply to Tap Hold keys. For automatic shifting of Tap Hold
48 keys see [Retro Shift](#retro-shift).
43 49
44## How Do I Enable Auto Shift? 50## How Do I Enable Auto Shift?
45 51
@@ -96,6 +102,34 @@ quicker than normal and you will be set.
96 102
97?> Auto Shift has three special keys that can help you get this value right very quick. See "Auto Shift Setup" for more details! 103?> Auto Shift has three special keys that can help you get this value right very quick. See "Auto Shift Setup" for more details!
98 104
105For more granular control of this feature, you can add the following to your `config.h`:
106
107```c
108#define AUTO_SHIFT_TIMEOUT_PER_KEY
109```
110
111You can then add the following function to your keymap:
112
113```c
114uint16_t get_autoshift_timeout(uint16_t keycode, keyrecord_t *record) {
115 switch(keycode) {
116 case AUTO_SHIFT_NUMERIC:
117 return 2 * get_generic_autoshift_timeout();
118 case AUTO_SHIFT_SPECIAL:
119 return get_generic_autoshift_timeout() + 50;
120 case AUTO_SHIFT_ALPHA:
121 default:
122 return get_generic_autoshift_timeout();
123 }
124}
125```
126
127Note that you cannot override individual keys that are in one of those groups
128if you are using them; trying to add a case for `KC_A` in the above example will
129not compile as `AUTO_SHIFT_ALPHA` is there. A possible solution is a second switch
130above to handle individual keys with no default case and only referencing the
131groups in the below fallback switch.
132
99### NO_AUTO_SHIFT_SPECIAL (simple define) 133### NO_AUTO_SHIFT_SPECIAL (simple define)
100 134
101Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>, 135Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>,
@@ -109,11 +143,24 @@ Do not Auto Shift numeric keys, zero through nine.
109 143
110Do not Auto Shift alpha characters, which include A through Z. 144Do not Auto Shift alpha characters, which include A through Z.
111 145
112### Auto Shift Per Key 146### Auto Shift Per Key
113 147
114This is a function that allows you to determine which keys shold be autoshifted, much like the tap-hold keys. 148There are functions that allows you to determine which keys shold be autoshifted, much like the tap-hold keys.
115 149
116The default function looks like this: 150The first of these, used to simply add a key to Auto Shift, is `get_custom_auto_shifted_key`:
151
152```c
153bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
154 switch(keycode) {
155 case KC_DOT:
156 return true;
157 default:
158 return false;
159 }
160}
161```
162
163For more granular control, there is `get_auto_shifted_key`. The default function looks like this:
117 164
118```c 165```c
119bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { 166bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
@@ -131,9 +178,10 @@ bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
131# endif 178# endif
132 return true; 179 return true;
133 } 180 }
134 return false; 181 return get_custom_auto_shifted_key(keycode, record);
135} 182}
136``` 183```
184
137This functionality is enabled by default, and does not need a define. 185This functionality is enabled by default, and does not need a define.
138 186
139### AUTO_SHIFT_REPEAT (simple define) 187### AUTO_SHIFT_REPEAT (simple define)
@@ -144,6 +192,106 @@ Enables keyrepeat.
144 192
145Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded. 193Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded.
146 194
195## Custom Shifted Values
196
197Especially on small keyboards, the default shifted value for many keys is not
198optimal. To provide more customizability, there are two user-definable
199functions, `autoshift_press/release_user`. These register or unregister the
200correct value for the passed key. Below is an example adding period to Auto
201Shift and making its shifted value exclamation point. Make sure to use weak
202mods - setting real would make any keys following it use their shifted values
203as if you were holding the key. Clearing of modifiers is handled by Auto Shift,
204and the OS-sent shift value if keyrepeating multiple keys is always that of
205the last key pressed (whether or not it's an Auto Shift key).
206
207You can also have non-shifted keys for the shifted values (or even no shifted
208value), just don't set a shift modifier!
209
210```c
211bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
212 switch(keycode) {
213 case KC_DOT:
214 return true;
215 default:
216 return false;
217 }
218}
219
220void autoshift_press_user(uint16_t keycode, bool shifted, keyrecord_t *record) {
221 switch(keycode) {
222 case KC_DOT:
223 register_code16((!shifted) ? KC_DOT : KC_EXLM);
224 break;
225 default:
226 if (shifted) {
227 add_weak_mods(MOD_BIT(KC_LSFT));
228 }
229 // & 0xFF gets the Tap key for Tap Holds, required when using Retro Shift
230 register_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode);
231 }
232}
233
234void autoshift_release_user(uint16_t keycode, bool shifted, keyrecord_t *record) {
235 switch(keycode) {
236 case KC_DOT:
237 unregister_code16((!shifted) ? KC_DOT : KC_EXLM);
238 break;
239 default:
240 // & 0xFF gets the Tap key for Tap Holds, required when using Retro Shift
241 // The IS_RETRO check isn't really necessary here, always using
242 // keycode & 0xFF would be fine.
243 unregister_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode);
244 }
245}
246```
247
248## Retro Shift
249
250Holding and releasing a Tap Hold key without pressing another key will ordinarily
251result in only the hold. With `retro shift` enabled this action will instead
252produce a shifted version of the tap keycode on release.
253
254It does not require [Retro Tapping](tap_hold.md#retro-tapping) to be enabled, and
255if both are enabled the state of `retro tapping` will only apply if the tap keycode
256is not matched by Auto Shift. `RETRO_TAPPING_PER_KEY` and its corresponding
257function, however, are checked before `retro shift` is applied.
258
259To enable `retro shift`, add the following to your `config.h`:
260
261```c
262#define RETRO_SHIFT
263```
264
265If `RETRO_SHIFT` is defined to a value, hold times greater than that value will
266not produce a tap on release for Mod Taps, and instead triggers the hold action.
267This enables modifiers to be held for combining with mouse clicks without
268generating taps on release. For example:
269
270```c
271#define RETRO_SHIFT 500
272```
273
274This value (if set) must be greater than one's `TAPPING_TERM`, as the key press
275must be designated as a 'hold' by `process_tapping` before we send the modifier.
276There is no such limitation in regards to `AUTO_SHIFT_TIMEOUT` for normal keys.
277
278### Retro Shift and Tap Hold Configurations
279
280Tap Hold Configurations work a little differently when using Retro Shift.
281Referencing `TAPPING_TERM` makes little sense, as holding longer would result in
282shifting one of the keys.
283
284`IGNORE_MOD_TAP_INTERRUPT` changes *only* rolling from a mod tap (releasing it
285first), sending both keys instead of the modifier on the second. Its effects on
286nested presses are ignored.
287
288As nested taps were changed to act as though `PERMISSIVE_HOLD` is set unless only
289`IGNORE_MOD_TAP_INTERRUPT` is (outside of Retro Shift), and Retro Shift ignores
290`IGNORE_MOD_TAP_INTERRUPT`, `PERMISSIVE_HOLD` has no effect on Mod Taps.
291
292Nested taps will *always* act as though the `TAPPING_TERM` was exceeded for both
293Mod and Layer Tap keys.
294
147## Using Auto Shift Setup 295## Using Auto Shift Setup
148 296
149This will enable you to define three keys temporarily to increase, decrease and report your `AUTO_SHIFT_TIMEOUT`. 297This will enable you to define three keys temporarily to increase, decrease and report your `AUTO_SHIFT_TIMEOUT`.
diff --git a/docs/tap_hold.md b/docs/tap_hold.md
index dbad48fd9..a343d0bc3 100644
--- a/docs/tap_hold.md
+++ b/docs/tap_hold.md
@@ -268,6 +268,10 @@ bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) {
268} 268}
269``` 269```
270 270
271### Retro Shift
272
273[Auto Shift,](feature_auto_shift.md) has its own version of `retro tapping` called `retro shift`. It is extremely similar to `retro tapping`, but holding the key past `AUTO_SHIFT_TIMEOUT` results in the value it sends being shifted. Other configurations also affect it differently; see [here](feature_auto_shift.md#retro-shift) for more information.
274
271## Why do we include the key record for the per key functions? 275## Why do we include the key record for the per key functions?
272 276
273One thing that you may notice is that we include the key record for all of the "per key" functions, and may be wondering why we do that. 277One thing that you may notice is that we include the key record for all of the "per key" functions, and may be wondering why we do that.
diff --git a/quantum/action.c b/quantum/action.c
index ceaaa551f..5e81efb67 100644
--- a/quantum/action.c
+++ b/quantum/action.c
@@ -45,10 +45,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
45 45
46int tp_buttons; 46int tp_buttons;
47 47
48#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) 48#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
49int retro_tapping_counter = 0; 49int retro_tapping_counter = 0;
50#endif 50#endif
51 51
52#if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
53# include "process_auto_shift.h"
54#endif
55
52#ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY 56#ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
53__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; } 57__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; }
54#endif 58#endif
@@ -69,7 +73,7 @@ void action_exec(keyevent_t event) {
69 dprint("EVENT: "); 73 dprint("EVENT: ");
70 debug_event(event); 74 debug_event(event);
71 dprintln(); 75 dprintln();
72#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) 76#if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
73 retro_tapping_counter++; 77 retro_tapping_counter++;
74#endif 78#endif
75 } 79 }
@@ -106,6 +110,11 @@ void action_exec(keyevent_t event) {
106#endif 110#endif
107 111
108#ifndef NO_ACTION_TAPPING 112#ifndef NO_ACTION_TAPPING
113# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
114 if (event.pressed) {
115 retroshift_poll_time(&event);
116 }
117# endif
109 if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { 118 if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) {
110 action_tapping_process(record); 119 action_tapping_process(record);
111 } 120 }
@@ -730,7 +739,7 @@ void process_action(keyrecord_t *record, action_t action) {
730#endif 739#endif
731 740
732#ifndef NO_ACTION_TAPPING 741#ifndef NO_ACTION_TAPPING
733# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) 742# if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
734 if (!is_tap_action(action)) { 743 if (!is_tap_action(action)) {
735 retro_tapping_counter = 0; 744 retro_tapping_counter = 0;
736 } else { 745 } else {
@@ -747,7 +756,11 @@ void process_action(keyrecord_t *record, action_t action) {
747 get_retro_tapping(get_event_keycode(record->event, false), record) && 756 get_retro_tapping(get_event_keycode(record->event, false), record) &&
748# endif 757# endif
749 retro_tapping_counter == 2) { 758 retro_tapping_counter == 2) {
759# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
760 process_auto_shift(action.layer_tap.code, record);
761# else
750 tap_code(action.layer_tap.code); 762 tap_code(action.layer_tap.code);
763# endif
751 } 764 }
752 retro_tapping_counter = 0; 765 retro_tapping_counter = 0;
753 } 766 }
diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c
index 60e56fb81..0586fad42 100644
--- a/quantum/action_tapping.c
+++ b/quantum/action_tapping.c
@@ -44,6 +44,10 @@ __attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *re
44__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { return false; } 44__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { return false; }
45# endif 45# endif
46 46
47# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
48# include "process_auto_shift.h"
49# endif
50
47static keyrecord_t tapping_key = {}; 51static keyrecord_t tapping_key = {};
48static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; 52static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
49static uint8_t waiting_buffer_head = 0; 53static uint8_t waiting_buffer_head = 0;
@@ -107,12 +111,29 @@ void action_tapping_process(keyrecord_t record) {
107/* return true when key event is processed or consumed. */ 111/* return true when key event is processed or consumed. */
108bool process_tapping(keyrecord_t *keyp) { 112bool process_tapping(keyrecord_t *keyp) {
109 keyevent_t event = keyp->event; 113 keyevent_t event = keyp->event;
114# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(TAPPING_TERM_PER_KEY) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(TAPPING_FORCE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEYPRESS_PER_KEY)
115 uint16_t tapping_keycode = get_record_keycode(&tapping_key, false);
116# endif
110 117
111 // if tapping 118 // if tapping
112 if (IS_TAPPING_PRESSED()) { 119 if (IS_TAPPING_PRESSED()) {
113 if (WITHIN_TAPPING_TERM(event)) { 120 // clang-format off
121 if (WITHIN_TAPPING_TERM(event)
122# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
123 || (
124# ifdef RETRO_TAPPING_PER_KEY
125 get_retro_tapping(tapping_keycode, keyp) &&
126# endif
127 (RETRO_SHIFT + 0) != 0 && TIMER_DIFF_16(event.time, tapping_key.event.time) < (RETRO_SHIFT + 0)
128 )
129# endif
130 ) {
131 // clang-format on
114 if (tapping_key.tap.count == 0) { 132 if (tapping_key.tap.count == 0) {
115 if (IS_TAPPING_RECORD(keyp) && !event.pressed) { 133 if (IS_TAPPING_RECORD(keyp) && !event.pressed) {
134# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
135 retroshift_swap_times();
136# endif
116 // first tap! 137 // first tap!
117 debug("Tapping: First tap(0->1).\n"); 138 debug("Tapping: First tap(0->1).\n");
118 tapping_key.tap.count = 1; 139 tapping_key.tap.count = 1;
@@ -128,22 +149,70 @@ bool process_tapping(keyrecord_t *keyp) {
128 * This can register the key before settlement of tapping, 149 * This can register the key before settlement of tapping,
129 * useful for long TAPPING_TERM but may prevent fast typing. 150 * useful for long TAPPING_TERM but may prevent fast typing.
130 */ 151 */
131# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) 152 // clang-format off
132 else if ((( 153# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
154 else if (
155 (
156 (
157 (
133# ifdef TAPPING_TERM_PER_KEY 158# ifdef TAPPING_TERM_PER_KEY
134 get_tapping_term(get_record_keycode(&tapping_key, false), keyp) 159 get_tapping_term(tapping_keycode, keyp)
135# else 160# else
136 TAPPING_TERM 161 TAPPING_TERM
137# endif 162# endif
138 >= 500) 163 >= 500
164 )
139 165
140# ifdef PERMISSIVE_HOLD_PER_KEY 166# ifdef PERMISSIVE_HOLD_PER_KEY
141 || get_permissive_hold(get_record_keycode(&tapping_key, false), keyp) 167 || get_permissive_hold(tapping_keycode, keyp)
142# elif defined(PERMISSIVE_HOLD) 168# elif defined(PERMISSIVE_HOLD)
143 || true 169 || true
170# endif
171 ) && IS_RELEASED(event) && waiting_buffer_typed(event)
172 )
173 // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
174 // unnecessarily and fixes them for Layer Taps.
175# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
176 || (
177# ifdef RETRO_TAPPING_PER_KEY
178 get_retro_tapping(tapping_keycode, keyp) &&
179# endif
180 (
181 // Rolled over the two keys.
182 (
183 (
184 false
185# if defined(HOLD_ON_OTHER_KEYPRESS) || defined(HOLD_ON_OTHER_KEYPRESS_PER_KEY)
186 || (
187 IS_LT(tapping_keycode)
188# ifdef HOLD_ON_OTHER_KEYPRESS_PER_KEY
189 && get_hold_on_other_keypress(tapping_keycode, keyp)
190# endif
191 )
192# endif
193# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
194 || (
195 IS_MT(tapping_keycode)
196# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
197 && !get_ignore_mod_tap_interrupt(tapping_keycode, keyp)
198# endif
199 )
200# endif
201 ) && tapping_key.tap.interrupted == true
202 )
203 // Makes Retro Shift ignore [IGNORE_MOD_TAP_INTERRUPT's
204 // effects on nested taps for MTs and the default
205 // behavior of LTs] below TAPPING_TERM or RETRO_SHIFT.
206 || (
207 IS_RETRO(tapping_keycode)
208 && (event.key.col != tapping_key.event.key.col || event.key.row != tapping_key.event.key.row)
209 && IS_RELEASED(event) && waiting_buffer_typed(event)
210 )
211 )
212 )
144# endif 213# endif
145 ) && 214 ) {
146 IS_RELEASED(event) && waiting_buffer_typed(event)) { 215 // clang-format on
147 debug("Tapping: End. No tap. Interfered by typing key\n"); 216 debug("Tapping: End. No tap. Interfered by typing key\n");
148 process_record(&tapping_key); 217 process_record(&tapping_key);
149 tapping_key = (keyrecord_t){}; 218 tapping_key = (keyrecord_t){};
@@ -181,7 +250,7 @@ bool process_tapping(keyrecord_t *keyp) {
181 tapping_key.tap.interrupted = true; 250 tapping_key.tap.interrupted = true;
182# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) 251# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
183# if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) 252# if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
184 if (get_hold_on_other_key_press(get_record_keycode(&tapping_key, false), keyp)) 253 if (get_hold_on_other_key_press(tapping_keycode, keyp))
185# endif 254# endif
186 { 255 {
187 debug("Tapping: End. No tap. Interfered by pressed key\n"); 256 debug("Tapping: End. No tap. Interfered by pressed key\n");
@@ -284,14 +353,25 @@ bool process_tapping(keyrecord_t *keyp) {
284 } 353 }
285 } 354 }
286 } else if (IS_TAPPING_RELEASED()) { 355 } else if (IS_TAPPING_RELEASED()) {
287 if (WITHIN_TAPPING_TERM(event)) { 356 // clang-format off
357 if (WITHIN_TAPPING_TERM(event)
358# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
359 || (
360# ifdef RETRO_TAPPING_PER_KEY
361 get_retro_tapping(tapping_keycode, keyp) &&
362# endif
363 (RETRO_SHIFT + 0) != 0 && TIMER_DIFF_16(event.time, tapping_key.event.time) < (RETRO_SHIFT + 0)
364 )
365# endif
366 ) {
367 // clang-format on
288 if (event.pressed) { 368 if (event.pressed) {
289 if (IS_TAPPING_RECORD(keyp)) { 369 if (IS_TAPPING_RECORD(keyp)) {
290//# ifndef TAPPING_FORCE_HOLD 370//# ifndef TAPPING_FORCE_HOLD
291# if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY) 371# if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY)
292 if ( 372 if (
293# ifdef TAPPING_FORCE_HOLD_PER_KEY 373# ifdef TAPPING_FORCE_HOLD_PER_KEY
294 !get_tapping_force_hold(get_record_keycode(&tapping_key, false), keyp) && 374 !get_tapping_force_hold(tapping_keycode, keyp) &&
295# endif 375# endif
296 !tapping_key.tap.interrupted && tapping_key.tap.count > 0) { 376 !tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
297 // sequential tap. 377 // sequential tap.
diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
index 4d928edb5..bbc6367ff 100644
--- a/quantum/process_keycode/process_auto_shift.c
+++ b/quantum/process_keycode/process_auto_shift.c
@@ -18,7 +18,6 @@
18 18
19# include <stdbool.h> 19# include <stdbool.h>
20# include <stdio.h> 20# include <stdio.h>
21
22# include "process_auto_shift.h" 21# include "process_auto_shift.h"
23 22
24# ifndef AUTO_SHIFT_DISABLED_AT_STARTUP 23# ifndef AUTO_SHIFT_DISABLED_AT_STARTUP
@@ -27,11 +26,25 @@
27# define AUTO_SHIFT_STARTUP_STATE false /* disabled */ 26# define AUTO_SHIFT_STARTUP_STATE false /* disabled */
28# endif 27# endif
29 28
30static uint16_t autoshift_time = 0; 29// Stores the last Auto Shift key's up or down time, for evaluation or keyrepeat.
31static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; 30static uint16_t autoshift_time = 0;
32static uint16_t autoshift_lastkey = KC_NO; 31# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
32// Stores the last key's up or down time, to replace autoshift_time so that Tap Hold times are accurate.
33static uint16_t retroshift_time = 0;
34// Stores a possibly Retro Shift key's up or down time, as retroshift_time needs
35// to be set before the Retro Shift key is evaluated if it is interrupted by an
36// Auto Shifted key.
37static uint16_t last_retroshift_time;
38# endif
39static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
40static uint16_t autoshift_lastkey = KC_NO;
41static keyrecord_t autoshift_lastrecord;
42// Keys take 8 bits if modifiers are excluded. This records the shift state
43// when pressed for each key, so that can be passed to the release function
44// and it knows which key needs to be released (if shifted is different base).
45static uint16_t autoshift_shift_states[((1 << 8) + 15) / 16];
33static struct { 46static struct {
34 // Whether autoshift is enabled. 47 // Whether Auto Shift is enabled.
35 bool enabled : 1; 48 bool enabled : 1;
36 // Whether the last auto-shifted key was released after the timeout. This 49 // Whether the last auto-shifted key was released after the timeout. This
37 // is used to replicate the last key for a tap-then-hold. 50 // is used to replicate the last key for a tap-then-hold.
@@ -40,43 +53,157 @@ static struct {
40 bool in_progress : 1; 53 bool in_progress : 1;
41 // Whether the auto-shifted keypress has been registered. 54 // Whether the auto-shifted keypress has been registered.
42 bool holding_shift : 1; 55 bool holding_shift : 1;
43} autoshift_flags = {AUTO_SHIFT_STARTUP_STATE, false, false, false}; 56 // Whether the user is holding a shift and we removed it.
57 bool cancelling_lshift : 1;
58 bool cancelling_rshift : 1;
59 // clang-format wants to remove the true for some reason.
60 // clang-format off
61} autoshift_flags = {AUTO_SHIFT_STARTUP_STATE, false, false, false, false, false};
62// clang-format on
63
64/** \brief Called on physical press, returns whether key should be added to Auto Shift */
65__attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { return false; }
66
67/** \brief Called on physical press, returns whether is Auto Shift key */
68__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
69 switch (keycode) {
70# ifndef NO_AUTO_SHIFT_ALPHA
71 case AUTO_SHIFT_ALPHA:
72# endif
73# ifndef NO_AUTO_SHIFT_NUMERIC
74 case AUTO_SHIFT_NUMERIC:
75# endif
76# ifndef NO_AUTO_SHIFT_SPECIAL
77 case AUTO_SHIFT_SPECIAL:
78# endif
79 return true;
80 }
81 return get_custom_auto_shifted_key(keycode, record);
82}
83
84/** \brief Called to check whether defines should apply if PER_KEY is set for it */
85__attribute__((weak)) bool get_auto_shift_repeat(uint16_t keycode, keyrecord_t *record) { return true; }
86__attribute__((weak)) bool get_auto_shift_no_auto_repeat(uint16_t keycode, keyrecord_t *record) { return true; }
87
88/** \brief Called when an Auto Shift key needs to be pressed */
89__attribute__((weak)) void autoshift_press_user(uint16_t keycode, bool shifted, keyrecord_t *record) {
90 if (shifted) {
91 add_weak_mods(MOD_BIT(KC_LSFT));
92 }
93 register_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode);
94}
95
96/** \brief Called when an Auto Shift key needs to be released */
97__attribute__((weak)) void autoshift_release_user(uint16_t keycode, bool shifted, keyrecord_t *record) { unregister_code16((IS_RETRO(keycode)) ? keycode & 0xFF : keycode); }
98
99/** \brief Sets the shift state to use when keyrepeating, required by custom shifts */
100void set_autoshift_shift_state(uint16_t keycode, bool shifted) {
101 keycode = keycode & 0xFF;
102 if (shifted) {
103 autoshift_shift_states[keycode / 16] |= (uint16_t)1 << keycode % 16;
104 } else {
105 autoshift_shift_states[keycode / 16] &= ~((uint16_t)1 << keycode % 16);
106 }
107}
108
109/** \brief Gets the shift state to use when keyrepeating, required by custom shifts */
110bool get_autoshift_shift_state(uint16_t keycode) {
111 keycode = keycode & 0xFF;
112 return (autoshift_shift_states[keycode / 16] & (uint16_t)1 << keycode % 16) != (uint16_t)0;
113}
114
115/** \brief Restores the shift key if it was cancelled by Auto Shift */
116static void autoshift_flush_shift(void) {
117 autoshift_flags.holding_shift = false;
118 del_weak_mods(MOD_BIT(KC_LSFT));
119 if (autoshift_flags.cancelling_lshift) {
120 autoshift_flags.cancelling_lshift = false;
121 add_mods(MOD_BIT(KC_LSFT));
122 }
123 if (autoshift_flags.cancelling_rshift) {
124 autoshift_flags.cancelling_rshift = false;
125 add_mods(MOD_BIT(KC_RSFT));
126 }
127 send_keyboard_report();
128}
44 129
45/** \brief Record the press of an autoshiftable key 130/** \brief Record the press of an autoshiftable key
46 * 131 *
47 * \return Whether the record should be further processed. 132 * \return Whether the record should be further processed.
48 */ 133 */
49static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) { 134static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) {
50 if (!autoshift_flags.enabled) { 135 // clang-format off
51 return true; 136 if ((get_mods()
52 } 137# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
53 138 | get_oneshot_mods()
139# endif
140 ) & (~MOD_BIT(KC_LSFT))
141 ) {
142 // clang-format on
143 // Prevents keyrepeating unshifted value of key after using it in a key combo.
144 autoshift_lastkey = KC_NO;
54# ifndef AUTO_SHIFT_MODIFIERS 145# ifndef AUTO_SHIFT_MODIFIERS
55 if (get_mods()) { 146 // We can't return true here anymore because custom unshifted values are
56 return true; 147 // possible and there's no good way to tell whether the press returned
57 } 148 // true upon release.
149 set_autoshift_shift_state(keycode, false);
150 autoshift_press_user(keycode, false, record);
151# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
152 set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT)));
153 clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
154# endif
155 return false;
58# endif 156# endif
59# ifdef AUTO_SHIFT_REPEAT 157 }
60 const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time); 158
61# ifndef AUTO_SHIFT_NO_AUTO_REPEAT 159 // Store record to be sent to user functions if there's no release record then.
62 if (!autoshift_flags.lastshifted) { 160 autoshift_lastrecord = *record;
161 autoshift_lastrecord.event.pressed = false;
162 autoshift_lastrecord.event.time = 0;
163 // clang-format off
164# if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)
165 if (keycode == autoshift_lastkey &&
166# ifdef AUTO_SHIFT_REPEAT_PER_KEY
167 get_auto_shift_repeat(autoshift_lastkey, record) &&
63# endif 168# endif
64 if (elapsed < TAPPING_TERM && keycode == autoshift_lastkey) { 169# if !defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY)
65 // Allow a tap-then-hold for keyrepeat. 170 (
66 if (!autoshift_flags.lastshifted) { 171 !autoshift_flags.lastshifted
67 register_code(autoshift_lastkey); 172# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY
68 } else { 173 || get_auto_shift_no_auto_repeat(autoshift_lastkey, record)
69 // Simulate pressing the shift key. 174# endif
70 add_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); 175 ) &&
71 register_code(autoshift_lastkey); 176# endif
72 } 177 TIMER_DIFF_16(now, autoshift_time) <
73 return false; 178# ifdef TAPPING_TERM_PER_KEY
179 get_tapping_term(autoshift_lastkey, record)
180# else
181 TAPPING_TERM
182# endif
183 ) {
184 // clang-format on
185 // Allow a tap-then-hold for keyrepeat.
186 if (get_mods() & MOD_BIT(KC_LSFT)) {
187 autoshift_flags.cancelling_lshift = true;
188 del_mods(MOD_BIT(KC_LSFT));
74 } 189 }
75# ifndef AUTO_SHIFT_NO_AUTO_REPEAT 190 if (get_mods() & MOD_BIT(KC_RSFT)) {
191 autoshift_flags.cancelling_rshift = true;
192 del_mods(MOD_BIT(KC_RSFT));
193 }
194 // autoshift_shift_state doesn't need to be changed.
195 autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record);
196 return false;
76 } 197 }
77# endif
78# endif 198# endif
79 199
200 // Use physical shift state of press event to be more like normal typing.
201# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
202 autoshift_flags.lastshifted = (get_mods() | get_oneshot_mods()) & MOD_BIT(KC_LSFT);
203 set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT)));
204# else
205 autoshift_flags.lastshifted = get_mods() & MOD_BIT(KC_LSFT);
206# endif
80 // Record the keycode so we can simulate it later. 207 // Record the keycode so we can simulate it later.
81 autoshift_lastkey = keycode; 208 autoshift_lastkey = keycode;
82 autoshift_time = now; 209 autoshift_time = now;
@@ -90,51 +217,70 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record)
90 217
91/** \brief Registers an autoshiftable key under the right conditions 218/** \brief Registers an autoshiftable key under the right conditions
92 * 219 *
93 * If the autoshift delay has elapsed, register a shift and the key. 220 * If autoshift_timeout has elapsed, register a shift and the key.
94 * 221 *
95 * If the autoshift key is released before the delay has elapsed, register the 222 * If the Auto Shift key is released before the delay has elapsed, register the
96 * key without a shift. 223 * key without a shift.
224 *
225 * Called on key down with keycode=KC_NO, auto-shifted key up, and timeout.
97 */ 226 */
98static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) { 227static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger, keyrecord_t *record) {
99 // Called on key down with KC_NO, auto-shifted key up, and timeout. 228 if (autoshift_flags.in_progress && (keycode == autoshift_lastkey || keycode == KC_NO)) {
100 if (autoshift_flags.in_progress) {
101 // Process the auto-shiftable key. 229 // Process the auto-shiftable key.
102 autoshift_flags.in_progress = false; 230 autoshift_flags.in_progress = false;
103 231 // clang-format off
104 // Time since the initial press was recorded. 232 autoshift_flags.lastshifted =
105 const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time); 233 autoshift_flags.lastshifted
106 if (elapsed < autoshift_timeout) { 234 || TIMER_DIFF_16(now, autoshift_time) >=
107 register_code(autoshift_lastkey); 235# ifdef AUTO_SHIFT_TIMEOUT_PER_KEY
108 autoshift_flags.lastshifted = false; 236 get_autoshift_timeout(autoshift_lastkey, record)
109 } else { 237# else
110 // Simulate pressing the shift key. 238 autoshift_timeout
111 add_weak_mods(MOD_BIT(KC_LEFT_SHIFT));
112 register_code(autoshift_lastkey);
113 autoshift_flags.lastshifted = true;
114# if defined(AUTO_SHIFT_REPEAT) && !defined(AUTO_SHIFT_NO_AUTO_REPEAT)
115 if (matrix_trigger) {
116 // Prevents release.
117 return;
118 }
119# endif 239# endif
240 ;
241 // clang-format on
242 set_autoshift_shift_state(autoshift_lastkey, autoshift_flags.lastshifted);
243 if (get_mods() & MOD_BIT(KC_LSFT)) {
244 autoshift_flags.cancelling_lshift = true;
245 del_mods(MOD_BIT(KC_LSFT));
246 }
247 if (get_mods() & MOD_BIT(KC_RSFT)) {
248 autoshift_flags.cancelling_rshift = true;
249 del_mods(MOD_BIT(KC_RSFT));
120 } 250 }
251 autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record);
121 252
253 // clang-format off
254# if (defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)) && (!defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY))
255 if (matrix_trigger
256# ifdef AUTO_SHIFT_REPEAT_PER_KEY
257 && get_auto_shift_repeat(autoshift_lastkey, record)
258# endif
259# ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY
260 && !get_auto_shift_no_auto_repeat(autoshift_lastkey, record)
261# endif
262 ) {
263 // Prevents release.
264 return;
265 }
266# endif
267 // clang-format on
122# if TAP_CODE_DELAY > 0 268# if TAP_CODE_DELAY > 0
123 wait_ms(TAP_CODE_DELAY); 269 wait_ms(TAP_CODE_DELAY);
124# endif 270# endif
125 unregister_code(autoshift_lastkey); 271
126 del_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); 272 autoshift_release_user(autoshift_lastkey, autoshift_flags.lastshifted, record);
273 autoshift_flush_shift();
127 } else { 274 } else {
128 // Release after keyrepeat. 275 // Release after keyrepeat.
129 unregister_code(keycode); 276 autoshift_release_user(keycode, get_autoshift_shift_state(keycode), record);
130 if (keycode == autoshift_lastkey) { 277 if (keycode == autoshift_lastkey) {
131 // This will only fire when the key was the last auto-shiftable 278 // This will only fire when the key was the last auto-shiftable
132 // pressed. That prevents aaaaBBBB then releasing a from unshifting 279 // pressed. That prevents 'aaaaBBBB' then releasing a from unshifting
133 // later Bs (if B wasn't auto-shiftable). 280 // later 'B's (if 'B' wasn't auto-shiftable).
134 del_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); 281 autoshift_flush_shift();
135 } 282 }
136 } 283 }
137 send_keyboard_report(); // del_weak_mods doesn't send one.
138 // Roll the autoshift_time forward for detecting tap-and-hold. 284 // Roll the autoshift_time forward for detecting tap-and-hold.
139 autoshift_time = now; 285 autoshift_time = now;
140} 286}
@@ -147,24 +293,29 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) {
147 */ 293 */
148void autoshift_matrix_scan(void) { 294void autoshift_matrix_scan(void) {
149 if (autoshift_flags.in_progress) { 295 if (autoshift_flags.in_progress) {
150 const uint16_t now = timer_read(); 296 const uint16_t now = timer_read();
151 const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time); 297 if (TIMER_DIFF_16(now, autoshift_time) >=
152 if (elapsed >= autoshift_timeout) { 298# ifdef AUTO_SHIFT_TIMEOUT_PER_KEY
153 autoshift_end(autoshift_lastkey, now, true); 299 get_autoshift_timeout(autoshift_lastkey, &autoshift_lastrecord)
300# else
301 autoshift_timeout
302# endif
303 ) {
304 autoshift_end(autoshift_lastkey, now, true, &autoshift_lastrecord);
154 } 305 }
155 } 306 }
156} 307}
157 308
158void autoshift_toggle(void) { 309void autoshift_toggle(void) {
159 autoshift_flags.enabled = !autoshift_flags.enabled; 310 autoshift_flags.enabled = !autoshift_flags.enabled;
160 del_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); 311 autoshift_flush_shift();
161} 312}
162 313
163void autoshift_enable(void) { autoshift_flags.enabled = true; } 314void autoshift_enable(void) { autoshift_flags.enabled = true; }
164 315
165void autoshift_disable(void) { 316void autoshift_disable(void) {
166 autoshift_flags.enabled = false; 317 autoshift_flags.enabled = false;
167 del_weak_mods(MOD_BIT(KC_LEFT_SHIFT)); 318 autoshift_flush_shift();
168} 319}
169 320
170# ifndef AUTO_SHIFT_NO_SETUP 321# ifndef AUTO_SHIFT_NO_SETUP
@@ -179,76 +330,158 @@ void autoshift_timer_report(void) {
179 330
180bool get_autoshift_state(void) { return autoshift_flags.enabled; } 331bool get_autoshift_state(void) { return autoshift_flags.enabled; }
181 332
182uint16_t get_autoshift_timeout(void) { return autoshift_timeout; } 333uint16_t get_generic_autoshift_timeout() { return autoshift_timeout; }
334__attribute__((weak)) uint16_t get_autoshift_timeout(uint16_t keycode, keyrecord_t *record) { return autoshift_timeout; }
183 335
184void set_autoshift_timeout(uint16_t timeout) { autoshift_timeout = timeout; } 336void set_autoshift_timeout(uint16_t timeout) { autoshift_timeout = timeout; }
185 337
186bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { 338bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
187 // Note that record->event.time isn't reliable, see: 339 // Note that record->event.time isn't reliable, see:
188 // https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550 340 // https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550
189 const uint16_t now = timer_read(); 341 // clang-format off
342 const uint16_t now =
343# if !defined(RETRO_SHIFT) || defined(NO_ACTION_TAPPING)
344 timer_read()
345# else
346 (record->event.pressed) ? retroshift_time : timer_read()
347# endif
348 ;
349 // clang-format on
190 350
191 if (record->event.pressed) { 351 if (record->event.pressed) {
192 if (autoshift_flags.in_progress) { 352 if (autoshift_flags.in_progress) {
193 // Evaluate previous key if there is one. Doing this elsewhere is 353 // Evaluate previous key if there is one.
194 // more complicated and easier to break. 354 autoshift_end(KC_NO, now, false, &autoshift_lastrecord);
195 autoshift_end(KC_NO, now, false);
196 } 355 }
197 // For pressing another key while keyrepeating shifted autoshift.
198 del_weak_mods(MOD_BIT(KC_LEFT_SHIFT));
199 356
200 switch (keycode) { 357 switch (keycode) {
201 case KC_ASTG: 358 case KC_ASTG:
202 autoshift_toggle(); 359 autoshift_toggle();
203 return true; 360 break;
204 case KC_ASON: 361 case KC_ASON:
205 autoshift_enable(); 362 autoshift_enable();
206 return true; 363 break;
207 case KC_ASOFF: 364 case KC_ASOFF:
208 autoshift_disable(); 365 autoshift_disable();
209 return true; 366 break;
210 367
211# ifndef AUTO_SHIFT_NO_SETUP 368# ifndef AUTO_SHIFT_NO_SETUP
212 case KC_ASUP: 369 case KC_ASUP:
213 autoshift_timeout += 5; 370 autoshift_timeout += 5;
214 return true; 371 break;
215 case KC_ASDN: 372 case KC_ASDN:
216 autoshift_timeout -= 5; 373 autoshift_timeout -= 5;
217 return true; 374 break;
218
219 case KC_ASRP: 375 case KC_ASRP:
220 autoshift_timer_report(); 376 autoshift_timer_report();
221 return true; 377 break;
378# endif
379 }
380 // If Retro Shift is disabled, possible custom actions shouldn't happen.
381 // clang-format off
382 if (IS_RETRO(keycode)
383# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
384 // Not tapped or #defines mean that rolls should use hold action.
385 && (
386 record->tap.count == 0
387# ifdef RETRO_TAPPING_PER_KEY
388 || !get_retro_tapping(keycode, record)
389# endif
390 || (record->tap.interrupted && (IS_LT(keycode)
391# if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
392# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
393 ? get_hold_on_other_key_press(keycode, record)
394# else
395 ? true
396# endif
397# else
398 ? false
399# endif
400# if defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
401# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
402 : !get_ignore_mod_tap_interrupt(keycode, record)
403# else
404 : false
405# endif
406# else
407 : true
408# endif
409 ))
410 )
411# endif
412 ) {
413 // clang-format on
414 autoshift_lastkey = KC_NO;
415 return true;
416 }
417 } else {
418 if (keycode == KC_LSFT) {
419 autoshift_flags.cancelling_lshift = false;
420 } else if (keycode == KC_RSFT) {
421 autoshift_flags.cancelling_rshift = false;
422 }
423 // Same as above (for pressed), additional checks are not needed because
424 // tap.count gets set to 0 in process_action
425 // clang-format off
426 else if (IS_RETRO(keycode)
427# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
428 && (
429 record->tap.count == 0
430# ifdef RETRO_TAPPING_PER_KEY
431 || !get_retro_tapping(keycode, record)
432# endif
433 )
222# endif 434# endif
435 ) {
436 // Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set.
437# if !defined(IGNORE_MOD_TAP_INTERRUPT) || defined(IGNORE_MOD_TAP_INTERRUPT_PER_KEY)
438 if (autoshift_flags.in_progress
439# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
440 && !get_ignore_mod_tap_interrupt(keycode, record)
441# endif
442 ) {
443 autoshift_end(KC_NO, now, false, &autoshift_lastrecord);
444 }
445# endif
446 // clang-format on
447 return true;
223 } 448 }
224 } 449 }
450
451 if (!autoshift_flags.enabled) {
452 return true;
453 }
225 if (get_auto_shifted_key(keycode, record)) { 454 if (get_auto_shifted_key(keycode, record)) {
226 if (record->event.pressed) { 455 if (record->event.pressed) {
227 return autoshift_press(keycode, now, record); 456 return autoshift_press(keycode, now, record);
228 } else { 457 } else {
229 autoshift_end(keycode, now, false); 458 autoshift_end(keycode, now, false, record);
230 return false; 459 return false;
231 } 460 }
232 } 461 }
462
463 // Prevent keyrepeating of older keys upon non-AS key event.
464 // Not commented at above returns but they serve the same function.
465 if (record->event.pressed) {
466 autoshift_lastkey = KC_NO;
467 }
233 return true; 468 return true;
234} 469}
235 470
236__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { 471# if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
237 switch (keycode) { 472// Called to record time before possible delays by action_tapping_process.
238# ifndef NO_AUTO_SHIFT_ALPHA 473void retroshift_poll_time(keyevent_t *event) {
239 case KC_A ... KC_Z: 474 last_retroshift_time = retroshift_time;
240# endif 475 retroshift_time = timer_read();
241# ifndef NO_AUTO_SHIFT_NUMERIC 476}
242 case KC_1 ... KC_0: 477// Used to swap the times of Retro Shifted key and Auto Shift key that interrupted it.
243# endif 478void retroshift_swap_times() {
244# ifndef NO_AUTO_SHIFT_SPECIAL 479 if (last_retroshift_time != 0 && autoshift_flags.in_progress) {
245 case KC_TAB: 480 uint16_t temp = retroshift_time;
246 case KC_MINUS ... KC_SLASH: 481 retroshift_time = last_retroshift_time;
247 case KC_NONUS_BACKSLASH: 482 last_retroshift_time = temp;
248# endif
249 return true;
250 } 483 }
251 return false;
252} 484}
485# endif
253 486
254#endif 487#endif
diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h
index 00a9ab036..ac6a14374 100644
--- a/quantum/process_keycode/process_auto_shift.h
+++ b/quantum/process_keycode/process_auto_shift.h
@@ -22,13 +22,31 @@
22# define AUTO_SHIFT_TIMEOUT 175 22# define AUTO_SHIFT_TIMEOUT 175
23#endif 23#endif
24 24
25#define IS_LT(kc) ((kc) >= QK_LAYER_TAP && (kc) <= QK_LAYER_TAP_MAX)
26#define IS_MT(kc) ((kc) >= QK_MOD_TAP && (kc) <= QK_MOD_TAP_MAX)
27#define IS_RETRO(kc) (IS_MT(kc) || IS_LT(kc))
28#define DO_GET_AUTOSHIFT_TIMEOUT(keycode, record, ...) record
29// clang-format off
30#define AUTO_SHIFT_ALPHA KC_A ... KC_Z
31#define AUTO_SHIFT_NUMERIC KC_1 ... KC_0
32#define AUTO_SHIFT_SPECIAL \
33 KC_TAB: \
34 case KC_MINUS ... KC_SLASH: \
35 case KC_NONUS_BSLASH
36// clang-format on
37
25bool process_auto_shift(uint16_t keycode, keyrecord_t *record); 38bool process_auto_shift(uint16_t keycode, keyrecord_t *record);
39void retroshift_poll_time(keyevent_t *event);
40void retroshift_swap_times(void);
26 41
27void autoshift_enable(void); 42void autoshift_enable(void);
28void autoshift_disable(void); 43void autoshift_disable(void);
29void autoshift_toggle(void); 44void autoshift_toggle(void);
30bool get_autoshift_state(void); 45bool get_autoshift_state(void);
31uint16_t get_autoshift_timeout(void); 46uint16_t get_generic_autoshift_timeout(void);
47// clang-format off
48uint16_t (get_autoshift_timeout)(uint16_t keycode, keyrecord_t *record);
32void set_autoshift_timeout(uint16_t timeout); 49void set_autoshift_timeout(uint16_t timeout);
33void autoshift_matrix_scan(void); 50void autoshift_matrix_scan(void);
34bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record); 51bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
52// clang-format on