/* * Moonlander Layout * * Copyright (C) 2024 Benedikt Peetz * SPDX-License-Identifier: AGPL-3.0-or-later * * This file is part of Moonlander Layout. * * You should have received a copy of the License along with this program. * If not, see . */ #include "hid/hid.h" #include "layout/layout.h" #include "macros.h" #include "version.h" #include #include bool process_record_user(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case VERSION_NUMBER: if (record->event.pressed) { SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION " (rev: " QMK_GIT_HASH ")"); } return false; break; case RGB_SLD: if (record->event.pressed) { rgblight_mode(1); } return false; } uint8_t unicode_saved_mods; // led_t unicode_saved_led_state; if (keycode >= UK_UNICODE && keycode <= UK_UNICODE_MAX && record->event.pressed) { // unicode_saved_led_state = host_keyboard_led_state(); // // // Note the order matters here! // // Need to do this before we mess around with the mods, or else // // UNICODE_KEY_LNX (which is usually Ctrl-Shift-U) might not work // // correctly in the shifted case. // if (unicode_saved_led_state.caps_lock) { // tap_code(KC_CAPS_LOCK); // } unicode_saved_mods = get_mods(); // Save current mods clear_mods(); // Unregister mods to start from a clean state clear_weak_mods(); tap_code16(HYPR(KC_Z)); // Give the pc time to start our application wait_ms(10); hid_send(QK_UNICODE_GET_CODE_POINT(keycode)); // if (unicode_saved_led_state.caps_lock) { // tap_code(KC_CAPS_LOCK); // } set_mods(unicode_saved_mods); // Reregister previously set mods return false; } return true; } typedef struct { bool is_press_action; uint8_t step; } tap; enum { SINGLE_TAP = 1, SINGLE_HOLD, DOUBLE_TAP, DOUBLE_HOLD, DOUBLE_SINGLE_TAP, MORE_TAPS }; static tap dance_state[5]; uint8_t dance_step(tap_dance_state_t *state); uint8_t dance_step(tap_dance_state_t *state) { if (state->count == 1) { if (state->interrupted || !state->pressed) return SINGLE_TAP; else return SINGLE_HOLD; } else if (state->count == 2) { if (state->interrupted) return DOUBLE_SINGLE_TAP; else if (state->pressed) return DOUBLE_HOLD; else return DOUBLE_TAP; } return MORE_TAPS; } void on_dance_0(tap_dance_state_t *state, void *user_data); void dance_0_finished(tap_dance_state_t *state, void *user_data); void dance_0_reset(tap_dance_state_t *state, void *user_data); void on_dance_0(tap_dance_state_t *state, void *user_data) { if (state->count == 3) { tap_code16(KC_SCLN); tap_code16(KC_SCLN); tap_code16(KC_SCLN); } if (state->count > 3) { tap_code16(KC_SCLN); } } void dance_0_finished(tap_dance_state_t *state, void *user_data) { dance_state[0].step = dance_step(state); switch (dance_state[0].step) { case SINGLE_TAP: register_code16(KC_SCLN); break; case SINGLE_HOLD: register_code16(KC_COLN); break; case DOUBLE_TAP: register_code16(KC_SCLN); register_code16(KC_SCLN); break; case DOUBLE_SINGLE_TAP: tap_code16(KC_SCLN); register_code16(KC_SCLN); } } void dance_0_reset(tap_dance_state_t *state, void *user_data) { wait_ms(10); switch (dance_state[0].step) { case SINGLE_TAP: unregister_code16(KC_SCLN); break; case SINGLE_HOLD: unregister_code16(KC_COLN); break; case DOUBLE_TAP: unregister_code16(KC_SCLN); break; case DOUBLE_SINGLE_TAP: unregister_code16(KC_SCLN); break; } dance_state[0].step = 0; } void on_dance_1(tap_dance_state_t *state, void *user_data); void dance_1_finished(tap_dance_state_t *state, void *user_data); void dance_1_reset(tap_dance_state_t *state, void *user_data); void on_dance_1(tap_dance_state_t *state, void *user_data) { if (state->count == 3) { tap_code16(KC_SLASH); tap_code16(KC_SLASH); tap_code16(KC_SLASH); } if (state->count > 3) { tap_code16(KC_SLASH); } } void dance_1_finished(tap_dance_state_t *state, void *user_data) { dance_state[1].step = dance_step(state); switch (dance_state[1].step) { case SINGLE_TAP: register_code16(KC_SLASH); break; case SINGLE_HOLD: register_code16(KC_BSLS); break; case DOUBLE_TAP: register_code16(KC_SLASH); register_code16(KC_SLASH); break; case DOUBLE_SINGLE_TAP: tap_code16(KC_SLASH); register_code16(KC_SLASH); } } void dance_1_reset(tap_dance_state_t *state, void *user_data) { wait_ms(10); switch (dance_state[1].step) { case SINGLE_TAP: unregister_code16(KC_SLASH); break; case SINGLE_HOLD: unregister_code16(KC_BSLS); break; case DOUBLE_TAP: unregister_code16(KC_SLASH); break; case DOUBLE_SINGLE_TAP: unregister_code16(KC_SLASH); break; } dance_state[1].step = 0; } void on_dance_2(tap_dance_state_t *state, void *user_data); void dance_2_finished(tap_dance_state_t *state, void *user_data); void dance_2_reset(tap_dance_state_t *state, void *user_data); void on_dance_2(tap_dance_state_t *state, void *user_data) { if (state->count == 3) { tap_code16(KC_MINUS); tap_code16(KC_MINUS); tap_code16(KC_MINUS); } if (state->count > 3) { tap_code16(KC_MINUS); } } void dance_2_finished(tap_dance_state_t *state, void *user_data) { dance_state[2].step = dance_step(state); switch (dance_state[2].step) { case SINGLE_TAP: register_code16(KC_MINUS); break; case SINGLE_HOLD: register_code16(KC_UNDS); break; case DOUBLE_TAP: register_code16(KC_MINUS); register_code16(KC_MINUS); break; case DOUBLE_SINGLE_TAP: tap_code16(KC_MINUS); register_code16(KC_MINUS); } } void dance_2_reset(tap_dance_state_t *state, void *user_data) { wait_ms(10); switch (dance_state[2].step) { case SINGLE_TAP: unregister_code16(KC_MINUS); break; case SINGLE_HOLD: unregister_code16(KC_UNDS); break; case DOUBLE_TAP: unregister_code16(KC_MINUS); break; case DOUBLE_SINGLE_TAP: unregister_code16(KC_MINUS); break; } dance_state[2].step = 0; } void on_dance_3(tap_dance_state_t *state, void *user_data); void dance_3_finished(tap_dance_state_t *state, void *user_data); void dance_3_reset(tap_dance_state_t *state, void *user_data); void on_dance_3(tap_dance_state_t *state, void *user_data) { if (state->count == 3) { tap_code16(KC_QUOTE); tap_code16(KC_QUOTE); tap_code16(KC_QUOTE); } if (state->count > 3) { tap_code16(KC_QUOTE); } } void dance_3_finished(tap_dance_state_t *state, void *user_data) { dance_state[3].step = dance_step(state); switch (dance_state[3].step) { case SINGLE_TAP: register_code16(KC_QUOTE); break; case SINGLE_HOLD: register_code16(KC_DQUO); break; case DOUBLE_TAP: register_code16(KC_QUOTE); register_code16(KC_QUOTE); break; case DOUBLE_SINGLE_TAP: tap_code16(KC_QUOTE); register_code16(KC_QUOTE); } } void dance_3_reset(tap_dance_state_t *state, void *user_data) { wait_ms(10); switch (dance_state[3].step) { case SINGLE_TAP: unregister_code16(KC_QUOTE); break; case SINGLE_HOLD: unregister_code16(KC_DQUO); break; case DOUBLE_TAP: unregister_code16(KC_QUOTE); break; case DOUBLE_SINGLE_TAP: unregister_code16(KC_QUOTE); break; } dance_state[3].step = 0; } void on_dance_4(tap_dance_state_t *state, void *user_data); void dance_4_finished(tap_dance_state_t *state, void *user_data); void dance_4_reset(tap_dance_state_t *state, void *user_data); void on_dance_4(tap_dance_state_t *state, void *user_data) { if (state->count == 3) { tap_code16(KC_EQUAL); tap_code16(KC_EQUAL); tap_code16(KC_EQUAL); } if (state->count > 3) { tap_code16(KC_EQUAL); } } void dance_4_finished(tap_dance_state_t *state, void *user_data) { dance_state[4].step = dance_step(state); switch (dance_state[4].step) { case SINGLE_TAP: register_code16(KC_EQUAL); break; case SINGLE_HOLD: register_code16(KC_PLUS); break; case DOUBLE_TAP: register_code16(KC_EQUAL); register_code16(KC_EQUAL); break; case DOUBLE_SINGLE_TAP: tap_code16(KC_EQUAL); register_code16(KC_EQUAL); } } void dance_4_reset(tap_dance_state_t *state, void *user_data) { wait_ms(10); switch (dance_state[4].step) { case SINGLE_TAP: unregister_code16(KC_EQUAL); break; case SINGLE_HOLD: unregister_code16(KC_PLUS); break; case DOUBLE_TAP: unregister_code16(KC_EQUAL); break; case DOUBLE_SINGLE_TAP: unregister_code16(KC_EQUAL); break; } dance_state[4].step = 0; } tap_dance_action_t tap_dance_actions[] = { [DANCE_0] = ACTION_TAP_DANCE_FN_ADVANCED(on_dance_0, dance_0_finished, dance_0_reset), [DANCE_1] = ACTION_TAP_DANCE_FN_ADVANCED(on_dance_1, dance_1_finished, dance_1_reset), [DANCE_2] = ACTION_TAP_DANCE_FN_ADVANCED(on_dance_2, dance_2_finished, dance_2_reset), [DANCE_3] = ACTION_TAP_DANCE_FN_ADVANCED(on_dance_3, dance_3_finished, dance_3_reset), [DANCE_4] = ACTION_TAP_DANCE_FN_ADVANCED(on_dance_4, dance_4_finished, dance_4_reset), };