aboutsummaryrefslogtreecommitdiff
path: root/quantum/process_keycode
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/process_keycode')
-rw-r--r--quantum/process_keycode/process_auto_shift.c8
-rw-r--r--quantum/process_keycode/process_combo.c184
-rw-r--r--quantum/process_keycode/process_combo.h4
-rw-r--r--quantum/process_keycode/process_haptic.c4
-rw-r--r--quantum/process_keycode/process_programmable_button.c31
-rw-r--r--quantum/process_keycode/process_programmable_button.h23
-rw-r--r--quantum/process_keycode/process_steno.c9
-rw-r--r--quantum/process_keycode/process_unicode_common.c47
8 files changed, 202 insertions, 108 deletions
diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
index 51b0efdb4..cc3a974ea 100644
--- a/quantum/process_keycode/process_auto_shift.c
+++ b/quantum/process_keycode/process_auto_shift.c
@@ -21,6 +21,12 @@
21 21
22# include "process_auto_shift.h" 22# include "process_auto_shift.h"
23 23
24#ifndef AUTO_SHIFT_DISABLED_AT_STARTUP
25# define AUTO_SHIFT_STARTUP_STATE true /* enabled */
26#else
27# define AUTO_SHIFT_STARTUP_STATE false /* disabled */
28#endif
29
24static uint16_t autoshift_time = 0; 30static uint16_t autoshift_time = 0;
25static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; 31static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
26static uint16_t autoshift_lastkey = KC_NO; 32static uint16_t autoshift_lastkey = KC_NO;
@@ -34,7 +40,7 @@ static struct {
34 bool in_progress : 1; 40 bool in_progress : 1;
35 // Whether the auto-shifted keypress has been registered. 41 // Whether the auto-shifted keypress has been registered.
36 bool holding_shift : 1; 42 bool holding_shift : 1;
37} autoshift_flags = {true, false, false, false}; 43} autoshift_flags = {AUTO_SHIFT_STARTUP_STATE, false, false, false};
38 44
39/** \brief Record the press of an autoshiftable key 45/** \brief Record the press of an autoshiftable key
40 * 46 *
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c
index e8661839c..a050161ed 100644
--- a/quantum/process_keycode/process_combo.c
+++ b/quantum/process_keycode/process_combo.c
@@ -18,10 +18,9 @@
18#include "process_combo.h" 18#include "process_combo.h"
19#include "action_tapping.h" 19#include "action_tapping.h"
20 20
21
22#ifdef COMBO_COUNT 21#ifdef COMBO_COUNT
23__attribute__((weak)) combo_t key_combos[COMBO_COUNT]; 22__attribute__((weak)) combo_t key_combos[COMBO_COUNT];
24uint16_t COMBO_LEN = COMBO_COUNT; 23uint16_t COMBO_LEN = COMBO_COUNT;
25#else 24#else
26extern combo_t key_combos[]; 25extern combo_t key_combos[];
27extern uint16_t COMBO_LEN; 26extern uint16_t COMBO_LEN;
@@ -46,64 +45,86 @@ __attribute__((weak)) bool process_combo_key_release(uint16_t combo_index, combo
46#endif 45#endif
47 46
48#ifndef COMBO_NO_TIMER 47#ifndef COMBO_NO_TIMER
49static uint16_t timer = 0; 48static uint16_t timer = 0;
50#endif 49#endif
51static bool b_combo_enable = true; // defaults to enabled 50static bool b_combo_enable = true; // defaults to enabled
52static uint16_t longest_term = 0; 51static uint16_t longest_term = 0;
53 52
54typedef struct { 53typedef struct {
55 keyrecord_t record; 54 keyrecord_t record;
56 uint16_t combo_index; 55 uint16_t combo_index;
57 uint16_t keycode; 56 uint16_t keycode;
58} queued_record_t; 57} queued_record_t;
59static uint8_t key_buffer_size = 0; 58static uint8_t key_buffer_size = 0;
60static queued_record_t key_buffer[COMBO_KEY_BUFFER_LENGTH]; 59static queued_record_t key_buffer[COMBO_KEY_BUFFER_LENGTH];
61 60
62typedef struct { 61typedef struct {
63 uint16_t combo_index; 62 uint16_t combo_index;
64} queued_combo_t; 63} queued_combo_t;
65static uint8_t combo_buffer_write= 0; 64static uint8_t combo_buffer_write = 0;
66static uint8_t combo_buffer_read = 0; 65static uint8_t combo_buffer_read = 0;
67static queued_combo_t combo_buffer[COMBO_BUFFER_LENGTH]; 66static queued_combo_t combo_buffer[COMBO_BUFFER_LENGTH];
68 67
69#define INCREMENT_MOD(i) i = (i + 1) % COMBO_BUFFER_LENGTH 68#define INCREMENT_MOD(i) i = (i + 1) % COMBO_BUFFER_LENGTH
70 69
71#define COMBO_KEY_POS ((keypos_t){.col=254, .row=254}) 70#define COMBO_KEY_POS ((keypos_t){.col = 254, .row = 254})
72
73 71
74#ifndef EXTRA_SHORT_COMBOS 72#ifndef EXTRA_SHORT_COMBOS
75/* flags are their own elements in combo_t struct. */ 73/* flags are their own elements in combo_t struct. */
76# define COMBO_ACTIVE(combo) (combo->active) 74# define COMBO_ACTIVE(combo) (combo->active)
77# define COMBO_DISABLED(combo) (combo->disabled) 75# define COMBO_DISABLED(combo) (combo->disabled)
78# define COMBO_STATE(combo) (combo->state) 76# define COMBO_STATE(combo) (combo->state)
79 77
80# define ACTIVATE_COMBO(combo) do {combo->active = true;}while(0) 78# define ACTIVATE_COMBO(combo) \
81# define DEACTIVATE_COMBO(combo) do {combo->active = false;}while(0) 79 do { \
82# define DISABLE_COMBO(combo) do {combo->disabled = true;}while(0) 80 combo->active = true; \
83# define RESET_COMBO_STATE(combo) do { \ 81 } while (0)
84 combo->disabled = false; \ 82# define DEACTIVATE_COMBO(combo) \
85 combo->state = 0; \ 83 do { \
86}while(0) 84 combo->active = false; \
85 } while (0)
86# define DISABLE_COMBO(combo) \
87 do { \
88 combo->disabled = true; \
89 } while (0)
90# define RESET_COMBO_STATE(combo) \
91 do { \
92 combo->disabled = false; \
93 combo->state = 0; \
94 } while (0)
87#else 95#else
88/* flags are at the two high bits of state. */ 96/* flags are at the two high bits of state. */
89# define COMBO_ACTIVE(combo) (combo->state & 0x80) 97# define COMBO_ACTIVE(combo) (combo->state & 0x80)
90# define COMBO_DISABLED(combo) (combo->state & 0x40) 98# define COMBO_DISABLED(combo) (combo->state & 0x40)
91# define COMBO_STATE(combo) (combo->state & 0x3F) 99# define COMBO_STATE(combo) (combo->state & 0x3F)
92 100
93# define ACTIVATE_COMBO(combo) do {combo->state |= 0x80;}while(0) 101# define ACTIVATE_COMBO(combo) \
94# define DEACTIVATE_COMBO(combo) do {combo->state &= ~0x80;}while(0) 102 do { \
95# define DISABLE_COMBO(combo) do {combo->state |= 0x40;}while(0) 103 combo->state |= 0x80; \
96# define RESET_COMBO_STATE(combo) do {combo->state &= ~0x7F;}while(0) 104 } while (0)
105# define DEACTIVATE_COMBO(combo) \
106 do { \
107 combo->state &= ~0x80; \
108 } while (0)
109# define DISABLE_COMBO(combo) \
110 do { \
111 combo->state |= 0x40; \
112 } while (0)
113# define RESET_COMBO_STATE(combo) \
114 do { \
115 combo->state &= ~0x7F; \
116 } while (0)
97#endif 117#endif
98 118
99static inline void release_combo(uint16_t combo_index, combo_t *combo) { 119static inline void release_combo(uint16_t combo_index, combo_t *combo) {
100 if (combo->keycode) { 120 if (combo->keycode) {
101 keyrecord_t record = { 121 keyrecord_t record = {
102 .event = { 122 .event =
103 .key = COMBO_KEY_POS, 123 {
104 .time = timer_read()|1, 124 .key = COMBO_KEY_POS,
105 .pressed = false, 125 .time = timer_read() | 1,
106 }, 126 .pressed = false,
127 },
107 .keycode = combo->keycode, 128 .keycode = combo->keycode,
108 }; 129 };
109#ifndef NO_ACTION_TAPPING 130#ifndef NO_ACTION_TAPPING
@@ -123,18 +144,17 @@ static inline bool _get_combo_must_hold(uint16_t combo_index, combo_t *combo) {
123#elif defined(COMBO_MUST_HOLD_PER_COMBO) 144#elif defined(COMBO_MUST_HOLD_PER_COMBO)
124 return get_combo_must_hold(combo_index, combo); 145 return get_combo_must_hold(combo_index, combo);
125#elif defined(COMBO_MUST_HOLD_MODS) 146#elif defined(COMBO_MUST_HOLD_MODS)
126 return (KEYCODE_IS_MOD(combo->keycode) || 147 return (KEYCODE_IS_MOD(combo->keycode) || (combo->keycode >= QK_MOMENTARY && combo->keycode <= QK_MOMENTARY_MAX));
127 (combo->keycode >= QK_MOMENTARY && combo->keycode <= QK_MOMENTARY_MAX));
128#endif 148#endif
129 return false; 149 return false;
130} 150}
131 151
132static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo ) { 152static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo) {
133 if (_get_combo_must_hold(combo_index, combo) 153 if (_get_combo_must_hold(combo_index, combo)
134#ifdef COMBO_MUST_TAP_PER_COMBO 154#ifdef COMBO_MUST_TAP_PER_COMBO
135 || get_combo_must_tap(combo_index, combo) 155 || get_combo_must_tap(combo_index, combo)
136#endif 156#endif
137 ) { 157 ) {
138 if (longest_term < COMBO_HOLD_TERM) { 158 if (longest_term < COMBO_HOLD_TERM) {
139 return COMBO_HOLD_TERM; 159 return COMBO_HOLD_TERM;
140 } 160 }
@@ -144,9 +164,8 @@ static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo ) {
144} 164}
145 165
146static inline uint16_t _get_combo_term(uint16_t combo_index, combo_t *combo) { 166static inline uint16_t _get_combo_term(uint16_t combo_index, combo_t *combo) {
147
148#if defined(COMBO_TERM_PER_COMBO) 167#if defined(COMBO_TERM_PER_COMBO)
149 return get_combo_term(combo_index, combo); 168 return get_combo_term(combo_index, combo);
150#endif 169#endif
151 170
152 return COMBO_TERM; 171 return COMBO_TERM;
@@ -154,7 +173,7 @@ static inline uint16_t _get_combo_term(uint16_t combo_index, combo_t *combo) {
154 173
155void clear_combos(void) { 174void clear_combos(void) {
156 uint16_t index = 0; 175 uint16_t index = 0;
157 longest_term = 0; 176 longest_term = 0;
158 for (index = 0; index < COMBO_LEN; ++index) { 177 for (index = 0; index < COMBO_LEN; ++index) {
159 combo_t *combo = &key_combos[index]; 178 combo_t *combo = &key_combos[index];
160 if (!COMBO_ACTIVE(combo)) { 179 if (!COMBO_ACTIVE(combo)) {
@@ -175,7 +194,7 @@ static inline void dump_key_buffer(void) {
175 key_buffer_next = key_buffer_i + 1; 194 key_buffer_next = key_buffer_i + 1;
176 195
177 queued_record_t *qrecord = &key_buffer[key_buffer_i]; 196 queued_record_t *qrecord = &key_buffer[key_buffer_i];
178 keyrecord_t *record = &qrecord->record; 197 keyrecord_t * record = &qrecord->record;
179 198
180 if (IS_NOEVENT(record->event)) { 199 if (IS_NOEVENT(record->event)) {
181 continue; 200 continue;
@@ -185,9 +204,9 @@ static inline void dump_key_buffer(void) {
185 process_combo_event(qrecord->combo_index, true); 204 process_combo_event(qrecord->combo_index, true);
186 } else { 205 } else {
187#ifndef NO_ACTION_TAPPING 206#ifndef NO_ACTION_TAPPING
188 action_tapping_process(*record); 207 action_tapping_process(*record);
189#else 208#else
190 process_record(record); 209 process_record(record);
191#endif 210#endif
192 } 211 }
193 record->event.time = 0; 212 record->event.time = 0;
@@ -242,7 +261,9 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
242 /* Apply combo's result keycode to the last chord key of the combo and 261 /* Apply combo's result keycode to the last chord key of the combo and
243 * disable the other keys. */ 262 * disable the other keys. */
244 263
245 if (COMBO_DISABLED(combo)) { return; } 264 if (COMBO_DISABLED(combo)) {
265 return;
266 }
246 267
247 // state to check against so we find the last key of the combo from the buffer 268 // state to check against so we find the last key of the combo from the buffer
248#if defined(EXTRA_EXTRA_LONG_COMBOS) 269#if defined(EXTRA_EXTRA_LONG_COMBOS)
@@ -254,12 +275,11 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
254#endif 275#endif
255 276
256 for (uint8_t key_buffer_i = 0; key_buffer_i < key_buffer_size; key_buffer_i++) { 277 for (uint8_t key_buffer_i = 0; key_buffer_i < key_buffer_size; key_buffer_i++) {
257
258 queued_record_t *qrecord = &key_buffer[key_buffer_i]; 278 queued_record_t *qrecord = &key_buffer[key_buffer_i];
259 keyrecord_t *record = &qrecord->record; 279 keyrecord_t * record = &qrecord->record;
260 uint16_t keycode = qrecord->keycode; 280 uint16_t keycode = qrecord->keycode;
261 281
262 uint8_t key_count = 0; 282 uint8_t key_count = 0;
263 uint16_t key_index = -1; 283 uint16_t key_index = -1;
264 _find_key_index_and_count(combo->keys, keycode, &key_index, &key_count); 284 _find_key_index_and_count(combo->keys, keycode, &key_index, &key_count);
265 285
@@ -271,7 +291,7 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
271 KEY_STATE_DOWN(state, key_index); 291 KEY_STATE_DOWN(state, key_index);
272 if (ALL_COMBO_KEYS_ARE_DOWN(state, key_count)) { 292 if (ALL_COMBO_KEYS_ARE_DOWN(state, key_count)) {
273 // this in the end executes the combo when the key_buffer is dumped. 293 // this in the end executes the combo when the key_buffer is dumped.
274 record->keycode = combo->keycode; 294 record->keycode = combo->keycode;
275 record->event.key = COMBO_KEY_POS; 295 record->event.key = COMBO_KEY_POS;
276 296
277 qrecord->combo_index = combo_index; 297 qrecord->combo_index = combo_index;
@@ -283,19 +303,15 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
283 // by making it a TICK event. 303 // by making it a TICK event.
284 record->event.time = 0; 304 record->event.time = 0;
285 } 305 }
286
287 } 306 }
288 drop_combo_from_buffer(combo_index); 307 drop_combo_from_buffer(combo_index);
289} 308}
290 309
291static inline void apply_combos(void) { 310static inline void apply_combos(void) {
292 // Apply all buffered normal combos. 311 // Apply all buffered normal combos.
293 for (uint8_t i = combo_buffer_read; 312 for (uint8_t i = combo_buffer_read; i != combo_buffer_write; INCREMENT_MOD(i)) {
294 i != combo_buffer_write;
295 INCREMENT_MOD(i)) {
296
297 queued_combo_t *buffered_combo = &combo_buffer[i]; 313 queued_combo_t *buffered_combo = &combo_buffer[i];
298 combo_t *combo = &key_combos[buffered_combo->combo_index]; 314 combo_t * combo = &key_combos[buffered_combo->combo_index];
299 315
300#ifdef COMBO_MUST_TAP_PER_COMBO 316#ifdef COMBO_MUST_TAP_PER_COMBO
301 if (get_combo_must_tap(buffered_combo->combo_index, combo)) { 317 if (get_combo_must_tap(buffered_combo->combo_index, combo)) {
@@ -310,15 +326,15 @@ static inline void apply_combos(void) {
310 clear_combos(); 326 clear_combos();
311} 327}
312 328
313combo_t* overlaps(combo_t *combo1, combo_t *combo2) { 329combo_t *overlaps(combo_t *combo1, combo_t *combo2) {
314 /* Checks if the combos overlap and returns the combo that should be 330 /* Checks if the combos overlap and returns the combo that should be
315 * dropped from the combo buffer. 331 * dropped from the combo buffer.
316 * The combo that has less keys will be dropped. If they have the same 332 * The combo that has less keys will be dropped. If they have the same
317 * amount of keys, drop combo1. */ 333 * amount of keys, drop combo1. */
318 334
319 uint8_t idx1 = 0, idx2 = 0; 335 uint8_t idx1 = 0, idx2 = 0;
320 uint16_t key1, key2; 336 uint16_t key1, key2;
321 bool overlaps = false; 337 bool overlaps = false;
322 338
323 while ((key1 = pgm_read_word(&combo1->keys[idx1])) != COMBO_END) { 339 while ((key1 = pgm_read_word(&combo1->keys[idx1])) != COMBO_END) {
324 idx2 = 0; 340 idx2 = 0;
@@ -335,7 +351,7 @@ combo_t* overlaps(combo_t *combo1, combo_t *combo2) {
335} 351}
336 352
337static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record, uint16_t combo_index) { 353static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record, uint16_t combo_index) {
338 uint8_t key_count = 0; 354 uint8_t key_count = 0;
339 uint16_t key_index = -1; 355 uint16_t key_index = -1;
340 _find_key_index_and_count(combo->keys, keycode, &key_index, &key_count); 356 _find_key_index_and_count(combo->keys, keycode, &key_index, &key_count);
341 357
@@ -369,12 +385,9 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
369 385
370 // disable readied combos that overlap with this combo 386 // disable readied combos that overlap with this combo
371 combo_t *drop = NULL; 387 combo_t *drop = NULL;
372 for (uint8_t combo_buffer_i = combo_buffer_read; 388 for (uint8_t combo_buffer_i = combo_buffer_read; combo_buffer_i != combo_buffer_write; INCREMENT_MOD(combo_buffer_i)) {
373 combo_buffer_i != combo_buffer_write; 389 queued_combo_t *qcombo = &combo_buffer[combo_buffer_i];
374 INCREMENT_MOD(combo_buffer_i)) { 390 combo_t * buffered_combo = &key_combos[qcombo->combo_index];
375
376 queued_combo_t *qcombo = &combo_buffer[combo_buffer_i];
377 combo_t *buffered_combo = &key_combos[qcombo->combo_index];
378 391
379 if ((drop = overlaps(buffered_combo, combo))) { 392 if ((drop = overlaps(buffered_combo, combo))) {
380 DISABLE_COMBO(drop); 393 DISABLE_COMBO(drop);
@@ -387,21 +400,19 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
387 INCREMENT_MOD(combo_buffer_read); 400 INCREMENT_MOD(combo_buffer_read);
388 } 401 }
389 } 402 }
390
391 } 403 }
392 404
393 if (drop != combo) { 405 if (drop != combo) {
394 // save this combo to buffer 406 // save this combo to buffer
395 combo_buffer[combo_buffer_write] = (queued_combo_t){ 407 combo_buffer[combo_buffer_write] = (queued_combo_t){
396 .combo_index=combo_index, 408 .combo_index = combo_index,
397 }; 409 };
398 INCREMENT_MOD(combo_buffer_write); 410 INCREMENT_MOD(combo_buffer_write);
399 411
400 // get possible longer waiting time for tap-/hold-only combos. 412 // get possible longer waiting time for tap-/hold-only combos.
401 longest_term = _get_wait_time(combo_index, combo); 413 longest_term = _get_wait_time(combo_index, combo);
402 } 414 }
403 } // if timer elapsed end 415 } // if timer elapsed end
404
405 } 416 }
406 } else { 417 } else {
407 // chord releases 418 // chord releases
@@ -416,7 +427,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
416 else if (get_combo_must_tap(combo_index, combo)) { 427 else if (get_combo_must_tap(combo_index, combo)) {
417 // immediately apply tap-only combo 428 // immediately apply tap-only combo
418 apply_combo(combo_index, combo); 429 apply_combo(combo_index, combo);
419 apply_combos(); // also apply other prepared combos and dump key buffer 430 apply_combos(); // also apply other prepared combos and dump key buffer
420# ifdef COMBO_PROCESS_KEY_RELEASE 431# ifdef COMBO_PROCESS_KEY_RELEASE
421 if (process_combo_key_release(combo_index, combo, key_index, keycode)) { 432 if (process_combo_key_release(combo_index, combo, key_index, keycode)) {
422 release_combo(combo_index, combo); 433 release_combo(combo_index, combo);
@@ -424,10 +435,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
424# endif 435# endif
425 } 436 }
426#endif 437#endif
427 } else if (COMBO_ACTIVE(combo) 438 } else if (COMBO_ACTIVE(combo) && ONLY_ONE_KEY_IS_DOWN(COMBO_STATE(combo)) && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)) {
428 && ONLY_ONE_KEY_IS_DOWN(COMBO_STATE(combo))
429 && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)
430 ) {
431 /* last key released */ 439 /* last key released */
432 release_combo(combo_index, combo); 440 release_combo(combo_index, combo);
433 key_is_part_of_combo = true; 441 key_is_part_of_combo = true;
@@ -435,9 +443,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
435#ifdef COMBO_PROCESS_KEY_RELEASE 443#ifdef COMBO_PROCESS_KEY_RELEASE
436 process_combo_key_release(combo_index, combo, key_index, keycode); 444 process_combo_key_release(combo_index, combo, key_index, keycode);
437#endif 445#endif
438 } else if (COMBO_ACTIVE(combo) 446 } else if (COMBO_ACTIVE(combo) && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)) {
439 && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)
440 ) {
441 /* first or middle key released */ 447 /* first or middle key released */
442 key_is_part_of_combo = true; 448 key_is_part_of_combo = true;
443 449
@@ -489,21 +495,21 @@ bool process_combo(uint16_t keycode, keyrecord_t *record) {
489 495
490 if (record->event.pressed && is_combo_key) { 496 if (record->event.pressed && is_combo_key) {
491#ifndef COMBO_NO_TIMER 497#ifndef COMBO_NO_TIMER
492# ifdef COMBO_STRICT_TIMER 498# ifdef COMBO_STRICT_TIMER
493 if (!timer) { 499 if (!timer) {
494 // timer is set only on the first key 500 // timer is set only on the first key
495 timer = timer_read(); 501 timer = timer_read();
496 } 502 }
497# else 503# else
498 timer = timer_read(); 504 timer = timer_read();
499# endif 505# endif
500#endif 506#endif
501 507
502 if (key_buffer_size < COMBO_KEY_BUFFER_LENGTH) { 508 if (key_buffer_size < COMBO_KEY_BUFFER_LENGTH) {
503 key_buffer[key_buffer_size++] = (queued_record_t){ 509 key_buffer[key_buffer_size++] = (queued_record_t){
504 .record = *record, 510 .record = *record,
505 .keycode = keycode, 511 .keycode = keycode,
506 .combo_index = -1, // this will be set when applying combos 512 .combo_index = -1, // this will be set when applying combos
507 }; 513 };
508 } 514 }
509 } else { 515 } else {
@@ -532,7 +538,7 @@ void combo_task(void) {
532 if (combo_buffer_read != combo_buffer_write) { 538 if (combo_buffer_read != combo_buffer_write) {
533 apply_combos(); 539 apply_combos();
534 longest_term = 0; 540 longest_term = 0;
535 timer = 0; 541 timer = 0;
536 } else { 542 } else {
537 dump_key_buffer(); 543 dump_key_buffer();
538 timer = 0; 544 timer = 0;
@@ -546,9 +552,9 @@ void combo_enable(void) { b_combo_enable = true; }
546 552
547void combo_disable(void) { 553void combo_disable(void) {
548#ifndef COMBO_NO_TIMER 554#ifndef COMBO_NO_TIMER
549 timer = 0; 555 timer = 0;
550#endif 556#endif
551 b_combo_enable = false; 557 b_combo_enable = false;
552 combo_buffer_read = combo_buffer_write; 558 combo_buffer_read = combo_buffer_write;
553 clear_combos(); 559 clear_combos();
554 dump_key_buffer(); 560 dump_key_buffer();
diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h
index 43c36d79e..4c4e574e3 100644
--- a/quantum/process_keycode/process_combo.h
+++ b/quantum/process_keycode/process_combo.h
@@ -43,8 +43,8 @@ typedef struct {
43#ifdef EXTRA_SHORT_COMBOS 43#ifdef EXTRA_SHORT_COMBOS
44 uint8_t state; 44 uint8_t state;
45#else 45#else
46 bool disabled; 46 bool disabled;
47 bool active; 47 bool active;
48# if defined(EXTRA_EXTRA_LONG_COMBOS) 48# if defined(EXTRA_EXTRA_LONG_COMBOS)
49 uint32_t state; 49 uint32_t state;
50# elif defined(EXTRA_LONG_COMBOS) 50# elif defined(EXTRA_LONG_COMBOS)
diff --git a/quantum/process_keycode/process_haptic.c b/quantum/process_keycode/process_haptic.c
index 64d455d00..466c8e554 100644
--- a/quantum/process_keycode/process_haptic.c
+++ b/quantum/process_keycode/process_haptic.c
@@ -17,6 +17,7 @@
17#include "process_haptic.h" 17#include "process_haptic.h"
18#include "quantum_keycodes.h" 18#include "quantum_keycodes.h"
19#include "action_tapping.h" 19#include "action_tapping.h"
20#include "usb_device_state.h"
20 21
21__attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record) { 22__attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record) {
22 switch (keycode) { 23 switch (keycode) {
@@ -32,6 +33,7 @@ __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t
32 break; 33 break;
33 case KC_LCTRL ... KC_RGUI: 34 case KC_LCTRL ... KC_RGUI:
34 case QK_MOMENTARY ... QK_MOMENTARY_MAX: 35 case QK_MOMENTARY ... QK_MOMENTARY_MAX:
36 case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
35#endif 37#endif
36#ifdef NO_HAPTIC_FN 38#ifdef NO_HAPTIC_FN
37 case KC_FN0 ... KC_FN31: 39 case KC_FN0 ... KC_FN31:
@@ -130,7 +132,7 @@ bool process_haptic(uint16_t keycode, keyrecord_t *record) {
130 } 132 }
131 } 133 }
132 134
133 if (haptic_get_enable()) { 135 if (haptic_get_enable() && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) {
134 if (record->event.pressed) { 136 if (record->event.pressed) {
135 // keypress 137 // keypress
136 if (haptic_get_feedback() < 2 && get_haptic_enabled_key(keycode, record)) { 138 if (haptic_get_feedback() < 2 && get_haptic_enabled_key(keycode, record)) {
diff --git a/quantum/process_keycode/process_programmable_button.c b/quantum/process_keycode/process_programmable_button.c
new file mode 100644
index 000000000..c6e77faac
--- /dev/null
+++ b/quantum/process_keycode/process_programmable_button.c
@@ -0,0 +1,31 @@
1/*
2Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "process_programmable_button.h"
19#include "programmable_button.h"
20
21bool process_programmable_button(uint16_t keycode, keyrecord_t *record) {
22 if (keycode >= PROGRAMMABLE_BUTTON_MIN && keycode <= PROGRAMMABLE_BUTTON_MAX) {
23 uint8_t button = keycode - PROGRAMMABLE_BUTTON_MIN + 1;
24 if (record->event.pressed) {
25 programmable_button_on(button);
26 } else {
27 programmable_button_off(button);
28 }
29 }
30 return true;
31}
diff --git a/quantum/process_keycode/process_programmable_button.h b/quantum/process_keycode/process_programmable_button.h
new file mode 100644
index 000000000..47c6ce561
--- /dev/null
+++ b/quantum/process_keycode/process_programmable_button.h
@@ -0,0 +1,23 @@
1/*
2Copyright 2021 Thomas Weißschuh <thomas@t-8ch.de>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#pragma once
19
20#include <stdint.h>
21#include "quantum.h"
22
23bool process_programmable_button(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c
index a964aead3..5d0bb313b 100644
--- a/quantum/process_keycode/process_steno.c
+++ b/quantum/process_keycode/process_steno.c
@@ -67,7 +67,7 @@ static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM,
67 67
68#ifdef STENO_COMBINEDMAP 68#ifdef STENO_COMBINEDMAP
69/* Used to look up when pressing the middle row key to combine two consonant or vowel keys */ 69/* Used to look up when pressing the middle row key to combine two consonant or vowel keys */
70static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E}; 70static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
71static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, STN_RL, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR, STN_O, STN_U}; 71static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, STN_RL, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR, STN_O, STN_U};
72#endif 72#endif
73 73
@@ -174,11 +174,10 @@ bool process_steno(uint16_t keycode, keyrecord_t *record) {
174 return false; 174 return false;
175 175
176#ifdef STENO_COMBINEDMAP 176#ifdef STENO_COMBINEDMAP
177 case QK_STENO_COMB ... QK_STENO_COMB_MAX: 177 case QK_STENO_COMB ... QK_STENO_COMB_MAX: {
178 {
179 uint8_t result; 178 uint8_t result;
180 result = process_steno(combinedmap_first[keycode-QK_STENO_COMB], record); 179 result = process_steno(combinedmap_first[keycode - QK_STENO_COMB], record);
181 result &= process_steno(combinedmap_second[keycode-QK_STENO_COMB], record); 180 result &= process_steno(combinedmap_second[keycode - QK_STENO_COMB], record);
182 return result; 181 return result;
183 } 182 }
184#endif 183#endif
diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c
index 46fcaaa86..7853c22c5 100644
--- a/quantum/process_keycode/process_unicode_common.c
+++ b/quantum/process_keycode/process_unicode_common.c
@@ -22,6 +22,7 @@
22unicode_config_t unicode_config; 22unicode_config_t unicode_config;
23uint8_t unicode_saved_mods; 23uint8_t unicode_saved_mods;
24bool unicode_saved_caps_lock; 24bool unicode_saved_caps_lock;
25bool unicode_saved_num_lock;
25 26
26#if UNICODE_SELECTED_MODES != -1 27#if UNICODE_SELECTED_MODES != -1
27static uint8_t selected[] = {UNICODE_SELECTED_MODES}; 28static uint8_t selected[] = {UNICODE_SELECTED_MODES};
@@ -79,13 +80,14 @@ void persist_unicode_input_mode(void) { eeprom_update_byte(EECONFIG_UNICODEMODE,
79 80
80__attribute__((weak)) void unicode_input_start(void) { 81__attribute__((weak)) void unicode_input_start(void) {
81 unicode_saved_caps_lock = host_keyboard_led_state().caps_lock; 82 unicode_saved_caps_lock = host_keyboard_led_state().caps_lock;
83 unicode_saved_num_lock = host_keyboard_led_state().num_lock;
82 84
83 // Note the order matters here! 85 // Note the order matters here!
84 // Need to do this before we mess around with the mods, or else 86 // Need to do this before we mess around with the mods, or else
85 // UNICODE_KEY_LNX (which is usually Ctrl-Shift-U) might not work 87 // UNICODE_KEY_LNX (which is usually Ctrl-Shift-U) might not work
86 // correctly in the shifted case. 88 // correctly in the shifted case.
87 if (unicode_config.input_mode == UC_LNX && unicode_saved_caps_lock) { 89 if (unicode_config.input_mode == UC_LNX && unicode_saved_caps_lock) {
88 tap_code(KC_CAPS); 90 tap_code(KC_CAPSLOCK);
89 } 91 }
90 92
91 unicode_saved_mods = get_mods(); // Save current mods 93 unicode_saved_mods = get_mods(); // Save current mods
@@ -99,8 +101,12 @@ __attribute__((weak)) void unicode_input_start(void) {
99 tap_code16(UNICODE_KEY_LNX); 101 tap_code16(UNICODE_KEY_LNX);
100 break; 102 break;
101 case UC_WIN: 103 case UC_WIN:
104 // For increased reliability, use numpad keys for inputting digits
105 if (!unicode_saved_num_lock) {
106 tap_code(KC_NUMLOCK);
107 }
102 register_code(KC_LALT); 108 register_code(KC_LALT);
103 tap_code(KC_PPLS); 109 tap_code(KC_KP_PLUS);
104 break; 110 break;
105 case UC_WINC: 111 case UC_WINC:
106 tap_code(UNICODE_KEY_WINC); 112 tap_code(UNICODE_KEY_WINC);
@@ -117,13 +123,16 @@ __attribute__((weak)) void unicode_input_finish(void) {
117 unregister_code(UNICODE_KEY_MAC); 123 unregister_code(UNICODE_KEY_MAC);
118 break; 124 break;
119 case UC_LNX: 125 case UC_LNX:
120 tap_code(KC_SPC); 126 tap_code(KC_SPACE);
121 if (unicode_saved_caps_lock) { 127 if (unicode_saved_caps_lock) {
122 tap_code(KC_CAPS); 128 tap_code(KC_CAPSLOCK);
123 } 129 }
124 break; 130 break;
125 case UC_WIN: 131 case UC_WIN:
126 unregister_code(KC_LALT); 132 unregister_code(KC_LALT);
133 if (!unicode_saved_num_lock) {
134 tap_code(KC_NUMLOCK);
135 }
127 break; 136 break;
128 case UC_WINC: 137 case UC_WINC:
129 tap_code(KC_ENTER); 138 tap_code(KC_ENTER);
@@ -139,26 +148,44 @@ __attribute__((weak)) void unicode_input_cancel(void) {
139 unregister_code(UNICODE_KEY_MAC); 148 unregister_code(UNICODE_KEY_MAC);
140 break; 149 break;
141 case UC_LNX: 150 case UC_LNX:
142 tap_code(KC_ESC); 151 tap_code(KC_ESCAPE);
143 if (unicode_saved_caps_lock) { 152 if (unicode_saved_caps_lock) {
144 tap_code(KC_CAPS); 153 tap_code(KC_CAPSLOCK);
145 } 154 }
146 break; 155 break;
147 case UC_WINC: 156 case UC_WINC:
148 tap_code(KC_ESC); 157 tap_code(KC_ESCAPE);
149 break; 158 break;
150 case UC_WIN: 159 case UC_WIN:
151 unregister_code(KC_LALT); 160 unregister_code(KC_LALT);
161 if (!unicode_saved_num_lock) {
162 tap_code(KC_NUMLOCK);
163 }
152 break; 164 break;
153 } 165 }
154 166
155 set_mods(unicode_saved_mods); // Reregister previously set mods 167 set_mods(unicode_saved_mods); // Reregister previously set mods
156} 168}
157 169
170// clang-format off
171
172static void send_nibble_wrapper(uint8_t digit) {
173 if (unicode_config.input_mode == UC_WIN) {
174 uint8_t kc = digit < 10
175 ? KC_KP_1 + (10 + digit - 1) % 10
176 : KC_A + (digit - 10);
177 tap_code(kc);
178 return;
179 }
180 send_nibble(digit);
181}
182
183// clang-format on
184
158void register_hex(uint16_t hex) { 185void register_hex(uint16_t hex) {
159 for (int i = 3; i >= 0; i--) { 186 for (int i = 3; i >= 0; i--) {
160 uint8_t digit = ((hex >> (i * 4)) & 0xF); 187 uint8_t digit = ((hex >> (i * 4)) & 0xF);
161 send_nibble(digit); 188 send_nibble_wrapper(digit);
162 } 189 }
163} 190}
164 191
@@ -171,10 +198,10 @@ void register_hex32(uint32_t hex) {
171 uint8_t digit = ((hex >> (i * 4)) & 0xF); 198 uint8_t digit = ((hex >> (i * 4)) & 0xF);
172 if (digit == 0) { 199 if (digit == 0) {
173 if (!onzerostart) { 200 if (!onzerostart) {
174 send_nibble(digit); 201 send_nibble_wrapper(digit);
175 } 202 }
176 } else { 203 } else {
177 send_nibble(digit); 204 send_nibble_wrapper(digit);
178 onzerostart = false; 205 onzerostart = false;
179 } 206 }
180 } 207 }