aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-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
4 files changed, 455 insertions, 111 deletions
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