diff options
author | Ofer Plesser <plesserofer@gmail.com> | 2016-12-10 16:11:59 +0200 |
---|---|---|
committer | Ofer Plesser <plesserofer@gmail.com> | 2016-12-10 16:11:59 +0200 |
commit | b6bf4e0dce062a535685c4e772f613252d401ed3 (patch) | |
tree | 26ed7273077f84e33d5cea525f7cc662637212c3 /quantum/process_keycode/process_combo.c | |
parent | eac8fa799909817bfc7cb4043448f85551154c6b (diff) | |
download | qmk_firmware-b6bf4e0dce062a535685c4e772f613252d401ed3.tar.gz qmk_firmware-b6bf4e0dce062a535685c4e772f613252d401ed3.zip |
Added support for timing out combos if a key as been pressed for longer than COMBO_TERM
Diffstat (limited to 'quantum/process_keycode/process_combo.c')
-rw-r--r-- | quantum/process_keycode/process_combo.c | 107 |
1 files changed, 79 insertions, 28 deletions
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c index a6cfed11a..ff7e8aba5 100644 --- a/quantum/process_keycode/process_combo.c +++ b/quantum/process_keycode/process_combo.c | |||
@@ -1,11 +1,6 @@ | |||
1 | #include "process_combo.h" | 1 | #include "process_combo.h" |
2 | #include "print.h" | 2 | #include "print.h" |
3 | 3 | ||
4 | // __attribute__ ((weak)) | ||
5 | // combo_t key_combos[] = { | ||
6 | |||
7 | // }; | ||
8 | |||
9 | #define SEND_KEY(key) \ | 4 | #define SEND_KEY(key) \ |
10 | do { \ | 5 | do { \ |
11 | register_code16(key); \ | 6 | register_code16(key); \ |
@@ -13,54 +8,110 @@ do { \ | |||
13 | unregister_code16(key); \ | 8 | unregister_code16(key); \ |
14 | } while(0) | 9 | } while(0) |
15 | 10 | ||
11 | #define COMBO_TIMER_ELAPSED -1 | ||
12 | |||
13 | #if COMBO_TERM | ||
14 | #define IS_COMBO_KEY_HELD(combo) (COMBO_TIMER_ELAPSED == combo->timer ? false : true) | ||
15 | #define RESET_COMBO_TIMER_AND_KEY(combo) combo->timer = 0; combo->key = 0 | ||
16 | #else | ||
17 | #define IS_COMBO_KEY_HELD(combo) (true) | ||
18 | #define RESET_COMBO_TIMER_AND_KEY(combo) do {} while (0) | ||
19 | #endif | ||
20 | |||
21 | |||
22 | __attribute__ ((weak)) | ||
23 | combo_t key_combos[COMBO_COUNT] = { | ||
24 | |||
25 | }; | ||
26 | |||
27 | static inline void reset_combo(combo_t *combo) | ||
28 | { | ||
29 | combo->state = 0; | ||
30 | RESET_COMBO_TIMER_AND_KEY(combo); | ||
31 | } | ||
16 | 32 | ||
17 | #define ALL_COMBO_KEYS_ARE_DOWN (((1<<count)-1) == combo->state) | 33 | #define ALL_COMBO_KEYS_ARE_DOWN (((1<<count)-1) == combo->state) |
34 | #define NO_COMBO_KEYS_ARE_DOWN (0 == combo->state) | ||
35 | #define KEY_STATE_DOWN(key) do{ combo->state |= (1<<key); } while(0) | ||
36 | #define KEY_STATE_UP(key) do{ combo->state &= ~(1<<key); } while(0) | ||
18 | static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record) | 37 | static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record) |
19 | { | 38 | { |
20 | uint8_t count = 0; | 39 | uint8_t count = 0; |
21 | bool is_combo_key = false; | 40 | uint8_t index = -1; |
22 | // bool combo_key_released = false; | 41 | /* Find index of keycode and number of combo keys */ |
42 | for (const uint16_t *keys = combo->keys; ;++count) { | ||
43 | uint16_t key = pgm_read_word(&keys[count]); | ||
44 | if (keycode == key) index = count; | ||
45 | if (COMBO_END == key) break; | ||
46 | } | ||
23 | 47 | ||
24 | // Count the number of combo keys | 48 | /* Return if not a combo key */ |
25 | for (const uint16_t *key = combo->keys; COMBO_END != pgm_read_word(key); ++key, ++count); | 49 | if (-1 == index) return false; |
26 | 50 | ||
27 | for (uint8_t i = 0; i < count; ++i) { | 51 | bool is_combo_active = IS_COMBO_KEY_HELD(combo); |
28 | uint16_t key = pgm_read_word(&combo->keys[i]); | ||
29 | 52 | ||
30 | if (key == keycode) { | 53 | if (record->event.pressed) { |
31 | is_combo_key = true; | 54 | KEY_STATE_DOWN(index); |
55 | |||
56 | #if COMBO_TERM | ||
57 | if (is_combo_active) { | ||
58 | combo->timer = timer_read(); | ||
59 | combo->key = keycode; | ||
60 | } | ||
61 | #endif | ||
32 | 62 | ||
33 | if (record->event.pressed) { | 63 | } else { |
34 | combo->state |= (1<<i); | 64 | if (is_combo_active && combo->state) { /* Combo key was tapped */ |
35 | } else { // Combo key released | 65 | RESET_COMBO_TIMER_AND_KEY(combo); |
36 | if (!combo->state) { | 66 | SEND_KEY(keycode); |
37 | // The combo was sent, no need to send released key | 67 | } |
38 | return true; | ||
39 | } | ||
40 | 68 | ||
41 | combo->state &= ~(1<<i); | 69 | #if COMBO_TERM |
42 | SEND_KEY(key); | 70 | if (!is_combo_active && keycode == combo->key) { /* Held combo key was released */ |
43 | } | 71 | unregister_code16(combo->key); |
44 | } | 72 | } |
73 | #endif | ||
74 | |||
75 | KEY_STATE_UP(index); | ||
45 | } | 76 | } |
46 | 77 | ||
47 | if (ALL_COMBO_KEYS_ARE_DOWN) { | 78 | if (ALL_COMBO_KEYS_ARE_DOWN && is_combo_active) { |
48 | SEND_KEY(combo->action); | 79 | SEND_KEY(combo->action); |
49 | combo->state = 0; | 80 | reset_combo(combo); |
81 | } | ||
82 | |||
83 | if(NO_COMBO_KEYS_ARE_DOWN && !is_combo_active) { | ||
84 | reset_combo(combo); | ||
50 | } | 85 | } |
51 | 86 | ||
52 | return is_combo_key; | 87 | return is_combo_active; |
53 | } | 88 | } |
54 | 89 | ||
55 | |||
56 | bool process_combo(uint16_t keycode, keyrecord_t *record) | 90 | bool process_combo(uint16_t keycode, keyrecord_t *record) |
57 | { | 91 | { |
58 | bool is_combo_key = false; | 92 | bool is_combo_key = false; |
59 | 93 | ||
60 | for (int i = 0; i < NUM_ELEMS(key_combos); ++i) { | 94 | for (int i = 0; i < COMBO_COUNT; ++i) { |
61 | combo_t *combo = &key_combos[i]; | 95 | combo_t *combo = &key_combos[i]; |
62 | is_combo_key |= process_single_combo(combo, keycode, record); | 96 | is_combo_key |= process_single_combo(combo, keycode, record); |
63 | } | 97 | } |
64 | 98 | ||
65 | return !is_combo_key; | 99 | return !is_combo_key; |
100 | } | ||
101 | |||
102 | void matrix_scan_combo(void) | ||
103 | { | ||
104 | #if COMBO_TERM | ||
105 | for (int i = 0; i < COMBO_COUNT; ++i) { | ||
106 | combo_t *combo = &key_combos[i]; | ||
107 | if (combo->timer && | ||
108 | combo->timer != COMBO_TIMER_ELAPSED && | ||
109 | timer_elapsed(combo->timer) > COMBO_TERM) { | ||
110 | |||
111 | combo->timer = COMBO_TIMER_ELAPSED; | ||
112 | unregister_code16(combo->key); | ||
113 | register_code16(combo->key); | ||
114 | } | ||
115 | } | ||
116 | #endif | ||
66 | } \ No newline at end of file | 117 | } \ No newline at end of file |