action.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. /*
  2. Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #include "host.h"
  15. #include "keycode.h"
  16. #include "keyboard.h"
  17. #include "mousekey.h"
  18. #include "command.h"
  19. #include "led.h"
  20. #include "backlight.h"
  21. #include "action_layer.h"
  22. #include "action_tapping.h"
  23. #include "action_macro.h"
  24. #include "action_util.h"
  25. #include "action.h"
  26. #ifdef DEBUG_ACTION
  27. #include "debug.h"
  28. #else
  29. #include "nodebug.h"
  30. #endif
  31. void action_exec(keyevent_t event)
  32. {
  33. if (!IS_NOEVENT(event)) {
  34. dprint("\n---- action_exec: start -----\n");
  35. dprint("EVENT: "); debug_event(event); dprintln();
  36. }
  37. keyrecord_t record = { .event = event };
  38. #ifndef NO_ACTION_TAPPING
  39. action_tapping_process(record);
  40. #else
  41. process_action(&record);
  42. if (!IS_NOEVENT(record.event)) {
  43. dprint("processed: "); debug_record(record); dprintln();
  44. }
  45. #endif
  46. }
  47. #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
  48. bool disable_action_cache = false;
  49. void process_action_nocache(keyrecord_t *record)
  50. {
  51. disable_action_cache = true;
  52. process_action(record);
  53. disable_action_cache = false;
  54. }
  55. #endif
  56. /*
  57. * Make sure the action triggered when the key is released is the same
  58. * one as the one triggered on press. It's important for the mod keys
  59. * when the layer is switched after the down event but before the up
  60. * event as they may get stuck otherwise.
  61. */
  62. action_t store_or_get_action(bool pressed, keypos_t key)
  63. {
  64. #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
  65. static action_t pressed_actions[MATRIX_ROWS][MATRIX_COLS];
  66. if (disable_action_cache) {
  67. return layer_switch_get_action(key);
  68. }
  69. if (pressed) {
  70. pressed_actions[key.row][key.col] = layer_switch_get_action(key);
  71. }
  72. return pressed_actions[key.row][key.col];
  73. #else
  74. return layer_switch_get_action(key);
  75. #endif
  76. }
  77. void process_action(keyrecord_t *record)
  78. {
  79. keyevent_t event = record->event;
  80. #ifndef NO_ACTION_TAPPING
  81. uint8_t tap_count = record->tap.count;
  82. #endif
  83. if (IS_NOEVENT(event)) { return; }
  84. action_t action = store_or_get_action(event.pressed, event.key);
  85. dprint("ACTION: "); debug_action(action);
  86. #ifndef NO_ACTION_LAYER
  87. dprint(" layer_state: "); layer_debug();
  88. dprint(" default_layer_state: "); default_layer_debug();
  89. #endif
  90. dprintln();
  91. switch (action.kind.id) {
  92. /* Key and Mods */
  93. case ACT_LMODS:
  94. case ACT_RMODS:
  95. {
  96. uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods :
  97. action.key.mods<<4;
  98. if (event.pressed) {
  99. if (mods) {
  100. add_weak_mods(mods);
  101. send_keyboard_report();
  102. }
  103. register_code(action.key.code);
  104. } else {
  105. unregister_code(action.key.code);
  106. if (mods) {
  107. del_weak_mods(mods);
  108. send_keyboard_report();
  109. }
  110. }
  111. }
  112. break;
  113. #ifndef NO_ACTION_TAPPING
  114. case ACT_LMODS_TAP:
  115. case ACT_RMODS_TAP:
  116. {
  117. uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods :
  118. action.key.mods<<4;
  119. switch (action.layer_tap.code) {
  120. #ifndef NO_ACTION_ONESHOT
  121. case MODS_ONESHOT:
  122. // Oneshot modifier
  123. if (event.pressed) {
  124. if (tap_count == 0) {
  125. register_mods(mods);
  126. }
  127. else if (tap_count == 1) {
  128. dprint("MODS_TAP: Oneshot: start\n");
  129. set_oneshot_mods(mods);
  130. }
  131. else {
  132. register_mods(mods);
  133. }
  134. } else {
  135. if (tap_count == 0) {
  136. clear_oneshot_mods();
  137. unregister_mods(mods);
  138. }
  139. else if (tap_count == 1) {
  140. // Retain Oneshot mods
  141. }
  142. else {
  143. clear_oneshot_mods();
  144. unregister_mods(mods);
  145. }
  146. }
  147. break;
  148. #endif
  149. case MODS_TAP_TOGGLE:
  150. if (event.pressed) {
  151. if (tap_count <= TAPPING_TOGGLE) {
  152. register_mods(mods);
  153. }
  154. } else {
  155. if (tap_count < TAPPING_TOGGLE) {
  156. unregister_mods(mods);
  157. }
  158. }
  159. break;
  160. default:
  161. if (event.pressed) {
  162. if (tap_count > 0) {
  163. #ifndef IGNORE_MOD_TAP_INTERRUPT
  164. if (record->tap.interrupted) {
  165. dprint("mods_tap: tap: cancel: add_mods\n");
  166. // ad hoc: set 0 to cancel tap
  167. record->tap.count = 0;
  168. register_mods(mods);
  169. } else
  170. #endif
  171. {
  172. dprint("MODS_TAP: Tap: register_code\n");
  173. register_code(action.key.code);
  174. }
  175. } else {
  176. dprint("MODS_TAP: No tap: add_mods\n");
  177. register_mods(mods);
  178. }
  179. } else {
  180. if (tap_count > 0) {
  181. dprint("MODS_TAP: Tap: unregister_code\n");
  182. unregister_code(action.key.code);
  183. } else {
  184. dprint("MODS_TAP: No tap: add_mods\n");
  185. unregister_mods(mods);
  186. }
  187. }
  188. break;
  189. }
  190. }
  191. break;
  192. #endif
  193. #ifdef EXTRAKEY_ENABLE
  194. /* other HID usage */
  195. case ACT_USAGE:
  196. switch (action.usage.page) {
  197. case PAGE_SYSTEM:
  198. if (event.pressed) {
  199. host_system_send(action.usage.code);
  200. } else {
  201. host_system_send(0);
  202. }
  203. break;
  204. case PAGE_CONSUMER:
  205. if (event.pressed) {
  206. host_consumer_send(action.usage.code);
  207. } else {
  208. host_consumer_send(0);
  209. }
  210. break;
  211. }
  212. break;
  213. #endif
  214. #ifdef MOUSEKEY_ENABLE
  215. /* Mouse key */
  216. case ACT_MOUSEKEY:
  217. if (event.pressed) {
  218. mousekey_on(action.key.code);
  219. mousekey_send();
  220. } else {
  221. mousekey_off(action.key.code);
  222. mousekey_send();
  223. }
  224. break;
  225. #endif
  226. #ifndef NO_ACTION_LAYER
  227. case ACT_LAYER:
  228. if (action.layer_bitop.on == 0) {
  229. /* Default Layer Bitwise Operation */
  230. if (!event.pressed) {
  231. uint8_t shift = action.layer_bitop.part*4;
  232. uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
  233. uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
  234. switch (action.layer_bitop.op) {
  235. case OP_BIT_AND: default_layer_and(bits | mask); break;
  236. case OP_BIT_OR: default_layer_or(bits | mask); break;
  237. case OP_BIT_XOR: default_layer_xor(bits | mask); break;
  238. case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
  239. }
  240. }
  241. } else {
  242. /* Layer Bitwise Operation */
  243. if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
  244. (action.layer_bitop.on & ON_RELEASE)) {
  245. uint8_t shift = action.layer_bitop.part*4;
  246. uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
  247. uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
  248. switch (action.layer_bitop.op) {
  249. case OP_BIT_AND: layer_and(bits | mask); break;
  250. case OP_BIT_OR: layer_or(bits | mask); break;
  251. case OP_BIT_XOR: layer_xor(bits | mask); break;
  252. case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
  253. }
  254. }
  255. }
  256. break;
  257. #ifndef NO_ACTION_TAPPING
  258. case ACT_LAYER_TAP:
  259. case ACT_LAYER_TAP_EXT:
  260. switch (action.layer_tap.code) {
  261. case 0xe0 ... 0xef:
  262. /* layer On/Off with modifiers(left only) */
  263. if (event.pressed) {
  264. layer_on(action.layer_tap.val);
  265. register_mods(action.layer_tap.code & 0x0f);
  266. } else {
  267. layer_off(action.layer_tap.val);
  268. unregister_mods(action.layer_tap.code & 0x0f);
  269. }
  270. break;
  271. case OP_TAP_TOGGLE:
  272. /* tap toggle */
  273. if (event.pressed) {
  274. if (tap_count < TAPPING_TOGGLE) {
  275. layer_invert(action.layer_tap.val);
  276. }
  277. } else {
  278. if (tap_count <= TAPPING_TOGGLE) {
  279. layer_invert(action.layer_tap.val);
  280. }
  281. }
  282. break;
  283. case OP_ON_OFF:
  284. event.pressed ? layer_on(action.layer_tap.val) :
  285. layer_off(action.layer_tap.val);
  286. break;
  287. case OP_OFF_ON:
  288. event.pressed ? layer_off(action.layer_tap.val) :
  289. layer_on(action.layer_tap.val);
  290. break;
  291. case OP_SET_CLEAR:
  292. event.pressed ? layer_move(action.layer_tap.val) :
  293. layer_clear();
  294. break;
  295. default:
  296. /* tap key */
  297. if (event.pressed) {
  298. if (tap_count > 0) {
  299. dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
  300. register_code(action.layer_tap.code);
  301. } else {
  302. dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
  303. layer_on(action.layer_tap.val);
  304. }
  305. } else {
  306. if (tap_count > 0) {
  307. dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
  308. unregister_code(action.layer_tap.code);
  309. } else {
  310. dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
  311. layer_off(action.layer_tap.val);
  312. }
  313. }
  314. break;
  315. }
  316. break;
  317. #endif
  318. #endif
  319. /* Extentions */
  320. #ifndef NO_ACTION_MACRO
  321. case ACT_MACRO:
  322. action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
  323. break;
  324. #endif
  325. #ifdef BACKLIGHT_ENABLE
  326. case ACT_BACKLIGHT:
  327. if (!event.pressed) {
  328. switch (action.backlight.opt) {
  329. case BACKLIGHT_INCREASE:
  330. backlight_increase();
  331. break;
  332. case BACKLIGHT_DECREASE:
  333. backlight_decrease();
  334. break;
  335. case BACKLIGHT_TOGGLE:
  336. backlight_toggle();
  337. break;
  338. case BACKLIGHT_STEP:
  339. backlight_step();
  340. break;
  341. case BACKLIGHT_LEVEL:
  342. backlight_level(action.backlight.level);
  343. break;
  344. }
  345. }
  346. break;
  347. #endif
  348. case ACT_COMMAND:
  349. break;
  350. #ifndef NO_ACTION_FUNCTION
  351. case ACT_FUNCTION:
  352. action_function(record, action.func.id, action.func.opt);
  353. break;
  354. #endif
  355. default:
  356. break;
  357. }
  358. }
  359. /*
  360. * Utilities for actions.
  361. */
  362. void register_code(uint8_t code)
  363. {
  364. if (code == KC_NO) {
  365. return;
  366. }
  367. #ifdef LOCKING_SUPPORT_ENABLE
  368. else if (KC_LOCKING_CAPS == code) {
  369. #ifdef LOCKING_RESYNC_ENABLE
  370. // Resync: ignore if caps lock already is on
  371. if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
  372. #endif
  373. add_key(KC_CAPSLOCK);
  374. send_keyboard_report();
  375. del_key(KC_CAPSLOCK);
  376. send_keyboard_report();
  377. }
  378. else if (KC_LOCKING_NUM == code) {
  379. #ifdef LOCKING_RESYNC_ENABLE
  380. if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
  381. #endif
  382. add_key(KC_NUMLOCK);
  383. send_keyboard_report();
  384. del_key(KC_NUMLOCK);
  385. send_keyboard_report();
  386. }
  387. else if (KC_LOCKING_SCROLL == code) {
  388. #ifdef LOCKING_RESYNC_ENABLE
  389. if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
  390. #endif
  391. add_key(KC_SCROLLLOCK);
  392. send_keyboard_report();
  393. del_key(KC_SCROLLLOCK);
  394. send_keyboard_report();
  395. }
  396. #endif
  397. else if IS_KEY(code) {
  398. // TODO: should push command_proc out of this block?
  399. if (command_proc(code)) return;
  400. #ifndef NO_ACTION_ONESHOT
  401. /* TODO: remove
  402. if (oneshot_state.mods && !oneshot_state.disabled) {
  403. uint8_t tmp_mods = get_mods();
  404. add_mods(oneshot_state.mods);
  405. add_key(code);
  406. send_keyboard_report();
  407. set_mods(tmp_mods);
  408. send_keyboard_report();
  409. oneshot_cancel();
  410. } else
  411. */
  412. #endif
  413. {
  414. add_key(code);
  415. send_keyboard_report();
  416. }
  417. }
  418. else if IS_MOD(code) {
  419. add_mods(MOD_BIT(code));
  420. send_keyboard_report();
  421. }
  422. else if IS_SYSTEM(code) {
  423. host_system_send(KEYCODE2SYSTEM(code));
  424. }
  425. else if IS_CONSUMER(code) {
  426. host_consumer_send(KEYCODE2CONSUMER(code));
  427. }
  428. }
  429. void unregister_code(uint8_t code)
  430. {
  431. if (code == KC_NO) {
  432. return;
  433. }
  434. #ifdef LOCKING_SUPPORT_ENABLE
  435. else if (KC_LOCKING_CAPS == code) {
  436. #ifdef LOCKING_RESYNC_ENABLE
  437. // Resync: ignore if caps lock already is off
  438. if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
  439. #endif
  440. add_key(KC_CAPSLOCK);
  441. send_keyboard_report();
  442. del_key(KC_CAPSLOCK);
  443. send_keyboard_report();
  444. }
  445. else if (KC_LOCKING_NUM == code) {
  446. #ifdef LOCKING_RESYNC_ENABLE
  447. if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
  448. #endif
  449. add_key(KC_NUMLOCK);
  450. send_keyboard_report();
  451. del_key(KC_NUMLOCK);
  452. send_keyboard_report();
  453. }
  454. else if (KC_LOCKING_SCROLL == code) {
  455. #ifdef LOCKING_RESYNC_ENABLE
  456. if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
  457. #endif
  458. add_key(KC_SCROLLLOCK);
  459. send_keyboard_report();
  460. del_key(KC_SCROLLLOCK);
  461. send_keyboard_report();
  462. }
  463. #endif
  464. else if IS_KEY(code) {
  465. del_key(code);
  466. send_keyboard_report();
  467. }
  468. else if IS_MOD(code) {
  469. del_mods(MOD_BIT(code));
  470. send_keyboard_report();
  471. }
  472. else if IS_SYSTEM(code) {
  473. host_system_send(0);
  474. }
  475. else if IS_CONSUMER(code) {
  476. host_consumer_send(0);
  477. }
  478. }
  479. void register_mods(uint8_t mods)
  480. {
  481. if (mods) {
  482. add_mods(mods);
  483. send_keyboard_report();
  484. }
  485. }
  486. void unregister_mods(uint8_t mods)
  487. {
  488. if (mods) {
  489. del_mods(mods);
  490. send_keyboard_report();
  491. }
  492. }
  493. void clear_keyboard(void)
  494. {
  495. clear_mods();
  496. clear_keyboard_but_mods();
  497. }
  498. void clear_keyboard_but_mods(void)
  499. {
  500. clear_weak_mods();
  501. clear_keys();
  502. send_keyboard_report();
  503. #ifdef MOUSEKEY_ENABLE
  504. mousekey_clear();
  505. mousekey_send();
  506. #endif
  507. #ifdef EXTRAKEY_ENABLE
  508. host_system_send(0);
  509. host_consumer_send(0);
  510. #endif
  511. }
  512. bool is_tap_key(keypos_t key)
  513. {
  514. action_t action = layer_switch_get_action(key);
  515. switch (action.kind.id) {
  516. case ACT_LMODS_TAP:
  517. case ACT_RMODS_TAP:
  518. case ACT_LAYER_TAP:
  519. case ACT_LAYER_TAP_EXT:
  520. switch (action.layer_tap.code) {
  521. case 0x00 ... 0xdf:
  522. case OP_TAP_TOGGLE:
  523. return true;
  524. }
  525. return false;
  526. case ACT_MACRO:
  527. case ACT_FUNCTION:
  528. if (action.func.opt & FUNC_TAP) { return true; }
  529. return false;
  530. }
  531. return false;
  532. }
  533. /*
  534. * debug print
  535. */
  536. void debug_event(keyevent_t event)
  537. {
  538. dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
  539. }
  540. void debug_record(keyrecord_t record)
  541. {
  542. debug_event(record.event);
  543. #ifndef NO_ACTION_TAPPING
  544. dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
  545. #endif
  546. }
  547. void debug_action(action_t action)
  548. {
  549. switch (action.kind.id) {
  550. case ACT_LMODS: dprint("ACT_LMODS"); break;
  551. case ACT_RMODS: dprint("ACT_RMODS"); break;
  552. case ACT_LMODS_TAP: dprint("ACT_LMODS_TAP"); break;
  553. case ACT_RMODS_TAP: dprint("ACT_RMODS_TAP"); break;
  554. case ACT_USAGE: dprint("ACT_USAGE"); break;
  555. case ACT_MOUSEKEY: dprint("ACT_MOUSEKEY"); break;
  556. case ACT_LAYER: dprint("ACT_LAYER"); break;
  557. case ACT_LAYER_TAP: dprint("ACT_LAYER_TAP"); break;
  558. case ACT_LAYER_TAP_EXT: dprint("ACT_LAYER_TAP_EXT"); break;
  559. case ACT_MACRO: dprint("ACT_MACRO"); break;
  560. case ACT_COMMAND: dprint("ACT_COMMAND"); break;
  561. case ACT_FUNCTION: dprint("ACT_FUNCTION"); break;
  562. default: dprint("UNKNOWN"); break;
  563. }
  564. dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
  565. }