diff options
author | Isaac Elenbaas <isaacelenbaas@gmail.com> | 2021-11-25 07:12:14 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-25 23:12:14 +1100 |
commit | d9393b86842b7ef143259b5f771ae7969f98cbb4 (patch) | |
tree | e0760c20f65c4cac7b6ffb3fedf3f36c6f7c13a2 | |
parent | 282e916d86a5d353b7cbdfef3afad3c7b011eb14 (diff) | |
download | qmk_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.md | 176 | ||||
-rw-r--r-- | docs/tap_hold.md | 4 | ||||
-rw-r--r-- | quantum/action.c | 19 | ||||
-rw-r--r-- | quantum/action_tapping.c | 106 | ||||
-rw-r--r-- | quantum/process_keycode/process_auto_shift.c | 419 | ||||
-rw-r--r-- | quantum/process_keycode/process_auto_shift.h | 22 |
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 | |||
26 | once then immediately (within `TAPPING_TERM`) hold it down again (this works | 26 | once then immediately (within `TAPPING_TERM`) hold it down again (this works |
27 | with the shifted value as well if auto-repeat is disabled). | 27 | with the shifted value as well if auto-repeat is disabled). |
28 | 28 | ||
29 | There are also the `get_auto_shift_repeat` and `get_auto_shift_no_auto_repeat` | ||
30 | functions 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 | ||
32 | are defined. | ||
33 | |||
29 | ## Are There Limitations to Auto Shift? | 34 | ## Are There Limitations to Auto Shift? |
30 | 35 | ||
31 | Yes, unfortunately. | 36 | Yes, unfortunately. |
32 | 37 | ||
33 | You will have characters that are shifted when you did not intend on shifting, and | 38 | 1. You will have characters that are shifted when you did not intend on shifting, and |
34 | other 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 |
35 | practice. 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 |
36 | shifted 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 |
37 | the 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 | 43 | 2. Additionally, with keyrepeat the desired shift state can get mixed up. It will | |
39 | Additionally, 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 |
40 | always '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) |
41 | and 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. |
42 | will result in the capital's *key* still being held, but shift not. | 47 | 3. 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 | ||
105 | For 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 | |||
111 | You can then add the following function to your keymap: | ||
112 | |||
113 | ```c | ||
114 | uint16_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 | |||
127 | Note that you cannot override individual keys that are in one of those groups | ||
128 | if you are using them; trying to add a case for `KC_A` in the above example will | ||
129 | not compile as `AUTO_SHIFT_ALPHA` is there. A possible solution is a second switch | ||
130 | above to handle individual keys with no default case and only referencing the | ||
131 | groups in the below fallback switch. | ||
132 | |||
99 | ### NO_AUTO_SHIFT_SPECIAL (simple define) | 133 | ### NO_AUTO_SHIFT_SPECIAL (simple define) |
100 | 134 | ||
101 | Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>, | 135 | Do not Auto Shift special keys, which include -\_, =+, [{, ]}, ;:, '", ,<, .>, |
@@ -109,11 +143,24 @@ Do not Auto Shift numeric keys, zero through nine. | |||
109 | 143 | ||
110 | Do not Auto Shift alpha characters, which include A through Z. | 144 | Do not Auto Shift alpha characters, which include A through Z. |
111 | 145 | ||
112 | ### Auto Shift Per Key | 146 | ### Auto Shift Per Key |
113 | 147 | ||
114 | This is a function that allows you to determine which keys shold be autoshifted, much like the tap-hold keys. | 148 | There are functions that allows you to determine which keys shold be autoshifted, much like the tap-hold keys. |
115 | 149 | ||
116 | The default function looks like this: | 150 | The first of these, used to simply add a key to Auto Shift, is `get_custom_auto_shifted_key`: |
151 | |||
152 | ```c | ||
153 | bool 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 | |||
163 | For more granular control, there is `get_auto_shifted_key`. The default function looks like this: | ||
117 | 164 | ||
118 | ```c | 165 | ```c |
119 | bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { | 166 | bool 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 | |||
137 | This functionality is enabled by default, and does not need a define. | 185 | This 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 | ||
145 | Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded. | 193 | Disables automatically keyrepeating when `AUTO_SHIFT_TIMEOUT` is exceeded. |
146 | 194 | ||
195 | ## Custom Shifted Values | ||
196 | |||
197 | Especially on small keyboards, the default shifted value for many keys is not | ||
198 | optimal. To provide more customizability, there are two user-definable | ||
199 | functions, `autoshift_press/release_user`. These register or unregister the | ||
200 | correct value for the passed key. Below is an example adding period to Auto | ||
201 | Shift and making its shifted value exclamation point. Make sure to use weak | ||
202 | mods - setting real would make any keys following it use their shifted values | ||
203 | as if you were holding the key. Clearing of modifiers is handled by Auto Shift, | ||
204 | and the OS-sent shift value if keyrepeating multiple keys is always that of | ||
205 | the last key pressed (whether or not it's an Auto Shift key). | ||
206 | |||
207 | You can also have non-shifted keys for the shifted values (or even no shifted | ||
208 | value), just don't set a shift modifier! | ||
209 | |||
210 | ```c | ||
211 | bool 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 | |||
220 | void 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 | |||
234 | void 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 | |||
250 | Holding and releasing a Tap Hold key without pressing another key will ordinarily | ||
251 | result in only the hold. With `retro shift` enabled this action will instead | ||
252 | produce a shifted version of the tap keycode on release. | ||
253 | |||
254 | It does not require [Retro Tapping](tap_hold.md#retro-tapping) to be enabled, and | ||
255 | if both are enabled the state of `retro tapping` will only apply if the tap keycode | ||
256 | is not matched by Auto Shift. `RETRO_TAPPING_PER_KEY` and its corresponding | ||
257 | function, however, are checked before `retro shift` is applied. | ||
258 | |||
259 | To enable `retro shift`, add the following to your `config.h`: | ||
260 | |||
261 | ```c | ||
262 | #define RETRO_SHIFT | ||
263 | ``` | ||
264 | |||
265 | If `RETRO_SHIFT` is defined to a value, hold times greater than that value will | ||
266 | not produce a tap on release for Mod Taps, and instead triggers the hold action. | ||
267 | This enables modifiers to be held for combining with mouse clicks without | ||
268 | generating taps on release. For example: | ||
269 | |||
270 | ```c | ||
271 | #define RETRO_SHIFT 500 | ||
272 | ``` | ||
273 | |||
274 | This value (if set) must be greater than one's `TAPPING_TERM`, as the key press | ||
275 | must be designated as a 'hold' by `process_tapping` before we send the modifier. | ||
276 | There is no such limitation in regards to `AUTO_SHIFT_TIMEOUT` for normal keys. | ||
277 | |||
278 | ### Retro Shift and Tap Hold Configurations | ||
279 | |||
280 | Tap Hold Configurations work a little differently when using Retro Shift. | ||
281 | Referencing `TAPPING_TERM` makes little sense, as holding longer would result in | ||
282 | shifting one of the keys. | ||
283 | |||
284 | `IGNORE_MOD_TAP_INTERRUPT` changes *only* rolling from a mod tap (releasing it | ||
285 | first), sending both keys instead of the modifier on the second. Its effects on | ||
286 | nested presses are ignored. | ||
287 | |||
288 | As 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 | |||
292 | Nested taps will *always* act as though the `TAPPING_TERM` was exceeded for both | ||
293 | Mod and Layer Tap keys. | ||
294 | |||
147 | ## Using Auto Shift Setup | 295 | ## Using Auto Shift Setup |
148 | 296 | ||
149 | This will enable you to define three keys temporarily to increase, decrease and report your `AUTO_SHIFT_TIMEOUT`. | 297 | This 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 | ||
273 | One 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. | 277 | One 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 | ||
46 | int tp_buttons; | 46 | int 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)) |
49 | int retro_tapping_counter = 0; | 49 | int 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 | |||
47 | static keyrecord_t tapping_key = {}; | 51 | static keyrecord_t tapping_key = {}; |
48 | static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; | 52 | static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; |
49 | static uint8_t waiting_buffer_head = 0; | 53 | static 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. */ |
108 | bool process_tapping(keyrecord_t *keyp) { | 112 | bool 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 | ||
30 | static uint16_t autoshift_time = 0; | 29 | // Stores the last Auto Shift key's up or down time, for evaluation or keyrepeat. |
31 | static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; | 30 | static uint16_t autoshift_time = 0; |
32 | static 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. | ||
33 | static 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. | ||
37 | static uint16_t last_retroshift_time; | ||
38 | # endif | ||
39 | static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; | ||
40 | static uint16_t autoshift_lastkey = KC_NO; | ||
41 | static 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). | ||
45 | static uint16_t autoshift_shift_states[((1 << 8) + 15) / 16]; | ||
33 | static struct { | 46 | static 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 */ | ||
100 | void 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 */ | ||
110 | bool 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 */ | ||
116 | static 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 | */ |
49 | static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) { | 134 | static 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 | */ |
98 | static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) { | 227 | static 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 | */ |
148 | void autoshift_matrix_scan(void) { | 294 | void 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 | ||
158 | void autoshift_toggle(void) { | 309 | void 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 | ||
163 | void autoshift_enable(void) { autoshift_flags.enabled = true; } | 314 | void autoshift_enable(void) { autoshift_flags.enabled = true; } |
164 | 315 | ||
165 | void autoshift_disable(void) { | 316 | void 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 | ||
180 | bool get_autoshift_state(void) { return autoshift_flags.enabled; } | 331 | bool get_autoshift_state(void) { return autoshift_flags.enabled; } |
181 | 332 | ||
182 | uint16_t get_autoshift_timeout(void) { return autoshift_timeout; } | 333 | uint16_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 | ||
184 | void set_autoshift_timeout(uint16_t timeout) { autoshift_timeout = timeout; } | 336 | void set_autoshift_timeout(uint16_t timeout) { autoshift_timeout = timeout; } |
185 | 337 | ||
186 | bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { | 338 | bool 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 | 473 | void 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 | 478 | void 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 | |||
25 | bool process_auto_shift(uint16_t keycode, keyrecord_t *record); | 38 | bool process_auto_shift(uint16_t keycode, keyrecord_t *record); |
39 | void retroshift_poll_time(keyevent_t *event); | ||
40 | void retroshift_swap_times(void); | ||
26 | 41 | ||
27 | void autoshift_enable(void); | 42 | void autoshift_enable(void); |
28 | void autoshift_disable(void); | 43 | void autoshift_disable(void); |
29 | void autoshift_toggle(void); | 44 | void autoshift_toggle(void); |
30 | bool get_autoshift_state(void); | 45 | bool get_autoshift_state(void); |
31 | uint16_t get_autoshift_timeout(void); | 46 | uint16_t get_generic_autoshift_timeout(void); |
47 | // clang-format off | ||
48 | uint16_t (get_autoshift_timeout)(uint16_t keycode, keyrecord_t *record); | ||
32 | void set_autoshift_timeout(uint16_t timeout); | 49 | void set_autoshift_timeout(uint16_t timeout); |
33 | void autoshift_matrix_scan(void); | 50 | void autoshift_matrix_scan(void); |
34 | bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record); | 51 | bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record); |
52 | // clang-format on | ||