]> git.gir.st - tmk_keyboard.git/blob - common/action.c
Merge branch 'action_refine'
[tmk_keyboard.git] / common / action.c
1 /*
2 Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "host.h"
18 #include "keycode.h"
19 #include "keyboard.h"
20 #include "mousekey.h"
21 #include "command.h"
22 #include "debug.h"
23 #include "led.h"
24 #include "action_layer.h"
25 #include "action_tapping.h"
26 #include "action_oneshot.h"
27 #include "action_macro.h"
28 #include "action.h"
29
30
31 void action_exec(keyevent_t event)
32 {
33 if (!IS_NOEVENT(event)) {
34 debug("\n---- action_exec: start -----\n");
35 debug("EVENT: "); debug_event(event); debug("\n");
36 }
37
38 keyrecord_t record = { .event = event };
39
40 #ifndef NO_ACTION_TAPPING
41 action_tapping_process(record);
42 #else
43 process_action(&record);
44 if (!IS_NOEVENT(record.event)) {
45 debug("processed: "); debug_record(record); debug("\n");
46 }
47 #endif
48 }
49
50 void process_action(keyrecord_t *record)
51 {
52 keyevent_t event = record->event;
53 #ifndef NO_ACTION_TAPPING
54 uint8_t tap_count = record->tap.count;
55 #endif
56
57 if (IS_NOEVENT(event)) { return; }
58
59 action_t action = layer_switch_get_action(event.key);
60 debug("ACTION: "); debug_action(action);
61 #ifndef NO_ACTION_LAYER
62 debug(" layer_state: "); layer_debug();
63 debug(" default_layer_state: "); default_layer_debug();
64 #endif
65 debug("\n");
66
67 switch (action.kind.id) {
68 /* Key and Mods */
69 case ACT_LMODS:
70 case ACT_RMODS:
71 {
72 uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods :
73 action.key.mods<<4;
74 if (event.pressed) {
75 if (mods) {
76 host_add_mods(mods);
77 host_send_keyboard_report();
78 }
79 register_code(action.key.code);
80 } else {
81 unregister_code(action.key.code);
82 if (mods) {
83 host_del_mods(mods);
84 host_send_keyboard_report();
85 }
86 }
87 }
88 break;
89 #ifndef NO_ACTION_TAPPING
90 case ACT_LMODS_TAP:
91 case ACT_RMODS_TAP:
92 {
93 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods :
94 action.key.mods<<4;
95 switch (action.layer_tap.code) {
96 #ifndef NO_ACTION_ONESHOT
97 case 0x00:
98 // Oneshot modifier
99 if (event.pressed) {
100 if (tap_count == 0) {
101 debug("MODS_TAP: Oneshot: add_mods\n");
102 add_mods(mods);
103 }
104 else if (tap_count == 1) {
105 debug("MODS_TAP: Oneshot: start\n");
106 oneshot_start(mods);
107 }
108 else if (tap_count == TAPPING_TOGGLE) {
109 debug("MODS_TAP: Oneshot: toggle\n");
110 oneshot_toggle();
111 }
112 else {
113 debug("MODS_TAP: Oneshot: cancel&add_mods\n");
114 // double tap cancels oneshot and works as normal modifier.
115 oneshot_cancel();
116 add_mods(mods);
117 }
118 } else {
119 if (tap_count == 0) {
120 debug("MODS_TAP: Oneshot: cancel/del_mods\n");
121 // cancel oneshot on hold
122 oneshot_cancel();
123 del_mods(mods);
124 }
125 else if (tap_count == 1) {
126 debug("MODS_TAP: Oneshot: del_mods\n");
127 // retain Oneshot
128 del_mods(mods);
129 }
130 else {
131 debug("MODS_TAP: Oneshot: del_mods\n");
132 // cancel Mods
133 del_mods(mods);
134 }
135 }
136 break;
137 #endif
138 default:
139 if (event.pressed) {
140 if (tap_count > 0) {
141 if (record->tap.interrupted) {
142 debug("MODS_TAP: Tap: Cancel: add_mods\n");
143 // ad hoc: set 0 to cancel tap
144 record->tap.count = 0;
145 add_mods(mods);
146 } else {
147 debug("MODS_TAP: Tap: register_code\n");
148 register_code(action.key.code);
149 }
150 } else {
151 debug("MODS_TAP: No tap: add_mods\n");
152 add_mods(mods);
153 }
154 } else {
155 if (tap_count > 0) {
156 debug("MODS_TAP: Tap: unregister_code\n");
157 unregister_code(action.key.code);
158 } else {
159 debug("MODS_TAP: No tap: add_mods\n");
160 del_mods(mods);
161 }
162 }
163 break;
164 }
165 }
166 break;
167 #endif
168 #ifdef EXTRAKEY_ENABLE
169 /* other HID usage */
170 case ACT_USAGE:
171 switch (action.usage.page) {
172 case PAGE_SYSTEM:
173 if (event.pressed) {
174 host_system_send(action.usage.code);
175 } else {
176 host_system_send(0);
177 }
178 break;
179 case PAGE_CONSUMER:
180 if (event.pressed) {
181 host_consumer_send(action.usage.code);
182 } else {
183 host_consumer_send(0);
184 }
185 break;
186 }
187 break;
188 #endif
189 #ifdef MOUSEKEY_ENABLE
190 /* Mouse key */
191 case ACT_MOUSEKEY:
192 if (event.pressed) {
193 mousekey_on(action.key.code);
194 mousekey_send();
195 } else {
196 mousekey_off(action.key.code);
197 mousekey_send();
198 }
199 break;
200 #endif
201 #ifndef NO_ACTION_LAYER
202 case ACT_LAYER:
203 if (action.layer_bitop.on == 0) {
204 /* Default Layer Bitwise Operation */
205 if (!event.pressed) {
206 uint8_t shift = action.layer_bitop.part*4;
207 uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
208 uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
209 switch (action.layer_bitop.op) {
210 case OP_BIT_AND: default_layer_and(bits | mask); break;
211 case OP_BIT_OR: default_layer_or(bits | mask); break;
212 case OP_BIT_XOR: default_layer_xor(bits | mask); break;
213 case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
214 }
215 }
216 } else {
217 /* Layer Bitwise Operation */
218 if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
219 (action.layer_bitop.on & ON_RELEASE)) {
220 uint8_t shift = action.layer_bitop.part*4;
221 uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
222 uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
223 switch (action.layer_bitop.op) {
224 case OP_BIT_AND: layer_and(bits | mask); break;
225 case OP_BIT_OR: layer_or(bits | mask); break;
226 case OP_BIT_XOR: layer_xor(bits | mask); break;
227 case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
228 }
229 }
230 }
231 break;
232 #ifndef NO_ACTION_TAPPING
233 case ACT_LAYER_TAP:
234 case ACT_LAYER_TAP1:
235 switch (action.layer_tap.code) {
236 case OP_TAP_TOGGLE:
237 /* tap toggle */
238 if (event.pressed) {
239 if (tap_count < TAPPING_TOGGLE) {
240 layer_invert(action.layer_tap.val);
241 }
242 } else {
243 if (tap_count <= TAPPING_TOGGLE) {
244 layer_invert(action.layer_tap.val);
245 }
246 }
247 break;
248 case OP_ON_OFF:
249 event.pressed ? layer_on(action.layer_tap.val) :
250 layer_off(action.layer_tap.val);
251 break;
252 case OP_OFF_ON:
253 event.pressed ? layer_off(action.layer_tap.val) :
254 layer_on(action.layer_tap.val);
255 break;
256 case OP_SET_CLEAR:
257 event.pressed ? layer_move(action.layer_tap.val) :
258 layer_clear();
259 break;
260 default:
261 /* tap key */
262 if (event.pressed) {
263 if (tap_count > 0) {
264 debug("KEYMAP_TAP_KEY: Tap: register_code\n");
265 register_code(action.layer_tap.code);
266 } else {
267 debug("KEYMAP_TAP_KEY: No tap: On on press\n");
268 layer_on(action.layer_tap.val);
269 }
270 } else {
271 if (tap_count > 0) {
272 debug("KEYMAP_TAP_KEY: Tap: unregister_code\n");
273 unregister_code(action.layer_tap.code);
274 } else {
275 debug("KEYMAP_TAP_KEY: No tap: Off on release\n");
276 layer_off(action.layer_tap.val);
277 }
278 }
279 break;
280 }
281 break;
282 #endif
283 #endif
284 /* Extentions */
285 #ifndef NO_ACTION_MACRO
286 case ACT_MACRO:
287 action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
288 break;
289 #endif
290 case ACT_COMMAND:
291 break;
292 #ifndef NO_ACTION_FUNCTION
293 case ACT_FUNCTION:
294 action_function(record, action.func.id, action.func.opt);
295 break;
296 #endif
297 default:
298 break;
299 }
300 }
301
302
303
304
305 /*
306 * Utilities for actions.
307 */
308 void register_code(uint8_t code)
309 {
310 if (code == KC_NO) {
311 return;
312 }
313 #ifdef CAPSLOCK_LOCKING_ENABLE
314 else if (KC_LOCKING_CAPS == code) {
315 #ifdef CAPSLOCK_LOCKING_RESYNC_ENABLE
316 // Resync: ignore if caps lock already is on
317 if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
318 #endif
319 host_add_key(KC_CAPSLOCK);
320 host_send_keyboard_report();
321 host_del_key(KC_CAPSLOCK);
322 host_send_keyboard_report();
323 }
324 #endif
325 else if IS_KEY(code) {
326 // TODO: should push command_proc out of this block?
327 if (command_proc(code)) return;
328
329 #ifndef NO_ACTION_ONESHOT
330 if (oneshot_state.mods && !oneshot_state.disabled) {
331 uint8_t tmp_mods = host_get_mods();
332 host_add_mods(oneshot_state.mods);
333
334 host_add_key(code);
335 host_send_keyboard_report();
336
337 host_set_mods(tmp_mods);
338 oneshot_cancel();
339 } else
340 #endif
341 {
342 host_add_key(code);
343 host_send_keyboard_report();
344 }
345 }
346 else if IS_MOD(code) {
347 host_add_mods(MOD_BIT(code));
348 host_send_keyboard_report();
349 }
350 }
351
352 void unregister_code(uint8_t code)
353 {
354 if (code == KC_NO) {
355 return;
356 }
357 #ifdef CAPSLOCK_LOCKING_ENABLE
358 else if (KC_LOCKING_CAPS == code) {
359 #ifdef CAPSLOCK_LOCKING_RESYNC_ENABLE
360 // Resync: ignore if caps lock already is off
361 if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
362 #endif
363 host_add_key(KC_CAPSLOCK);
364 host_send_keyboard_report();
365 host_del_key(KC_CAPSLOCK);
366 host_send_keyboard_report();
367 }
368 #endif
369 else if IS_KEY(code) {
370 host_del_key(code);
371 host_send_keyboard_report();
372 }
373 else if IS_MOD(code) {
374 host_del_mods(MOD_BIT(code));
375 host_send_keyboard_report();
376 }
377 }
378
379 void add_mods(uint8_t mods)
380 {
381 if (mods) {
382 host_add_mods(mods);
383 host_send_keyboard_report();
384 }
385 }
386
387 void del_mods(uint8_t mods)
388 {
389 if (mods) {
390 host_del_mods(mods);
391 host_send_keyboard_report();
392 }
393 }
394
395 void set_mods(uint8_t mods)
396 {
397 host_set_mods(mods);
398 host_send_keyboard_report();
399 }
400
401 void clear_keyboard(void)
402 {
403 host_clear_mods();
404 clear_keyboard_but_mods();
405 }
406
407 void clear_keyboard_but_mods(void)
408 {
409 host_clear_keys();
410 host_send_keyboard_report();
411 #ifdef MOUSEKEY_ENABLE
412 mousekey_clear();
413 mousekey_send();
414 #endif
415 #ifdef EXTRAKEY_ENABLE
416 host_system_send(0);
417 host_consumer_send(0);
418 #endif
419 }
420
421 bool sending_anykey(void)
422 {
423 return (host_has_anykey() || host_mouse_in_use() ||
424 host_last_sysytem_report() || host_last_consumer_report());
425 }
426
427 bool is_tap_key(key_t key)
428 {
429 action_t action = layer_switch_get_action(key);
430
431 switch (action.kind.id) {
432 case ACT_LMODS_TAP:
433 case ACT_RMODS_TAP:
434 case ACT_LAYER_TAP:
435 case ACT_LAYER_TAP1:
436 return true;
437 case ACT_MACRO:
438 case ACT_FUNCTION:
439 if (action.func.opt & FUNC_TAP) { return true; }
440 return false;
441 }
442 return false;
443 }
444
445
446 /*
447 * debug print
448 */
449 void debug_event(keyevent_t event)
450 {
451 debug_hex16((event.key.row<<8) | event.key.col);
452 if (event.pressed) debug("d("); else debug("u(");
453 debug_dec(event.time); debug(")");
454 }
455
456 void debug_record(keyrecord_t record)
457 {
458 debug_event(record.event);
459 #ifndef NO_ACTION_TAPPING
460 debug(":"); debug_dec(record.tap.count);
461 if (record.tap.interrupted) debug("-");
462 #endif
463 }
464
465 void debug_action(action_t action)
466 {
467 switch (action.kind.id) {
468 case ACT_LMODS: debug("ACT_LMODS"); break;
469 case ACT_RMODS: debug("ACT_RMODS"); break;
470 case ACT_LMODS_TAP: debug("ACT_LMODS_TAP"); break;
471 case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break;
472 case ACT_USAGE: debug("ACT_USAGE"); break;
473 case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break;
474 case ACT_LAYER: debug("ACT_LAYER"); break;
475 case ACT_LAYER_TAP: debug("ACT_LAYER_TAP"); break;
476 case ACT_LAYER_TAP1: debug("ACT_LAYER_TAP1"); break;
477 case ACT_MACRO: debug("ACT_MACRO"); break;
478 case ACT_COMMAND: debug("ACT_COMMAND"); break;
479 case ACT_FUNCTION: debug("ACT_FUNCTION"); break;
480 default: debug("UNKNOWN"); break;
481 }
482 debug("[");
483 debug_hex4(action.kind.param>>8);
484 debug(":");
485 debug_hex8(action.kind.param & 0xff);
486 debug("]");
487 }
Imprint / Impressum