+
+
+
+/*
+ * Utilities for actions.
+ */
+void register_code(uint8_t code)
+{
+ if (code == KC_NO) {
+ return;
+ }
+#ifdef CAPSLOCK_LOCKING_ENABLE
+ else if (KC_LOCKING_CAPS == code) {
+#ifdef CAPSLOCK_LOCKING_RESYNC_ENABLE
+ // Resync: ignore if caps lock already is on
+ if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
+#endif
+ host_add_key(KC_CAPSLOCK);
+ host_send_keyboard_report();
+ host_del_key(KC_CAPSLOCK);
+ host_send_keyboard_report();
+ }
+#endif
+ else if IS_KEY(code) {
+ // TODO: should push command_proc out of this block?
+ if (command_proc(code)) return;
+
+#ifndef NO_ACTION_ONESHOT
+ if (oneshot_state.mods && !oneshot_state.disabled) {
+ uint8_t tmp_mods = host_get_mods();
+ host_add_mods(oneshot_state.mods);
+
+ host_add_key(code);
+ host_send_keyboard_report();
+
+ host_set_mods(tmp_mods);
+ oneshot_cancel();
+ } else
+#endif
+ {
+ host_add_key(code);
+ host_send_keyboard_report();
+ }
+ }
+ else if IS_MOD(code) {
+ host_add_mods(MOD_BIT(code));
+ host_send_keyboard_report();
+ }
+}
+
+void unregister_code(uint8_t code)
+{
+ if (code == KC_NO) {
+ return;
+ }
+#ifdef CAPSLOCK_LOCKING_ENABLE
+ else if (KC_LOCKING_CAPS == code) {
+#ifdef CAPSLOCK_LOCKING_RESYNC_ENABLE
+ // Resync: ignore if caps lock already is off
+ if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
+#endif
+ host_add_key(KC_CAPSLOCK);
+ host_send_keyboard_report();
+ host_del_key(KC_CAPSLOCK);
+ host_send_keyboard_report();
+ }
+#endif
+ else if IS_KEY(code) {
+ host_del_key(code);
+ host_send_keyboard_report();
+ }
+ else if IS_MOD(code) {
+ host_del_mods(MOD_BIT(code));
+ host_send_keyboard_report();
+ }
+}
+
+void add_mods(uint8_t mods)
+{
+ if (mods) {
+ host_add_mods(mods);
+ host_send_keyboard_report();
+ }
+}
+
+void del_mods(uint8_t mods)
+{
+ if (mods) {
+ host_del_mods(mods);
+ host_send_keyboard_report();
+ }
+}
+
+void set_mods(uint8_t mods)
+{
+ host_set_mods(mods);
+ host_send_keyboard_report();
+}
+
+void clear_keyboard(void)
+{
+ host_clear_mods();
+ clear_keyboard_but_mods();
+}
+
+void clear_keyboard_but_mods(void)
+{
+ host_clear_keys();
+ host_send_keyboard_report();
+#ifdef MOUSEKEY_ENABLE
+ mousekey_clear();
+ mousekey_send();
+#endif
+#ifdef EXTRAKEY_ENABLE
+ host_system_send(0);
+ host_consumer_send(0);
+#endif
+}
+
+bool sending_anykey(void)
+{
+ return (host_has_anykey() || host_mouse_in_use() ||
+ host_last_sysytem_report() || host_last_consumer_report());
+}
+
+bool is_tap_key(key_t key)
+{
+ action_t action = layer_switch_get_action(key);
+
+ switch (action.kind.id) {
+ case ACT_LMODS_TAP:
+ case ACT_RMODS_TAP:
+ return true;
+ case ACT_KEYMAP:
+ case ACT_OVERLAY:
+ switch (action.layer.code) {
+ case 0x04 ... 0xEF: /* tap key */
+ case OP_INV:
+ return true;
+ default:
+ return false;
+ }
+ case ACT_MACRO:
+ case ACT_FUNCTION:
+ if (action.func.opt & FUNC_TAP) { return true; }
+ return false;
+ }
+ return false;
+}
+
+
+/*
+ * debug print
+ */
+static void debug_event(keyevent_t event)
+{
+ debug_hex16((event.key.row<<8) | event.key.col);
+ if (event.pressed) debug("d("); else debug("u(");
+ debug_dec(event.time); debug(")");
+}
+
+static void debug_record(keyrecord_t record)
+{
+ debug_event(record.event); debug(":"); debug_dec(record.tap.count);
+ if (record.tap.interrupted) debug("-");
+}
+
+static void debug_action(action_t action)
+{
+ switch (action.kind.id) {
+ case ACT_LMODS: debug("ACT_LMODS"); break;
+ case ACT_RMODS: debug("ACT_RMODS"); break;
+ case ACT_LMODS_TAP: debug("ACT_LMODS_TAP"); break;
+ case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break;
+ case ACT_USAGE: debug("ACT_USAGE"); break;
+ case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break;
+ case ACT_KEYMAP: debug("ACT_KEYMAP"); break;
+ case ACT_OVERLAY: debug("ACT_OVERLAY"); break;
+ case ACT_MACRO: debug("ACT_MACRO"); break;
+ case ACT_COMMAND: debug("ACT_COMMAND"); break;
+ case ACT_FUNCTION: debug("ACT_FUNCTION"); break;
+ default: debug("UNKNOWN"); break;
+ }
+ debug("[");
+ debug_hex4(action.kind.param>>8);
+ debug(":");
+ debug_hex8(action.kind.param & 0xff);
+ debug("]");
+}
+
+
+
+#ifndef NO_ACTION_TAPPING