aboutsummaryrefslogtreecommitdiff
path: root/quantum/process_keycode
diff options
context:
space:
mode:
authorJason Janse van Rensburg <l33tjas.0n@gmail.com>2016-08-30 14:54:00 +0200
committerJason Janse van Rensburg <l33tjas.0n@gmail.com>2016-08-30 14:54:00 +0200
commitfc2ca62a3b9552175eb7c27cc11f3a5af6cfae50 (patch)
tree59b2f2406f472a9fd2af4946420d1a1c880929c0 /quantum/process_keycode
parenta41a7a9100b9f4c6bfdf49b39b05e626ffd95397 (diff)
parent8e00c464e6f488d86e0768a77a2ad5ee238dba6d (diff)
downloadqmk_firmware-fc2ca62a3b9552175eb7c27cc11f3a5af6cfae50.tar.gz
qmk_firmware-fc2ca62a3b9552175eb7c27cc11f3a5af6cfae50.zip
Merge branch 'master'
Conflicts: keyboards/planck/keymaps/bone2planck/keymap.c
Diffstat (limited to 'quantum/process_keycode')
-rw-r--r--quantum/process_keycode/process_tap_dance.c115
-rw-r--r--quantum/process_keycode/process_tap_dance.h8
-rw-r--r--quantum/process_keycode/process_unicode.c209
-rw-r--r--quantum/process_keycode/process_unicode.h40
4 files changed, 290 insertions, 82 deletions
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
index d240dc2e6..07de3ecb8 100644
--- a/quantum/process_keycode/process_tap_dance.c
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -1,14 +1,16 @@
1#include "quantum.h" 1#include "quantum.h"
2#include "action_tapping.h"
2 3
3static qk_tap_dance_state_t qk_tap_dance_state; 4static uint16_t last_td;
5static int8_t highest_td = -1;
4 6
5void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) { 7void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) {
6 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; 8 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
7 9
8 if (state->count == 1) { 10 if (state->count == 1) {
9 register_code (pair->kc1); 11 register_code16 (pair->kc1);
10 } else if (state->count == 2) { 12 } else if (state->count == 2) {
11 register_code (pair->kc2); 13 register_code16 (pair->kc2);
12 } 14 }
13} 15}
14 16
@@ -16,102 +18,117 @@ void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) {
16 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; 18 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
17 19
18 if (state->count == 1) { 20 if (state->count == 1) {
19 unregister_code (pair->kc1); 21 unregister_code16 (pair->kc1);
20 } else if (state->count == 2) { 22 } else if (state->count == 2) {
21 unregister_code (pair->kc2); 23 unregister_code16 (pair->kc2);
22 } 24 }
23} 25}
24 26
25static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state, 27static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state,
26 void *user_data, 28 void *user_data,
27 qk_tap_dance_user_fn_t fn) 29 qk_tap_dance_user_fn_t fn)
28{ 30{
29 if (fn) { 31 if (fn) {
30 fn(state, user_data); 32 fn(state, user_data);
31 } 33 }
32} 34}
33 35
34static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t action) 36static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t *action)
35{ 37{
36 _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_each_tap); 38 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_each_tap);
37} 39}
38 40
39static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t action) 41static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t *action)
40{ 42{
41 _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_dance_finished); 43 if (action->state.finished)
44 return;
45 action->state.finished = true;
46 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
42} 47}
43 48
44static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t action) 49static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action)
45{ 50{
46 _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_reset); 51 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset);
47} 52}
48 53
49bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { 54bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
50 bool r = true;
51 uint16_t idx = keycode - QK_TAP_DANCE; 55 uint16_t idx = keycode - QK_TAP_DANCE;
52 qk_tap_dance_action_t action; 56 qk_tap_dance_action_t *action;
57
58 if (last_td && last_td != keycode) {
59 (&tap_dance_actions[last_td - QK_TAP_DANCE])->state.interrupted = true;
60 }
53 61
54 switch(keycode) { 62 switch(keycode) {
55 case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: 63 case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
56 action = tap_dance_actions[idx]; 64 if ((int16_t)idx > highest_td)
65 highest_td = idx;
66 action = &tap_dance_actions[idx];
57 67
58 process_tap_dance_action_on_each_tap (action); 68 action->state.keycode = keycode;
59 if (qk_tap_dance_state.keycode && qk_tap_dance_state.keycode != keycode) { 69 action->state.pressed = record->event.pressed;
60 process_tap_dance_action_on_dance_finished (action);
61 } else if (qk_tap_dance_state.active && qk_tap_dance_state.pressed) {
62 reset_tap_dance (&qk_tap_dance_state);
63 } else {
64 r = false;
65 }
66
67 qk_tap_dance_state.active = true;
68 qk_tap_dance_state.pressed = record->event.pressed;
69 if (record->event.pressed) { 70 if (record->event.pressed) {
70 qk_tap_dance_state.keycode = keycode; 71 action->state.count++;
71 qk_tap_dance_state.timer = timer_read (); 72 action->state.timer = timer_read();
72 qk_tap_dance_state.count++; 73
74 if (last_td && last_td != keycode) {
75 qk_tap_dance_action_t *paction = &tap_dance_actions[last_td - QK_TAP_DANCE];
76 paction->state.interrupted = true;
77 process_tap_dance_action_on_dance_finished (paction);
78 reset_tap_dance (&paction->state);
79 }
73 } 80 }
81 last_td = keycode;
82
74 break; 83 break;
75 84
76 default: 85 default:
77 if (qk_tap_dance_state.keycode) { 86 if (!record->event.pressed)
78 // if we are here, the tap dance was interrupted by a different key 87 return true;
79 idx = qk_tap_dance_state.keycode - QK_TAP_DANCE;
80 action = tap_dance_actions[idx];
81 88
82 process_tap_dance_action_on_each_tap (action); 89 if (highest_td == -1)
90 return true;
91
92 for (int i = 0; i <= highest_td; i++) {
93 action = &tap_dance_actions[i];
94 if (action->state.count == 0)
95 continue;
96 action->state.interrupted = true;
83 process_tap_dance_action_on_dance_finished (action); 97 process_tap_dance_action_on_dance_finished (action);
84 reset_tap_dance (&qk_tap_dance_state); 98 reset_tap_dance (&action->state);
85 qk_tap_dance_state.active = false;
86 } 99 }
87 break; 100 break;
88 } 101 }
89 102
90 return r; 103 return true;
91} 104}
92 105
93void matrix_scan_tap_dance () { 106void matrix_scan_tap_dance () {
94 if (qk_tap_dance_state.active && timer_elapsed (qk_tap_dance_state.timer) > TAPPING_TERM) { 107 if (highest_td == -1)
95 // if we are here, the tap dance was timed out 108 return;
96 uint16_t idx = qk_tap_dance_state.keycode - QK_TAP_DANCE; 109
97 qk_tap_dance_action_t action = tap_dance_actions[idx]; 110 for (int i = 0; i <= highest_td; i++) {
111 qk_tap_dance_action_t *action = &tap_dance_actions[i];
98 112
99 process_tap_dance_action_on_dance_finished (action); 113 if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) {
100 reset_tap_dance (&qk_tap_dance_state); 114 process_tap_dance_action_on_dance_finished (action);
115 reset_tap_dance (&action->state);
116 }
101 } 117 }
102} 118}
103 119
104void reset_tap_dance (qk_tap_dance_state_t *state) { 120void reset_tap_dance (qk_tap_dance_state_t *state) {
105 uint16_t idx = state->keycode - QK_TAP_DANCE; 121 qk_tap_dance_action_t *action;
106 qk_tap_dance_action_t action;
107 122
108 if (state->pressed) 123 if (state->pressed)
109 return; 124 return;
110 125
111 action = tap_dance_actions[idx]; 126 action = &tap_dance_actions[state->keycode - QK_TAP_DANCE];
127
112 process_tap_dance_action_on_reset (action); 128 process_tap_dance_action_on_reset (action);
113 129
114 state->keycode = 0;
115 state->count = 0; 130 state->count = 0;
116 state->active = false; 131 state->interrupted = false;
132 state->finished = false;
133 last_td = 0;
117} 134}
diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h
index e2c74efe9..d7b857bdc 100644
--- a/quantum/process_keycode/process_tap_dance.h
+++ b/quantum/process_keycode/process_tap_dance.h
@@ -11,8 +11,9 @@ typedef struct
11 uint8_t count; 11 uint8_t count;
12 uint16_t keycode; 12 uint16_t keycode;
13 uint16_t timer; 13 uint16_t timer;
14 bool active:1; 14 bool interrupted;
15 bool pressed:1; 15 bool pressed;
16 bool finished;
16} qk_tap_dance_state_t; 17} qk_tap_dance_state_t;
17 18
18#define TD(n) (QK_TAP_DANCE + n) 19#define TD(n) (QK_TAP_DANCE + n)
@@ -26,6 +27,7 @@ typedef struct
26 qk_tap_dance_user_fn_t on_dance_finished; 27 qk_tap_dance_user_fn_t on_dance_finished;
27 qk_tap_dance_user_fn_t on_reset; 28 qk_tap_dance_user_fn_t on_reset;
28 } fn; 29 } fn;
30 qk_tap_dance_state_t state;
29 void *user_data; 31 void *user_data;
30} qk_tap_dance_action_t; 32} qk_tap_dance_action_t;
31 33
@@ -48,7 +50,7 @@ typedef struct
48 .fn = { user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_reset } \ 50 .fn = { user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_reset } \
49 } 51 }
50 52
51extern const qk_tap_dance_action_t tap_dance_actions[]; 53extern qk_tap_dance_action_t tap_dance_actions[];
52 54
53/* To be used internally */ 55/* To be used internally */
54 56
diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c
index ad5d7f86b..06c1694f2 100644
--- a/quantum/process_keycode/process_unicode.c
+++ b/quantum/process_keycode/process_unicode.c
@@ -13,45 +13,196 @@ uint16_t hex_to_keycode(uint8_t hex)
13 } 13 }
14} 14}
15 15
16void set_unicode_mode(uint8_t os_target) 16void set_unicode_input_mode(uint8_t os_target)
17{ 17{
18 input_mode = os_target; 18 input_mode = os_target;
19} 19}
20 20
21__attribute__((weak))
22void unicode_input_start (void) {
23 switch(input_mode) {
24 case UC_OSX:
25 register_code(KC_LALT);
26 break;
27 case UC_LNX:
28 register_code(KC_LCTL);
29 register_code(KC_LSFT);
30 register_code(KC_U);
31 unregister_code(KC_U);
32 unregister_code(KC_LSFT);
33 unregister_code(KC_LCTL);
34 break;
35 case UC_WIN:
36 register_code(KC_LALT);
37 register_code(KC_PPLS);
38 unregister_code(KC_PPLS);
39 break;
40 }
41 wait_ms(UNICODE_TYPE_DELAY);
42}
43
44__attribute__((weak))
45void unicode_input_finish (void) {
46 switch(input_mode) {
47 case UC_OSX:
48 case UC_WIN:
49 unregister_code(KC_LALT);
50 break;
51 case UC_LNX:
52 register_code(KC_SPC);
53 unregister_code(KC_SPC);
54 break;
55 }
56}
57
58void register_hex(uint16_t hex) {
59 for(int i = 3; i >= 0; i--) {
60 uint8_t digit = ((hex >> (i*4)) & 0xF);
61 register_code(hex_to_keycode(digit));
62 unregister_code(hex_to_keycode(digit));
63 }
64}
65
21bool process_unicode(uint16_t keycode, keyrecord_t *record) { 66bool process_unicode(uint16_t keycode, keyrecord_t *record) {
22 if (keycode > QK_UNICODE && record->event.pressed) { 67 if (keycode > QK_UNICODE && record->event.pressed) {
23 uint16_t unicode = keycode & 0x7FFF; 68 uint16_t unicode = keycode & 0x7FFF;
24 switch(input_mode) { 69 unicode_input_start();
25 case UC_OSX: 70 register_hex(unicode);
26 register_code(KC_LALT); 71 unicode_input_finish();
27 break; 72 }
28 case UC_LNX: 73 return true;
29 register_code(KC_LCTL); 74}
30 register_code(KC_LSFT); 75
31 register_code(KC_U); 76#ifdef UCIS_ENABLE
32 unregister_code(KC_U); 77qk_ucis_state_t qk_ucis_state;
33 break; 78
34 case UC_WIN: 79void qk_ucis_start(void) {
35 register_code(KC_LALT); 80 qk_ucis_state.count = 0;
36 register_code(KC_PPLS); 81 qk_ucis_state.in_progress = true;
37 unregister_code(KC_PPLS); 82
38 break; 83 qk_ucis_start_user();
84}
85
86__attribute__((weak))
87void qk_ucis_start_user(void) {
88 unicode_input_start();
89 register_hex(0x2328);
90 unicode_input_finish();
91}
92
93static bool is_uni_seq(char *seq) {
94 uint8_t i;
95
96 for (i = 0; seq[i]; i++) {
97 uint16_t code;
98 if (('1' <= seq[i]) && (seq[i] <= '0'))
99 code = seq[i] - '1' + KC_1;
100 else
101 code = seq[i] - 'a' + KC_A;
102
103 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
104 return false;
105 }
106
107 return (qk_ucis_state.codes[i] == KC_ENT ||
108 qk_ucis_state.codes[i] == KC_SPC);
109}
110
111__attribute__((weak))
112void qk_ucis_symbol_fallback (void) {
113 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
114 uint8_t code = qk_ucis_state.codes[i];
115 register_code(code);
116 unregister_code(code);
117 wait_ms(UNICODE_TYPE_DELAY);
118 }
119}
120
121void register_ucis(const char *hex) {
122 for(int i = 0; hex[i]; i++) {
123 uint8_t kc = 0;
124 char c = hex[i];
125
126 switch (c) {
127 case '0':
128 kc = KC_0;
129 break;
130 case '1' ... '9':
131 kc = c - '1' + KC_1;
132 break;
133 case 'a' ... 'f':
134 kc = c - 'a' + KC_A;
135 break;
136 case 'A' ... 'F':
137 kc = c - 'A' + KC_A;
138 break;
39 } 139 }
40 for(int i = 3; i >= 0; i--) { 140
41 uint8_t digit = ((unicode >> (i*4)) & 0xF); 141 if (kc) {
42 register_code(hex_to_keycode(digit)); 142 register_code (kc);
43 unregister_code(hex_to_keycode(digit)); 143 unregister_code (kc);
144 wait_ms (UNICODE_TYPE_DELAY);
44 } 145 }
45 switch(input_mode) { 146 }
46 case UC_OSX: 147}
47 case UC_WIN: 148
48 unregister_code(KC_LALT); 149bool process_ucis (uint16_t keycode, keyrecord_t *record) {
49 break; 150 uint8_t i;
50 case UC_LNX: 151
51 unregister_code(KC_LCTL); 152 if (!qk_ucis_state.in_progress)
52 unregister_code(KC_LSFT); 153 return true;
154
155 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
156 !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
157 return false;
158 }
159
160 if (!record->event.pressed)
161 return true;
162
163 qk_ucis_state.codes[qk_ucis_state.count] = keycode;
164 qk_ucis_state.count++;
165
166 if (keycode == KC_BSPC) {
167 if (qk_ucis_state.count >= 2) {
168 qk_ucis_state.count -= 2;
169 return true;
170 } else {
171 qk_ucis_state.count--;
172 return false;
173 }
174 }
175
176 if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
177 bool symbol_found = false;
178
179 for (i = qk_ucis_state.count; i > 0; i--) {
180 register_code (KC_BSPC);
181 unregister_code (KC_BSPC);
182 wait_ms(UNICODE_TYPE_DELAY);
183 }
184
185 if (keycode == KC_ESC) {
186 qk_ucis_state.in_progress = false;
187 return false;
188 }
189
190 unicode_input_start();
191 for (i = 0; ucis_symbol_table[i].symbol; i++) {
192 if (is_uni_seq (ucis_symbol_table[i].symbol)) {
193 symbol_found = true;
194 register_ucis(ucis_symbol_table[i].code + 2);
53 break; 195 break;
196 }
54 } 197 }
198 if (!symbol_found) {
199 qk_ucis_symbol_fallback();
200 }
201 unicode_input_finish();
202
203 qk_ucis_state.in_progress = false;
204 return false;
55 } 205 }
56 return true; 206 return true;
57} \ No newline at end of file 207}
208#endif
diff --git a/quantum/process_keycode/process_unicode.h b/quantum/process_keycode/process_unicode.h
index ca17f8f66..02ce3dd7e 100644
--- a/quantum/process_keycode/process_unicode.h
+++ b/quantum/process_keycode/process_unicode.h
@@ -8,10 +8,48 @@
8#define UC_WIN 2 8#define UC_WIN 2
9#define UC_BSD 3 9#define UC_BSD 3
10 10
11#ifndef UNICODE_TYPE_DELAY
12#define UNICODE_TYPE_DELAY 10
13#endif
14
11void set_unicode_input_mode(uint8_t os_target); 15void set_unicode_input_mode(uint8_t os_target);
16void unicode_input_start(void);
17void unicode_input_finish(void);
18void register_hex(uint16_t hex);
12 19
13bool process_unicode(uint16_t keycode, keyrecord_t *record); 20bool process_unicode(uint16_t keycode, keyrecord_t *record);
14 21
22#ifdef UCIS_ENABLE
23#ifndef UCIS_MAX_SYMBOL_LENGTH
24#define UCIS_MAX_SYMBOL_LENGTH 32
25#endif
26
27typedef struct {
28 char *symbol;
29 char *code;
30} qk_ucis_symbol_t;
31
32typedef struct {
33 uint8_t count;
34 uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
35 bool in_progress:1;
36} qk_ucis_state_t;
37
38extern qk_ucis_state_t qk_ucis_state;
39
40#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}}
41#define UCIS_SYM(name, code) {name, #code}
42
43extern const qk_ucis_symbol_t ucis_symbol_table[];
44
45void qk_ucis_start(void);
46void qk_ucis_start_user(void);
47void qk_ucis_symbol_fallback (void);
48void register_ucis(const char *hex);
49bool process_ucis (uint16_t keycode, keyrecord_t *record);
50
51#endif
52
15#define UC_BSPC UC(0x0008) 53#define UC_BSPC UC(0x0008)
16 54
17#define UC_SPC UC(0x0020) 55#define UC_SPC UC(0x0020)
@@ -119,4 +157,4 @@ bool process_unicode(uint16_t keycode, keyrecord_t *record);
119#define UC_TILD UC(0x007E) 157#define UC_TILD UC(0x007E)
120#define UC_DEL UC(0x007F) 158#define UC_DEL UC(0x007F)
121 159
122#endif \ No newline at end of file 160#endif